49


11

bashでkillした後にTerminatedメッセージを抑制する方法

bashスクリプトでプロセスを強制終了した後に表示される `Terminated`メッセージをどのように抑制できますか?

私は `set bm`を試しましたが、うまくいきません。

私は別の解決策が `exec 2> / dev / null`を呼び出すことを含むことを知っています、しかしそれは信頼できますか? stderrを見続けられるようにするには、どうすればリセットできますか?

12 Answer


112


メッセージを黙らせるためには、メッセージが生成された時に stderr`をリダイレクトしなければなりません*。 http://ss64.com/bash/kill.html [`kill]コマンドはシグナルを送り、ターゲットプロセスが応答するのを待たないので、` kill`コマンドの stderr`をリダイレクトしても意味がありません。 。 bashビルトインhttp://ss64.com/bash/wait.html [`wait]は特にこの目的のために作られました。

これはごく最近のバックグラウンドコマンドを殺す非常に簡単な例です。 (https://stackoverflow.com/a/5163260/117471 [$についての詳細をご覧ください。 ここに。])

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

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

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

私はここからhttps://stackoverflow.com/questions/5719030/bash-silently-kill-background-function-process/5722850 [bash:暗黙のうちにバックグラウンド関数プロセスを強制終了します]から導かれました。


16


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

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

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

(スクリプト2> / dev / null)

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

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

exec 3>

しかし、私はこれをお勧めしません - 最初のものからの唯一の利点は、スクリプトがファイル記述子を変更した場合、より複雑で、おそらくスクリプトの動作を変更しながら、サブシェル呼び出しを節約することです。

'' '' '

編集:

より適切な回答を確認するには Mark Edgarで回答を確認してください_


15


https://stackoverflow.com/a/4849503 [MarcH’s answer]からヒントを得た 私は彼がいくらかの成功を収めていると示唆しているように `kill -INT`を使っていましたが、それはいくつかのプロセスを殺していないことに気づきました。 他のシグナルをテストした後、私は `SIGPIPE`がメッセージなしで同様にkillするのを見ます。

kill -PIPE

あるいは単に

kill -13


8


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

デモ:

cat> silent.sh << "EOF" sleep 100 1 EOFを眠る

sh silent.sh


4


多分 `disown`を呼び出して現在のシェルプロセスからプロセスを切り離すことができますか?


1


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

要らない:

$ 3スリープ
[1]
234

$ $
[1]
眠りました3 $

募集:

$(セットm;スリープ3

$ $ $ $ $

ご覧のとおり、ジョブ終了メッセージはありません。 私の代わりにbashスクリプトを使用します。これはkillされたバックグラウンドプロセスに対しても同様です。

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


1


これはkillallにも有効です(それを好む人のために):

killall -s SIGINT(あなたのプログラム)

私はバックグラウンドモードでmpg123を実行していました。 SIGTERM(デフォルト)の代わりにctrl-c(SIGINT)を送信することによってのみ黙って殺すことができます。


1


ジョブ通知を無効にするもう1つの方法は、コマンドを `sh -c 'コマンドでバックグラウンドにすることです。

#!/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}"
'


0


disownは私にとってまさに正しいことをしました - exec 3>


0


'`jobs 2>を追加して成功しました

    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