すべてのbashスクリプトアクションを完全にログに記録するにはどうすればよいですか?


44

スクリプト出力から、エラーメッセージを含むすべてのログデータをキャプチャし、それらをすべてログファイルにリダイレクトしたいと思います。

私は次のようなスクリプトを持っています:

#!/bin/bash
(
echo " `date` : part 1 - start "
ssh -f admin@server.com 'bash /www/htdocs/server.com/scripts/part1.sh logout exit'
echo " `date` : sleep 120"
sleep 120
echo " `date` : part 2 - start"
ssh admin@server.com 'bash /www/htdocs/server.com/scripts/part2.sh logout exit'
echo " `date` : part 3 - start"
ssh admin@server.com 'bash /www/htdocs/server.com/scripts/part3.sh logout exit'
echo " `date` : END"
) | tee -a /home/scripts/cron/logs

ファイル内のすべてのアクションを確認したい /home/scripts/cron/logs

しかし、echoコマンドの後に配置したものだけが表示されます。

ログをチェックインする方法はSSHコマンドが成功しましたか?

すべてのログデータを収集する必要があります。これは、スクリプト内のすべてのコマンドの結果を監視し、スクリプトが失敗したときに何が起こっているかをよりよく分析するために必要です。


「スクリプト」を使用してこれを実行することもできます。この記事を参照してください:[ここ] [1] [1]:stackoverflow.com/questions/5985060/...
xX0v0Xx

あなたはerrexitに注意する必要があります-私はそれが無視されるか、エラーがスクリプトを終了しないことに気付きました。スクリプトに次のようなものがある場合:command || dosmthgコマンドが失敗した場合、スクリプトはerrexitを設定してすぐに終了せず、dosmthgを実行してスクリプトを続行します

回答:


67

通常、すべてのスクリプトの先頭に次のようなものを置きます(特にデーモンとして実行する場合)。

#!/bin/bash
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>log.out 2>&1
# Everything below will go to the file 'log.out':

説明:

  1. exec 3>&1 4>&2

    ファイル記述子を保存して、リダイレクト前の状態に復元したり、次のリダイレクト前の状態に出力したりできるようにします。

  2. trap 'exec 2>&4 1>&3' 0 1 2 3

    特定の信号のファイル記述子を復元します。サブシェルの終了時に復元する必要があるため、通常は必要ありません。

  3. exec 1>log.out 2>&1

    stdoutファイルlog.outにリダイレクトしてstderrからにリダイレクトしますstdout。同じファイルに移動する場合は順序が重要であることに注意してください。stdout しなければならない前にリダイレクトすることstderrにリダイレクトされますstdout

それ以降、コンソールで出力を表示するには(たぶん)、単ににリダイレクトできます&3。例えば、

echo "$(date) : part 1 - start" >&3

stdout上記の3行目を実行する前に、おそらくコンソールに向けられた場所に移動します。


<< niceroot、ありがとう!これらの3行(exec、trap、exec)をスクリプトの先頭に追加しました。標準出力と標準エラー出力の両方を取得できます。しかし、1つの問題:「some_commandでファイル記述子3(pipe:XXX)がリークしました」...これらのエラーを回避する方法を教えてください。カスタムボードでbusyboxベースのshを使用しています。
クマール

3
ここに素晴らしいカンフー!-さらに良いのはを使用することtrap 'exec 2>&4 1>&3' 0 1 2 3 RETURNです。RETURN疑似sigspecは、シェル関数またはスクリプトがで実行されるたびにファイル記述子を復元します。またはソースビルトインの実行が終了します。このため(および他の理由のために)私のスクリプトで、私は最後の2行として追加:returnexit 0-ちょうど私の2セント、賛辞あなたに@nicerobot!
-DavAlPi

シェルのグローバル変数を介したシェルスクリプトのロギングについては、かなりの詳細があります。シェルスクリプトで同様の種類のログをエミュレートできます:cubicrace.com/2016/03/efficient-logging-mechnism-in-shell.html この投稿には、INFO、DEBUG、ERRORなどのログレベルの導入に関する詳細が記載されています。スクリプトエントリ、スクリプト出口、関数エントリ、関数出口などの詳細をトレースします。
ピユーシュコルディア16年

trap信号の列挙は少し奇妙に見えます。通常15、同様に含める必要があります。
トリプリー


14

sshの出力をログファイルに取得するには、にリダイレクトstderrする必要がありますstdout。これを行うには2>&1、bashスクリプトの後に追加します。

次のようになります。

#!/bin/bash
(
...
) 2>&1 | tee ...

これでメッセージが正しい順序で表示されない場合は、別のサブシェルを追加してみてください。

#!/bin/bash
((
...
) 2>&1) | tee ...

1
これはうまく機能します。:実際には、あなたは両方のstdoutとstderrと指示することができます( ... ) |& tee output.log
ノーム・マノス

13

あなたの質問を読んだとき、あなたは出力をログに記録したくありませんが、コマンドのシーケンス全体は、その場合、他の答えはあなたを助けません。

-xを指定してシェルスクリプトを呼び出し、すべてを出力します。

sh -x foo.sh

必要なファイルにログを記録します。

sh -x foo.sh >> /home/scripts/cron/logs


2
-xオプションの+1
Coc

10

bashでは、置くことができset -x、その後実行するすべてのコマンド(およびbash変数)を出力します。でオフにできますset +x

妄想的になりたい場合set -o errexitは、スクリプトを挿入できます。これは、あるコマンドがゼロ以外の終了コードを返した場合、スクリプトが失敗して停止することを意味します。

より良いログを取得したい場合tsは、moreutilsdebian / ubuntuパッケージをご覧ください。各行の前にタイムスタンプを付けて出力します。そのため、いつ事態が発生したかを確認できます。


1
「セット-e」と同じものでなければならない「-o ERREXIT設定」
Ajithアントニー

0

他の人が言ったことに続いて、セットマニュアルは良いリソースです。置いた:

#!/usr/bin/env bash
exec 1> command.log 2>&1
set -x

スクリプトの先頭で、続行し続けるかset -ex、エラーで終了するかどうかを確認します。


これはsshログとコマンドの正常な実行にどのように役立ちますか?
asktyagi

OPのダミースクリプトを使用してテストし、各コマンドとその結果(sshタイムアウト、誤ったドメインなど)を記録します。または、有効なsshアドレスの場合、リモートシェルにコマンドを記録します。sshログインに関する詳細情報が必要な場合、おそらくssh -vv
dragon951
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.