只需使用启动命令 Ubuntu 即可停止和启动服务

只需使用启动命令 Ubuntu 即可停止和启动服务

我最近在 Ubuntu LTS 服务器上创建了一项服务,允许我测试网络的正常运行时间。脚本本身按预期工作,但是当我尝试将其变成服务时,我遇到了一些问题,服务一启动就自行停止(通过命令 stop)。

控制文件:

#!/bin/bash

case "$1" in
start)
   /home/user/network_script/network_script.sh &
   echo $!>/var/run/network_script.pid
   ;;
stop)
   kill `cat /var/run/network_script.pid`
   rm /var/log/network_output.status
   rm /var/run/network_script.pid
   ;;
restart)
   $0 stop
   $0 start
   ;;
status)
   if [ -e /var/run/network_script.pid ]; then
      echo network_script.sh is running, pid=`cat /var/run/network_script.pid`
      echo /var/log/network_script.status
   else
      echo network_script.sh is NOT running
      exit 1
   fi
   ;;
*)
   echo "Usage: $0 {start|stop|status|restart}"
esac

exit 0

系统文件:

[Unit]
Description=Network Script

[Service]
ExecStart=/home/user/network_script/network_script_controls.sh start
ExecStop=/home/user/network_script/network_script_controls.sh stop
ExecRestart=/home/user/network_script/network_script_controls.sh restart
ExecStatus=/home/user/network_script/network_script_controls.sh status

[Install]
WantedBy=multi-user.target

状态输出:

network_script.service - Network Script
     Loaded: loaded (/etc/systemd/system/network_script.service; enabled; vendor preset: enabled)
     Active: inactive (dead) since Tue 2023-01-03 14:07:46 EST; 8s ago
    Process: 25131 ExecStart=/home/user/network_script/network_script_controls.sh start (code=exited, status=0/S>
    Process: 25133 ExecStop=/home/user/network_script/network_script_controls.sh stop (code=exited, status=0/SUC>
   Main PID: 25131 (code=exited, status=0/SUCCESS)
        CPU: 9ms

Jan 03 14:07:46 greengoblin systemd[1]: Started Network Script.
Jan 03 14:07:46 greengoblin network_script_controls.sh[25136]: rm: cannot remove '/var/log/network_output.status>
Jan 03 14:07:46 greengoblin systemd[1]: network_script.service: Deactivated successfully.

答案1

添加Type=forking到您的[Service]部分。,

来自手册页:

如果设置为 forking,则预计使用 ExecStart= 配置的进程将调用 fork() 作为其启动的一部分。当启动完成并且所有通信通道都建立后,父进程预计将退出。子进程继续作为主服务进程运行,当父进程退出时,服务管理器会认为该单元已启动。这是传统 UNIX 服务的行为。如果使用此设置,建议同时使用PIDFile=选项,以便systemd能够可靠地识别服务的主进程。一旦父进程退出,systemd 将继续启动后续单元。

此外,最好让 systemd 了解您的 PID 文件,以便它可以确定进程是否仍在运行或崩溃:

手册页是这样说的PIDFile=

采用引用服务的 PID 文件的路径。对于 Type= 设置为分叉的服务,建议使用此选项。指定的路径通常指向 /run/ 下面的文件。如果指定了相对路径,则其前缀为 /run/。服务启动后,服务管理器会从该文件中读取该服务主进程的PID。服务管理器不会写入此处配置的文件,但如果该文件仍然存在,它会在服务关闭后删除该文件。 PID 文件不需要由特权用户拥有,但如果它由非特权用户拥有,则会强制执行附加安全限制:该文件可能不是指向其他用户拥有的文件的符号链接(无论是直接还是间接) ,并且 PID 文件必须引用已经属于该服务的进程。

请注意,现代项目中应避免使用 PID 文件。尽可能使用 Type=notify 或 Type=simple,这样不需要使用 PID 文件来确定服务的主进程,并避免不必要的分叉。

这意味着您的服务应该如下所示:

[Service]
Type=forking
PIDFile=/var/run/network_script.pid
ExecStart=/home/user/network_script/network_script_controls.sh start
ExecStop=/home/user/network_script/network_script_controls.sh stop
ExecRestart=/home/user/network_script/network_script_controls.sh restart
ExecStatus=/home/user/network_script/network_script_controls.sh status

也就是说,仔细看看最后一段PIDFile=。由于您使用的是 systemd,因此您不需要自己跟踪 PID。这使得你的分叉脚本变得不必要。 Systemd 会为您自动执行此操作。

我会放弃/home/user/network_script/network_script_controls.sh并使用这个单元文件:

[Unit]
Description=Network Script

[Service]
Type=simple
ExecStart=/home/user/network_script/network_script.sh

[Install]
WantedBy=multi-user.target

相关内容