Systemd 服务未按预期重启

Systemd 服务未按预期重启

下面引用的所有文件都可以在这里看到 https://github.com/sm0svx/svxlink/tree/master/src/svxlink/systemd

问题:

警告 - 我是一名具有一定脚本编写能力的硬件工程师,我不介意深入研究某些东西,但我没有丰富的操作系统类型的经验,所以我可能会问一些看似菜鸟的问题,请原谅这些问题,因为我是一个试图学习和理解的菜鸟。

我遇到了一个超出我理解范围的系统问题,尽管我预计对于那些更熟悉的人来说这相当简单。

    [Unit]
Description=SvxLink repeater control software GPIO setup
Documentation=man:svxlink(1)

[Service]
Type=oneshot
ExecStart=@SBIN_INSTALL_DIR@/svxlink_gpio_up
ExecStop=@SBIN_INSTALL_DIR@/svxlink_gpio_down

#Restart=on-failure
TimeoutStartSec=60
WorkingDirectory=@SVX_SYSCONF_INSTALL_DIR@
RemainAfterExit=True

[Install]
WantedBy=multi-user.target

代码正确执行的是,在启动时调用 svxlink_gpio_up 脚本,并且一切都正确设置。当我手动运行 svxlink_gpio_down 脚本时,它也能正确运行。

但是我遇到的问题是,当我想重新启动此服务时,gpio 不会被拆除并重建,所以我必须重新启动设备才能按预期重新配置 gpio。

我认为我需要在 [Service] 部分添加以下内容。我关心的是,首先,这是正确的方法吗?其次,是否存在我需要了解和应对的任何类型的竞争条件。

一个可能相关的问题是,Type=OneShot 是否合适?我认为这应该是 Type=simple,因为对我来说 OneShot 就是只能运行一次的东西。

ExecReload=@SBIN_INSTALL_DIR@/svxlink_gpio_down;@SBIN_INSTALL_DIR@/svxlink_gpio_up

    or 

    ExecReload=@SBIN_INSTALL_DIR@/svxlink_gpio_down
    ExecReload=@SBIN_INSTALL_DIR@/svxlink_gpio_up

///////////////////////////////////////////////////////////////////////

2019 年 10 月 27 日 - 根据 Grawity 的反馈添加其他信息

systemctl stop svxlink由于 gpio 没有像预期的那样被拆除,因此任务实际上并没有完全成功。

pi-star@pi-repeater-mmdvm(ro):~$ ls /sys/class/gpio/gpio
gpio472/     gpio475/     gpiochip0/   gpiochip464/ gpiochip496/
gpio474/     gpio478/     gpiochip100/ gpiochip480/ gpiochip504/

当我停止服务后查询服务状态时,我没有发现任何问题

● svxlink.service - SvxLink repeater control software
   Loaded: loaded (/lib/systemd/system/svxlink.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Sun 2019-10-27 19:22:58 PDT; 1min 48s ago
     Docs: man:svxlink(1)
  Process: 1085 ExecStartPre=/bin/touch ${LOGFILE} (code=exited, status=0/SUCCESS)
  Process: 1098 ExecStartPre=/bin/chown ${RUNASUSER} ${LOGFILE} (code=exited, status=0/SUCCESS)
  Process: 1100 ExecStart=/usr/bin/svxlink --logfile=${LOGFILE} --config=${CFGFILE} --pidfile=${PIDFILE} --runasuser
 Main PID: 1100 (code=exited, status=0/SUCCESS)

Oct 27 19:22:58 pi-repeater-mmdvm systemd[1]: Stopping SvxLink repeater control software...
Oct 27 19:22:58 pi-repeater-mmdvm systemd[1]: svxlink.service: Succeeded.
Oct 27 19:22:58 pi-repeater-mmdvm systemd[1]: Stopped SvxLink repeater control software.
Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.

我还检查了 svxlink 日志,没有错误迹象

Sun Oct 27 19:22:58 2019: SIGTERM received. Shutting down application...

当我直接调用 _down 任务时,一切都按预期进行

pi-star@pi-repeater-mmdvm(ro):~$ /usr/sbin/svxlink_gpio_down
pi-star@pi-repeater-mmdvm(ro):~$ ls /sys/class/gpio/
export       gpiochip0/   gpiochip100/ gpiochip464/ gpiochip480/ gpiochip496/ gpiochip504/ unexport

我还尝试再次启动 svxlink 应用程序,但 gpio 仍未配置

pi-star@pi-repeater-mmdvm(ro):~$ sudo systemctl start svxlink.service
pi-star@pi-repeater-mmdvm(ro):~$ ls /sys/class/gpio/gpiochip
gpiochip0/   gpiochip100/ gpiochip464/ gpiochip480/ gpiochip496/ gpiochip504/
pi-star@pi-repeater-mmdvm(ro):~$ ls /sys/class/gpio/gpiochip

答案1

代码正确执行的是,在启动时调用 svxlink_gpio_up 脚本,并且一切都正确设置。当我手动运行 svxlink_gpio_down 脚本时,它也能正确运行。

但是我遇到的问题是,当我想重新启动此服务时,gpio 不会被拆除并重建,所以我必须重新启动设备才能按预期重新配置 gpio。

调查具体是哪个部分进程失败。它可能在 _down 脚本期间失败,也可能在 _up 脚本期间失败,或者在两者之间的某个地方失败。

确保您的服务在启动后确实显示为“活动” systemctl status(即它没有失败,并且您的 RemainOnExit 设置也受到尊重)。

当您systemctl restart在 Type=oneshot 服务上使用时,这基本上相当于systemctl stop紧接着立即执行systemctl start。为了使“停止”作业正常工作,服务实际上必须处于“活动”状态。

尝试确保脚本本身可以应对任何情况 - 例如,即使部分或全部 GPIO 之前已被拆除,_down 脚本也应始终无错误地运行,_up 脚本也是如此。它们可以显示类似警告但不会因错误而死亡。

我认为我需要在 [Service] 部分添加以下内容。我关心的是,首先,这是正确的方法吗?其次,是否存在我需要了解和应对的任何类型的竞争条件。

如果您想使用,这将有效systemctl reload,但有点多余,因为它所做的事情与重新启动完全相同。

(通常systemctl reload是为了以不需要完全拆除现有配置的方式应用配置。)

一个可能相关的问题是,Type=OneShot 是否合适?我认为这应该是 Type=simple,因为对我来说 OneShot 就是只能运行一次的东西。

Type=oneshot是没有长寿命进程的服务单元。服务的所有 ExecStart 进程运行完成后,该服务将被标记为“已启动”。

Type=simple是具有一个主进程的服务单元。一旦其(一个)ExecStart 进程启动,该服务就会被标记为“已启动”开始,当该进程退出时被标记为“停止”。

相关内容