Come faccio a creare un servizio per uno script di shell in modo da poterlo avviare e arrestarlo come un demone?


22

Sto usando CentOS 7 quale è il mio obiettivo di creare un cron per ogni cinque secondi ma, come ho studiato, possiamo usare cron solo per un minuto, quindi quello che sto facendo ora è che ho creato un file shell.
hit.sh

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

ma l'ho colpito manualmente facendo clic con il tasto destro del mouse.

Quello che voglio è creare un servizio per quel file in modo da poterlo avviare e arrestarlo automaticamente.

Ho trovato lo script per creare un servizio

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

Ma non so cosa scrivere nei metodi start o stop Ho provato a inserire lo stesso contenuto di hit.sh start(){}ma ha dato errore }nel metodo stop.


Funziona /usr/bin/myscriptbene quando lo esegui da solo? Qual è l'output di echo $?quando lo script ha completato un'esecuzione? È 203?
Alexander,

@Alexander /usr/bin/myscript.shfunziona benissimo sull'esecuzione tramite terminale e echo$?mi ha dato1
codegasmer il

Lo script dovrebbe restituire il codice di errore 0 se non ci sono problemi. Il codice di errore 1 indica un errore.
Alexander,

Risposte:


30

Se desideri riutilizzare l'esempio di codice, potrebbe essere simile a:

#!/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, lo script che si desidera eseguire come servizio dovrebbe andare ad es /usr/local/bin/hit.sh. E il codice sopra dovrebbe andare a /etc/init.d/hitservice.

Per ogni runlevel che necessita di questo servizio in esecuzione, dovrai creare un rispettivo link simbolico. Ad esempio, un /etc/init.d/rc5.d/S99hitservicecollegamento simbolico denominato avvierà il servizio per runlevel 5. Naturalmente, è ancora possibile avviarlo e arrestarlo manualmente tramite service hitservice start/service hitservice stop


Il file ha bisogno di un suffisso come: hitservice.service? Successivamente: Impossibile avviare backupservice.service: unità non trovata. Su CentOS 7 quindi perché questo è suggerito come risposta
Spektakulatius

@ Code.IT Si noti che l'OP voleva uno script SystemV, non uno systemdscript, quindi non è necessario alcun suffisso. systemdTuttavia, dovresti essere in grado di eseguire vecchi script . Ci hai provato systemctl enable hitservice?
Dmitry Grigoryev

@DmitryGrigoryev: questo script non impedisce più istanze né interrompe tutte le istanze multiple create, il file pid memorizza solo il processo generato dall'ultimo pid.
Luciano,

27

Credo che CentOS 7 e versioni successive utilizzino systemd. In tal caso, provare il seguente sistema:

  1. Inserire i comandi di script in cui si desidera eseguire /usr/bin/myscript.

  2. Ricorda di rendere eseguibile lo script con chmod +x.

  3. Crea il seguente file:

/etc/systemd/system/my.service

[Unit]
Description=My Script

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

[Install]
WantedBy=multi-user.target
  1. Ricarica tutti i file di servizio di systemd: systemctl daemon-reload

  2. Verificare che funzioni avviando il servizio con systemctl start my.

Bonus:

Per testare il servizio systemd, è possibile avviare un ambiente tmux con due riquadri di finestre, in cui la finestra superiore controlla l'output dello script ( stdoute stderr) e la finestra inferiore può essere utilizzata per riavviare i servizi. Questo richiede tmuxl'installazione, quindi semplicemente:

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

Quindi riavviare il servizio con:

systemctl restart my

Esci tmuxcon ctrl-de poi ctrl-c.


grazie per la risposta ho provato la soluzione ma il servizio non si avvia puoi guardare la mia domanda ho aggiunto i dettagli
codegasmer

Penso che funzionerà se lo script non fallisce, ma restituisce il codice di errore 0.
Alexander

4
Ora mi piace systemd!
DenisKolodin,

1
Lo script può essere posizionato ovunque, purché il servizio systemd possa accedervi ed eseguirlo.
Alexander

2
Non lo consiglierei Type=forking. È probabile che il richiedente abbia bisogno, Type=simplema in generale non è consigliabile il biforcazione: 0pointer.de/public/systemd-man/… . Le persone hanno preso i loro vecchi script init e li hanno inseriti in systemdmodo che l'avvio del loro servizio continuasse systemd(init-script(service)). Tuttavia systemdè un sostituto per gli script di init, quindi dovresti chiamare il servizio direttamente in systemdmodo che appaia systemd(service).
Centimane,

3

Questa è la mia sceneggiatura come servizio:

[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


0

Vedi il progetto Bash Service Manager : https://github.com/reduardo7/bash-service-manager

Esempio di implementazione

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

Esempio di utilizzo

$ ./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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.