シェルスクリプト全体の出力をスクリプト自体にリダイレクトするにはどうすればよいでしょうか? 質問する

シェルスクリプト全体の出力をスクリプト自体にリダイレクトするにはどうすればよいでしょうか? 質問する

スクリプト自体の中にシェル コマンドを含めて、Bourne シェル スクリプトの出力をすべてどこかにリダイレクトすることは可能ですか?

単一のコマンドの出力をリダイレクトするのは簡単ですが、次のようなものが必要です。

#!/bin/sh
if [ ! -t 0 ]; then
    # redirect all of my output to a file here
fi

# rest of script...

意味: スクリプトが非対話的に実行される場合 (たとえば、cron)、すべての出力をファイルに保存します。シェルから対話的に実行される場合は、通常どおり出力を stdout に送信します。

私は、FreeBSD の定期ユーティリティによって通常実行されるスクリプトに対してこれを実行したいと考えています。これは毎日の実行の一部ですが、通常は電子メールで毎日確認する必要はないため、送信は行いません。ただし、この特定のスクリプト内で何かが失敗した場合、それは私にとって重要なので、毎日のジョブのこの一部の出力をキャプチャして電子メールで送信できるようにしたいと考えています。

更新: Joshua の回答は正確ですが、スクリプト全体の stdout と stderr を保存および復元したいと考えていました。これは次のように行います。

# save stdout and stderr to file 
# descriptors 3 and 4, 
# then redirect them to "foo"
exec 3>&1 4>&2 >foo 2>&1

# ...

# restore stdout and stderr
exec 1>&3 2>&4

ベストアンサー1

質問を更新して対応します。

#...part of script without redirection...

{
    #...part of script with redirection...
} > file1 2>file2 # ...and others as appropriate...

#...residue of script without redirection...

中括弧 '{ ... }' は、I/O リダイレクトの単位を提供します。中括弧は、コマンドが出現する可能性のある場所 (単純に言えば、行の先頭またはセミコロンの後) に出現する必要があります。(はい、より正確に表現できます。細かい点にこだわりたい場合は、お知らせください。 )

ご指摘のとおり、リダイレクトを使用すると元の stdout と stderr を保持できますが、リダイレクトされたコードのスコープを上記のように設定すると、後でスクリプトを保守する必要がある人にとって何が起こっているのか理解しやすくなります。

Bashマニュアルの関連セクションはコマンドのグループ化そしてI/O リダイレクトPOSIXシェル仕様の関連セクションは以下のとおりです。複合コマンドそしてI/O リダイレクトBash にはいくつか追加の表記法がありますが、それ以外は POSIX シェル仕様と同様です。

おすすめ記事