以下のように液晶画面に書き込むシステムサービスがあります。
[Unit]
Description=LCD Screen
[Service]
Type=simple
User=admin
WorkingDirectory=/lcd
ExecStart=sudo /run_lcd.py
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=lcd-service
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
LCDがコンピュータに接続されている場合にのみサービスを実行したいと思います。パネルはシリアルポートを介して接続されているため、これを知る唯一の方法は特定のメッセージをLCD画面に送信することです。このメッセージは、接続されると値を返します。これをスクリプトで実行する場合、スクリプトの出力を取得し、その出力に基づいてサービスを実行する方法はありますか?
私は見たことがないsystemdの条件と主張しかし、私が望むことができるオプションは表示されません。どんな助けでも大変感謝します。
答え1
Edgarの答えはExecStartPre=
悪くありませんが、実行がブロックされるとExecStart=
サービスにフラグが立てられますfailed
。
また、それを試すことができますExecCondition=
。この動作はExecStartPre=
とのCondition*=
混合と同じです。
終了コード | 行動 |
---|---|
0 | デバイスは引き続き起動します。 |
1-254 | 開始は放棄され、ユニットは続くinactive (dead) |
255 | 捨て始め、ユニットはfailed |
簡単な例は次のとおりです。
$ cat condition.service
[Service]
ExecCondition=/bin/false
ExecStart=/bin/sleep 20
$ systemctl --user start condition.service
$ systemctl --user status condition.service
● condition.service
Loaded: loaded
Active: inactive (dead)
Starting condition.service...
condition.service: Control process exited, code=exited, status=1/FAILURE
condition.service: Skipped due to 'exec-condition'.
あなたはrestart=always
質問を提出します。起動が無効になったらExecCondition=
もう一度やり直してください...永遠に...(RestartSec=
起動制限に達するのを防ぎます)これはあなたが望むものではないかもしれません。
restart=on-failure
あなたのサービスが返されたら、EXIT_SUCCESS
おそらくそのタスクは完了したので、そのタスクを再要求する必要はありません。ただし、return EXIT_FAILURE;
エラーが発生した場合はいつでも再起動できます。 ExecCondition=
これを可能にしなさい。
を使用すると、ExecStartPre=
スクリプトがサービスを無効にしようとすると、サービスは失敗して終了します。これはrestart=on-failure
あなたが利用できず、唯一のオプションかもしれないrestart=on-success
ことを意味します。restart=no
その他のヒント:
User=admin
sudo
スクリプトで使用しています。これはNOPASSWD:
sudoeradmin
に依存するだけでなくroot
。このスクリプトを実行するためにroot権限が必要な場合は、サービスをrootとして直接実行してこの行を削除してください。
ExecStart=sudo /run_lcd.py
run_lcd.py
一般的にはインストールしないでください/
。自分で作成した(または手動でインストールした)スクリプトであれば、それに入れてください/usr/local/bin
。このような組織は、新しいサーバーを再作成するときに「すべてのローカルコンテンツ」を見つけるのに本当に役立ちます。ハードウェア。
Type=simple
- 明示的に表現しても悪いことはないと思いますが、これがデフォルトです
Type=
。ファイルが複雑になるので、これを追加しません。
- 明示的に表現しても悪いことはないと思いますが、これがデフォルトです
Standard{Output,Error}=syslog
- この
syslog
オプションはsystemdから削除されました。それでも以前のバージョンと互換性がありますが、以下から削除されました。文書。デフォルトのログを使用するには、この行を削除します(必要に応じて渡されます)。ドキュメント(Debian Busterの確認)では、次のように述べています。
システムログロギングに加えて、標準出力はsyslog(3)システムのsyslogサービスに接続されます。ロギングデーモンは通常、受信したすべてをsyslogに渡すように構成されています。この場合、このオプションはロギングと変わりません。
- この
RestartSec=10
- これは、人々が再起動制限に達するのを避けるために使用するトリックです。
multi-user.target
起動後にグラフィックアプリケーションを起動する人に特に便利です。より良い解決策は、リソースが準備された後にのみデバイスを起動することです。一般的に使用するのがWantedBy=graphical.target
正しい解決策です。After=graphical.target
また、すべてが準備されるまでサービスが開始されないようにします。あなたのサービスはグラフィックに関連しているように見えるので、これらのコンテンツが役に立つと思います。それにもかかわらず、最終的にうまく機能するサービスを持っていれば、RestartSet=
それは必要ありません。
- これは、人々が再起動制限に達するのを避けるために使用するトリックです。
それを組み合わせるには、次のようにします。
[Unit]
Description=LCD Screen
After=graphical.target
[Service]
WorkingDirectory=/lcd
ExecCondition=/usr/bin/python3 /usr/local/bin/checkScreen.py
ExecStart=/usr/local/bin/run_lcd.py
SyslogIdentifier=lcd-service
Restart=on-failure
[Install]
WantedBy=graphical.target
答え2
@Pankiが言ったようRestart=always
にに変更する必要があります。Restart=on-success
ExecStartPre
したがって、別のスクリプト(Pythonと仮定)を使用して画面が接続されていることを確認することをお勧めします。たとえば、単純なPythonスクリプトは次のようになります。
/checkScreen.py
#you will have to add before this lines the code
#used for getting the status of screen
if screenIsConnected:
exit(0)
else:
exit(1)
あなたのシステムサービスは次のとおりです。
[Unit]
Description=LCD Screen
[Service]
Type=simple
User=admin
WorkingDirectory=/lcd
ExecStartPre=/usr/bin/python3 /checkScreen.py
ExecStart=sudo /run_lcd.py
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=lcd-service
Restart=on-success
RestartSec=10
[Install]
WantedBy=multi-user.target