我在这样的bash脚本中包装一个fastcgi应用程序:
#!/bin/bash
# stuff
./fastcgi_bin
# stuff
由于bash仅在前台脚本结束时执行信号陷阱而不能kill -TERM scriptpid
,因为fastcgi应用程序将保持活动状态。
我已经尝试将二进制文件发送到后台:
#!/bin/bash
# stuff
./fastcgi_bin &
PID=$!
trap "kill $PID" TERM
# stuff
但如果我这样做,显然stdin和stdout没有正确重定向,因为它没有与lighttpds mod_fastgi连接,前台版本确实有效。
编辑:我一直在关注这个问题,这是因为bash在后台启动程序时将/ dev / null重定向到stdin,所以任何避免这种情况的方法都应解决我的问题问题也是如此。
有关如何解决此问题的任何提示?
答案 0 :(得分:15)
我想到了一些选择:
从shell脚本启动进程时,两者都属于同一进程组。杀死父进程会让孩子们活着,所以应该杀死整个进程组。这可以通过将否定的PGID(进程组ID)传递给kill来实现,这与父进程的PID相同。 ej:kill -TERM -$PARENT_PID
不要执行二进制文件
一个孩子,但更换脚本
exec
进程。你失去了
事后能够执行的东西
但是,因为exec
完全
替换父进程。
不要杀死shell脚本进程,而是杀死FastCGI二进制文件。然后,在脚本中检查返回代码并相应地执行操作。例如:./fastcgi_bin || exit -1
根据mod_fastcgi处理工作进程的方式,只有第二个选项可行。
答案 1 :(得分:1)
我不知道这是否是你的选择,但是因为你有赏金我假设你可能会选择不在乎的想法。
你能在Perl中重写bash脚本吗? Perl有几种管理子进程的方法。您可以在核心模块perldoc perlipc
和IPC::Open2
中阅读IPC::Open3
及更多细节。
我不知道这将如何与lighttpd等接口,或者这种方法中是否有更多功能,但至少它为您提供了更多的灵活性,还有更多内容可供您阅读。
答案 2 :(得分:1)
我在几分钟前写了这个脚本来杀死一个bash脚本及其所有的孩子......
#!/bin/bash
# This script will kill all the child process id for a given pid
# based on http://www.unix.com/unix-dummies-questions-answers/5245-script-kill-all-child-process-given-pid.html
ppid=$1
if [ -z $ppid ] ; then
echo "This script kills the process identified by pid, and all of its kids";
echo "Usage: $0 pid";
exit;
fi
for i in `ps j | awk '$3 == '$ppid' { print $2 }'`
do
$0 $i
kill -9 $i
done
确保脚本可执行,否则您将在$ 0 $ i
上收到错误消息答案 3 :(得分:0)
我不确定我是否完全明白你的意思,但这是我尝试过的,而且这个过程似乎能够管理陷阱(称之为trap.sh):
#!/bin/bash
trap "echo trap activated" TERM INT
echo begin
time sleep 60
echo end
启动它:
./trap.sh &
并使用它(一次只能执行其中一个命令):
kill -9 %1
kill -15 %1
或从前景开始:
./trap.sh
用control-C中断。
似乎适合我。 究竟什么对你不起作用?
答案 4 :(得分:0)
您可以通过自己重定向stdin来覆盖后台进程的隐式</dev/null
,例如:
sh -c 'exec 3<&0; { read x; echo "[$x]"; } <&3 3<&- & exec 3<&-; wait'
答案 5 :(得分:0)
尝试使用stdin
保留原始./fastcgi_bin 0<&0 &
:
#!/bin/bash
# stuff
./fastcgi_bin 0<&0 &
PID=$!./fastcgi_bin 0<&0 &
trap "kill $PID" TERM
# stuff
# test
#sh -c 'sleep 10 & lsof -p ${!}'
#sh -c 'sleep 10 0<&0 & lsof -p ${!}'
答案 6 :(得分:-1)
您可以使用coprocess。
执行此操作编辑:好吧,coprocesses是可以打开stdin和stdout的后台进程(因为bash为它们准备了fifos)。但是你仍然需要读取/写入那些fifos,而唯一有用的原语是bash的read
(可能带有超时或文件描述符);没有足够强大的cgi。所以在第二个想法,我的建议是不要在bash中做这件事。在fastcgi或WSGI等http包装器中做额外的工作会更方便。