如何在bash中杀死单个后台进程

时间:2014-08-13 21:20:08

标签: bash shell scripting background-process

我想在bash中杀死一个后台进程

$SCRIPT_DIR/utils/monitor.sh -f $root/save &
$SCRIPT_DIR/utils/run.sh -f $save
$SCRIPT_DIR/utils/Monkey.sh  -f $save

我想在完成Monkey.sh后杀死monitor.sh。

我尝试使用pid,但它无效。

4 个答案:

答案 0 :(得分:1)

您正在寻找'jobs'和'kill'命令

$ ls -l
    total 4.0K
    -rwxr-xr-x. 1 probinson probinso 52 Aug 13 14:25 x.sh
    lrwxrwxrwx. 1 probinson probinso  4 Aug 13 14:28 y.sh -> x.sh
    lrwxrwxrwx. 1 probinson probinso  4 Aug 13 14:28 z.sh -> y.sh

$ cat x.sh 
    for i in $(find / 2> /dev/null ); do echo ${i} &> /dev/null; done

$ ./x.sh & ./y.sh & ./z.sh &
$ jobs
    [1]   Running                 ./x.sh &
    [2]-  Running                 ./y.sh &
    [3]+  Running                 ./z.sh &
$ kill %2
$ jobs
    [1]   Running                 ./x.sh &
    [2]-  Terminated              ./y.sh &
    [3]+  Running                 ./z.sh &
$ jobs
    [1]-  Running                 ./x.sh &
    [3]+  Running                 ./z.sh &

# this should kill job one after job three finishes
$ ./x.sh; x.sh & y.sh & z.sh; kill %1

答案 1 :(得分:1)

看起来这个问题可能与调用monitor.sh的方式有关。如果我有一个脚本' foo.sh'它只有一个shell命令,我不认为它被识别为' foo.sh'在ps列表中,但如果我使用sh(或bash)调用它,那么我会这样做。似乎如果' foo.sh'是一个shell命令列表,shell会将其更改为bash,你不会看到foo.sh'在ps列表中,但如果我用bash明确地称它,即

bash foo.sh

然后我在ps列表中看到它。

然而,shell脚本的最佳实践是从适当的' hashbang'开始。命令,即对于bash脚本,第一行应该是

#!/bin/bash

这似乎也解决了我的问题。我猜测monitor.sh可能会遗漏这一行,这就是为什么你不能使用pskillall看到它。一旦到位,你应该可以做到

killall -9 monitor.sh

或类似的它会起作用。要么是以bash monitor.sh调用它,要么将其作为{{1}}调用,但通常的最佳做法是以任一方式包含第一行。

cf - http://www.unix.com/shell-programming-and-scripting/21446-ps-command-does-not-display-shell-script-running.html

答案 2 :(得分:1)

另一种方法是保存后台进程的PID:

$SCRIPT_DIR/utils/monitor.sh -f $root/save &
MONITOR_PID=$!
...
kill $MONITOR_PID

这优于killall的优势在于它会杀死这个特定的过程。如果您运行的脚本有多个副本,则不会终止同时运行的其他monitor.sh脚本。

另请参阅:https://stackoverflow.com/a/1911387/1563512

答案 3 :(得分:0)

您有多种选择:

首先,您可以使用kill。但是您需要使用pspidofpgrep来获取流程的pid。

ps -A  // to get the pid, can be combined with grep
-or-
pidof <name>
-or-
pgrep <name>

kill <pid>

可以通过知道名称来杀死进程。使用pkillkillall

pkill <name>
-or-
killall <name>

所有命令都向进程发送信号。如果进程挂起,可能需要向进程发送sigkill(这是信号9,因此以下示例也是如此):

pkill -9 <name>
pkill -SIGKILL <name>

您也可以将此选项与killkillall一起使用。

阅读这篇关于controlling processes的文章,以获得有关流程的更多信息。

归功于tanascius

你应该试试

killall Monkey.sh