Bash

在 systemd 腳本中執行時為真

  • February 11, 2018

我有一個 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 循環?

你需要讓 systemd 為你工作。讓它處理開始時的分叉和程序的終止。例如,將您的服務元件替換為

[Service]
Type=simple
ExecStart=/usr/local/bin/somescript
PIDFile=/tmp/somescript.pid

然後你可以使用systemctl start,statusstop. 您必須記住 systemd 中的行不是由 shell 解釋的,因此例如您&;只是作為另一個 2 個字元的參數傳遞給您的腳本。

根據您的要求,您可能會考慮用 systemd 計時器配置替換循環。即使 server_send_message 花費的時間超過“OnUnitActiveSec”,它也不會啟動服務兩次:

somescript.timer

[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'

引用自:https://unix.stackexchange.com/questions/303926