我在 bash 中有一个简短的脚本,需要在后台作为守护进程运行。它基于 inotifywait,它应该等待指定文件夹的更改,如果有任何更改,它应该运行复制过程。
#! /bin/sh
case "$1" in
start)
dir=/var/www/www/source/
target=/var/www/www/htdocs/application/cache/target/
inotifywait -m "$dir" --format '%w%f' -e close_write |
while read file; do
cp "$file" "$target"
done
;;
stop)
;;
esac
我已经将其放入/etc/init.d,保存后运行update-rc.d myscript 默认值但是现在,当我尝试启动它并抛出服务启动命令时,它会停止并停留在来自 inotifywait 的消息上。
/etc/init.d/bash start
Setting up watches.
Watches established.
您能否提示我如何在后台进程中运行它而不输出任何消息(理想的方式是在启动后立即运行)?
答案1
所以我让它工作了,但它是一个相当丑陋的黑客。关于如何正确编写 init 脚本,我建议这个链接。
我想要做的只是用“&”将进程放在后台。
/etc/init.d/myinitscript.sh
#! /bin/sh
case "$1" in
start)
dir=/var/www/www/source/
target=/var/www/www/htdocs/application/cache/target/
inotifywait -m "$dir" --format '%w%f' -e close_write |
while read file; do
cp "$file" "$target"
done & ## <--- why not just put it in the background?
;;
stop)
;;
esac
对于某些“work”值,此方法“有效”。 “myinitscript.sh”在启动时运行,并执行其应执行的操作,但导致此进程挂起:
$ ps aux | grep -i init
[... snip ...]
root 2341 0.0 0.1 4096 600 ? Ss 18:02 0:00 startpar -f -- myinitscript.sh
[... snip ...]
此问题的原因和可能的解决方案可以在这里找到。
我随后的解决方案很糟糕,如果你在生产中这样做,那么你做错了。
我使用了两个脚本,一个在 /etc/init.d 中,另一个在 /root 中。
/etc/init.d/myinitscript.sh
#! /bin/sh
case "$1" in
start)
/root/initscriptbody.sh > /dev/null 2>&1
;;
stop)
;;
esac
不将 stdout 和 stderr 重定向到 /dev/null 会导致“starpar”进程挂起。第二个脚本包含所有功能,可以将其放在后台,而不会导致“starpar”进程挂起:
/root/initscriptbody.sh
#! /bin/sh
dir=/var/www/www/source/
target=/var/www/www/htdocs/application/cache/target/
inotifywait -m "$dir" --format '%w%f' -e close_write |
while read file
do
cp "$file" "$target"
done & ## <-- no problem backgrounding this now
答案2
你可以使用屏幕,或者按照评论中的建议,禁止. 两者都可以以自动化方式使用,例如使用 init 脚本。
对于 screen,您可能需要特别注意,如果从 init 脚本之类的东西中使用,它将成功打开 screen 会话。具体来说,设置正确的 $TERM 环境并以特定用户身份运行它。
如果操作正确,它还有附加到屏幕会话和分离它的额外好处。不过对于您的特定用途屏幕来说可能有点过头了。
另请查看/etc/init.d/skeleton它提供了创建初始化脚本的模板。
以下行是执行开始()函数可能正好满足你的需要:
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON
您只需要在开始时更改变量以指向您的脚本和相关内容,它就可以按原样工作。
答案3
一种可能的方法是使用守护进程工具启动你的 bash 脚本。Daemontools 是一个控制脚本执行的守护进程 - 监听它的 stdout 并在它退出时重新启动。还有一些替代方案,例如主管或者使用以下命令运行脚本Systemd 服务单元