2015年8月9日日曜日

[シェル] 画面とログファイルの両方に出力


bash で以下のようにすると、標準出力と標準エラー出力を画面とログファイルの両方に出力します。
#!/bin/bash

#--------------------------------------------------------#
# 標準出力と標準エラーを画面とログファイルへ出力する設定 #
#--------------------------------------------------------#
LOG=/tmp/debug.log
exec > >(tee ${LOG}) 2>&1
#--------------------------------------------------------#

echo "** `date '+%Y-%m-%d %H:%M:%S'` - START"

# 正常
uptime

# エラーを起こしてみる
unknown_cmd

echo "** `date '+%Y-%m-%d %H:%M:%S'` - END"

exit 0

sh では、以下のようにします。
#!/bin/sh

#--------------------------------------------------------#
# 標準出力と標準エラーを画面とログファイルへ出力する設定 #
#--------------------------------------------------------#
FIFO=/tmp/$$.fifo
LOG=/tmp/debug.log
mkfifo ${FIFO}
trap '/bin/rm -f ${FIFO}' EXIT
tee ${LOG} < ${FIFO} &
exec > ${FIFO} 2>&1
#--------------------------------------------------------#

echo "** `date '+%Y-%m-%d %H:%M:%S'` - START"

# 正常
uptime

# エラーを起こしてみる
unknown_cmd

echo "** `date '+%Y-%m-%d %H:%M:%S'` - END"

exit 0

上記どちらを実行しても、以下のように、画面に表示されたものと同じ内容がログファイルに記録されます。
% ./test.sh
** 2012-07-14 16:32:02 - START
 16:32:02 up  4:59,  1 user,  load average: 0.09, 0.11, 0.09
./xxx.sh: line 20: unknown_cmd: コマンドが見つかりません
** 2012-07-14 16:32:02 - END
% cat /tmp/debug.log
** 2012-07-14 16:32:02 - START
 16:32:02 up  4:59,  1 user,  load average: 0.09, 0.11, 0.09
./xxx.sh: line 20: unknown_cmd: コマンドが見つかりません
** 2012-07-14 16:32:02 - END
CentOSだと、/bin/sh は /bin/bash にシンボリックリンクしてますが、/bin/sh を使用すると、bashの機能が制限されて Bシェルとして動くみたいです。