QEMU仮想マシンをモードで実行し、-daemonize
QEMUインスタンスと対話するように設計されたランダムなフォアグラウンド(対話型)プロセスを作成します。通常、フォアグラウンドプロセスが完了すると、pidfileを介してQEMUインスタンスをクリーンアップします。
qemu-system ... -pidfile ./qemu.pid -daemonize
/my/custom/interactive/process
pkill -F ./qemu.pid
ただし、場合によっては、フォアグラウンドプロセスの実行中にQEMUが独立して終了することがあります。でも、万が一に備えてブロックしたいです。したがって、私のカスタムインタラクションプロセスは次のように機能するはずです。
tail -f --pid=./qemu.pid /dev/null
どうすればうまくできますか?おそらくタイムアウトの一種のラッパーがあるので、次のように実行できます。
trackpid ./qemu.pid /my/custom/interactive/process
答え1
qemuプロセスをポーリングして消えるかどうかを確認し、消えたら早く終了することができます。特にqemu-system
。
それもかなりたくさんあります。この行を削除できますが#DEBUG
、これらの行がどのように結合されているかを確認するには、コメントを外してプログラムの出力をコードと比較します。
#!/bin/bash
InvokeQemu()
{
local i pid pidFile=qemu.pid
# Start the qemu process, and return the PID if possible
#
(
# qemu-system ... -pidFile "$pidFile" -daemonize
( sleep 30 & sleep 0.5 && echo $! >"$pidFile" ) # FAKE IT for half a minute
) >/dev/null 2>&1 </dev/null
#echo "InvokeQemu: checking for successful daemonisation" >&2 #DEBUG
for i in 1 2 3
do
# Does the PID file exist yet
#echo "InvokeQemu: attempt $i" >&2 #DEBUG
if [[ -s "$pidFile" ]] && pid=$(cat "$pidFile") && [[ -n "$pid" ]]
then
printf "%s\n" $pid
#echo "InvokeQemu: pid=$pid" >&2 #DEBUG
return 0
fi
# Pause a moment or so before trying again
sleep 2
done
return 1
}
MonitorPIDs()
{
local pid
for pid in "$@"
do
#echo "MonitorPIDs: checking pid $pid" >&2 #DEBUG
if err=$(kill -0 "$pid" 2>&1) || [[ "$err" == *permitted* || "$err" == *denied* ]]
then
# Process still exists
:
#echo "MonitorPIDs: pid $pid still alive" >&2 #DEBUG
else
#echo "MonitorPIDs: pid $pid has died" >&2 #DEBUG
echo "$pid"
return 1
fi
done
#echo "MonitorPIDs: all good" >&2 #DEBUG
return 0
}
########################################################################
# Go
myPid=$$
# Start the qemu emulator
echo "Starting qemu emulator"
qemuPid=$(InvokeQemu)
if [[ -z "$qemuPid" ]]
then
echo "Could not start qemu" >&2
exit 1
fi
# Start the monitor process
#
# Once any of them is no longer running it will fire SIGTERM to its
# remaining PIDs and then exit
echo "Starting monitor process"
(
while MonitorPIDs $qemuPid $myPid >/dev/null
do
#echo "(Monitor): all good" >&2 #DEBUG
sleep 2
done
kill $qemuPid $myPid 2>/dev/null
) &
# Start your interactive foreground process
#
# You will receive SIGTERM within a few seconds of the emulator exiting,
# so you may want to trap that
echo "Starting interactive process"
while read -p "What do you want to do? " x
do
echo "OK"
sleep 1
done
exit 0
答え2
最後に、次のコードを取得しました。
qemu-system ... -pidfile ./qemu.pid -daemonize
{
tail -f --pidfile="$(cat ./qemu.pid)" /dev/null
kill -INT 0
} &
/my/custom/interactive/process
kill $!
pkill -F ./qemu.pid
中かっこ内のスクリプトは、実際にバックグラウンドで実行されるpidfileモニタです。 pidが消えると、モニタは現在のプロセスグループを終了します。kill -INT 0
最も信頼性が高くクリーンな結果を提供するために使用します。
他のオプションは次のとおりです。
kill -- 0
(TERM信号を使用して終了すると、対話型プロセスを正しく終了できません)
kill -INT $$
(シェルプロセスのみ終了し、対話型プロセスは正しく終了できません)
kill -- -$$
sudo
(シェルのpidで表示されるプロセスグループを殺すことは、プロセスグループリーダーとして呼び出されるため、常に正しく機能していないようです)
pkill -P $$
(サブプロセスのみを終了することは実際には機能しますが、組み込みシェルを使用してCtrl-Cを使用してアクションを処理することをお勧めします。)
もう1つのポイントは、対話型プロセスが独自に完了したら、シャットダウンスクリプトとクリーンアップスクリプトの追加の推論を避けるためにモニタプロセスを終了する必要があることです。