ฉันจะสร้างบริการสำหรับเชลล์สคริปต์ได้อย่างไรเพื่อให้ฉันสามารถเริ่มต้นและหยุดเหมือน daemon ได้?


22

ฉันใช้ CentOS 7 เป้าหมายของฉันคือการสร้าง cron ทุก ๆ ห้าวินาที แต่ในขณะที่ฉันวิจัยเราสามารถใช้ cron เพียงหนึ่งนาทีดังนั้นสิ่งที่ฉันทำตอนนี้คือฉันได้สร้างเชลล์ไฟล์
hit.sh

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

แต่ฉันกดมันเองด้วยการคลิกขวา

สิ่งที่ฉันต้องการคือการสร้างบริการสำหรับไฟล์นั้นเพื่อให้ฉันสามารถเริ่มและหยุดโดยอัตโนมัติ

ฉันพบสคริปต์เพื่อสร้างบริการ

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

แต่ฉันไม่ทราบว่าจะเขียนวิธีเริ่มต้นหรือหยุดฉันพยายามวางเนื้อหาเดียวกันของ hit.sh ในstart(){}แต่ก็ให้ข้อผิดพลาด}ในวิธีหยุด


ไม่/usr/bin/myscriptปรับการทำงานเมื่อคุณใช้มันในตัวเอง? ผลลัพธ์ของecho $?เมื่อสคริปต์เสร็จสิ้นการทำงานคืออะไร? มันเป็น 203
Alexander

@Alexander /usr/bin/myscript.shทำงานได้ดีในการดำเนินการผ่านทางสถานีและecho$?ให้ฉัน1
codegasmer

สคริปต์ควรส่งคืนรหัสข้อผิดพลาด 0 หากไม่มีปัญหา รหัสข้อผิดพลาด 1 ระบุถึงข้อผิดพลาด
Alexander

คำตอบ:


30

หากคุณต้องการใช้ตัวอย่างรหัสของคุณซ้ำมันอาจมีลักษณะดังนี้:

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

โดยปกติสคริปต์ที่คุณต้องการเรียกใช้งานเป็นบริการควรไปเช่น /usr/local/bin/hit.sh/etc/init.d/hitserviceและโค้ดข้างต้นควรจะไป

สำหรับ runlevel แต่ละครั้งที่ต้องการใช้บริการนี้คุณจะต้องสร้าง symlink ตามลำดับ ตัวอย่างเช่น symlink ชื่อ/etc/init.d/rc5.d/S99hitserviceจะเริ่มให้บริการสำหรับ runlevel 5 แน่นอนคุณยังสามารถเริ่มต้นและหยุดด้วยตนเองผ่านservice hitservice start/service hitservice stop


ไฟล์ต้องการคำต่อท้ายเช่น: hitservice.service หรือไม่ หลังจากนี้: ไม่สามารถเริ่มต้น backupservice.service: ไม่พบหน่วย ใน CentOS 7 เหตุใดข้อเสนอแนะนี้จึงเป็นคำตอบ
Spektakulatius

@ Code.IT โปรดทราบว่า OP ต้องการสคริปต์ SystemV ไม่ใช่systemdสคริปต์ดังนั้นจึงไม่จำเป็นต้องต่อท้าย คุณควรจะสามารถเรียกใช้สคริปต์เก่าด้วยsystemdดีแม้ว่า คุณเคยลองsystemctl enable hitserviceไหม
Dmitry Grigoryev

@DmitryGrigoryev: สคริปต์นี้ไม่ได้ป้องกันหลาย ๆ อินสแตนซ์หรือหยุดสร้างหลายอินสแตนซ์pidfile จะเก็บเฉพาะกระบวนการที่เกิดจาก pid ล่าสุดเท่านั้น
Luciano

27

ฉันเชื่อว่า CentOS 7 ขึ้นไปใช้ systemd หากเป็นกรณีสำหรับระบบของคุณลองต่อไปนี้:

  1. /usr/bin/myscriptวางคำสั่งสคริปต์ที่คุณต้องการที่จะทำงานใน

  2. chmod +xอย่าลืมที่จะทำให้ปฏิบัติการสคริปต์ด้วย

  3. สร้างไฟล์ต่อไปนี้:

/etc/systemd/system/my.service

[Unit]
Description=My Script

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

[Install]
WantedBy=multi-user.target
  1. โหลดไฟล์บริการ systemd ใหม่ทั้งหมด: systemctl daemon-reload

  2. systemctl start myตรวจสอบว่ามีการทำงานโดยเริ่มต้นให้บริการกับ

โบนัส:

สำหรับการทดสอบเซอร์วิส systemd เป็นไปได้ที่จะเรียกใช้สภาวะแวดล้อม tmux ด้วยสองหน้าต่างบานหน้าต่างซึ่งหน้าต่างด้านบนมอนิเตอร์เอาต์พุตจากสคริปต์ ( stdoutและstderr) และหน้าต่างด้านล่างสามารถใช้เพื่อรีสตาร์ทเซอร์วิส สิ่งนี้จำเป็นต้องtmuxติดตั้งจากนั้นเพียง:

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

จากนั้นรีสตาร์ทบริการด้วย:

systemctl restart my

ทางออกtmuxด้วยแล้วctrl-dctrl-c


ขอบคุณสำหรับการตอบฉันพยายามให้คุณแก้ปัญหา แต่บริการไม่เริ่มคุณสามารถดูคำถามของฉันฉันได้เพิ่มรายละเอียด
codegasmer

ฉันคิดว่ามันจะใช้งานได้หากสคริปต์ของคุณไม่ได้ล้มเหลว แต่ส่งคืนรหัสข้อผิดพลาด 0
Alexander

4
ตอนนี้ฉันชอบ systemd!
DenisKolodin

1
สคริปต์สามารถวางได้ทุกที่ตราบใดที่เซอร์วิส systemd สามารถเข้าถึงและดำเนินการได้
Alexander

2
Type=forkingฉันจะไม่แนะนำ โอกาสที่ผู้ถามจะต้องType=simpleแต่ในฟอร์กทั่วไปไม่แนะนำ: 0pointer.de/public/systemd-man/... คนได้รับการสคริปต์ init เก่าของพวกเขาและพวกเขาในการตัดเพื่อให้การเริ่มต้นของการให้บริการของพวกเขาไปsystemd systemd(init-script(service))แต่systemdจะเปลี่ยนสำหรับสคริปต์ init ดังนั้นคุณควรจะเรียกบริการโดยตรงเพื่อให้ดูเหมือนว่าsystemd systemd(service)
Centimane

3

นี่คือสคริปต์ของฉันเป็นบริการ:

[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

2

ดูที่ fpm มันเป็นเครื่องมือที่จะสร้างสคริปต์เริ่มต้นสำหรับคุณ ใช้งานได้กับหลายแพลตฟอร์ม (systemd, พุ่งพรวด, ฯลฯ .. )

https://github.com/jordansissel/fpm


0

ดูโครงการBash Service Manager : https://github.com/reduardo7/bash-service-manager

ตัวอย่างการนำไปปฏิบัติ

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

ตัวอย่างการใช้งาน

$ ./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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.