cat $ERR_TXT | mail -s $SUBJECT -r $FROM_ADDR $TO_ADDR
みたいな感じで、サーバからファイルの内容をメール本文にしてメールで飛ばすときに、
メール本文が空っぽになってしまって、かわりによくわからんバイナリファイルが添付でくっついてきた。
#対応
結論だけ先に書くと、catコマンドのオプション -v を使えば解決した。
cat -v $ERR_TXT | mail -s $SUBJECT -r $FROM_ADDR $TO_ADDR
参考:
CentOS 6.xのmailコマンドでメールを送信すると添付ファイルになる場合の対処
[mailx コマンドで日本語を本文に入れると添付ファイルになってしまう?]
(http://zisakuzien.exblog.jp/20406030)
ただし、今回の件は上記2件とはちょっと異なる状況だったのでメモ。
#やろうとしたこと。
cronで動かしてるバッチファイル(シェルスクリプト)を使って、定期的にsftpでとあるログファイルをログ保存サーバへ飛ばしている。
sftpの処理に失敗したら、失敗した旨の標準エラー出力をメール本文に貼りつけてメールで飛ばしたい。
#つまったこと。
動作確認のために、わざとログ保存サーバのiptablesで飛ばし元サーバからのアクセスを遮断して、
sftpの処理に失敗したことを正しくメールで通知してくれるか確認しようとしたら、
メール本文がからっぽで、かわりに添付ファイル(.bin)がくっついてた。なんだこれ?
#切り分け。
###1 sftpが失敗している標準エラー出力をちゃんとシェル変数にしまっているか?
こんな感じで取得させてる。
SFTP_RESULT_TXT=`sftp -oIdentityfile=$SSHKEY -b $BAT sftpuser@$REMOTE_LOG_SERVER 2>&1`
SFTP_RESULT=$?
で、SFTP_RESULTが0じゃなかったら、メール通知、っていう流れ。
成功したらそのまま(メール通知なし)。
で、ちゃんと取れてることを以下のように確認。
- 処理の中で、そのまま $SFTP_RESULT_TXT を標準出力に吐かせてみて出力されることを確認。
- $SFTP_RESULT_TXT をメール本文になる $ERR_TXT に吐かせてみて出力されることを確認。
どちらも問題なし。
※ちなみにエラー内容は以下のもの。普通のsshのタイムアウト(ホスト名はてきとうです)。
ssh: connect to host hogehoge port 22: Connection timed out
Couldn't read packet: Connection reset by peer
###2 取得したエラーメッセージはメール本文用のテキストファイルに書かず、そのまま$ERR_TXTをmailコマンドで送信してみる。
こちらもちゃんとできる。
もちろんこちらの実施結果では、メール本文にsftpが失敗した時の標準エラー出力は表示されない(テスト用の文章のみ)。
###3 想定した流れでメールを飛ばしてみる。
=> やっぱり添付ファイルになる!なんぞこれ。
#わからんのでググりましょう。
素直に先人の知恵を借りましょう。でさくっとヒットしたのが参考の2ページ。もいちど貼る。
参考:
CentOS 6.xのmailコマンドでメールを送信すると添付ファイルになる場合の対処
[mailx コマンドで日本語を本文に入れると添付ファイルになってしまう?]
(http://zisakuzien.exblog.jp/20406030)
うーん、パッと見、どちらもlocaleを問題にしてるみたいだけど、関係あるかなー、、と思いつつわからんので試してみると、
正しく飛びました。ちゃんちゃん。という流れでした。
#考察
標準エラー出力をシェル変数経由でファイルに吐かせたのが問題だったのでしょうか?
ちなみにcat -v のmanを見ると、
-v, --show-nonprinting
use ^ and M- notation, except for LFD and TAB
とのこと。
WEBで確認すると、
-v, --show-nonprinting
<LFD> と <TAB> とを除く制御文字を `^' 表記を使って表示する。 高位ビットがセットされている文字は、前に `M-' を置いて表わす。
とのこと。。うーん、制御文字の問題??