Jak utworzyć usługę dla skryptu powłoki, aby można ją było uruchomić i zatrzymać jak demon?


22

Korzystam z CentOS 7, a moim celem jest tworzenie crona co pięć sekund, ale kiedy badałem, możemy używać crona tylko przez minutę, więc teraz tworzę plik powłoki.
hit.sh

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

ale trafiłem go ręcznie, klikając go prawym przyciskiem myszy.

Chcę utworzyć usługę dla tego pliku, aby móc go uruchomić i zatrzymać automatycznie.

Znalazłem skrypt do stworzenia usługi

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

Ale nie wiem, co napisać w metodach start lub stop Próbowałem umieścić tę samą zawartość hit.sh w, start(){}ale dało to błąd }w metodzie in stop.


Czy /usr/bin/myscriptdziała dobrze, gdy uruchamiasz go samodzielnie? Jakie są wyniki, echo $?kiedy skrypt zakończy działanie? Czy to 203?
— Alexander

@Alexander /usr/bin/myscript.shdziała dobrze przy wykonywaniu przez terminal i echo$?dał mi1
— codegasmer

Skrypt powinien zwrócić kod błędu 0, jeśli nie ma żadnych problemów. Kod błędu 1 oznacza błąd.
— Alexander

Odpowiedzi:


30

Jeśli chcesz ponownie użyć próbki kodu, może wyglądać mniej więcej tak:

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

Oczywiście skrypt, który chcesz wykonać jako usługę, powinien przejść np. /usr/local/bin/hit.shDo powyższego kodu /etc/init.d/hitservice.

Dla każdego poziomu działania, który wymaga uruchomienia tej usługi, musisz utworzyć odpowiednie dowiązanie symboliczne. Na przykład nazwane dowiązanie symboliczne /etc/init.d/rc5.d/S99hitserviceuruchomi usługę dla poziomu uruchamiania 5. Oczywiście nadal można uruchomić i zatrzymać ją ręcznie za pomocą service hitservice start/service hitservice stop


Czy plik potrzebuje sufiksu takiego jak: hitservice.service? Następnie: Nie można uruchomić backupservice.service: Nie znaleziono urządzenia. Na CentOS 7 więc dlaczego jest to sugerowane jako odpowiedź
— Spektakulatius

@ Code.IT Należy pamiętać, że OP chciał skryptu SystemV, a nie systemdskryptu, dlatego nie jest potrzebny przyrostek. Powinieneś być w stanie uruchomić stare skrypty z systemddobrze. Próbowałeś systemctl enable hitservice?
— Dmitrij Grigoriew

@DmitryGrigoryev: Ten skrypt nie zapobiega wielu wystąpieniom ani nie zatrzymuje wszystkich utworzonych wielu wystąpień, plik pid przechowuje tylko proces odradzania ostatniego pid.
— Luciano

27

Wierzę, że CentOS 7 i wyżej używa systemd. Jeśli tak jest w przypadku twojego systemu, spróbuj wykonać następujące czynności:

  1. Umieść polecenia skryptu, w których chcesz uruchomić /usr/bin/myscript.

  2. Pamiętaj, aby skrypt był wykonywalny za pomocą chmod +x.

  3. Utwórz następujący plik:

/etc/systemd/system/my.service

[Unit]
Description=My Script

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

[Install]
WantedBy=multi-user.target
  1. Załaduj ponownie wszystkie pliki usługi systemowej: systemctl daemon-reload

  2. Sprawdź, czy działa, uruchamiając usługę za pomocą systemctl start my.

Premia:

W celu przetestowania usystematyzowanej usługi można uruchomić środowisko tmux z dwoma panelami okien, w których górne okno monitoruje dane wyjściowe skryptu ( stdouti stderr), a dolne okno może być użyte do ponownego uruchomienia usług. Wymaga tmuxto instalacji, a następnie:

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

Następnie uruchom ponownie usługę za pomocą:

systemctl restart my

Wyjdź za tmuxpomocą, ctrl-da następnie ctrl-c.


dziękuję za odpowiedź Próbowałem rozwiązania, ale usługa się nie uruchamia. Możesz spojrzeć na moje pytanie. Dodałem szczegóły
— codegasmer

Myślę, że zadziała, jeśli skrypt nie zawiedzie, ale zwróci kod błędu 0.
— Alexander

4
Teraz lubię systemd!
— DenisKolodin

1
Skrypt można umieścić w dowolnym miejscu, o ile usługa systemowa może uzyskać do niego dostęp i go wykonać.
— Alexander

2
Nie poleciłbym Type=forking. Są szanse, że pytający będzie potrzebował, Type=simpleale generalnie rozwidlenie nie jest zalecane: 0pointer.de/public/systemd-man/… . Ludzie biorą swoje stare skrypty inicjujące i pakują je systemdtak, aby rozpocząć uruchamianie ich usługi systemd(init-script(service)). Jednak systemdzastępuje skrypty init, więc powinieneś wywoływać usługę bezpośrednio systemd, aby wyglądała systemd(service).
— Centimane

3

To jest mój skrypt jako usługa:

[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

Zobacz projekt Bash Service Manager : https://github.com/reduardo7/bash-service-manager

Przykład realizacji

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

Przykład użycia

$ ./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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.