我正在一个环境中运行bash脚本,该环境会在10分钟内没有输出的情况下杀死进程。因此,我正在运行一个后台进程,注入换行符以防止发生超时。
到目前为止,该方法仍然有效,但是在脚本完成后,似乎无法正确杀死keep-alive循环。睡眠命令最多持续590秒。
#!/usr/bin/env bash
# Exit on any error
set -e
# Some other commands
# ...
(while true; do echo "" && sleep 590; done) &
trap "kill $!" EXIT
ps all
looong_running_command_with_no_output
# Exit normally
我的脚本中ps
的输出:
PID PPID PGID WINPID TTY UID STIME COMMAND
1607 1606 1467 5032 ? 197608 20:21:05 /usr/bin/bash
1468 1467 1467 4592 ? 197608 20:20:49 /usr/bin/bash
1608 1607 1467 4064 ? 197608 20:21:05 /usr/bin/sleep
1467 1 1467 4472 ? 197608 20:20:49 /usr/bin/bash
1609 1606 1467 4768 ? 197608 20:21:05 /usr/bin/ps
1606 1468 1467 4168 ? 197608 20:21:05 /usr/bin/bash
脚本完成后ps
的输出:
PID PPID PGID WINPID TTY UID STIME COMMAND
1468 1467 1467 4592 ? 197608 20:20:49 /usr/bin/bash
1637 1468 1467 2436 ? 197608 20:21:09 /usr/bin/ps
1608 1 1467 4064 ? 197608 20:21:05 /usr/bin/sleep
1467 1 1467 4472 ? 197608 20:20:49 /usr/bin/bash
您可以看到睡眠仍在后台运行。 PPID现在已经更改为1,因为它会将后台进程重新初始化为init。但是,我根本不明白为什么会这样。 kill是否不会终止所有子进程(在这种情况下为睡眠和回声)?
更新:我的脚本正在运行-e标志。也许这很重要。我还添加了ps的输出。
Update2:
看起来kill
确实并没有杀死注释中提到的整个进程树。 pkill
可以,但是我的脚本在pkill
不可用的Git Bash中运行。在阅读了很多带有复杂建议的帖子后,我最终遇到了以下陷阱:
trap "kill $!; wait $! 2>/dev/null; killall sleep" EXIT
这对于我的用例来说已经足够好了。
答案 0 :(得分:2)
问题是:使用( ... )
语法时,您将创建一个子shell ...让我们来展示:
在某些终端控制台中:
tty
/dev/pts/24
ps --tty pts/24 fw
PID TTY STAT TIME COMMAND
28983 pts/24 Ss 0:00 bash
29322 pts/24 R+ 0:00 \_ ps --tty pts/24 fw
( echo foo; sleep 300 ) &
[1] 30214
foo
ps --tty pts/24 fw
PID TTY STAT TIME COMMAND
28983 pts/24 Ss 0:00 bash
30214 pts/24 S 0:00 \_ bash
30215 pts/24 S 0:00 | \_ sleep 300
30377 pts/24 R+ 0:00 \_ ps --tty pts/24 fw
ps $!
PID TTY STAT TIME COMMAND
30214 pts/24 S 0:00 bash
所以$!
是bash
subshell ,而sleep
有另一个pid。
因此杀死$!
只会杀死bash:
kill $!
[1]+ Terminated ( echo foo; sleep 300 )
但是
ps --tty pts/24 fw
PID TTY STAT TIME COMMAND
28983 pts/24 Ss 0:00 bash
30793 pts/24 R+ 0:00 \_ ps --tty pts/24 fw
30215 pts/24 S 0:00 sleep 300
睡眠仍然存在。
在上一个长时间运行的命令上使用exec
:
( echo foo; exec sleep 300 ) &
[1] 31557
foo
ps --tty pts/24 fw
PID TTY STAT TIME COMMAND
28983 pts/24 Ss 0:00 bash
31557 pts/24 S 0:00 \_ sleep 300
31558 pts/24 R+ 0:00 \_ ps --tty pts/24 fw
然后
kill $!
[1]+ Terminated ( echo foo; exec sleep 300 )
ps --tty pts/24 fw
PID TTY STAT TIME COMMAND
28983 pts/24 Ss 0:00 bash
31706 pts/24 R+ 0:00 \_ ps --tty pts/24 fw
似乎还可以。
ps --tty pts/24 fw
PID TTY STAT TIME COMMAND
28983 pts/24 Ss 0:00 bash
1176 pts/24 R+ 0:00 \_ ps --tty pts/24 fw
for ((i=3;i--;)){ sleep 300 & trap "kill $!;exit" 0 1 2 3 6 9 15;wait $!;} &
[1] 1178
ps --tty pts/24 fw
PID TTY STAT TIME COMMAND
28983 pts/24 Ss 0:00 bash
1178 pts/24 S 0:00 \_ bash
1179 pts/24 S 0:00 | \_ sleep 300
1180 pts/24 R+ 0:00 \_ ps --tty pts/24 fw
好吧,现在:
kill -1 $!
[1]+ Done for ((i=3; i--; 1))
do
sleep 300 & trap "kill $!;exit" 0 1 2 3 6 9 15; wait $!;
done
ps --tty pts/24 fw
PID TTY STAT TIME COMMAND
28983 pts/24 Ss 0:00 bash
1299 pts/24 R+ 0:00 \_ ps --tty pts/24 fw
似乎很好!