追加読書

追加読書

手動で起動しますが、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とプログラムが再起動されます。 」。

SIGPIPEsystemdはサービスを実行するときにデフォルトでシグナルを無視するため、これは間違っています。したがって、サービスプロセスとそのサブプロセス(この場合はスクリプトを解釈するシェル)は、すべてのSIGPIPEsを無視して続行します。

なぜsystemdがこれをするのか?systemd-journald以前のバージョンのsystemdでは、systemd-journald競合が発生したり終了したときに標準出力と標準エラーが送信されたすべてのサービスが受信されたためですSIGPIPE。無視しないと、システム内のほぼすべてのサービスがクローズされます。systemd-journald言うまでもなく不幸な状況。システムに属する人々は、daemontoolsから教訓を得られませんでした。 daemontoolsは、svscan「メイン」サービスと「ログ」サービスの間のパイプのオープンファイル記述子を維持し、「メイン」サービスが「ログ」エラーがSIGPIPE発生したときに偽のケースを取得しないようにします。 「サービス。何らかの理由でサービスが再起動されました。

数年後、ついに彼らは追いつき、systemdは現在開かれたファイル記述子をservicesに接続されたパイプに保存しますsystemd-journald。しかし、これはやや迂回的な方法で行われます。つまり、プロセスが選択したファイル記述子をプロセス#1に注入することを許可します。SIGPIPEもともと元の問題を隠す必要はないので、もはや標準を無視する必要はありません。

IgnoreSIGPIPEただし、サービスユニット設定のデフォルト値はそのまま残りますyes

noサービス単位に変更してください。

追加読書

関連情報