Bash 脚本作为 Debian 上的守护进程

Bash 脚本作为 Debian 上的守护进程

我在 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 服务单元

相关内容