Як створити службу для сценарію оболонки, щоб я міг її запустити та зупинити як демон?


22

Я використовую CentOS 7, що моя мета - створити крон кожні п’ять секунд, але, як я досліджував, ми можемо використовувати 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 /usr/bin/myscript.shчудово працює над виконанням через термінал і echo$?дав мені1
codegasmer

Сценарій повинен повернути код помилки 0, якщо немає проблем. Код помилки 1 вказує на помилку.
Олександр

Відповіді:


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.

Для кожного рівня запуску, для якого потрібна ця послуга, вам потрібно буде створити відповідне посилання. Наприклад, посилання з іменем /etc/init.d/rc5.d/S99hitserviceзапустить службу для запуску рівня 5. Звичайно, ви все одно можете запустити та зупинити її вручну через service hitservice start/service hitservice stop


Чи потрібен файлу суфікс типу: hitservice.service? Після цього: Не вдалося запустити backupservice.service: Блок не знайдено. На CentOS 7 так чому це пропонується як відповідь
Spektakulatius

@ Code.IT Зауважте, що ОП хотів скрипт SystemV, а не systemdсценарій, тому суфікс не потрібен. Ви повинні мати змогу запускати старі сценарії з systemdпросто чудовими. Ви пробували systemctl enable hitservice?
Дмитро Григор’єв

@DmitryGrigoryev: Цей скрипт не запобігає множині екземплярів і не зупиняє всі створені декілька екземплярів; pidfile зберігає лише останній породжений процес pid.
Лучано

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. Перезавантажте всі системні файли обслуговування: systemctl daemon-reload

  2. Переконайтесь, що він працює, запустивши послугу з systemctl start my.

Бонус:

Для тестування системної служби можна запустити середовище 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-dі потім ctrl-c.


дякую за відповідь Я спробував вам рішення, але сервіс не запускається. Ви можете подивитися на моє запитання, я додав деталі
codegasmer

Я думаю, що це спрацює, якщо ваш сценарій не вийде з ладу, але поверне код помилки 0.
Олександр

4
Тепер мені подобається systemd!
Денис Колодін

1
Сценарій можна розмістити в будь-якому місці, доки системна служба може отримати доступ та виконати його.
Олександр

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


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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.