4

誰かがこれを手伝ってくれるのだろうか?

私はbashスクリプトを持っています。別の GUI ベースのアプリケーションであるサブプロセスを開始します。次に、bash スクリプトはインタラクティブ モードになり、ユーザーからの入力を取得します。この対話モードは無期限に続きます。サブプロセスの gui アプリケーションが終了したときに終了させたいと思います。

SIGCHLD を見てきましたが、これは答えではないようです。これが私が試したことですが、プログラムが終了したときに信号が届きません。

set -o monitor

"${prog}" &
prog_pid=$!

function check_pid {
    kill -0 $1 2> /dev/null
}

function cleanup {
    ### does cleanup stuff here
    exit
}


function sigchld {
    check_pid $prog_pid
    [[ $? == 1 ]] && cleanup
}

trap sigchld SIGCHLD

次の回答を更新しました。「nosid」からの提案を使用して、これが機能するようになりました。関連するもう 1 つの問題があります。これは、次のインタラクティブなプロセスが、ユーザーからのキー入力の待機をブロックする基本的なメニュー駆動型のプロセスであるということです。子プロセスが終了すると、入力が受信されるまで USR1 シグナルは処理されません。シグナルを強制的にすぐに処理する方法はありますか?

待機の様子は次のようになります。

stty raw                 # set the tty driver to raw mode 
max=$1                   # maximum valid choice
choice=$(expr $max + 1)  # invalid choice
while [[ $choice -gt $max ]]; do
    choice=`dd if=/dev/tty bs=1 count=1 2>/dev/null`
done
stty sane                # restore tty

ソリューションで更新されました。私はこれを解決しました。その秘訣は、読み取りにノンブロッキング I/O を使用することでした。今、「nosid」からの回答と私の修正により、私はまさに私が望むものを手に入れました。完全を期すために、これが私にとってうまくいくものです:

#!/bin/bash -bm
{
"${1}"
kill -USR1 $$
} &

function cleanup {
    # cleanup stuff
    exit
}

trap cleanup SIGUSR1

while true ; do
   stty raw                 # set the tty driver to raw mode 
   max=9                    # maximum valid choice
   while [[ $choice -gt $max || -z $choice ]]; do
       choice=`dd iflag=nonblock if=/dev/tty bs=1 count=1 2>/dev/null`
   done
   stty sane                # restore tty

   # process choice       

done
4

4 に答える 4

7

ここに別のアプローチがあります。SIGCHLD を使用する代わりに、GUI アプリケーションが終了するとすぐに任意のコマンドを実行できます。

{
    some_command args...
    kill -USR1 $$
} &

function sigusr1() { ... }

trap sigusr1 SIGUSR1
于 2012-10-05T18:04:31.240 に答える
1

Ok。私はあなたが必要なものを理解していると思います。私の .xinitrc を見てください:

   xrdb ~/.Xdefaults
   source ~/.xinitrc.hw.settings
   xcompmgr &
   xscreensaver &
   # after starting some arbitrary crap we want to start the main gui.       

   startfluxbox &  PIDOFAPP=$! ## THIS IS THE IMPORTANT PART
   setxkbmap genja

   wmclockmon -bl &


   sleep 1
   wmctrl -s 3  && aterms sone &
   sleep 1
   wmctrl -s 0


   wait $PIDOFAPP ## THIS IS THE SECOND PART OF THE IMPORTANT PART

   xeyes -geometry 400x400+500+400 &
   sleep 2
   echo im out!

何が起こるかというと、プロセスをバックグラウンドに送信した後、wait を使用してプロセスが停止するまで待機できます。アプリケーションが実行されている限り、待機の後にあるものは実行されません。これを使用して、GUI がシャットダウンされた後に終了できます。

PS: bash を実行しています。

于 2012-10-05T21:44:19.120 に答える
0

私はあなたがする必要があると思います:

set -bm

また

set -o monitor notify

bashマニュアルに従って:

-b
    Cause the status of terminated background jobs to be reported immediately, rather than before printing the next primary prompt.
于 2012-10-05T17:59:00.210 に答える
0

シェルの主な仕事は子プロセスの実行であり、独自の目的のために SIGCHLD をキャッチする必要があります。これにより、シグナルをスクリプト自体に渡すことが何らかの形で制限されます。

子供pidを確認して、それに基づいてアラートを送信していただけますか。pid以下のように子を見つけることができます-

bash_pid=$$
while true
do
    children=`ps -eo ppid | grep -w $bash_pid`
    if [ -z "$children" ]; then
        cleanup
        alert
        exit
    fi
done
于 2012-10-05T18:02:15.310 に答える