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를 사용하여 동작을 처리하는 것을 선호합니다.)
또 다른 요점은 대화형 프로세스가 자체적으로 완료되면 종료 및 정리 스크립트에 대한 추가 추론을 피하기 위해 모니터 프로세스를 종료해야 한다는 것입니다.