2015-09-02 49 views
2

我需要在短暂的容器/ VMS(远程)壳为一个测试执行引擎上运行基本上任意命令泄漏后台进程。有时这些泄漏后台进程,然后导致整个命令挂起。这可以归结为简单的命令:壳:清理该挂起由于共享标准输出/ stderr的

$ sh -c 'sleep 30 & echo payload' 
payload 
$ 

这里转到后台sleep 30起着泄露过程(这在现实中会像dbus-daemon)的作用和回声是我要运行的实际的事情。这里应该将sleep 30 & echo payload视为一个原子不透明的示例命令。

上述命令是细并立即返回作为外壳的,并且还睡眠的stdout/stderr的是一个PTY。但是,捕获命令的输出时,管道/文件(测试跑步想要的一切保存到一个日志,毕竟),整个命令挂起:

$ sh -c 'sleep 30 & echo payload' | cat 
payload 
# ... does not return to the shell (until the sleep finishes) 

现在,这可能是固定的一些相当复杂的外壳魔法,它决定了从/proc/$$/fd/{1,2}开始的stdout/err的FD,迭代ls /proc/[0-9]*/fd/*并杀死每个同样具有stdout/stderr的进程。但是这涉及很多脆弱的shell代码和昂贵的shell字符串比较。

有没有办法以更优雅和更简单的方式清理这些泄漏的后台进程? setsid没有帮助:

$ sh -c 'setsid -w sh -c "sleep 30 & echo payload"' | cat 
payload 
# hangs... 

注意进程组/会话和杀害他们批发是不够的,因为泄漏的进程(如DBUS守护进程)通常setsid自己。

P.S.我只能在这些环境中假设POSIX shell或bash;没有Python,Perl等。

谢谢你提前!

+0

以下的工作,但我不服气它回答你的问题:'sh -c'{sleep 30 |猫 ; }&{echo payload |猫 ; }'' –

+0

谢谢,但我没有专门寻找睡眠和回声的解决方案;这只是一个示例命令,用于“某些命令泄漏后台命令”的情况。我对这个问题做了一些澄清。 –

+0

我发现了一个初始近似值:'$ setsid -w sh -c'sleep 30&echo payload; RC = $ ?; for p in $(pgrep --pgroup 0);做[$ p = $$] ||杀死$ p;完成;退出$ RC'|只要使用'kill - - $$'就太过分了,因为它也会杀死shell。 –

回答

0

我们在Launchpad中进行并行测试时遇到了这个问题。我们当时最简单的解决方案 - 运行良好 - 只是为了确保没有进程共享标准输出/标准输入/标准错误(除非你真的想要挂起,例如测试工人本身)。

0

嗯,已经重新读取这个我不能给你,你是该解决方案后(使用systemd杀死他们)。我们提出的是简单地忽略流程,但当我们等待的单个流程完成时,可靠地不会挂起。请注意,这与管道关闭明显不同。

另一种选择,而不是完美的,但有用的,是成为当地的收割与使用prctl(2)和PR_SET_CHILD_SUBREAPER。这将允许您成为所有可以重新启动init的进程的父项。通过这种安排,你可以尝试杀死所有那些你为ppid的进程。这很糟糕,但它是使用cgroups最接近的最好的东西。

但要注意,除非你正在运行的这个助手作为root你会发现,实际测试可能产卵,将潜伏一些setuid的东西并不会killable。这真是一个令人讨厌的问题。

+0

对于我们在plainbox中的相同问题(另一个测试工具;-)您可以看看这个bug https://bugs.launchpad.net/plainbox/+bug/1377270但所有的细节都一样。我只是将其链接起来以便于交叉引用。 –

0

使用script -qfc代替sh -c

相关问题