当信号到来时杀死 bash 脚本前台子进程
我将 fastcgi 应用程序包装在 bash 脚本中,如下所示:
#!/bin/bash
# stuff
./fastcgi_bin
# stuff
由于 bash 仅在前台脚本结束时执行信号陷阱,所以我不能只是 kill -TERM scriptpid
因为 fastcgi 应用程序将保持活动状态。
我尝试将二进制文件发送到后台:
#!/bin/bash
# stuff
./fastcgi_bin &
PID=$!
trap "kill $PID" TERM
# stuff
但是如果我这样做,显然标准输入和标准输出没有正确重定向,因为它没有与lighttpds mod_fastgi连接,前台版本确实可以工作。
编辑:我一直在研究这个问题,发生这种情况是因为当程序在后台启动时 bash 将 /dev/null 重定向到 stdin,所以任何避免这种情况的方法也应该解决我的问题。
关于如何解决这个问题有任何提示吗?
I am wrapping a fastcgi app in a bash script like this:
#!/bin/bash
# stuff
./fastcgi_bin
# stuff
As bash only executes traps for signals when the foreground script ends I can't just kill -TERM scriptpid
because the fastcgi app will be kept alive.
I've tried sending the binary to the background:
#!/bin/bash
# stuff
./fastcgi_bin &
PID=$!
trap "kill $PID" TERM
# stuff
But if I do it like this, apparently the stdin and stdout aren't properly redirected because it does not connect with lighttpds mod_fastgi, the foreground version does work.
EDIT: I've been looking at the problem and this happens because bash redirects /dev/null to stdin when a program is launched in the background, so any way of avoiding this should solve my problem as well.
Any hint on how to solve this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我想到了一些选项:
当从 shell 脚本启动进程时,两者都属于同一进程组。杀死父进程会使子进程存活,因此应该杀死整个进程组。这可以通过将否定的PGID(进程组ID)传递给kill来实现,它与父进程的PID相同。 ej:
kill -TERM -$PARENT_PID
不要执行二进制文件
一个孩子,但替换了脚本
使用
exec
进行处理。你失去了之后执行事情的能力
不过,因为
exec
完全替换父进程。
不要杀死 shell 脚本进程,而是杀死 FastCGI 二进制文件。然后,在脚本中检查返回代码并采取相应措施。例如:
./fastcgi_bin || exit -1
根据 mod_fastcgi 如何处理工作进程,只有第二个选项可能是可行的。
There are some options that come to my mind:
When a process is launched from a shell script, both belong to the same process group. Killing the parent process leaves the children alive, so the whole process group should be killed. This can be achieved by passing the negated PGID (Process Group ID) to kill, which is the same as the parent's PID. ej:
kill -TERM -$PARENT_PID
Do not execute the binary as
a child, but replacing the script
process with
exec
. You lose theability to execute stuff afterwards
though, because
exec
completelyreplaces the parent process.
Do not kill the shell script process, but the FastCGI binary. Then, in the script, examine the return code and act accordingly. e.g:
./fastcgi_bin || exit -1
Depending on how mod_fastcgi handles worker processes, only the second option might be viable.
我几分钟前写了这个脚本来杀死一个 bash 脚本及其所有子脚本...
确保该脚本是可执行的,否则您将在 $0 $i 上收到错误
I wrote this script just minutes ago to kill a bash script and all of its children...
Make sure the script is executable, or you will get an error on the $0 $i
我不知道这是否适合您,但由于您有赏金,我假设您可能会寻求跳出框框的想法。
你能用 Perl 重写 bash 脚本吗? Perl 有多种管理子进程的方法。您可以阅读
perldoc perlipc
以及核心模块中的更多详细信息IPC::Open2
和IPC::Open3
。我不知道这将如何与 lighttpd 等接口,或者这种方法是否有更多功能,但至少它为您提供了更多的灵活性和更多的阅读内容。
I have no idea if this is an option for you or not, but since you have a bounty I am assuming you might go for ideas that are outside the box.
Could you rewrite the bash script in Perl? Perl has several methods of managing child processes. You can read
perldoc perlipc
and more specifics in the core modulesIPC::Open2
andIPC::Open3
.I don't know how this will interface with lighttpd etc or if there is more functionality in this approach, but at least it gives you some more flexibility and some more to read in your hunt.
您可以通过自己重定向 stdin 来覆盖后台进程的隐式
,例如:
You can override the implicit
</dev/null
for a background process by redirecting stdin yourself, for example:我不确定我完全明白你的意思,但这是我尝试过的,该过程似乎能够管理陷阱(称之为 trap.sh):
启动它:
并使用它(一次只能使用其中一个命令) ):
或在前台启动:
并使用 control-C 中断。
似乎对我有用。
到底什么对你不起作用?
I'm not sure I fully get your point, but here's what I tried and the process seems to be able to manage the trap (call it trap.sh):
Start it:
And play with it (only one of those commands at once):
Or start in foreground:
And interrupt with control-C.
Seems to work for me.
What exactly does not work for you?
尝试使用
./fastcgi_bin 0<&0 &
保留原始的stdin
:Try keeping the original
stdin
using./fastcgi_bin 0<&0 &
:您可以使用协进程来做到这一点。
编辑:嗯,协进程是可以打开 stdin 和 stdout 的后台进程(因为 bash 为它们准备了 fifo)。但是您仍然需要读/写这些 fifo,唯一有用的原语是 bash 的 read(可能带有超时或文件描述符);对于 cgi 来说,没有什么足够强大的。所以再想一想,我的建议是不要在 bash 中做这件事。在 fastcgi 或像 WSGI 这样的 http 包装器中完成额外的工作会更方便。
You can do that with a coprocess.
Edit: well, coprocesses are background processes that can have stdin and stdout open (because bash prepares fifos for them). But you still need to read/write to those fifos, and the only useful primitive for that is bash's
read
(possibly with a timeout or a file descriptor); nothing robust enough for a cgi. So on second thought, my advice would be not to do this thing in bash. Doing the extra work in the fastcgi, or in an http wrapper like WSGI, would be more convenient.