15

私はいくつかの同様の質問(Bashのコマンドからの出力に変数を設定する方法など)をフォローしてきましたが、受け入れられた答えは私には機能しないようです。他の人の質問を脱線させるべきか、自分の複製を投稿するべきかわからなかったので、ここで間違った選択をした場合はお詫びします。

まとめているスクリプト内のいくつかのコマンドの出力と終了ステータスを取得したいと思います。これが私が使っているものの例です:

cmd_output=$(rm $file)
exit_status=$?
if [ "${exit_status}" -eq 0 ]
then
log "Successfully removed the original" ${TAB_LEVEL}
else
fail "Failed to remove the original, the output was: \n ${cmd_output}"
fi

ログ関数と失敗関数は次のとおりです。

# Usage: fail "Failure message"
function fail {
echo "FATAL ERROR: $1" >> "${LOG_DIR}/${LOG_FILE}"
exit 1
}

# Usage: log "Log message" 3    Where the tab-level is 3.
function log {
if (("${2}" > 0))
then
eval "printf '    %.0s' {1..$2}" >> "${LOG_DIR}/${LOG_FILE}"
fi
echo "$1" >> "${LOG_DIR}/${LOG_FILE}"
return 0
}

上記の例では、$(cmd)形式を使用していますが、バッククォートも使用してみました。

私のログファイルでは、障害が発生したときに表示されるのは次のとおりです。

致命的なエラー:オリジナルの削除に失敗しました。出力は次のとおりです:\ n

また、失敗したコマンドの出力は、通常どおり画面に表示されます。cmd_output変数が空のままになる一般的な理由はありますか?

4

3 に答える 3

35

特別な標準エラー出力ストリームの出力を含める必要があります。

cmd_output=$(rm "$file" 2>&1)

すべてのプログラムには 3 つのデフォルト ストリームがあります (番号付きのファイル記述子)。

0. Standard input (where the program normally reads from)
1. Standard output (where the program normally writes to)
2. Standard error (where the program normally writes error messages)

したがって、エラー メッセージをキャプチャするには、標準エラー出力 (stderr) を通常の標準出力 (stdout) にリダイレクトする必要があります。これは、$(...)式によってキャプチャされます。

リダイレクトの構文は、>「演算子」を使用します。その直前に、リダイレクトするファイル記述子を指定します (デフォルトは 1、つまり stdout です)。また、ファイルにリダイレクトするように指定できます。その後にアンパサンド ( &) を記述すると、強制的に別のファイル記述子にリダイレクトされます。したがって、この例では、ファイル記述子 2 (stderr) をファイル記述子 1 (stdout) にリダイレクトします。

また、<「operator」で入力をリダイレクトすることもできますが、この場合、デフォルトのファイル記述子は 0 (stdin) です。

もう 1 つの観察事項は、$file変数に空白文字が含まれている場合に備えて、変数を二重引用符で囲むことをお勧めします。

これが少し役立つことを願っています=)

于 2012-10-05T01:56:05.370 に答える
6

* nixコマンドには通常、標準出力()と標準エラー( )の2つの形式の出力がありますstdoutstderr

FOO=$(...)キャプチャするだけstdoutで、stderr妨げられません。

stderrこの構文での内容が必要な場合は、にマージされる2>&1ようにコマンドの接尾辞を付ける必要があります。(例えばそうです:)stderrstdoutrm $file 2>&1

于 2012-10-05T02:02:16.713 に答える
0

あなたのfail関数はちょうど終了しているので、単純に行う方がはるかに簡単です:

set -e  # Abort on failure
exec 2>> "${LOG_DIR}/${LOG_FILE}"  # Append all errors to LOG_FILE
if cmd_output=$(rm $file)
  log "Successfully removed the original" ${TAB_LEVEL}
fi

これと元のコードの唯一の違いは、テキストを出力しないことですFATAL ERROR:log簡潔さが美徳であるため、関数を完全にスキップする方がよいでしょう。エラーを大声で報告します。静かに成功します。

于 2012-10-05T04:24:48.020 に答える