我有一个 bash 脚本,基本上运行这个:
#!/bin/bash
[...]
while true; do
str="broadcast "`randArrayElement "messages[@]"`
server_send_message $str
sleep $interval
done
现在我想将其作为 systemd 服务运行,我的服务脚本如下所示:
[Unit]
Description=Announcer
After=network.target
[Service]
ExecStart=/usr/local/bin/somescript &; disown
ExecStop=/usr/bin/kill -9 `cat /tmp/somescript.pid`
Type=forking
PIDFile=/tmp/somescript.pid
[Install]
WantedBy=default.target
不幸的是,当我通过它运行该服务时,service somescript start
它正在工作,但由于 while true 循环,我的终端卡在启动脚本中:
● somescript.service - somescript service
Loaded: loaded (/etc/systemd/system/somescript.service; disabled; vendor preset: enabled)
Active: activating (start) since Wed 2016-08-17 12:22:34 CEST; 43s ago
Control: 17395 (somescript)
CGroup: /system.slice/somescript.service
├─17395 /bin/bash /usr/local/bin/somescript &; disown
└─17409 sleep 600
如何将此脚本作为服务运行而不陷入“启动”/ while true 循环?
答案1
您需要让 systemd 为您工作。让它处理启动时的分叉和进程的终止。例如,将您的维修部件更换为
[Service]
Type=simple
ExecStart=/usr/local/bin/somescript
PIDFile=/tmp/somescript.pid
那么你可以使用systemctl start
,status
和stop
。您必须记住 systemd 中的行是不是由 shell 解释,因此例如您&;
只是作为另一个 2 个字符的参数传递给您的脚本。
答案2
根据您的要求,您可能会考虑用 systemd 计时器配置替换循环。即使 server_send_message 花费的时间比“OnUnitActiveSec”长,它也不会启动服务两次:
一些脚本.定时器
[Unit]
Description=Announce every minute
[Timer]
OnUnitActiveSec=1m
AccuracySec=10s
Unit=somescript.service
[Install]
WantedBy=default.target
somescript.service 服务部分:
[Service]
Type=oneshot
ExecStart=/usr/bin/sh -c 'str="broadcast "`randArrayElement "messages[@]"`; server_send_message $str'