What is the best way to close this group of processes?
I have the following group of processes, which need to be closed programmatically by the first listed process, which is a C program that I am coding.
PID PGRP SESN PPID USER TTY CMD
6553 6553 6553 1 root ? ./startserv
6554 6553 6553 6553 root ? expect -- /usr/bin/unbuffer ./srcds_run...
6555 6555 6555 6554 root pts/1 /bin/sh ./srcds_run -autoupdate -game c...
6565 6555 6555 6555 root pts/1 ./srcds_linux -autoupdate -game cstrike...
What I usually do by开发者_如何学运维 hand in this situation is kill 6553 6555. Obviously I know my own pid, but it seems a bit silly to code something like "kill my pid + 2" (although it seems that this would [almost] always work. Help?
None of these answers are very correct - the easiest way to handle this is to put the processes in a process group (child processes inherit the parent's process group, so your closed-source binaries should be good too) via getpgrp/setpgrp, then kill them all in one fell-swoop via killpg, which guarantees that all of them will receive the signal at the same time, without any race conditions which would let a child process forked at the right time to escape.
This sounds like an all-around bad design. Why do you need it like that? Would it make more sense for your startserv
process to launch others as child processes, in which case killing them is simple? What are you trying to achieve?
From the kill(2) system call's man page:
If pid is negative but not -1, sig is sent to all processes (except an unspecified set of system processes) whose process group ID is equal to the absolute value of pid and for which the process has permission to send a signal.
EDIT
(I'm asking for clarification here, but I need room and formatting that aren't available in the comment area)
So pstree would print:
startserv --- expect --- /bin/sh --- srcds_linux
And grouping the groups would be:
{startserv --- expect} --- {/bin/sh --- srcds_linux}
And from startserv
you want to kill expect
, /bin/sh
, and srcds_linux
, but killing expect
does not result in expect
killing its immediate child (much less the group that that child is the head of).
Some more suggestions
It may be that killing expect with some signal besides SIGKILL
(9) such as SIGTERM
might cause expect
to kill its child (and maybe group) for you before terminating itself, but you may have already tried that.
Baring that you could try looking through /proc/*/stat
to build a process tree, and find your expect
process (you already know its pid), and then kill it and all of its children. This isn't perfect since it's not atomic (/bin/sh could fork some more children or something), but if you want to try to catch that as well you could send all processes in this sub-tree SIGSTOP
as realize that they are under the expect
sub-tree to stabilize that tree. Then send them all a stronger kill possibly followed by a SIGCONT
.
A more automatic way to accomplish this would be to have startserv
create a psudoterminal to run expect
(and its descendants) on and then close the controlling side of the psudoterminal and hope that all of those programs die on SIGHUP
.
It seems like the easiest way to do this is simply going to be to use bash. I can simply capture the output of ps axo pid,ppid. I already have the first process generate a lock file with its pid so a bash script would be able to look up the first item with a ppid of the parent's pid and send it a SIGTERM along with the parent.
In the end my solution was: get the pid of the child that the parent forks from within the program (the expect process). Write that pid to a lock file along with the pid of the first process. Write a bash script that looks up what processes have a parent that has the pid of the of the second process. Kill the first process and the process id returned by the bash script. Everything terminates cleanly. It is possible that it would be best to use the killpg command with this method, I will take a look at that.
精彩评论