手動で起動しますが、systemd(HOST_TX)では機能しない一連のコマンドがあります。
所有者_買収:
nc -v -l -p 5006
Listen[0.0.0.0](シリーズ 0、ポート 5006)
所有者_送信:
/opt/sendtofifo.sh > /tmp/tofifo1 # in a shell
nc -v -w 3 HOST_RX 5006 < /tmp/tofifo1 # in a second shell
fifoを使用していない場合は、手動で送信できます。
/bin/bash -xc '/opt/sendtofifo.sh | /bin/nc -v -T lowdelay HOST_RX 5006'
HOST_RXが受信を停止すると、両方のコマンドはsystemdを実行し続けるのではなく、状態を無視してクリーン/opt/sendtofifo.sh
終了しますnc
。
次のようにsystemdサービスを設定してみてください。
[Service]
Type=simple
RestartSec=2
ExecStart=/bin/bash -xc '/opt/sendtofifo.sh | /bin/nc -v -T lowdelay HOST_RX 5006'
Restart=always
これは最初に機能します:
root@rx(boot:ro,root:rw):/home/pi# systemctl status rx_rc.service
● rx_rc.service - RX RC Service
Loaded: loaded (/etc/systemd/system/rx_rc.service; static; vendor preset: enabled)
Active: active (running) since Tue 2020-06-09 14:34:52 CEST; 4s ago
Main PID: 28649 (bash)
CGroup: /system.slice/rx_rc.service
├─28649 /bin/bash -xc /opt/sendtofifo.sh | /bin/nc -v -T lowdelay 10.11.10.11 5006; exit
├─28650 /opt/sendtofifo.sh
└─28651 /bin/nc -v -T lowdelay 10.11.10.11 5006
HOST_RX が接続を閉じると、次のような結果が得られます。
● rx_rc.service - RX RC Service
Loaded: loaded (/etc/systemd/system/rx_rc.service; static; vendor preset: enabled)
Active: active (running) since Tue 2020-06-09 14:34:52 CEST; 1min 11s ago
Main PID: 28649 (bash)
CGroup: /system.slice/rx_rc.service
├─28649 /bin/bash -xc /opt/sendtofifo.sh | /bin/nc -v -T lowdelay 10.11.10.11 5006; exit
└─28650 /opt/sendtofifo.sh
nc
サービスが失敗した場合に再起動する方法はありますか?
コメントへの返信
/opt/sendtofifo.sh プロセスの strace 出力
nanosleep({tv_sec=0, tv_nsec=200000000}, NULL) = 0
write(1, "\0\0\f\0\4\200\0\0\30\0\0\0\264\277\0\0\271\315\6\0002\364\301\22\257\4 \0\315", 29) = -1 EPIPE (Broken pipe)
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=1589, si_uid=0} ---
nanosleep({tv_sec=0, tv_nsec=200000000}, NULL) = 0
答え1
明らかに間違った答えは「しかしSIGPIPE
〜するプログラムが終了するためプログラムが終了するため、設定SIGPIPE
するRestart=always
とプログラムが再起動されます。 」。
SIGPIPE
systemdはサービスを実行するときにデフォルトでシグナルを無視するため、これは間違っています。したがって、サービスプロセスとそのサブプロセス(この場合はスクリプトを解釈するシェル)は、すべてのSIGPIPE
sを無視して続行します。
なぜsystemdがこれをするのか?systemd-journald
以前のバージョンのsystemdでは、systemd-journald
競合が発生したり終了したときに標準出力と標準エラーが送信されたすべてのサービスが受信されたためですSIGPIPE
。無視しないと、システム内のほぼすべてのサービスがクローズされます。systemd-journald
言うまでもなく不幸な状況。システムに属する人々は、daemontoolsから教訓を得られませんでした。 daemontoolsは、svscan
「メイン」サービスと「ログ」サービスの間のパイプのオープンファイル記述子を維持し、「メイン」サービスが「ログ」エラーがSIGPIPE
発生したときに偽のケースを取得しないようにします。 「サービス。何らかの理由でサービスが再起動されました。
数年後、ついに彼らは追いつき、systemdは現在開かれたファイル記述子をservicesに接続されたパイプに保存しますsystemd-journald
。しかし、これはやや迂回的な方法で行われます。つまり、プロセスが選択したファイル記述子をプロセス#1に注入することを許可します。SIGPIPE
もともと元の問題を隠す必要はないので、もはや標準を無視する必要はありません。
IgnoreSIGPIPE
ただし、サービスユニット設定のデフォルト値はそのまま残りますyes
。
no
サービス単位に変更してください。