我需要在临时容器/VM 中的(远程)shell 上为测试执行引擎运行基本上任意命令。有时这些泄漏后台进程会导致整个命令挂起。这可以归结为这个简单的命令:
$ sh -c 'sleep 30 & echo payload'
payload
$
在这里,backgroundedsleep 30
扮演了泄露进程的角色(实际上将类似于dbus-daemon
),而 echo 是我想要运行的实际内容。此处应将其sleep 30 & echo payload
视为原子不透明示例命令。
上面的命令很好,并立即返回,因为 shell 和 sleep 的 stdout/stderr 都是 PTY。但是,当将命令的输出捕获到管道/文件时(毕竟,测试运行程序希望将所有内容保存到日志中),整个命令会挂起:
$ sh -c 'sleep 30 & echo payload' | cat
payload
# ... does not return to the shell (until the sleep finishes)
现在,这可以通过一些相当可笑的复杂 shell 魔法来解决,它确定 stdout/err 的 FD /proc/$$/fd/{1,2}
,迭代ls /proc/[0-9]*/fd/*
并杀死每个也具有相同 stdout/stderr 的进程。但这涉及到大量脆弱的 shell 代码和昂贵的 shell 字符串比较。
有没有办法以更优雅、更简单的方式清理这些泄露的后台进程?setsid
没有帮助:
$ sh -c 'setsid -w sh -c "sleep 30 & echo payload"' | cat
payload
# hangs...
请注意,进程组/会话并彻底杀死它们是不够的,因为泄漏的进程(如 dbus-daemon)通常会自行设置。
PS 我只能在这些环境中假设 POSIX shell 或 bash;没有 Python、Perl 等。
先感谢您!