Como crio um serviço para um script de shell para poder iniciá-lo e pará-lo como um daemon?

22

Estou usando o CentOS 7, meu objetivo é criar um cron a cada cinco segundos, mas, como pesquisei, podemos usar o cron apenas por um minuto, então o que estou fazendo agora é que criei um arquivo shell.
hit.sh

while sleep 5; do curl http://localhost/test.php; done

mas eu acertei manualmente clicando com o botão direito do mouse.

O que eu quero é criar um serviço para esse arquivo, para que eu possa iniciar e pará-lo automaticamente.

Encontrei o script para criar um serviço

#!/bin/bash
# chkconfig: 2345 20 80
# description: Description comes here....

# Source function library.
. /etc/init.d/functions

start() {
    # code to start app comes here 
    # example: daemon program_name &
}

stop() {
    # code to stop app comes here 
    # example: killproc program_name
}

case "$1" in 
    start)
       start
       ;;
    stop)
       stop
       ;;
    restart)
       stop
       start
       ;;
    status)
       # code to check status of app comes here 
       # example: status program_name
       ;;
    *)
       echo "Usage: $0 {start|stop|status|restart}"
esac

exit 0 

Mas eu não sei o que escrever nos métodos start ou stop. Tentei colocar o mesmo conteúdo do hit.sh, start(){}mas deu erro }no método in stop.

codegasmer
fonte
Será que /usr/bin/myscriptfuncionam bem quando você executá-lo em seu próprio país? Qual é o resultado de echo $?quando o script concluiu uma execução? É 203?
1140 Alexander Alexander
@Alexander /usr/bin/myscript.shfunciona bem em execução através do terminal e echo$?me deu1
codegasmer
O script deve retornar o código de erro 0 se não houver problemas. O código de erro 1 indica um erro.
1100 Alexander Alexander

Respostas:

30

Se você deseja reutilizar seu exemplo de código, pode ser algo como:

#!/bin/bash

case "$1" in 
start)
   /path/to/hit.sh &
   echo $!>/var/run/hit.pid
   ;;
stop)
   kill `cat /var/run/hit.pid`
   rm /var/run/hit.pid
   ;;
restart)
   $0 stop
   $0 start
   ;;
status)
   if [ -e /var/run/hit.pid ]; then
      echo hit.sh is running, pid=`cat /var/run/hit.pid`
   else
      echo hit.sh is NOT running
      exit 1
   fi
   ;;
*)
   echo "Usage: $0 {start|stop|status|restart}"
esac

exit 0 

Naturalmente, o script que você deseja executar como serviço deve ir para /usr/local/bin/hit.sh, por exemplo , e o código acima deve ir para /etc/init.d/hitservice.

Para cada nível de execução que precisa desse serviço, você precisará criar um respectivo link simbólico. Por exemplo, um link simbólico chamado /etc/init.d/rc5.d/S99hitserviceiniciará o serviço para o nível de execução 5. Claro, você ainda pode iniciar e parar manualmente via service hitservice start/service hitservice stop

Dmitry Grigoryev
fonte
O arquivo precisa de um sufixo como: hitservice.service? Depois disso: falha ao iniciar o backupservice.service: Unidade não encontrada. No CentOS 7 então porque é que isto sugerida como resposta
Spektakulatius
@ Code.IT Observe que o OP queria um script SystemV, não um systemdscript, portanto, nenhum sufixo é necessário. Você deve ser capaz de executar scripts antigos systemdmuito bem. Você já tentou systemctl enable hitservice?
Dmitry Grigoryev
@DmitryGrigoryev: Esse script não impede várias instâncias nem interrompe todas as várias instâncias criadas; o arquivo pidfile armazena apenas o processo gerado pelo último pid.
Luciano
27

Eu acredito que o CentOS 7 e acima usam systemd. Se for esse o caso do seu sistema, tente o seguinte:

  1. Coloque os comandos de script que você deseja executar /usr/bin/myscript.

  2. Lembre-se de tornar o script executável com chmod +x.

  3. Crie o seguinte arquivo:

/etc/systemd/system/my.service

[Unit]
Description=My Script

[Service]
Type=forking
ExecStart=/usr/bin/myscript

[Install]
WantedBy=multi-user.target
  1. Recarregue todos os arquivos de serviço do systemd: systemctl daemon-reload

  2. Verifique se está funcionando iniciando o serviço systemctl start my.

Bônus:

Para testar o serviço systemd, é possível ativar um ambiente tmux com dois painéis de janela, em que a janela superior monitora a saída do script ( stdoute stderr) e a janela inferior pode ser usada para reiniciar os serviços. Isso requer tmuxa instalação, e simplesmente:

tmux new-session \; select-layout even-horizontal \; split-window -v journalctl -o cat --since=@$(date +%s) -f -u my \; rotate-window \; set -g status-bg colour0 \; set -g status-fg colour9 \; attach

Em seguida, reinicie o serviço com:

systemctl restart my

Saia tmuxcom ctrl-de depois ctrl-c.

Alexander
fonte
obrigado por responder Tentei lhe solução, mas o serviço não está começando você pode olhar para a minha pergunta eu adicionei os detalhes
codegasmer
Eu acho que vai funcionar se o seu script não falhar, mas o código de erro retorna 0.
Alexander
4
Agora eu gosto do systemd!
DenisKolodin
1
O script pode ser colocado em qualquer lugar, desde que o serviço systemd possa acessá-lo e executá-lo.
Alexander
2
Eu não recomendaria Type=forking. As chances são de que o solicitante precisaria, Type=simplemas em geral a bifurcação não é recomendada: 0pointer.de/public/systemd-man/… . As pessoas pegaram seus scripts init antigos e os agruparam systemdpara que a inicialização de seu serviço continue systemd(init-script(service)). No entanto, systemdé um substituto para os scripts init, portanto, você deve ligar diretamente systemdpara o serviço para que ele pareça systemd(service).
Centimane 5/0118
3

Este é o meu script como serviço:

[Unit]
Description=To change In test buffer
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/test.sh
TimeoutStartSec=0

[Install]
WantedBy=default.target
decimal
fonte
2

Dê uma olhada no fpm. É uma ferramenta que criará scripts de inicialização para você. Funciona em várias plataformas (systemd, upstart, ect ..)

https://github.com/jordansissel/fpm

spuder
fonte
0

Consulte o projeto do Bash Service Manager : https://github.com/reduardo7/bash-service-manager

Exemplo de implementação

#!/usr/bin/env bash

export PID_FILE_PATH="/tmp/my-service.pid"
export LOG_FILE_PATH="/tmp/my-service.log"
export LOG_ERROR_FILE_PATH="/tmp/my-service.error.log"

. ./services.sh

run-script() {
  local action="$1" # Action

  while true; do
    echo "@@@ Running action '${action}'"
    echo foo
    echo bar >&2

    [ "$action" = "run" ] && return 0
    sleep 5
    [ "$action" = "debug" ] && exit 25
  done
}

before-start() {
  local action="$1" # Action

  echo "* Starting with $action"
}

after-finish() {
  local action="$1" # Action
  local serviceExitCode=$2 # Service exit code

  echo "* Finish with $action. Exit code: $serviceExitCode"
}

action="$1"
serviceName="Example Service"

serviceMenu "$action" "$serviceName" run-script "$workDir" before-start after-finish

Exemplo de uso

$ ./example-service
# Actions: [start|stop|restart|status|run|debug|tail(-[log|error])]

$ ./example-service start
# Starting Example Service service...

$ ./example-service status
# Serive Example Service is runnig with PID 5599

$ ./example-service stop
# Stopping Example Service...

$ ./example-service status
# Service Example Service is not running
Eduardo Cuomo
fonte