%20%E3%81%AE%E5%87%BA%E5%8A%9B%E3%82%92%E5%88%A5%E3%81%AE%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AB%E3%83%91%E3%82%A4%E3%83%97%E3%81%97%E3%81%BE%E3%81%99%E3%80%82.png)
私はsshとrsyncに関連する一種のバックアップ用のスクリプトを書いています。スクリプトを実行するたびに、すべての出力をログファイルにリダイレクトします。ログエントリを標準化するために、タイムスタンプとログレベルを追加するログ関数を作成しました。私の考えは、各コマンドラインのstdoutとstderrを1行ずつ読み、対応するログ関数を呼び出すことです。だから以下の答えに従いました。https://serverfault.com/questions/526592/pipe-stderr-and-stdout-to- Different-commands-not-just-to-files。
私のスクリプトは次のとおりです(使用されているすべての変数が正しく設定されていると仮定すると縮小されます)。
#!/bin/bash
# function: print a formatted log message including timestamp with given level and message to stdout
# arguments: <LEVEL> <MESSAGE>
log()
{
timestamp=$(date +"%F %T.%3N")
level=$1
message=$2
echo $timestamp $level: $message
}
# function: read command output from stdin and log it with given level
# arguments: <LEVEL>
logoutput()
{
sed 1d | \
while read i
do
log "$1" "$i"
done
}
log INFO "START ssh"
(ssh $connection mkdir -p $destStaticDirectory | logoutput INFO) 3>&1 1>&2 2>&3 | logoutput ERROR
log INFO "START rsync"
(rsync $rsyncArguments $linkDest $fromDirectory $connection:$destStaticDirectory | logoutput INFO) 3>&1 1>&2 2>&3 | logoutput ERROR
この機能はlog()
ログエントリをエコーするために使用され、この機能は1行ずつ読み込み、各行を記録するために使用さlogoutput()
れます。stdout
これで問題は、すべてがrsyncコマンドによって期待どおりに機能することです。しかし、sshコマンドでは機能しません。ssh $connection mkdir -p $destStaticDirectory
正しく呼び出されると、stdoutに出力がないことがわかります。だから私はsshを未知のホストに接続してテストしましたが、結果はssh: Could not resolve hostname XXX: Name or service not known
...しかし何もありません。また、すべての出力を期待どおりに印刷する同じsshコマンド "unwrapped"をスクリプトに追加しました。最後に、SSHの詳細モードをオンにしてエラーログエントリが発生しました。しかし、私のログにSSHのバグメッセージが表示されたくないので、これはオプションではありません。
私は何を逃したことがありませんか? sshが行うのと同じ奇妙なstdout、err処理がありますが、私が知らないのでしょうか?私がやろうとしていることが明らかになったことを願っています。
答え1
問題は、「sed 1d」が探している出力を削除するログ出力機能で発生する可能性が高いです。 「sed 1d」行を削除し、スクリプトが期待どおりに実行されていることを確認してください。
答え2
使用を検討しましたか?ロガー(1)ロギングが自動的に行われ、タイムスタンプなどが追加されます。
だから良い
{ ssh ... | logger ...; } 2>&1 | logger ...
最初の部分はロガーを介してstdoutをログファイルに送信し、2番目の部分はstderrをログファイルに送信するため、必要なものでなければなりません。ロガーのコマンドラインオプションを使用して、ロギング機能やファイルなどを選択できます。
これを行うためのよりきれいな方法もあります。使用プロセスの交換例えば
ssh ... > >(logger ...) 2> >(logger ...)
これにより、すべてのファイル記述子をジャグリングする必要がなくなります。