Bagaimana cara membuat layanan untuk skrip shell sehingga saya dapat memulai dan menghentikannya seperti daemon?

22

Saya menggunakan CentOS 7 apa tujuan saya adalah membuat cron untuk setiap lima detik, tetapi ketika saya meneliti kita dapat menggunakan cron hanya untuk satu menit sehingga yang saya lakukan sekarang adalah saya telah membuat file shell.
hit.sh

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

tapi saya telah memukulnya secara manual melalui mengklik kanan itu.

Yang saya inginkan adalah membuat layanan untuk file itu sehingga saya dapat memulai dan menghentikannya secara otomatis.

Saya menemukan skrip untuk membuat layanan

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

Tetapi saya tidak tahu apa yang harus ditulis dalam metode start atau stop. Saya mencoba menempatkan konten yang sama dari hit.sh di start(){}tetapi itu memberi kesalahan }dalam metode berhenti.

codegasmer
sumber
Apakah /usr/bin/myscriptberfungsi dengan baik ketika Anda menjalankannya sendiri? Apa output echo $?ketika skrip telah menyelesaikan proses? Apakah itu 203?
Alexander
@Alexander /usr/bin/myscript.shberfungsi dengan baik pada eksekusi melalui terminal dan echo$?memberi saya1
codegasmer
Script harus mengembalikan kode kesalahan 0 jika tidak ada masalah. Kode kesalahan 1 menunjukkan kesalahan.
Alexander

Jawaban:

30

Jika Anda ingin menggunakan kembali contoh kode Anda, itu bisa terlihat seperti:

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

Tentu saja, skrip yang ingin Anda jalankan sebagai layanan harus menuju ke misalnya /usr/local/bin/hit.sh, dan kode di atas harus pergi ke /etc/init.d/hitservice.

Untuk setiap runlevel yang membutuhkan layanan ini berjalan, Anda harus membuat symlink masing-masing. Misalnya, symlink bernama /etc/init.d/rc5.d/S99hitserviceakan memulai layanan untuk runlevel 5. Tentu saja, Anda masih dapat memulai dan menghentikannya secara manual melalui service hitservice start/service hitservice stop

Dmitry Grigoryev
sumber
Apakah file memerlukan akhiran seperti: hitservice.service? Setelah ini: Gagal memulai backupservice.service: Unit tidak ditemukan. Pada CentOS 7 jadi mengapa ini disarankan sebagai jawaban
Spektakulatius
@ Code.IT Perhatikan bahwa OP menginginkan skrip SystemV, bukan systemdskrip, sehingga sufiks tidak diperlukan. Anda harus dapat menjalankan skrip lama dengan systemdbaik. Sudahkah Anda mencoba systemctl enable hitservice?
Dmitry Grigoryev
@DmitryGrigoryev: Script ini tidak mencegah banyak instance atau menghentikan semua multiple instance yang dibuat, pidfile hanya menyimpan proses spawned pid terakhir.
Luciano
27

Saya percaya CentOS 7 dan di atas menggunakan systemd. Jika demikian halnya dengan sistem Anda, coba yang berikut ini:

  1. Tempatkan perintah skrip yang ingin Anda jalankan /usr/bin/myscript.

  2. Ingatlah untuk membuat skrip dapat dieksekusi chmod +x.

  3. Buat file berikut:

/etc/systemd/system/my.service

[Unit]
Description=My Script

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

[Install]
WantedBy=multi-user.target
  1. Muat ulang semua file layanan systemd: systemctl daemon-reload

  2. Periksa apakah berfungsi dengan memulai layanan dengan systemctl start my.

Bonus:

Untuk menguji layanan systemd, dimungkinkan untuk meluncurkan lingkungan tmux dengan dua panel jendela, di mana jendela atas memonitor output dari skrip ( stdoutdan stderr) dan jendela bawah dapat digunakan untuk memulai kembali layanan. Ini perlu tmuxdiinstal, maka cukup:

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

Kemudian mulai kembali layanan dengan:

systemctl restart my

Keluar tmuxdengan ctrl-dlalu ctrl-c.

Alexander
sumber
terima kasih telah menjawab saya mencoba solusi Anda tetapi layanan tidak mulai dapatkah Anda melihat pertanyaan saya, saya menambahkan rincian
codegasmer
Saya pikir ini akan berfungsi jika skrip Anda tidak gagal, tetapi mengembalikan kode kesalahan 0.
Alexander
4
Sekarang saya suka systemd!
DenisKolodin
1
Script dapat ditempatkan di mana saja, selama layanan systemd dapat mengakses dan menjalankannya.
Alexander
2
Saya tidak akan merekomendasikan Type=forking. Kemungkinan penanya perlu Type=simpletetapi secara umum forking tidak disarankan: 0pointer.de/public/systemd-man/… . Orang-orang telah mengambil skrip init lama mereka dan membungkusnya systemdsehingga permulaan layanan mereka berjalan systemd(init-script(service)). Namun systemdadalah pengganti untuk skrip init, jadi Anda harus memanggil layanan secara langsung systemdsehingga terlihat seperti systemd(service).
Centimane
3

Ini skrip saya sebagai layanan:

[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
desimal
sumber
2

Lihatlah fpm. Ini adalah alat yang akan membuat skrip init untuk Anda. Bekerja pada banyak platform (systemd, pemula, dll ..)

https://github.com/jordansissel/fpm

spuder
sumber
0

Lihat proyek Bash Service Manager : https://github.com/reduardo7/bash-service-manager

Contoh implementasi

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

Contoh penggunaan

$ ./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
sumber