シェルスクリプトを使用したロギング - STDERRをキャプチャしてタイムスタンプでロギング

シェルスクリプトを使用したロギング - STDERRをキャプチャしてタイムスタンプでロギング

解決済み:

数ヶ月前、私はログインシェルスクリプトに興味がありました。

最初のアイデアは、次のように関数を手動で記録することです。

add2log() {
    printf "$(date)\tINFO\t%s\t%s\n" "$1" "$2" >>"$logPATH"
}

しかし、自動化したいです。たとえば、STDERRが自動的に記録されます。

久しぶりに満足のいく答えを見つけて、いよいよ共有する時間を持つようになりました。


これで、各シェルスクリプトに対して「main.sh」を使用して、ロギング機能と構成(ログと構成ファイルの設定)をアーカイブします。次のようになります。

#!/bin/bash

###################################################################
# MY HEADERS
###################################################################


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~Global vars

mainScriptNAME=$(basename "$0")
mainScriptNAME="${mainScriptNAME%.*}"
mainScriptDIR=$(dirname "$0")
version="v0.0"
scriptsDIR="$mainScriptDIR/SCRIPTS"
addonsDIR="$mainScriptDIR/ADDONS"


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~LOGGER FUNCS

manualLogger() {

    # $1=PRIORITY $2=FUNCNAME $3=message
    printf "$(date)\t%s\t%s()\t%s\n" "$1" "$2" "$3" >>"$logFilePATH"
}

stdoutLogger() {

    # $1=message
    printf "$(date)\tSTDOUT\t%s\n" "$1" >>"$logFilePATH"
}

stderrLogger() {

    # $1=message
    printf "$(date)\tSTDERR\t%s\n" "$1" >>"$logFilePATH"
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~LOG & CONF

createLog() {
    # code to set and touch logFilePATH & confFilePATH
    manualLogger "INFO" "${FUNCNAME[0]}" "Log file created."
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~MAIN

#
createLog

#run scripts
{

    #
    source "$scriptsDIR/file1.sh"
    doSomthing1
    doSomthing2

    #
    source "$scriptsDIR/file2.sh"
    anotherFunction1
    anotherFunction2

    ...


} 2> >(while read -r line; do stderrLogger "$line"; done) \
1> >(while read -r line; do stdoutLogger "$line"; done) 


言い換えれば:

  • 私が実行したいすべてのスクリプト/関数は./SCRIPTSフォルダの別のファイルにあります(私のmain.shはほぼ常に同じです)。
  • STDOUTとSTDERRをキャプチャするために、これらすべてのスクリプトを{...}グループに入れます。
  • 対応するSTDOUTとSTDERRは、対応するロガー機能にリダイレクトされます。

ログファイルは次のとおりです(手動ロガー、STDOUTロガー、およびSTDERRロガーの例)。

Lun 23 mai 2022 12:20:42 CEST   INFO    createLog() Log file created.
Lun 23 mai 2022 12:20:42 CEST   STDOUT  Some standard output
Lun 23 mai 2022 12:20:42 CEST   STDERR  ls: sadsdasd: No such file or directory

チームはすべての出力をログに収集します。代わりにリダイレクト2> >(while read ...と。1> >(while read ...たとえば、doSomthing1STDOUTとSTDERRは記録されますが、doSomthing2STDERRのみがリダイレクトされます。

答え1

表面的には、ちょうどデバッグステートメントを追加したようです。ここで「重い」とはどういう意味ですか? Bashスクリプト(またはその問題に対する他のプログラミング言語)で何かを再エコーする必要がある場合は、インタプリタに渡したことを知らせるechoステートメントが必要です。

スクリプト(またはコードスニペット)の特定のポイントで操作を実行したい場合は、コマンドの作成に代わる方法はありません。

IOリダイレクトを使用してさまざまなトリックを取得できますが、目的の効果を得るには、最初と最後に1つずつ2つのステートメントが必要です。

完全に文書化されたスクリプトが必要な場合はを参照してくださいset -x。スクリプトの特定の機能のみを記録するには、set -xsuhshellでその機能を使用してください。

(set -x; func1)

答え2

専用ディレクトリにフラグファイルを使用します。

foo.bash:
  
#!/bin/bash
[[ -f $HOME/.local/debug/foo.debug ]] && \
  source $HOME/.local/debug/foo.debug
...

foo.debugのようなものを含め、私の好きなものをdebug_foofunction=1すべてファイルに入れることができますfoo。簡単に言えば、すべてのデバッグコードはオフになります。に変更すると、他のデバッグ設定(たとえば)を維持しながらデバッグをオフにできます。foofunctiondebug_foofunction
rm $HOME/.local/debug/foo.debugdebug_foofunction=0foofunctiondebug_foootherfunction=1

man bash" trap"組み込みについて読んでください。

実際の解決策は複雑なスクリプトを書かないことです。問題セットに合ったプログラミング言語を使用してください。

必ずスクリプトをhttps://shellcheck.net構文チェッカーに貼り付けるか、shellcheckローカルにインストールしてください。使用をshellcheck開発プロセスの一部として作成します。

関連情報