Wie erstelle ich einen Dienst für ein Shell-Skript, damit ich es wie einen Dämon starten und stoppen kann?


22

Ich verwende CentOS 7. Mein Ziel ist es, alle fünf Sekunden ein Cron zu erstellen. Als ich jedoch recherchierte, können wir Cron nur für eine Minute verwenden. Was ich jetzt tue, ist, dass ich eine Shell-Datei erstellt habe.
hit.sh

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

aber ich habe es manuell durch Rechtsklick getroffen.

Ich möchte einen Dienst für diese Datei erstellen, damit ich sie automatisch starten und stoppen kann.

Ich habe das Skript zum Erstellen eines Dienstes gefunden

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

Aber ich weiß nicht, was ich in Start- oder Stoppmethoden schreiben soll. Ich habe versucht, den gleichen Inhalt von hit.sh in zu platzieren, start(){}aber es gab einen Fehler für die Stoppmethode }.


Funktioniert es einwandfrei /usr/bin/myscript, wenn Sie es alleine ausführen? Was wird ausgegeben, echo $?wenn das Skript eine Ausführung abgeschlossen hat? Ist es 203?
Alexander

@Alexander /usr/bin/myscript.shfunktioniert gut bei der Ausführung über das Terminal und echo$?gab mir1
Codegasmer

Das Skript sollte den Fehlercode 0 zurückgeben, wenn keine Probleme vorliegen. Fehlercode 1 zeigt einen Fehler an.
Alexander

Antworten:


30

Wenn Sie Ihr Codebeispiel wiederverwenden möchten, könnte es ungefähr so ​​aussehen:

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

Natürlich sollte das Skript, das als Dienst ausgeführt werden soll, z. B. /usr/local/bin/hit.shund der obige Code sollte z /etc/init.d/hitservice.

Für jedes Runlevel, auf dem dieser Dienst ausgeführt werden soll, müssen Sie einen entsprechenden Symlink erstellen. Zum Beispiel /etc/init.d/rc5.d/S99hitservicestartet ein Symlink mit dem Namen den Dienst für Runlevel 5. Natürlich können Sie ihn auch weiterhin manuell über service hitservice start/ starten und stoppen.service hitservice stop


Benötigt die Datei ein Suffix wie: hitservice.service? Danach: Fehler beim Starten von backupservice.service: Gerät nicht gefunden. Warum wird dies auf CentOS 7 als Antwort vorgeschlagen
Spektakulatius

@ Code.IT Beachten Sie, dass das OP ein SystemV-Skript wollte, kein systemdSkript, daher wird kein Suffix benötigt. Sie sollten in der Lage sein, alte Skripte ohne Probleme auszuführen systemd. Hast du es versucht systemctl enable hitservice?
Dmitry Grigoryev

@DmitryGrigoryev: Dieses Skript verhindert weder mehrere Instanzen, noch stoppt es alle erstellten Instanzen. Die PID-Datei speichert nur den Spawn-Prozess der letzten PID .
Luciano

27

Ich glaube, dass CentOS 7 und höher systemd verwendet. Wenn dies bei Ihrem System der Fall ist, versuchen Sie Folgendes:

  1. Platzieren Sie die Skriptbefehle, die Sie ausführen möchten /usr/bin/myscript.

  2. Denken Sie daran, das Skript mit ausführbar zu machen chmod +x.

  3. Erstellen Sie die folgende Datei:

/etc/systemd/system/my.service

[Unit]
Description=My Script

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

[Install]
WantedBy=multi-user.target
  1. Laden Sie alle Systemd-Servicedateien neu: systemctl daemon-reload

  2. Überprüfen Sie, ob es funktioniert, indem Sie den Dienst mit starten systemctl start my.

Bonus:

Zum Testen des systemd-Dienstes kann eine tmux-Umgebung mit zwei Fenstern gestartet werden, in der das obere Fenster die Ausgabe des Skripts ( stdoutund stderr) überwacht und das untere Fenster zum Neustarten der Dienste verwendet werden kann. Dies muss tmuxinstalliert werden, dann einfach:

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

Starten Sie dann den Dienst neu mit:

systemctl restart my

Beenden Sie tmuxmit ctrl-dund dann ctrl-c.


danke für die antwort ich habe versucht sie zu
lösen

Ich denke, es wird funktionieren, wenn Ihr Skript nicht fehlschlägt, aber Fehlercode 0 zurückgibt.
Alexander

4
Jetzt mag ich systemd!
DenisKolodin

1
Das Skript kann an einer beliebigen Stelle abgelegt werden, solange der systemd-Dienst darauf zugreifen und es ausführen kann.
Alexander

2
Ich würde es nicht empfehlen Type=forking. Die Chancen stehen gut, dass der Fragesteller sie braucht, Type=simpleaber im Allgemeinen wird das Gabeln nicht empfohlen: 0pointer.de/public/systemd-man/… . Die Leute haben ihre alten Init-Skripte genommen und sie eingepackt, systemddamit der Start ihres Dienstes funktioniert systemd(init-script(service)). Es systemdist jedoch ein Ersatz für Init-Skripte, daher sollten Sie den Dienst direkt mit aufrufen, damit er systemdso aussieht systemd(service).
Centimane

3

Dies ist mein Skript als Service:

[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

Siehe Bash Service Manager- Projekt: https://github.com/reduardo7/bash-service-manager

Implementierungsbeispiel

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

Anwendungsbeispiel

$ ./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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.