4

私は現在、このようなスクリプトを持っています。

# code

mplayer "$vid"

# more code

問題は、このスクリプトが強制終了された場合、mplayerプロセスが存続することです。スクリプトを殺すとmplayerも殺されるようにするにはどうすればよいのだろうか。

execmplayerの後にコマンドを実行する必要があるため、使用できません。

exec mplayer "$vid"

私が考えることができる唯一の解決策は、バックグラウンドでスポーンし、手動で終了するまで待つことです。そうすれば、PIDを取得して、スクリプトが強制終了されたときに強制終了できますが、正確にはエレガントではありません。私はこれを行うための「適切な」または最良の方法は何であるか疑問に思いました。

4

5 に答える 5

4

コメントで投稿したprctlのアイデアをテストすることができましたが、うまくいくようです。これをコンパイルする必要があります:


#include "sys/prctl.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"

int main(int argc, char ** argv){

  prctl(PR_SET_PDEATHSIG, atoi(argv[1]),0,0,0);

  char * argv0 = strdup(argv[2]);

  char * slashptr = strrchr(argv0, '/');
  if(slashptr){
    argv0 = slashptr + 1;
  }

   return execvp(argv0, &(argv[2]));



}

上記を「prun」という名前の実行可能ファイルにコンパイルし、それがパスにあるとします。スクリプトが「foo.sh」と呼ばれ、パスにも含まれているとします。を呼び出すラッパースクリプトを作成します

prun 15 foo.sh

foo.shは、SIGKILLであっても、何らかの理由でラッパースクリプトが終了したときにSIGTERMを取得する必要があります。

注:これはLinuxのみのソリューションであり、提示されたcソースコードには引数の詳細なチェックが含まれていません

于 2012-11-06T18:18:05.290 に答える
3

リードしてくれたMuxに感謝します。手動で信号をキャッチする以外に、bashでこれを行う方法はないようです。これが最終的な(過度にコメントされた)バージョンです。

trap : SIGTERM SIGINT # Trap these two (killing) signals.  These will cause wait
                      # to return a value greater than 128 immediately after received.

mplayer "$vid" & # Start in background (PID gets put in `$!`)
pid=$!

wait $pid # Wait for mplayer to finish.
[ $? -gt 128 ] && { kill $pid ; exit 128; } ; # If a signal was recieved
                                              # kill mplayer and exit.

参照:-トラップ:http ://tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html

于 2012-11-04T23:59:41.283 に答える
2

代わりに、プロセスグループを強制終了することもできます。この方法では、プロセスツリー全体が強制終了されます。まず、グループIDを確認します。

ps x -o  "%p %r  %c" | grep <name>

そして、次のようにkillを使用します。

kill -TERM -<gid>

プロセスグループIDの前のダッシュに注意してください。またはワンライナー:

kill -TERM -$(pgrep <name>)
于 2012-11-04T18:34:11.900 に答える
2

更新)私はあなたが今探しているものを理解していると思います:

これを実現するには、新しいターミナルを生成してスクリプトを実行します。

gnome-terminal -x /path_to_dir_of_your_script/your_script_name

(または、使用xterm -eしているシステムに応じて、konsole -eの代わりに使用します)gnome-terminal -x

したがって、スクリプトが終了/終了するたびに(スクリプトの特定の部分があると想定しますexit 0exit 1、スクリプトが終了したため、新しく生成されたターミナルも終了します。これにより、その新しいターミナルで生成されたアプリケーションもすべて強制終了されます。

たとえば、次のスクリプトを使用して上記のコマンドをテストしました。

#!/bin/bash

gedit &
pid=$!
echo "$pid"

sleep 5
exit 0

ご覧のとおり、新しいgeditプロセスを強制終了する明示的な呼び出しはありませんが、スクリプトが終了するとすぐにアプリケーション(gedit)が閉じます。

(前の回答:あるいは、単にプロセスを強制終了する方法について質問した場合)これは、を使用してそれを達成する方法の簡単な例ですkill

#!/bin/bash

gedit &
pid=$!
echo "$pid"

sleep 5
kill -s SIGKILL $pid

私があなたの質問を誤解しない限り、あなたはそれが終了するまで待つのではなく、スポーンされたプロセスのPIDをすぐに得ることができます。

于 2012-11-04T18:16:02.460 に答える
0

おそらく、コマンド置換mplayer "$vid"を使用してサブシェルで実行します。

$(mplayer "$vid")

私はそれをこのようにテストしました:

tesh.sh:

#!/bin/sh
$vid = "..."
$(mplayer "$vid")

% test.sh

別の端末で:

% pkill test.sh

元の端末では、mplayerが停止し、stderrに出力します

Terminated
MPlayer interrupted by signal 13 in module: av_sync
于 2012-11-04T20:51:24.267 に答える