bash 使用陷阱 SIGCHLD 重新启动子进程?
我见过监控程序要么在使用“ps”或“服务状态(在 Linux 上)”定期检查进程状态的脚本中,要么在分叉并等待进程的 C/C++ 中......
我想知道是否有可能使用 bash 和 trap 并在收到 SIGCLD 时重新启动子进程?
我已经在 RedHat Linux 上测试了一个基本套件,其想法如下(当然它不起作用......)
#!/bin/bash
set -o monitor # can someone explain this? discussion on Internet say this is needed
trap startProcess SIGCHLD
startProcess() {
/path/to/another/bash/script.sh & # the one to restart
while [ 1 ]
do
sleep 60
done
}
startProcess
正在启动的 bash 脚本只是休眠几秒钟然后暂时退出。
观察到的几个问题:
- 当 shell 在前台启动时,SIGCHLD 将仅被处理一次。 trap 是否像 signal() 一样重置信号处理?
- 该脚本及其子脚本似乎不受 SIGINT 的影响,这意味着它们不能被 ^C 停止
- ,因为无法关闭,我关闭了终端。剧本好像是HUP,留下了很多僵尸小孩。
- 当在后台运行时,脚本导致终端死机
......无论如何,这根本不起作用。我不得不说我对这个话题了解太少了。 有人可以建议或给出一些可行的例子吗? 有这样的用途的脚本吗?
那么在 bash 中使用 wait 怎么样?
谢谢
I've seen monitoring programs either in scripts that check process status using 'ps' or 'service status(on Linux)' periodically, or in C/C++ that forks and wait on the process...
I wonder if it is possible to use bash with trap and restart the sub-process when SIGCLD received?
I have tested a basic suite on RedHat Linux with following idea (and certainly it didn't work...)
#!/bin/bash
set -o monitor # can someone explain this? discussion on Internet say this is needed
trap startProcess SIGCHLD
startProcess() {
/path/to/another/bash/script.sh & # the one to restart
while [ 1 ]
do
sleep 60
done
}
startProcess
what the bash script being started just sleep for a few seconds and exit for now.
several issues observed:
- when the shell starts in foreground, SIGCHLD will be handled only once. does trap reset signal handling like signal()?
- the script and its child seem to be immune to SIGINT, which means they cannot be stopped by ^C
- since cannot be closed, I closed the terminal. The script seems to be HUP and many zombie children left.
- when run in background, the script caused terminal to die
... anyway, this does not work at all. I have to say I know too little about this topic.
Can someone suggest or give some working examples?
Are there scripts for such use?
how about use wait in bash, then?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我可以尝试回答你的一些问题,但不是全部基于我的内容
知道。
行
set -o monitor
(或等效的set -m
)启动作业控制,默认情况下仅对交互式 shell 启用。这似乎
需要发送 SIGCHLD。然而,工作控制更多的是
交互式功能,并不真正适合在 shell 脚本中使用
(另请参见 这个问题)。
另请记住,这可能不是您想要做的
因为一旦启用作业控制,每个都会发送 SIGCHLD
存在的外部命令(例如每次运行
ls
或grep
或任何事情,当该命令完成并且你的陷阱时,SIGCHLD 将会触发
将运行)。
我怀疑 SIGCHLD 陷阱只出现一次的原因是
因为你的陷阱处理程序包含一个前台无限循环,所以你的
脚本卡在陷阱处理程序中。似乎没有什么意义
无论如何,你可以简单地删除它。
脚本对 SIGINT 的“免疫”似乎是启用的效果
作业控制(监视器部分)。我的预感是打开作业控制,
运行脚本的 bash 子实例不再终止
本身响应 SIGINT,而是将 SIGINT 传递给
它的前台子进程。在您的脚本中,
^C
即 SIGINT只是像其他编程语言中的
continue
语句一样这种情况下,由于 SIGINT 只会终止当前正在运行的
sleep 60
,随后 while 循环将立即运行一个新的
sleep 60
。当我尝试运行你的脚本然后杀死它时(来自另一个
终端),我最终得到的是两个杂散睡眠进程。
尽管如此,将该脚本作为后台也会杀死我的 shell
行为并不是非常一致(有时会发生
立即,其他时候则根本不)。似乎输入任何其他键
比 Enter 导致 EOF 以某种方式发送。即使在航站楼之后
退出脚本继续在后台运行。我不知道
这里发生了什么。
更具体地说明你想要完成的事情会有所帮助。如果
您只需要一个命令在您的生命周期内连续运行
脚本中,您可以在后台运行无限循环,例如
注意
done
之后的&
。对于其他任务,
wait
可能比使用作业控制更好在 shell 脚本中。同样,这取决于你到底想做什么
去做。
I can try to answer some of your questions but not all based on what I
know.
The line
set -o monitor
(or equivalently,set -m
) turns on jobcontrol, which is only on by default for interactive shells. This seems
to be required for SIGCHLD to be sent. However, job control is more of
an interactive feature and not really meant to be used in shell scripts
(see also this question).
Also keep in mind this is probably not what you intended to do
because once you enable job control, SIGCHLD will be sent for every
external command that exists (e.g. every time you run
ls
orgrep
oranything, a SIGCHLD will fire when that command completes and your trap
will run).
I suspect the reason the SIGCHLD trap only appears to run once is
because your trap handler contains a foreground infinite loop, so your
script gets stuck in the trap handler. There doesn't seem to be a point
to that loop anyways, so you could simply remove it.
The script's "immunity" to SIGINT seems to be an effect of enabling
job control (the monitor part). My hunch is with job control turned on,
the sub-instance of bash that runs your script no longer terminates
itself in response to a SIGINT but instead passes the SIGINT through to
its foreground child process. In your script, the
^C
i.e. SIGINTsimply acts like a
continue
statement in other programming languagescase, since SIGINT will just kill the currently running
sleep 60
,whereupon the while loop will immediately run a new
sleep 60
.When I tried running your script and then killing it (from another
terminal), all I ended up with were two stray sleep processes.
Backgrounding that script also kills my shell for me, although
the behavior is not terribly consistent (sometimes it happens
immediately, other times not at all). It seems typing any keys other
than enter causes an EOF to get sent somehow. Even after the terminal
exits the script continues to run in the background. I have no idea
what is going on here.
Being more specific about what you want to accomplish would help. If
you just want a command to run continuously for the lifetime of your
script, you could run an infinite loop in the background, like
Note the
&
after thedone
.For other tasks,
wait
is probably a better idea than using job controlin a shell script. Again, it would depend on what exactly you are trying
to do.