1. ホーム
  2. バッシュ

[解決済み】シェルスクリプト全体の出力を、スクリプト自体の中でリダイレクトするには?

2022-04-02 03:54:15

質問

Bourne シェルスクリプトの出力をすべてどこかにリダイレクトすることは可能ですか?ただし、シェルコマンドはスクリプト自体の中に入れてください。

一つのコマンドの出力をリダイレクトするのは簡単ですが、もう少しこういったものが欲しいのです。

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

# rest of script...

意味:スクリプトが非対話的に実行される場合(例えば、cron)、すべての出力をファイルに保存してください。 シェルから対話的に実行される場合は、通常通り標準出力に出力させる。

FreeBSDのperiodicユーティリティで通常実行されるスクリプトでこれを行いたいのです。 これは毎日実行されるものの一部で、普段は毎日メールで見る気にならないので、送信させないようにしています。 しかし、この特定のスクリプト内の何かが失敗した場合、それは私にとって重要であり、毎日のジョブのこの部分の出力をキャプチャしてメールできるようにしたいのです。

更新: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

解決方法は?

更新された質問に対応します。

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

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

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

中括弧 '{ ... }' は、I/Oリダイレクションの単位となるものです。 中括弧は、コマンドが出現しうる場所、簡単に言えば、行頭かセミコロンの後に出現させなければならない。 ( そう、もっと正確に言えばいいんだ。屁理屈を言いたいなら言ってくれ。 )

あなたが示したリダイレクトで元の標準出力と標準エラー出力を保持できるのは正しいのですが、通常は上記のようにリダイレクトされたコードをスコープ化した方が、後でスクリプトをメンテナンスしなければならない人たちにとって何が起こっているのか理解するのがよりシンプルになります。

Bashマニュアルの該当箇所は コマンドのグループ化 I/Oリダイレクション . POSIX シェル仕様の該当箇所は以下の通りです。 複合コマンド I/Oリダイレクション . Bashにはいくつかの特別な表記がありますが、それ以外はPOSIXシェル仕様に似ています。