68

Terminatedbash スクリプトでプロセスを強制終了した後に表示されるメッセージを抑制するにはどうすればよいですか?

試しset +bmましたが、うまくいきません。

を呼び出す別の解決策は知ってexec 2> /dev/nullいますが、それは信頼できますか? stderr を引き続き表示できるようにリセットするにはどうすればよいですか?

4

12 に答える 12

149

stderr メッセージを無音にするには、メッセージが生成された時点でリダイレクトしている必要があります。killコマンドはシグナルを送信し、ターゲット プロセスが応答するのを待たないため、コマンドのリダイレクトstderrkill役に立ちません。bash ビルトインwaitは、この目的のために特別に作成されました。

これは、最新のバックグラウンド コマンドを強制終了する非常に単純な例です。( $! の詳細については、こちらをご覧ください。 )

kill $!
wait $! 2>/dev/null

と の両方が複数の pidkillwait受け入れるため、バッチ キルも実行できます。これは、すべてのバックグラウンド プロセス (もちろん現在のプロセス/スクリプト) を強制終了する例です。

kill $(jobs -rp)
wait $(jobs -rp) 2>/dev/null

私は bash からここに導かれました: 静かにバックグラウンド関数プロセスを殺します

于 2011-04-19T21:22:01.720 に答える
22

簡単な答えはあなたができないということです。Bashは常にフォアグラウンドジョブのステータスを出力します。監視フラグはバックグラウンドジョブにのみ適用され、スクリプトではなくインタラクティブシェルにのみ適用されます。

jobs.cのnotify_of_job_status()を参照してください。

あなたが言うように、あなたはリダイレクトすることができるので、標準エラーは/ dev / nullを指していますが、それからあなたは他のエラーメッセージを見逃します。スクリプトを実行するサブシェルでリダイレクトを実行することにより、一時的にすることができます。これにより、元の環境がそのままになります。

(script 2> /dev/null)

これにより、すべてのエラーメッセージが失われますが、そのスクリプトからだけであり、そのシェルで実行されている他のメッセージからは失われません。

新しいファイル記述子をそこを指すようにリダイレクトすることにより、標準エラーを保存および復元できます。

exec 3>&2          # 3 is now a copy of 2
exec 2> /dev/null  # 2 now points to /dev/null
script             # run script with redirected stderr
exec 2>&3          # restore stderr to saved
exec 3>&-          # close saved version

しかし、これはお勧めしません。最初の利点の唯一の利点は、サブシェルの呼び出しを保存する一方で、より複雑になり、スクリプトがファイル記述子を変更した場合にスクリプトの動作を変更する可能性があることです。


編集:

より適切な回答については、 MarkEdgarによる回答を確認してください

于 2008-09-17T10:07:39.663 に答える
9

解決策: SIGINT を使用します (非対話型シェルでのみ機能します)。

デモ:

cat > silent.sh <<"EOF"
sleep 100 &
kill -INT $!
sleep 1
EOF

sh silent.sh

http://thread.gmane.org/gmane.comp.shells.bash.bugs/15798

于 2011-01-31T09:55:05.200 に答える
7

たぶん、呼び出して現在のシェルプロセスからプロセスを切り離しdisownますか?

于 2008-09-17T09:44:15.303 に答える
3

これは私たち全員が探しているものですか?

要らない:

$ sleep 3 &
[1] 234
<pressing enter a few times....>
$
$
[1]+  Done                    sleep 3
$

募集:

$ (set +m; sleep 3 &)
<again, pressing enter several times....>
$
$
$
$
$

ご覧のとおり、ジョブ終了メッセージはありません。強制終了されたバックグラウンド プロセスに対しても、bash スクリプトでも機能します。

'set +m' は、現在のシェルのジョブ制御 ('help set' を参照) を無効にします。そのため、コマンドをサブシェルに入力しても (ここでは括弧内に入力します)、現在のシェルのジョブ制御設定に影響を与えることはありません。唯一の欠点は、バックグラウンド プロセスが終了したかどうかを確認する場合、またはリターン コードを評価する場合に、バックグラウンド プロセスの pid を現在のシェルに戻す必要があることです。

于 2012-08-30T13:35:40.483 に答える
2

これはkillallでも機能します(それを好む人向け):

killall -s SIGINT (yourprogram) 

メッセージを抑制します...バックグラウンドモードでmpg123を実行していました。SIGTERM (デフォルト) の代わりに ctrl-c (SIGINT) を送信することによってのみ、サイレントに強制終了できます。

于 2012-11-04T21:43:10.020 に答える
1

disown は私にとってまさに正しいことをしました- exec 3>&2 は多くの理由で危険です- set +bm はスクリプト内では機能しないようで、コマンドプロンプトでのみ機能しました

于 2011-01-28T21:04:58.983 に答える
0

ジョブ通知を無効にする別の方法は、コマンドをバックグラウンドでsh -c 'cmd &'構成することです。

#!/bin/bash
# ...
pid="`sh -c 'sleep 30 & echo ${!}' | head -1`"
kill "$pid"
# ...

# or put several cmds in sh -c '...' construct
sh -c '
sleep 30 &
pid="${!}"
sleep 5 
kill "${pid}"
'
于 2013-03-08T17:49:16.907 に答える
0

' ' をスクリプトに追加することに成功しましjobs 2>&1 >/dev/nullたが、それが他の人のスクリプトに役立つかどうかは定かではありませんが、ここにサンプルがあります。

    while true; do echo $RANDOM; done | while read line
    do
    echo Random is $line the last jobid is $(jobs -lp)
    jobs 2>&1 >/dev/null
    sleep 3
    done
于 2013-05-07T16:34:40.177 に答える
-1

単純:

{ kill $! } 2>/dev/null

アドバンテージ?任意の信号を使用できます

元:

{ kill -9 $PID } 2>/dev/null
于 2013-06-23T05:31:26.183 に答える