将shell脚本作为守护程序运行的“正确”方法


20

我正在编写一个shell脚本,希望在启动时作为守护程序运行,而无需使用daemontoolsdaemonize之类的外部工具


Linux守护程序编写方法

根据Linux Daemon Writing HOWTO的规定适当的守护程序具有以下特征:

  • 来自父进程的分叉
  • 关闭所有文件描述符(即stdinstdoutstderr
  • 打开写入日志(如果已配置)
  • 工作目录更改为永久目录(通常为/
  • 重置文件模式掩码(umask)
  • 创建一个唯一的会话ID(SID)

守护简介

守护进程介绍更进一步,指出一个典型的守护程序也:

  • 从其控制终端取消关联(如果有),并忽略所有终端信号
  • 从其流程组中脱离
  • 处理 SIGCLD

我将如何做到这一切的shdashbash只用普通的Linux工具脚本?

尽管Debian是我们的主要重点,但该脚本应该能够在尽可能多的发行版上运行而无需其他软件。


注意:我知道在StackExchange网络上有很多建议使用nohup或的答案setsid,但是这些方法都不能满足上述所有要求。


编辑:守护进程(7)用户手册还给出了一些三分球,虽然似乎有老式的之间的一些差异SysV守护程序和更新systemd的。由于与各种发行版的兼容性很重要,因此请确保答案清楚说明所有差异。



1
制作自己的shell脚本的“正确”方法是使其进行自己的日志记录,提供将其作为守护程序启动的方法,等等。诸如此类的daemon事情用于运行任意的 shell脚本,而无须以一个守护程序。由于您是作者,因此完全可以控制该脚本的编写方式,因此可以直接从systemd unitfile或rc.d脚本启动该脚本。您确实指定了“正确”!
Rich

Answers:


16

使用systemd,您应该能够通过创建一个简单的单元将脚本作为守护程序运行。您可以添加很多不同的选项,但这几乎就可以轻松实现。

假设您有一个脚本/usr/bin/mydaemon

#!/bin/sh

while true; do
  date;
  sleep 60;
done

您创建一个单位/etc/systemd/system/mydaemon.service

[Unit]
Description=My daemon

[Service]
ExecStart=/usr/bin/mydaemon
Restart=on-failure

[Install]
WantedBy=multi-user.target 

要开始运行恶魔

systemctl start mydaemon.service 

要在启动时启动,请启用它

systemctl enable mydaemon.service

如果在当今大多数Linux发行版都基于systemd的系统上,那么它实际上不是外部工具。不利的是,尽管它不能在任何地方都起作用。


3
虽然我喜欢systemd方法,但是OP表示“没有外部工具”。有些Linux发行版还没有systemd,或者让您在systemd和其他东西(例如OpenRC)之间进行选择。
Cristian Ciupitu

5
对于使用systemd的发行版,systemd不再是“外部工具” bash
亚历山大

7

我可能在这里错过了一些东西。为什么恰恰nohup不合适呢?当然,仅凭它还不够,但是对其进行补充似乎很简单。

#!/bin/bash

if [ "$1" = "DAEMON" ]; then
    # is this necessary? Add other signals at will (TTIN TTOU INT STOP TSTP)
    trap '' INT
    cd /tmp
    shift
    ### daemonized section ######
    for i in $( seq 1 10 ); do
        date
        sleep 5
    done
    #### end of daemonized section ####
    exit 0
fi

export PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin
umask 022
# You can add nice and ionice before nohup but they might not be installed
nohup setsid $0 DAEMON $* 2>/var/log/mydaemon.err >/var/log/mydaemon.log &

据我所知:

  • 输出被适当地重定向(必要时使用/ dev / null)
  • umask是继承的
  • stdin 在父脚本的末尾死亡
  • daemon.sh脚本被重新绑定到init(或systemd

我有一种强烈的感觉,我想念显而易见的东西。Downvote,但请告诉我这是什么:-)


2
我打算提出一些非常相似的建议。我使用nohupwith &和I / O重定向来启动几个非C守护程序实用程序,也许还增加了安全性,可以将nohup命令包装在a中su -c "nohup ... &" -s /bin/bash systemUser以非特权用户身份运行守护程序。
111 ---

4

screen大多数发行版中包含的Linux 命令可以守护shell脚本。我经常使用它。这是一个开始,列出和退出独立屏幕会话的快速示例...

# screen -dmS Session_Name  bash -c "while true; do date; sleep 60; done"

# screen -ls
There are screens on:
        8534.Session_Name       (04/04/2018 08:46:27 PM)        (Detached)

# screen -S Session_Name -X quit

2
screen不会妖化shell脚本。它只是在杰出的终端中运行它们,并且可以从该终端分离(例如从PC拔下键盘),而无需关闭会话。因此,在独立终端中运行的程序在后台运行。因此-在后台分离通过程序。
尤里·贡恰鲁克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.