Bir kabuk betiği için nasıl bir hizmet oluşturabilirim, böylece bir daemon gibi başlatabilir ve durdurabilirim?


22

CentOS 7 kullanıyorum, amacım her beş saniyede bir cron oluşturmak. Ama araştırdığımda sadece bir dakikalığına cron kullanabiliriz, şimdi yaptığım şey bir kabuk dosyası oluşturdum.
hit.sh

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

ama sağ tıklatarak elle çarptım.

İstediğim şey o dosya için bir hizmet oluşturmak, böylece onu otomatik olarak başlatıp durdurabilirim.

Hizmet oluşturmak için komut dosyasını buldum

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

Ancak start veya stop yöntemlerinde ne yazacağımı bilmiyorum. Aynı içeriği hit.sh içine yerleştirmeye çalıştım start(){}ama }stop yönteminde hata verdi .


/usr/bin/myscriptKendi başına çalıştırdığınızda iyi çalışıyor mu ? echo $?Komut dosyası bir işlemi tamamladığında çıktısı nedir ? 203 mü?
Alexander

@Alexander /usr/bin/myscript.shterminal aracılığıyla yürütmek için iyi çalışıyor ve echo$?bana verdi1
codegasmer

Sorun yoksa, komut dosyası 0 hata kodunu döndürmelidir. Hata kodu 1, bir hatayı gösterir.
Alexander,

Yanıtlar:


30

Kod numaranızı yeniden kullanmak isterseniz, şuna benzer bir şey olabilir:

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

Doğal olarak, bir hizmet olarak yürütülmesini istediğiniz komut dosyası örneğin gitmeli /usr/local/bin/hit.shve yukarıdaki kod gitmelidir /etc/init.d/hitservice.

Bu hizmetin çalışmasını gerektiren her çalışma seviyesi için, ilgili bir sembolik bağlantı oluşturmanız gerekecektir. Örneğin, bir symlink /etc/init.d/rc5.d/S99hitservice, runlevel 5 için servisi başlatacaktır. Tabii ki, hala service hitservice start/ üzerinden manuel olarak başlatabilir ve durdurabilirsiniz.service hitservice stop


Dosyaya benzer bir sonek gerekiyor mu: hitservice.service? Bundan sonra: backupservice.service başlatılamadı: Birim bulunamadı. CentOS 7'de neden bu cevap olarak öneriliyor?
Spektakulatius

@ Code.IT OP'nin bir systemdscript değil bir SystemV betiği istediğini ve dolayısıyla sonek gerekmediğini unutmayın. Eski senaryoları systemdsadece iyi bir şekilde çalıştırabilmelisiniz . Denedin systemctl enable hitservicemi
Dmitry Grigoryev

@DmitryGrigoryev: Bu komut dosyası birden fazla örneği engellemiyor ya da oluşturulan tüm birden fazla örneği durdurmuyor , pidfile yalnızca son teklifin yarattığı işlemi saklıyor .
Luciano

27

CentOS 7 ve üstünün sistem kullandığını düşünüyorum. Sisteminizde durum buysa, aşağıdakileri deneyin:

  1. Çalıştırmak istediğiniz komut dosyası komutlarını yerleştirin /usr/bin/myscript.

  2. Komut dosyasını çalıştırılabilir hale getirmeyi unutmayın chmod +x.

  3. Aşağıdaki dosyayı oluşturun:

/etc/systemd/system/my.service

[Unit]
Description=My Script

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

[Install]
WantedBy=multi-user.target
  1. Tüm systemd servis dosyalarını yeniden yükle: systemctl daemon-reload

  2. Servisi başlatarak çalıştığını kontrol edin systemctl start my.

Bonus:

Sistem hizmetini test etmek için, üst pencerenin betiğin ( stdoutve stderr) çıktılarını izlediği ve alt pencerenin hizmetleri yeniden başlatmak için kullanılabileceği iki pencere bölmesi ile bir tmux ortamı başlatmak mümkündür . Bunun tmuxkurulmasını gerektirir , sonra basitçe:

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

Ardından hizmeti şu şekilde yeniden başlatın:

systemctl restart my

Exit tmuxile ctrl-dve daha sonra ctrl-c.


I yanıtlarken için teşekkür eder çözümü denedik ama hizmet ayrıntılar ekledi sen benim soruya bakabilirsiniz başlangıç değil
codegasmer

Komut dosyanız başarısız olmazsa işe yarayacağını ancak 0 kodunu döndürdüğünü düşünüyorum.
Alexander

4
Şimdi systemd'i seviyorum!
DenisKolodin

1
Betik, systemd servisi erişip yürütebildiği sürece herhangi bir yere yerleştirilebilir.
Alexander,

2
Tavsiye etmem Type=forking. Askerin ihtiyaç duyacağı ihtimaller vardır Type=simpleancak genel olarak çatallanma tavsiye edilmez: 0pointer.de/public/systemd-man/… . İnsanlar eski init senaryolarını alıyor ve systemdhizmetlerinin başlaması için onları içeriyorlar systemd(init-script(service)). Bununla birlikte systemd, init betiklerinin yerine geçiyor, bu nedenle hizmeti doğrudan systemdgörünecek şekilde aramanız gerekir systemd(service).
Centimane

3

Bu benim bir servis olarak betiğim:

[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

Bash Service Manager projesine bakın : https://github.com/reduardo7/bash-service-manager

Uygulama örneği

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

Kullanım örneği

$ ./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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.