Làm cách nào để tạo một dịch vụ cho tập lệnh shell để tôi có thể bắt đầu và dừng nó như một daemon?


22

Tôi đang sử dụng CentOS 7, mục đích của tôi là tạo ra một cron cứ sau 5 giây nhưng khi tôi nghiên cứu, chúng tôi chỉ có thể sử dụng cron trong một phút, vì vậy những gì tôi đang làm bây giờ là tôi đã tạo một tệp shell.
hit.sh

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

nhưng tôi đã nhấn nó bằng tay thông qua nhấp chuột phải vào nó.

Điều tôi muốn là tạo một dịch vụ cho tập tin đó để tôi có thể bắt đầu và dừng nó tự động.

Tôi tìm thấy tập lệnh để tạo một dịch vụ

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

Nhưng tôi không biết nên viết gì khi bắt đầu hoặc dừng phương thức. Tôi đã thử đặt cùng một nội dung của hit.sh start(){}nhưng nó đã báo lỗi cho }phương thức dừng.


/usr/bin/myscripthoạt động tốt khi bạn tự chạy nó không? Đầu ra echo $?khi kịch bản đã hoàn thành chạy là gì? Có phải 203 không?
Alexander

@Alexander /usr/bin/myscript.shhoạt động tốt khi thực hiện thông qua thiết bị đầu cuối và echo$?đưa cho tôi1
codegasmer

Kịch bản sẽ trả về mã lỗi 0 nếu không có vấn đề gì. Mã lỗi 1 chỉ ra lỗi.
Alexander

Câu trả lời:


30

Nếu bạn muốn sử dụng lại mẫu mã của mình, nó có thể trông giống như:

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

Đương nhiên, tập lệnh bạn muốn được thực thi như một dịch vụ nên chuyển đến /usr/local/bin/hit.sh, ví dụ , và đoạn mã trên sẽ được chuyển đến /etc/init.d/hitservice.

Đối với mỗi runlevel cần dịch vụ này đang chạy, bạn sẽ cần tạo một liên kết tượng trưng tương ứng. Ví dụ: một liên kết tượng trưng có tên /etc/init.d/rc5.d/S99hitservicesẽ khởi động dịch vụ cho runlevel 5. Tất nhiên, bạn vẫn có thể bắt đầu và dừng thủ công thông qua service hitservice start/service hitservice stop


Tập tin có cần một hậu tố như: hitervice.service không? Sau này: Không thể bắt đầu backupservice.service: Không tìm thấy đơn vị. Trên CentOS 7, tại sao điều này được đề xuất là câu trả lời
Spektakulatius

@ Code.IT Lưu ý rằng OP muốn có tập lệnh SystemV, không phải systemdtập lệnh, do đó không cần hậu tố. Bạn sẽ có thể chạy các kịch bản cũ systemdchỉ với tốt. Bạn đã thử systemctl enable hitservicechưa
Dmitry Grigoryev

@DmitryGrigoryev: Kịch bản này không ngăn chặn nhiều trường hợp cũng như dừng tất cả nhiều trường hợp được tạo, pidfile chỉ lưu trữ quá trình sinh sản cuối cùng của pid.
Luciano

27

Tôi tin rằng CentOS 7 trở lên sử dụng systemd. Nếu đó là trường hợp cho hệ thống của bạn, hãy thử như sau:

  1. Đặt các lệnh script mà bạn muốn chạy vào /usr/bin/myscript.

  2. Hãy nhớ để làm cho kịch bản thực thi với chmod +x.

  3. Tạo tập tin sau:

/etc/systemd/system/my.service

[Unit]
Description=My Script

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

[Install]
WantedBy=multi-user.target
  1. Tải lại tất cả các tệp dịch vụ systemd: systemctl daemon-reload

  2. Kiểm tra xem nó đang hoạt động bằng cách bắt đầu dịch vụ với systemctl start my.

Tiền thưởng:

Để thử nghiệm dịch vụ systemd, có thể khởi chạy môi trường tmux với hai ô cửa sổ, trong đó cửa sổ trên cùng theo dõi đầu ra từ tập lệnh ( stdoutstderr) và cửa sổ dưới cùng có thể được sử dụng để khởi động lại dịch vụ. Điều này đòi hỏi tmuxphải được cài đặt, sau đó chỉ cần:

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

Sau đó khởi động lại dịch vụ với:

systemctl restart my

Thoát tmuxvới ctrl-dvà sau đó ctrl-c.


cảm ơn vì đã trả lời tôi đã thử giải pháp cho bạn nhưng dịch vụ chưa bắt đầu, bạn có thể xem câu hỏi của tôi không, tôi đã thêm chi tiết
codegasmer

Tôi nghĩ nó sẽ hoạt động nếu tập lệnh của bạn không bị lỗi, nhưng trả về mã lỗi 0.
Alexander

4
Bây giờ tôi thích systemd!
DenisKolodin

1
Kịch bản có thể được đặt ở bất cứ đâu, miễn là dịch vụ systemd có thể truy cập và thực thi nó.
Alexander

2
Tôi sẽ không đề nghị Type=forking. Rất có thể là người hỏi sẽ cần Type=simplenhưng nói chung, không được khuyến khích: 0pulum.de/public/systemd-man/ ,. Mọi người đã lấy các tập lệnh init cũ của họ và gói chúng lại systemdđể khởi động dịch vụ của họ systemd(init-script(service)). Tuy nhiên, systemdlà sự thay thế cho các tập lệnh init, vì vậy bạn nên gọi trực tiếp dịch vụ systemdđể nó trông như thế systemd(service).
Centimane

3

Đây là kịch bản của tôi như một dịch vụ:

[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

Xem dự án Bash Service Manager : https://github.com/reduardo7/bash-service-manager

Ví dụ thực hiện

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

Ví dụ sử dụng

$ ./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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.