在systemd服务内部启动systemd服务会导致死锁

利维坦

我有一个first.service调用bash脚本的systemd服务(我们称之为)。

在该bash脚本中,我首先停止然后使用来启动另一个服务systemctl(例如systemctl start another.service

我已经注意到,当我在shell中执行脚本时,一切都可以正常运行,another.service并且正在停止并随后启动。

当我打电话给systemctl restart first.servicesystemdanother.service时,它会正确停止“ ”,但会挂起。

当我检查ps它的结果时,这两个systemctl调用都可以正常工作,即systemctl restart first.servicesystemctl start another.service

我使用systemd 230

这是已知的行为吗?我怎样才能解决这个问题?

有没有更好的方法来从一项服务中处理(重新)启动systemd服务?

编辑:我的first.service文件:

[Unit]
Description=First service
#Before=local-fs.target apache2.service rsyslog.service

[Service]
Type=oneshot
ExecStart=/usr/bin/test.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

我的another.service档案:

[Unit]
Description=Test service

[Service]
Type=oneshot
ExecStart=/bin/bash -c "while ( true  ) ; do { date ; echo 'It works!' ; sleep 10 ; } done"
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

和我的bash脚本:

#!/bin/bash
echo stopping
systemctl stop another.service
echo "result of stop = $?"
echo starting
systemctl start another.service
echo "result of start = $?"
echo DONE

挂起后,我得到以下输出ps

[piotr@/etc/systemd/system] $ ps -aux | grep systemctl
root      7801  0.0  0.0  27696  1336 pts/21   S+   16:06   0:00 systemctl restart first
root      7807  0.0  0.0  27696  1320 ?        S    16:06   0:00 systemctl start another.service
piotr     7915  0.0  0.0  15752   968 pts/22   S+   16:06   0:00 grep --color=auto systemctl

EDIT2:我systemctl status在另一个控制台打电话的确切时间从这两种服务发表systemctl restart first

我还在bash脚本中添加了检查返回值。上面更新。

first.service

● first.service - First service
Loaded: loaded (/etc/systemd/system/first.service; disabled; vendor preset: enabled)
Active: activating (start) since Wed 2017-04-19 16:34:43 CEST; 46s ago
Main PID: 12761 (test.sh)
CGroup: /system.slice/first.service
├─12761 /bin/bash /usr/bin/test.sh
└─12766 systemctl start another.service

Apr 19 16:34:43 piotr-ideapad systemd[1]: Starting First service...
Apr 19 16:34:43 piotr-ideapad test.sh[12761]: stopping
Apr 19 16:34:43 piotr-ideapad test.sh[12761]: result of stop = 0
Apr 19 16:34:43 piotr-ideapad test.sh[12761]: starting

another.service

● another.service - Test service
Loaded: loaded (/etc/systemd/system/another.service; disabled; vendor preset: enabled)
Active: activating (start) since Wed 2017-04-19 16:34:43 CEST; 1min 40s ago
Main PID: 12767 (bash)
CGroup: /system.slice/another.service
├─12767 /bin/bash -c while ( true   ) ; do { date ; echo 'It works!' ; sleep 10 ;  } done
└─13066 sleep 10

Apr 19 16:35:43 piotr-ideapad bash[12767]: Mi 19. Apr 16:35:43 CEST 2017
Apr 19 16:35:43 piotr-ideapad bash[12767]: It works!
Apr 19 16:35:53 piotr-ideapad bash[12767]: Mi 19. Apr 16:35:53 CEST 2017
Apr 19 16:35:53 piotr-ideapad bash[12767]: It works!
Apr 19 16:36:03 piotr-ideapad bash[12767]: Mi 19. Apr 16:36:03 CEST 2017
Apr 19 16:36:03 piotr-ideapad bash[12767]: It works!
Apr 19 16:36:13 piotr-ideapad bash[12767]: Mi 19. Apr 16:36:13 CEST 2017
Apr 19 16:36:13 piotr-ideapad bash[12767]: It works!
Apr 19 16:36:23 piotr-ideapad bash[12767]: Mi 19. Apr 16:36:23 CEST 2017
Apr 19 16:36:23 piotr-ideapad bash[12767]: It works!

EDIT3:交换一些评论后,我将尝试重述该问题。

假设我上面列出的所有进程均未启用或启动。当我打电话systemctl status给他们时-他们loaded只是inactive
然后我打电话systemctl start first,这个终端命令没有完成。
如果我调用systemctl status这些服务Active:,则它们的状态均为,activating (start)但是我systemctl start first在终端中的执行仍然没有退出,并且无限期挂起。

我认为这两个进程都已排队,并且systemctl start another在我的bash脚本中,等待进程systemctl start first完成之前,进程本身就完成了,在这里我们遇到了死锁。

马克·斯托斯伯格

看来是僵局的实际上是该Type=oneshot指令如所宣传的那样工作。可以通过another.service直接运行您的命令来触发“挂起”

systemctl start another

取消后,可以查看journalctl一下它根本不是“挂起”,而是按预期运行了无限循环。在中man systemd.service,我们找到有关以下内容的文档Type=oneshot

oneshot的行为类似于简单。但是,可以预期该过程必须在systemd启动后续单元之前退出。

换句话说,您已经编写了一个无限循环,然后指示systemd等待直到完成,然后再继续。

您要么需要使用其他变量Type=(如)Type=simple要么需要对主进程使用无限循环退出。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章