I knew I was grasping at straws, but UNIX never fails!
Here's how I managed it:
bash$ gdb --pid 8909
...
Loaded symbols for /lib/i386-linux-gnu/i686/cmov/libnss_files.so.2
0xb76e7424 in __kernel_vsyscall ()
Then at the (gdb)
prompt I ran the command, call write_history("/tmp/foo")
which will write this history to the file /tmp/foo
.
(gdb) call write_history("/tmp/foo")
$1 = 0
I then detach from the process.
(gdb) detach
Detaching from program: /bin/bash, process 8909
And quit gdb
.
(gdb) q
And sure enough...
bash$ tail -1 /tmp/foo
while true ; do echo 1 ; echo 2>/dev/null ; sleep 30 ; done
For easy future re-use, I wrote a bash script, automating the process.
To background itself, that application forks a child process and exits the parent. The shell knows of the parent process as that's the one it has forked itself before executing the command itself, but it has no visibility on the children or grand-children that that process may have spawned.
A simpler example of such a backgrounding command would be:
$ sh -c 'ps -j; sleep 10 &'
PID PGID SID TTY TIME CMD
6562 6562 14469 pts/13 00:00:00 sh
6563 6562 14469 pts/13 00:00:00 ps
14469 14469 14469 pts/13 00:00:00 zsh
My zsh
knows about that sh
process and its process group.
However, all it sees is that 6562 process exiting. It has no way to know that 6562 process has spawned a 6563 one.
$ ps -j
PID PGID SID TTY TIME CMD
6564 6562 14469 pts/13 00:00:00 sleep
6565 6565 14469 pts/13 00:00:00 ps
14469 14469 14469 pts/13 00:00:00 zsh
However, you can see the process running sleep
is also in that 6562 process group (though, there's nothing stopping commands start new process groups, or even sessions (as daemons typically do)).
Those process groups are only created when the shell is interactive though.
Another thing you could do is:
cmd | cat &
wait
If the processes that cmd spawns don't close their stdout, then cat
won't die until they have all died.
Best Answer
The PID of the last executed command is in the
$!
shell variable: