~についてシステム、他のサービスの実行中に実行中のサービスを一時停止または停止できますか(すべてのデータが記録されていることを確認)。
私のシナリオは次のとおりです。センサーを構築しました(Raspberry Pi Zero WベースとKali Linuxを実行)。認識に使用されるデーモンは、sensor.service
起動プロセスが完了した直後に起動されます(システムサービス単位で)。
[Unit]
Description=Arbitrary sensor
After=network.target
[Service]
ExecStart=/usr/local/bin/sense --daemon
[Install]
WantedBy=multi-user.target
センサーは常にローカルでデータを収集して保存します。データは定期的に計算され、結果はネットワークを介して送信されます。今計算するときすべてのデータが記録されていることを確認するには、センサーからのデータの受信を中断する必要があります。、計算が始まる前に。計算が完了したら、センサーは追加のデータ収集を開始する必要があります。
はい、この問題を処理するためにスクリプトを直接作成できます。
systemctl stop sensor.service
systemctl start compute.service # Terminates itself
systemctl start sensor.service
しかし、これがsystemdが私のために処理できるシナリオかどうか疑問に思います。特にスクリプトを直接書く必要はありません。私が想像するのは、compute.timer
上記の3行を処理するユニットです。
答え1
あなたの質問に書いたスクリプトに小さな問題があります。compute.service
始める前に停止するのを待ちませんsensor.service
。
戦略
以下は4つの戦略です。私の考えでは、3番目は私が一番好きだと思います。
並行性を実行する別の方法を見つける
sensor.service
停止する必要があるかどうかわかりません。これを行う理由は、新しいデータが計算に影響を与えないためです。この場合、データファイルのスナップショットを撮ります。その後、そのスナップショットに基づいて計算が行われます。このスナップショットは計算中に更新されないため、並行性の問題が解決されます。使用することは、サービスが停止したときに削除される新しい一時インストールを効果的にインポートすることをPrivateTmp=
意味します。/tmp
# /etc/systemd/system/compute.service
[Service]
ExecStartPre=/bin/cp /var/lib/sensor/data /tmp/data_to_compute
ExecStart=/usr/bin/compute /tmp/data_to_compute
PrivateTmp=yes
時間のあるスクリプトですべての作業を行います。
本当にsensor.serviceを停止する必要がある場合、スクリプトのアイデアも悪くありません。おそらく次の内容compute.timer
がcompute.service
含まれますExecStart=/usr/local/bin/compute.sh
。
#!/bin/sh
systemctl stop sensor.service
/usr/bin/compute /var/lib/sensor/data
systemctl start sensor.service
システム関係の使用
前の例では、systemctl
systemd が実行するスクリプト内で呼び出しを行いました。何か間違っていると思います。 systemd の関係は、Conflicts=
サービスの開始時に競合するサービスが自動的に停止することを意味します。 systemdは、他のプロセスが完了したときにプロセスを開始することとは関係がないため、ExecStartPost=
ここで使用できます。
したがって、次の項目に追加してくださいcompute.service
。
[Unit]
Conflicts=sensor.service
[Service]
ExecStart=/usr/bin/compute /var/lib/sensor/data
ExecStopPost=systemctl start sensor.service
sensor.service
トリガーしたら、停止したい目標を達成しますcompute.timer
。カスタムシェルスクリプトの代わりにすべてをユニットファイルに移動しました。 systemd内で使用したときに発生する不快感の問題はsystemctl
解決されませんでしたが、少なくともこれを減らして透明性を高めました(スクリプトに隠すことなく)。
2つのタイマー
ちょっととんでもないですが、行を変更したい場合は、2つのExecStopPost=
タイマーを使用できます。 compute.timer
すでにやっているように、必要に応じて頻繁に計算するように設定します。 5分のデータを計算するには、トリガーの5分前から開始するように設定しますsensor.timer
。sensor.service
compute.timer
それらを一つにまとめる
どの戦略を使用してもcompute.timer
心の平和が必要ですcompute.service
が、接触は必要ありませんsensor.service
。私はあなたがシステムタイマーを作る方法を尋ねたかもしれないことを知っています。戦略3を全体的に実装する方法は次のとおりです。
# /etc/systemd/system/compute.timer
[Unit]
Description=Timer to trigger computations every 15 minutes
[Timer]
OnCalendar=*:0/15
[Install]
WantedBy=timers.target
compute.timer
compute.service
(上)は15分ごとに始まります(下)。
# /etc/systemd/system/compute.service
[Unit]
Description=Runs computation (triggered by compute.timer)
Conflicts=sensor.service
[Service]
ExecStart=/usr/bin/compute /var/lib/sensor/data
ExecStopPost=systemctl start sensor.service
次にタイマーを有効にします(または再起動したくない場合はタイマーを起動します)。
systemctl enable compute.timer
systemctl start compute.timer
答え2
私の問題を解決するためにこれまでに見つけたベストプラクティスは、他の質問で説明されています。https://unix.stackexchange.com/a/318744/208465