Maneira "adequada" de executar o shell script como um daemon

20

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


HOWTO de gravação de daemon do Linux

De acordo com o HOWTO de Daemon de Gravação do Linux , um daemon adequado possui as seguintes características:

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

daemonize Introdução

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

  • desassocia-se do seu terminal de controle (se houver) e ignora todos os sinais do terminal
  • desassocia-se de seu grupo de processos
  • alças SIGCLD

Como eu poderia fazer tudo isso em um sh, dashou bashscript com apenas ferramentas comuns do Linux?

O script deve ser capaz de executar o maior número possível de distribuições sem software adicional, embora o Debian seja nosso foco principal.


NOTA: Sei que há muitas respostas na rede StackExchange que recomendam o uso de nohupor setsid, mas nenhum desses métodos atende a todos os requisitos acima.


EDIT: A página de manual do daemon (7) também fornece algumas dicas, embora pareça haver algumas diferenças entre os SysVdaemons de estilo antigo e os mais systemdnovos. Como a compatibilidade com uma variedade de distribuições é importante, verifique se a resposta esclarece todas as diferenças.


user339676
fonte
1
A maneira "adequada" de criar seu próprio script de shell é fazer com que ele faça seu próprio registro, forneça um método para iniciá-lo como um daemon etc. Coisas assim daemone outras coisas são para executar scripts shell arbitrários sem nenhuma provisão para execução como um daemon. Como você é o autor, totalmente no controle de como esse script é escrito, faça com que ele possa ser iniciado apenas a partir de um arquivo systemd unitfile ou rc.d. Você se especificar "adequada"!
Rico

Respostas:

16

Usando systemd, você poderá executar um script como um daemon criando uma unidade simples. Você pode adicionar muitas opções diferentes , mas isso é o mais simples possível.

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 você corre

systemctl start mydaemon.service 

Para iniciar na inicialização, habilite-o

systemctl enable mydaemon.service

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

johnramsden
fonte
3
Embora eu goste da abordagem systemd, o OP disse "sem ferramentas externas". Existem distribuições Linux que ainda não possuem systemd, ou permitem que você escolha entre systemd e outra coisa, por exemplo, OpenRC.
Cristian Ciupitu
5
Para distribuições que usam systemd, systemdnão é mais uma "ferramenta externa" do que bash.
Alexander
7

Provavelmente estou perdendo alguma coisa aqui; por que exatamente não nohupseria apropriado? Claro que não basta apenas , 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 para init(ou systemd)

Tenho uma forte sensação de que estou perdendo o óbvio. Voto a favor, mas por favor me diga o que é :-)

LSerni
fonte
2
Eu estava prestes a sugerir algo muito semelhante. Eu uso nohupcom &e redirecionamento de E / S para iniciar vários Cutilitários que não são daemon, talvez com a segurança adicional de agrupar seu nohupcomando dentro de um su -c "nohup ... &" -s /bin/bash systemUserpara executar o daemon como um usuário não privilegiado.
111 ---
4

O screencomando Linux contido na maioria das distros pode daemonizar um script de shell. Eu o uso frequentemente. 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
S.Haran
fonte
2
screennão desonra o script de shell. Basta executá-los em um terminal distinto e pode se desconectar desse terminal (como desconectar o teclado do PC) sem fechar a sessão. Portanto, o programa em execução no terminal desanexado está sendo executado em segundo plano. Portanto - desanexe o programa de aprovação em segundo plano.
Yurij Goncharuk 04/04