0

I want to get the pids of two background processes,

sleep 20 & pid1=$\!; sleep 10 & pid2=$\!; echo "pid1: $pid1, pid2: $pid2"

and get output like below:

[1] 124646
[2] 124648
pid1: $!, pid2: $!

the output I desired to get is like:

pid1: 124646, pid2: 124648

Anyone know why and can help to achieve this?

[add 2018/01/02]

Sorry for really late response, one hand is busy, another is that I want to verify the script.

The actual script I want to run is like below:

sh -c "sleep 20 & pid1=$!; sleep 10 & pid2=$!; echo \"pid1: $pid1, pid2: $pid2\""

and as it will report bash: !: event not found, so I tried to add \ and become:

sh -c "sleep 20 & pid1=$\!; sleep 10 & pid2=$\!; echo \"pid1: $pid1, pid2: $pid2\""

and for make the problem simple, I just rmeove sh -c while this make it a quite different problem.

for my problem, I found out that below script will work:

sh -c 'sleep 20 & pid1=$!; sleep 10 & pid2=$!; echo "pid1: $pid1, pid2: $pid2"'

Yet there is another question, how to make below script to work:

name='bob'
# below script reports 'bash: !: event not found' error
sh -c "echo $name; sleep 20 & pid1=$!; sleep 10 & pid2=$!; echo \"pid1: $pid1, pid2: $pid2\"" 
# below script $name will not become bob
sh -c 'echo $name; sleep 20 & pid1=$!; sleep 10 & pid2=$!; echo \"pid1: $pid1, pid2: $pid2\"' 
Y.Huang
  • 119
  • 2
  • 11

3 Answers3

3

The backslash is causing the value to be the string $! verbatim. Don't put a backslash in the assignment.

On the command line, you may want to temporarily set +H to avoid getting event not found warnings; but this only affects the interactive shell. In a script, set -H is never active (and would be meaningless anyway).

(I'm speculating this is the reason you put the backslash there in the first place. If not, simply just take it out.)

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Actually, I recommend using `set +H` as a permanent setting in your `.bashrc` unless you actually understand what the `event not found` warning means and are actively using this facility. – tripleee Dec 20 '17 at 07:33
  • Thanks for reply, could you please take another look on how to make script `sh -c "echo $name; sleep 20 & pid1=$!; sleep 10 & pid2=$!; echo \"pid1: $pid1, pid2: $pid2\"" ` runnable? – Y.Huang Jan 02 '18 at 09:03
  • Is there a reason you are not following the advice to `set +H` at least temporarily to disable the "event not found" problem? Also, updating your question to pile on new requirements is not very good form; you should probably accept one of the answers here and post a new question with better focus. – tripleee Jan 02 '18 at 09:06
  • thanks for your advice. I will post another question for the later one. As to the reason that not using `set +H`, I works fine to get rid of `event not found` warning, thanks. – Y.Huang Jan 02 '18 at 13:32
  • *That's what it does!* – tripleee Jan 02 '18 at 13:41
1

Your syntax kindly incorrect, try this:

[root@XXX ~]# sleep 5 & pid1=$!; sleep 6 & pid2=$!; echo "pid1: ${pid1}, pid2: ${pid2}"
[1] 2308
[2] 2309
pid1: 2308, pid2: 2309
Viktor Khilin
  • 1,760
  • 9
  • 21
  • If I do want to use `sh -c "sleep 20 & pid1=$!; sleep 10 & pid2=$!; echo \"pid1: $pid1, pid2: $pid2\""` how can I write the script, can you help on this? thanks! – Y.Huang Jan 02 '18 at 08:49
0

I have accomplished this in the past by using bash arrays to hold the PIDs. I had a sequence of database imports to run and when handled sequentially they took ~8 hours to complete. I launched them all as background processes and tracked the list of PIDs to watch for completion and it got the processing time down to 45 minutes.

Here is an example of launching background processes, storing the PIDs in an array, and then printing all of the array values:

$ pids=()
$ sleep 20 &
22991
$ pids+=($!)
$ sleep 20 &
23298
$ pids+=($!)
$ j=0;for i in "${pids[@]}";do ((j=j+1));echo 'pid'$j': '$i;done
pid1: 22991
pid2: 23298
sorak
  • 2,607
  • 2
  • 16
  • 24