I'm playing with job management in bash, and am seeing confusing behavior.
Here is a minimal script to demonstrate:
#!/bin/bash
set -e
function start_job {
echo "Kicking off job that sleeps for ${1}"
sleep "${1}" && echo "Slept for ${1}!" &
}
# Start some jobs - print current child pids.
echo "Jobs are: $(jobs -p)"
start_job 5
echo "Jobs are: $(jobs -p)"
start_job 6
echo "Jobs are: $(jobs -p)"
start_job 7
echo "Jobs are: $(jobs -p)"
# Wait long enough for all children to finish.
echo "Main thread sleeping for 10 and killing all remaining jobs."
sleep 10
echo "Killing sub-jobs."
echo "Jobs are: $(jobs -p)"
kill $(jobs -p)
We create a bunch of child jobs (sleep and report back).
Then we wait for all them them to have a chance to terminate.
Then we invoke jobs -p and kill any pid it returns.
If I change things so my last sleep is 5 seconds, it correctly identifies the 2 remaining pids and kills them.
But if I run it as-is (sleep until they ALL finish), I get the following output:
Jobs are:
Kicking off job that sleeps for 5
Jobs are: 3352412
Kicking off job that sleeps for 6
Jobs are: 3352412
3352415
Kicking off job that sleeps for 7
Jobs are: 3352412
3352415
3352418
Main thread sleeping for 10 and killing all remaining jobs.
Slept for 5!
Slept for 6!
Slept for 7!
Killing sub-jobs.
Jobs are: 3352418
./mini_job_test.sh: line 23: kill: (3352418) - No such process
This seems totally broken. That 3352418 corresponds to the Slept for 7 job, which, as kill correctly reports back, is a pid that doesn't exist. What gives?
EDIT
Looks like I can specify -r for running jobs and -s for stopped jobs, and with -r, it seems to behave.
... but then I'd expect the funky pid to be stopped... but if I do -s, then that doesn't show up... so:
- jobs -p: returns that last pid
- jobs -pr: returns no pids
- jobs -ps: returns no pids <-- shouldn't it at least show up here if jobs -p is returning a non-running pid???