バックグラウンドプロセスがシェルで終了するまでフォアグラウンドプロセスを実行します。

バックグラウンドプロセスがシェルで終了するまでフォアグラウンドプロセスを実行します。

QEMU仮想マシンをモードで実行し、-daemonizeQEMUインスタンスと対話するように設計されたランダムなフォアグラウンド(対話型)プロセスを作成します。通常、フォアグラウンドプロセスが完了すると、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

おすすめ記事