2017-02-22 9 views
5

私は非常に多くの外部コマンド(git clonewgetapt-getなど)を標準出力に多く出力するかなり長いbashスクリプトを持っています。シェルスクリプト内でログの冗長性を管理するにはどうすればよいですか?

スクリプトにいくつかの冗長オプションを設定して、外部コマンド、要約版(たとえば、 "依存関係のインストール..."、 "コンパイル..."など)からすべてを出力するようにしたいまったく。しかし、すべてのコードを乱雑にすることなく、どうすればいいですか?

私はこれに対して可能な解決策を考えました。一つは、外部コマンドを実行し、最初に設定されたオプションに応じて標準出力に必要なものを出力するラッパー関数を作成することです。これは実装が簡単なようですが、コードに余分な混乱を与えることになります。

もう1つの解決策は、すべての出力をいくつかの外部ファイルに送信し、スクリプトの開始時に引数を解析するときに、冗長性が指定されている場合はtail -fをそのファイルで実行することです。これは実装が非常に簡単ですが、私にとってはかなりハッキーなようですが、私はそのパフォーマンスの影響について心配しています。

どちらが優れていますか?私は他のソリューションにもオープンしています。

+1

あなたは '-x設定使用して考えがあります'?スクリプトの一番上でこのコマンドを呼び出すと、それ以降のすべてのコマンドがエコーされます。あなたは 'set + x'でそれをオフにすることができます。 –

+1

さらに、コマンドが0以外のステータスで終了したときにスクリプトを中止するには、 'set -e'を使用することもできます。 –

+0

いいえ、それは私が必要なものではありません。私はどのコマンドを実行しているのか知っています。私は、スクリプトがいくつかのオプションに応じて出力するすべてのものを印刷するようにしたいだけです。それは実際のコードよりもユーザーのものです。 – Ocab19

答えて

4

あなたの質問(ラッパー関数)で最もクリーンなアイデアはすでにありますが、それは面倒であると思われるようです。私はあなたが再考することをお勧めします。

#!/bin/bash 

# Argument 1 : Logging level for that command 
# Arguments 2... : Command to execute 
# Output suppressed if command level >= current logging level 
log() 
{ 
if 
    (($1 >= logging_level)) 
then 
    "${@:2}" >/dev/null 2>&1 
else 
    "${@:2}" 
fi 
} 

logging_level=2 

log 1 command1 and its args 
log 2 command2 and its args 
log 3 command4 and its args 

(したい場合は、ファイルディスクリプタで)あなたが必要なリダイレクトを手配することができますに処理される:それは(ちょうどあなたの基本的なアイデアを与えるために、必ずしも本格的なソリューション)は、次のようになります。スクリプトの残りの部分は、選択されたロギングレベルに応じて、リダイレクトや条件がなくても読み込み可能な状態になります。もう少しフレッドのアイデア@上の改善

+0

私が実行するすべてのコマンドに「ログ」を追加するのが最もクリーンな解決策であるかどうかはまだ分かりません。私はこの方法で他の人がコードを読むのに苦労することを心配しています。しかし、より良い方法がないようですので、私は最後にこれと一緒に行くつもりだと思います。 – Ocab19

+0

@ Ocab19 - 私の[回答](http://stackoverflow.com)の 'log_debug_file'と' log_verbose_file'関数を見てください。/a/42426680/6862601)。これらを使用すると、「log 1」などの構造体によって引き起こされるクラッタ/可読性の損失を排除することができ、出力を抑制する必要があるすべてのコマンドに接頭辞を付けます。しかし、出力をリダイレクトしてからログ機能を呼び出すのも面倒です。 – codeforester

1

解決策1. 追加のファイル記述子の使用を検討してください。 必要なファイル記述子をSTDOUTまたは/ dev/nullにリダイレクトします。 スクリプト内のすべてのステートメントの出力を、その重要度に対応するファイル記述子にリダイレクトします。 https://unix.stackexchange.com/a/218355をご覧ください。

1

ソリューション二つのパラメータ、このような何かを持つヘルパースクリプトに、スクリプト内のすべてのステートメントの2

セット$のrequired_verbosityとパイプSTDOUT:

声明| logger actual_verbosity $ required_verbosity

loggerスクリプトでは、$ actual_verbosity> = $ required_verbosityの場合、STDOUTをSTDOUT(またはログファイル)にエコーします。

4

、私たちはこのように小さいのロギングライブラリーを構築することができ:

declare -A _log_levels=([FATAL]=0 [ERROR]=1 [WARN]=2 [INFO]=3 [DEBUG]=4 [VERBOSE]=5) 
declare -i _log_level=3 
set_log_level() { 
    level="${1:-INFO}" 
    _log_level="${_log_levels[$level]}" 
} 

log_execute() { 
    level=${1:-INFO} 
    if (($1 >= ${_log_levels[$level]})); then 
    "${@:2}" >/dev/null 
    else 
    "${@:2}" 
    fi 
} 

log_fatal() { ((_log_level >= ${_log_levels[FATAL]})) && echo "$(date) FATAL $*"; } 
log_error() { ((_log_level >= ${_log_levels[ERROR]})) && echo "$(date) ERROR $*"; } 
log_info() { ((_log_level >= ${_log_levels[INFO]})) && echo "$(date) INFO $*"; } 
log_debug() { ((_log_level >= ${_log_levels[DEBUG]})) && echo "$(date) DEBUG $*"; } 
log_verbose() { ((_log_level >= ${_log_levels[VERBOSE]})) && echo "$(date) VERBOSE $*"; } 

# functions for logging command output 
log_debug_file() { ((_log_level >= ${_log_levels[DEBUG]})) && [[ -f $1 ]] && echo "=== command output start ===" && cat "$1" && echo "=== command output end ==="; } 
log_verbose_file() { ((_log_level >= ${_log_levels[VERBOSE]})) && [[ -f $1 ]] && echo "=== command output start ===" && cat "$1" && echo "=== command output end ==="; } 

はのは、上記のソースはlogging_libと呼ばれるライブラリファイルであるとしましょう。SH、我々は通常のシェルスクリプトでこのようにそれを使用することができます:

#!/bin/bash 

source /path/to/lib/logging_lib.sh 

set_log_level DEBUG 

log_info "Starting the script..." 

# method 1 of controlling a command's output based on log level 
log_execute INFO date 

# method 2 of controlling the output based on log level 
date &> date.out 
log_debug_file date.out 

log_debug "This is a debug statement" 
... 
log_error "This is an error" 
... 
log_fatal "This is a fatal error" 
... 
log_verbose "This is a verbose log!" 

は、この出力になります:

Fri Feb 24 06:48:18 UTC 2017 INFO Starting the script... 
Fri Feb 24 06:48:18 UTC 2017 
=== command output start === 
Fri Feb 24 06:48:18 UTC 2017 
=== command output end === 
Fri Feb 24 06:48:18 UTC 2017 DEBUG This is a debug statement 
Fri Feb 24 06:48:18 UTC 2017 ERROR This is an error 
Fri Feb 24 06:48:18 UTC 2017 FATAL This is a fatal error 

我々が見ることができるように、log_verboseは、ログレベル以来、任意の出力を生成しませんでしたVERBOSEの1レベル下のDEBUGにあります。しかし、log_debug_file date.outは出力を生成したので、ログレベルは> = INFOのDEBUGに設定されているので、log_execute INFOを出力しました。所定の位置にこれらと

git_wrapper() { 
    # run git command and print the output based on log level 
} 

、スクリプトが判断できる引数--log-level levelを取るように強化することができます。

ベースとして、これを使用して、我々はまた、我々はさらに多くの微調整が必​​要な場合は、コマンドのラッパーを書くことができますそれを実行する必要があるログの冗長性。


誰でもいくつかの変数が有力で命名されている理由について興味ある場合は、上記のコードでアンダースコア、この記事を参照してください。

+0

@ charlesduffyさんの考えをこのページで入手することは素晴らしいことです。 – codeforester

関連する問題