Search code examples
linuxvariable-assignmentbackground-process

Linux | Background assignment of command output to variable


I need 3 commands to be run and their (single-line) outputs assigned to 3 different variables, which then I use to write to a file. I want to wait till the variable assignment is complete for all 3 before I echo the variables to the file. I am running these in a loop within a bash script.

This is what I have tried -

var1=$(longRunningCommand1) &
var2=$(longRunningCommand2) &
var3=$(longRunningCommand3) &

wait %1 %2 %3
echo "$var1,$var2,$var3">>$logFile

This gives no values at all, for the variables. I get -

,,
,,
,,

However, if I try this -

var1=$(longRunningCommand1 &)
var2=$(longRunningCommand2 &)
var3=$(longRunningCommand3 &)

wait %1 %2 %3
echo "$var1,$var2,$var3">>$logFile

I get the desired output,

o/p of longRunningCommand1, o/p of longRunningCommand2, o/p of longRunningCommand3
o/p of longRunningCommand1, o/p of longRunningCommand2, o/p of longRunningCommand3
o/p of longRunningCommand1, o/p of longRunningCommand2, o/p of longRunningCommand3

but the nohup.out for this shell script indicates that there was no background job to wait for -

netmon.sh: line 35: wait: %1: no such job
netmon.sh: line 35: wait: %2: no such job
netmon.sh: line 35: wait: %3: no such job

I would not have bothered much about this, but I definitely need to make sure that my script is waiting for all the 3 variables to be assigned before attempting the write. Whereas, the nohup.out tells me otherwise! I think I want to know if the 2nd approach is the right way when I run into a situation where any of those 3 commands are running for more than a few seconds. I have not yet been able to get a really long running command or a resource contention on the box to actually resolve this doubt of mine.

Thank you very much for any helpful thoughts.

-MT


Solution

  • Your goal of writing the output of echo "$var1,$var2,$var3">>$logFile while backgrounding actual processes of longRunningCommand1, ..2, ..3 can be accomplished using a list and redirection. As @that_other_guy notes, you cannot assign the result of a command substitution to a variable in the background to begin with. However, for a shell that provides process substitution like bash, you can write the output of a process to a file in the background and separating your processes and redirections by a ';' will insure the sequential write of command1, ..2, ..3 to the log file, e.g.:

    Commands that are separated by a <semicolon> ( ';' ) 
    shall be executed sequentially.
    

    POSIX Specification - lists

    Putting those pieces together, you would sequentially write the results of your comment to $logfile with something similar to the following,

    ( (longRunningCommand1) >> $logfile; (longRunningCommand2) >> $logfile; \
      (longRunningCommand3) >> $logfile) &
    

    (note: the ';' between commands writing to $logfile)

    While not required, if you wanted to wait until all commands had been written to $logfile within your script (and your script supports $! as the PID for the last backgrouded process), you could simply wait $!, though that is not required to insure the write to the file completes.