成功した場合にのみシェルコマンドの出力を非表示にしますか?


12

通常、シェルコマンドの出力を非表示にするには、 stderrとstdoutをリダイレクトする必要があります。デフォルトで出力を非表示にするが、エラー時にすべての累積出力をダンプする組み込み機能またはコマンドはありますか?これをリモートsshコマンドのラッパーとして実行したいと思います。今、私はそれらをリダイレクトを使用していますが、何が失敗したのかについての手がかりが得られず、それらは非常に冗長です。

編集:最後に、スクリプトから以前のすべてのコマンドを蓄積し、現在のプロセス識別子を使用し、ログを自動的に削除し、失敗の赤いエラーを追加するために少し調整した@Belminの答えに基づいて次のテンプレートを作成しました何かがうまくいかないときのメッセージ。このテンプレートでは、最初のsilentラッパーは成功し、ディレクトリがすでに存在するため、3番目のコマンドは失敗します。

#!/bin/sh

set -e

SILENT_LOG=/tmp/silent_log_$$.txt
trap "/bin/rm -f $SILENT_LOG" EXIT

function report_and_exit {
    cat "${SILENT_LOG}";
    echo "\033[91mError running command.\033[39m"
    exit 1;
}

function silent {
    $* 2>>"${SILENT_LOG}" >> "${SILENT_LOG}" || report_and_exit;
}

silent mkdir -v pepe
silent mkdir -v pepe2
silent mkdir -v pepe
silent mkdir -v pepe2

2
stdoutのみをリダイレクトする場合、stderrは引き続き表示されます。これで十分ですか、エラーがある場合は標準出力も表示しますか?
クローミー14年

私は両方を見たいが、何かがうまくいかない場合にのみ、そうでなければ私は何も見たくない。
グジェゴシアダムHankiewicz

2
私がやることは、ログファイルにstdoutとstderrを印刷して、画面が乱雑にならないようにすることです。また、stderrを画面に出力するため、エラーがある場合表示できます。詳細が必要な場合は、ログファイルを確認できます。ログファイルには、プログラムの出力とプログラムエラーが含まれています。この方法で、「何かがうまくいかない場合にのみ、両方を見ることができます」。これは役立ちますか?stackoverflow.com/questions/2871233/を

1
stderrとstdoutを2つの別々のリダイレクトで同じファイルにリダイレクトするのは安全ですか?私は2>&1、次のようなものを常に使用する必要があると考えました:$* >>"${SILENT_LOG}" 2>&1" || report_and_exit
psmith

回答:


3

次のようなbash関数をセットアップします。

function suppress { /bin/rm --force /tmp/suppress.out 2> /dev/null; ${1+"$@"} > /tmp/suppress.out 2>&1 || cat /tmp/suppress.out; /bin/rm /tmp/suppress.out; }

次に、コマンドを実行するだけです:

suppress foo -a bar

システム上で非ルートアクセス権を持つ攻撃者は、rmとコマンドコールの間にシンボリックリンクを作成しようとする可能性があり/etc/passswdます。
ミタール

1
ところで、上記のリダイレクトの順序は次のようになります。$* > /tmp/surpress.out 2>&1これは本当にstderrをキャプチャします。
ミタール

2
$*任意の入力を処理するのに最適ではありません。特に、スペースまたはフラグが含まれる場合。最もポータブル${1+"$@"}
なのは

両方のコメントごとに変更。ありがとう---良い情報。
ベルミンフェルナンデス


7

この目的のためにスクリプトを書くのは十分簡単でなければなりません。

この完全にテストされていないスクリプトのようなもの。

OUTPUT=`tempfile`
program_we_want_to_capture &2>1 > $OUTPUT
[ $? -ne 0 ]; then
    cat $OUTPUT
    exit 1
fi
rm $OUTPUT

一方、スクリプトの一部として実行するコマンドの場合、通常はすべての出力を単に印刷するよりも優れたものが必要です。私はしばしば、見ているものを未知のものに限定しています。これは、10年以上前に読んだものから改作したスクリプトです。

#!/bin/bash

the_command 2>&1 | awk '
BEGIN \
{
  # Initialize our error-detection flag.
  ErrorDetected = 0
}
# Following are regex that will simply skip all lines
# which are good and we never want to see
/ Added UserList source/ || \
/ Added User/ || \
/ init domainlist / || \
/ init iplist / || \
/ init urllist / || \
/ loading dbfile / || \
/^$/ {next} # Uninteresting message.  Skip it.

# Following are lines that we good and we always want to see
/ INFO: ready for requests / \
{
  print "  " $0 # Expected message we want to see.
  next
}

# any remaining lines are unexpected, and probably error messages.  These will be printed out and highlighted.
{
  print "->" $0 # Unexpected message.  Print it
  ErrorDetected=1
}

END \
{
  if (ErrorDetected == 1) {
    print "Unexpected messages (\"->\") detected in execution."
    exit 2
  }
}
'
exit $?

5

私はこれを行うためのきれいな方法があるとは思わない、私が考えることができる唯一のものは

  • コマンドの出力をキャプチャします。
  • コマンドの戻り値を確認し、失敗した場合
    • キャプチャされた出力を表示します。

ただし、これを実装することは興味深いプロジェクトかもしれませんが、おそらくQ&Aを超えています。


関数で実行可能である必要があります。うーん、試してみましょう。
ベルミンフェルナンデス14年

1

のようなもので不足している tehcommand &>/tmp/$$ || cat /tmp/$$

どの程度のユーザビリティ/タイピングが必要か/必要かによって異なります。(たとえば、パイプとして使用するか、引数でコマンドを渡す)

@zoredacheの短いスクリプトは基本的にこれのプロトラッパーであり、より堅牢性を高め、並行性を処理します。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.