In the following "one-liner," when I change the variable ID value at the start of the script, the disk variable that follows does not seem to update. Namely, at the end of the script, the >> /md0/DiskAnalysis/$disk.txt portion uses the value of the $disk variable that was generated by a different $ID variable value than the one defined at the start of the script.

Full one-liner script

nohup sh -c ID="c"; disk=`udevadm info --query=all /dev/sd$ID | grep ID_SCSI_SERIAL | awk -F'=' '{print $2}'`; size=`lsblk -b --output SIZE -n -d /dev/sd$ID`; size=`echo "$size / 1024 / 1024 / 10" | bc`; for i in $(seq 0 $size); do dd if=/dev/sd$ID of=/dev/shm/$ID.dd bs=10M skip=$i count=1 2>1; sha256=`sha256sum /dev/shm/$ID.dd | awk -F' ' '{print $1}'`; md5=`md5sum /dev/shm/$ID.dd | awk -F' ' '{print $1}'`; echo "$i,$sha256,$md5" >> /md0/DiskAnalysis/$disk.txt; done &

So, when I change ID="b" to ID="c", the

disk=`udevadm info --query=all /dev/sd$ID | grep ID_SCSI_SERIAL | awk -F'=' '{print $2}'`

portion of the script does not update its value to reflect the change in the $ID variable value. However, If I were to execute the following by itself in terminal:

ID="b"; disk=`udevadm info --query=all /dev/sd$ID | grep ID_SCSI_SERIAL | awk -F'=' '{print $2}'`; echo $disk


ID="c"; disk=`udevadm info --query=all /dev/sd$ID | grep ID_SCSI_SERIAL | awk -F'=' '{print $2}'`; echo $disk

I get two different values for $disk.

What am I missing that is resulting in the $disk variable value not updating in the full script?

For the moment, I am assuming the change in the $ID value in other parts of the script (i.e. the checksums) is working correctly. However, since the $disk value is not updating correctly, the output isn't writing to the desired file. In fact, every time I run the script with an $ID value different from the original (ID="b"), the output from the rest of the script simple writes to the output file (i.e. $disk) defined by the first original $ID.



There's an unquoted, unescaped ; there.

nohup sh -c ID="c"; whatever runs nohup sh -c ID="c" first, then whatever.

The first command is almost a no-op. It doesn't affect the variables of the current shell, it doesn't affect expansions when whatever is interpreted in the current shell, it doesn't affect whatever in the way you want. It only creates nohup.out (if not yet created).

Basically you need nohup sh -c 'ID="c"; whatever' (add & if needed). Here ; is not interpreted by the current shell. The entire single-quoted string will eventually become an option-argument passed to sh -c.

I haven't analyzed your specific command thoroughly enough to tell:

In general these are different issues.


In your 'script' as written, the sh -c only applies to ID="c", i.e. not to everything to the right of the semicolon. This means ID="c" is set in a child process which is cleaned up before executing the next command. To see this, just do sh -c somevar="x"; echo $somevar.

For the variable to be shared, it either needs to be exported (see Difference between "a=b" and "export a=b" in bash) or have the same parent process.

For example, somevar="x"; echo $somevar (without setting the variable in a child process) would work; or sh -c 'somevar="x"; echo $somevar' would also work, since the two commands are both children of sh -c.

  • Thank you. In my attempt to make "nohup" and "&" work I came across a "solution' using "sh -c". I am/was not familiar with "sh -c" but it seem to fix my "nohup"/"&" problem. I am now reading up to better understand how to properly use "export" to make everything work as desired. Even though putting it into a file and then running that script would be easier/quicker, I am in it to pick up a few new skills at this point. – Brian Aug 15 '20 at 2:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.