我正在为一个工具编写一个包装脚本。包装器脚本应该准备环境,然后在后台调用该工具,然后退出。它看起来像这样:
#!/bin/bash
export FOO=1
tool "$@" &
这里没什么了不起的。除了我错误地没有调用该工具(/usr/bin/tool),而是有效地调用了包装器脚本本身(~/bin/tool)。不知不觉中我运行了包装脚本,但什么也没发生。至少没有任何可见的东西。
我想知道为什么什么也没发生。再次打开脚本。查看错误(未调用 /usr/bin/tool)。修复它以运行实际工具并保存。突然,这个工具弹出来了。经过一番思考后,我意识到包装器脚本正在后台一遍又一遍地运行。当我编辑脚本以调用实际工具时,脚本的下一次调用立即调用该工具并停止链。
因为它不分叉,所以不是分叉炸弹。但这似乎是一个递归幽灵。我重新创建了静默递归包装器并尝试检测。我的知识有限。我不是大师。我尝试过 ps 和 pgrep 等工具。我给这个脚本起了一个朗朗上口的名字:pgrep。但 pgrep 大多数时候什么也看不到。在循环中运行 pgrep 有时会捕获失控的脚本。大约每十秒一次?我没有做统计。
递归幽灵脚本是良性的。几乎不吃任何资源。也许唯一可见的效果是它导致 PID 快速升高。因为每次新的调用都会得到一个新的 PID。
如何检测并阻止在后台调用自身并退出的失控递归幽灵脚本?
以下是如何重现:
创建
woop
使用以下内容调用的脚本#!/bin/sh ./woop &
打开两个终端并在文本编辑器中打开脚本
在一个终端运行
./woop
。注意没有任何可见的事情发生。它将立即返回提示。在第二个终端运行
while true; do pgrep -fa woop; done
。大约每十秒看到一个结果。在文本编辑器中将行更改
./woop &
为./woops &
或其他内容并保存。注意第一个终端的错误 (./woop: line 2: ./woops: No such file or directory
)在第二个终端中通知不再找到任何结果。
答案1
使用forkstat
如果可用的话应该可以很好地指示是否有任何进程正在运行。例如:
forkstat -e fork
当确定后,执行以下一项或全部操作:
chmod -x /path/to/file
mv ...
rm ...
可以选择使用该-S
标志(这里是简化的统计数据):
$ forkstat -S
... loads of lines
^C
Fork Exec Exit ... Total Process
11546 11532 11547 ... 34625 /bin/bash - ./woop
...