私はFIFOのコマンドを受け取り、ラズベリーパイでデバッグのためにいくつかのファイルを収集するスクリプトを書いています。うまくいく私がシステム単位のファイルを書くことに決めるまでは、私はそうです。実行するとsystemctl start crashcollector
スクリプトが起動しますが、実行中のパイプから何も読みませんが、何もせずにsystemctl stop crashcollector
サービスを停止するのに時間がかかります。そのため、多くの作業で通常のファイルを作成したにもかかわらず、私のユニットファイルに問題があると推測されます。
バッシュスクリプト:
#!/bin/bash
collectCrashReport() {
# teleport to cache dir
cd /mnt/cache
# remove any previous report
rm -rf crash/crashreport_*
# create report directory
directory=crashreport_`cat /etc/hostname`_$(date +%Y%m%d%H%M%S)
mkdir $directory
cd $directory
# snatch all the logs
cp -r /var/log/ .
ps --no-headers -ax > processes.dump
# dump dmesg to file
dmesg > dmesg.dump
# create crash dir
mkdir crash
# zip the whole thing
zip -qr /mnt/cache/crash/"$directory.zip" .
# remove collection dir
rm -rf /mnt/cache/crashreport_*
# done and done
}
# check if already running and kill
PIDFILE=/var/run/crashcollector.pid
# check if already running
if [ -f $PIDFILE ]; then
kill `cat $PIDFILE`
fi
echo $$ > $PIDFILE
cleanup() {
rm -f $PIDFILE
exit 0
}
# trap them signals
trap "cleanup" INT TERM EXIT
that_awesome_pipe="CCPipe"
[ -p $that_awesome_pipe ] || mkfifo $that_awesome_pipe
chmod 766 $that_awesome_pipe
while :; do
if read line; then
case $line in
"collect")
collectCrashReport
;;
*)
log "Received bad command $line, ignoring..."
;;
esac
fi
done <"$that_awesome_pipe"
システム単位ファイル:
[Unit]
Description=Crash report collector
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/crashCollector
ExecStop=/usr/bin/kill -9 `cat /var/run/crashcollector.pid`
KillMode=process
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
ここで正確に何を見逃しているのか分かりません。そのif read line
ブロックを削除すると、すべてが機能しました。
ベストアンサー1
そこには多くの問題があります。
ExecStart
とExecStop
シェルのコマンドラインを考えないでください。そうではありません。 systemd マニュアルはこれについて警告します。コマンド置換などのシェル拡張は次のとおりです。いいえこれらのサービス単位ファイル設定で使用できます。これはいいえシェル言語。- 開始する実際のサービスマネージャがある場合は、PIDファイルメカニズムを作成しないでください。 PIDファイルは1980年代以降に破損したメカニズムなので、適切なサービス管理によってPIDファイルの必要性が完全になくなりました。サービス管理者がいます。 それいつでも最大1つのサービスインスタンスが実行されることを保証します。 それプロセスIDが追跡されます。 それサービスが終了すると、サービスプロセスに終了信号を送信するタスクが処理される。
- FIFO の生成やサーバー側のオープンなど、基本的なサーバー側の項目をサーバープロセスに入れないでください。
この方法:
- サービスユニットとともにソケットユニットを作成します。
- からFIFOのすべての明示的な処理を削除します
crashCollector
。 ListenFIFO
ソケットユニットに使用されます。もちろん絶対パス名が必要です。StandardInput=socket
サービスユニットに使用されます。crashcollector
標準入力からのみスクリプトを読むようにしてください。crashCollector
.- すべての信号のキャプチャと
cleanup()
アイテムをcrashCollector
。 - 使用された明示的な殺人とサービスユニットの外部
ExecStop
で実行したいフォローアップの両方を取ってください。KillMode
StandardError=journal
サービスユニットに使用されます。log
単純エラーからecho 1>&2
標準エラーに置き換えられました。
追加読書
- ジョナサン・ドボイン・ポラード(2001)。 Unixデーモンを設計する際に避けるべき間違い。一般的な答え。
- Lennart Potlinget al。システムソケット。システムのマニュアルページ。 freedesktop.org.
- FIFOソケットからサービスを読む方法