如何为Shell脚本创建服务,以便可以像守护程序一样启动和停止它?


22

我使用CentOS 7的目的是每五秒钟创建一个cron,但正如我研究的那样,我们只能使用一分钟的cron,所以我现在要做的是创建一个shell文件。
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 

但是我不知道在start或stop方法中该写些什么,我试图将hit.sh的相同内容放入其中,start(){}但是}in stop方法却给出了错误。


单独/usr/bin/myscript运行它是否可以正常工作?echo $?脚本完成运行后的输出是什么?是203吗?
亚历山大

@Alexander /usr/bin/myscript.sh可以通过终端执行正常,并echo$?给了我1
codegasmer

如果没有问题,脚本应返回错误代码0。错误代码1表示错误。
亚历山大

Answers:


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请注意,OP需要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. 重新加载所有systemd服务文件: systemctl daemon-reload

  2. 通过启动服务来检查其是否正常工作systemctl start my

奖金:

为了测试systemd服务,可以使用两个窗格来启动tmux环境,其中顶部窗口监视脚本(stdoutstderr)的输出,底部窗口可用于重新启动服务。这需要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

用退出tmuxctrl-d然后ctrl-c


感谢您的答复我尝试了您的解决方案,但是服务没有启动,您能否看一下我的问题,我添加了详细信息
codegasmer 2015年

我认为如果您的脚本没有失败,它会工作,但是返回错误代码0。–
Alexander

4
现在我喜欢系统化!
DenisKolodin '16

1
该脚本可以放置在任何地方,只要systemd服务可以访问和执行它即可。
亚历山大

2
我不推荐Type=forking请求者可能会需要机会,Type=simple但通常不建议分叉:0pointer.de/public/systemd-man/…。人们一直在使用旧的init脚本并将它们包装起来,systemd以便启动服务systemd(init-script(service))。但是,systemd它是代替初始化脚本的,因此您应该直接使用调用服务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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.