Caminho “correto” para executar o shell script como um daemon

14

Estou escrevendo um script de shell que gostaria de executar como um daemon na inicialização sem usar ferramentas externas como daemontools ou daemonize .

Linux Daemon Writing HOWTO

De acordo com o Linux Daemon Writing HOWTO , um adequado tem as seguintes características:

  • garfos do processo pai
  • fecha todos os descritores de arquivo (por exemplo, stdin , stdout , stderr )
  • abre registros para gravação (se configurado)
  • altera o diretório de trabalho para um que seja persistente (geralmente / )
  • redefine a máscara do modo de arquivo (umask)
  • cria um ID de sessão (SID)
  • exclusivo

daemonize Introdução

O daemonize Introdução vai além, afirmando que um daemon típico também:

  • se desassocia do seu terminal de controle (se houver) e ignora todos os sinais do terminal
  • se desassocia do seu grupo de processos
  • lida com SIGCLD

Como eu faria tudo isso em um script sh , dash ou bash apenas com ferramentas comuns do Linux?

O script deve ser capaz de rodar em tantas distribuições quanto possível sem software adicional, embora Debian seja nosso foco principal.

NOTA: sei que há muitas respostas na rede do StackExchange recomendando o uso de nohup ou setsid , mas nenhum desses métodos aborda todos os requisitos acima.

EDITAR: O daemon (7) manpage também fornece alguns apontadores, embora pareça haver algumas diferenças entre os daemons SysV do estilo antigo e os systemd mais recentes. Como a compatibilidade com uma variedade de distros é importante, por favor, assegure-se de que a resposta deixe claras quaisquer diferenças.

por user339676 27.02.2018 / 07:55

3 respostas

7

Usando systemd , você deve ser capaz de executar um script como um daemon, criando uma unidade simples. Existem diversas opções que você pode adicionar, mas isso é tão simples quanto você pode ficar.

Digamos que você tenha um script /usr/bin/mydaemon .

#!/bin/sh

while true; do
  date;
  sleep 60;
done

Você cria uma unidade /etc/systemd/system/mydaemon.service .

[Unit]
Description=My daemon

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

[Install]
WantedBy=multi-user.target 

Para iniciar o demônio que você executa

systemctl start mydaemon.service 

Para começar na inicialização, ative-a

systemctl enable mydaemon.service

Se em um sistema baseado em systemd, que a maioria das distribuições Linux é hoje, isso não é realmente uma ferramenta externa. O negativo seria que não funcionaria em todos os lugares.

    
por 04.04.2018 / 04:14
3

Provavelmente estou sentindo falta de algo aqui; por que exatamente não seria nohup apropriado? Claro que não é suficiente sozinho , mas complementá-lo parece simples.

#!/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 &

Tanto quanto eu posso ver:

  • a saída é redirecionada adequadamente (use / dev / null, se necessário)
  • o umask é herdado
  • stdin morre no final do script pai, no entanto
  • o script daemon.sh é reparado em init (ou systemd )

Eu tenho um strong sentimento de que estou perdendo o óbvio. Downvote, mas por favor me diga o que é: -)

    
por 04.04.2018 / 20:17
3

O comando Linux screen contido na maioria das distros pode daemonizar um script de shell. Eu uso isso com freqüência. Aqui está um exemplo rápido para iniciar, listar e sair de uma sessão de tela desanexada ...

# 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
    
por 04.04.2018 / 23:00