ラッパー関数を使用して処理するためにパイプラインコマンドをグループ化する方法

ラッパー関数を使用して処理するためにパイプラインコマンドをグループ化する方法

私はbashシェルのロギング関数を自分で書こうとしています。私の目標は、コマンドの前にプレフィックスを付け、コマンドのstdoutとstderrを日付ログファイルに渡す機能を持つことです。現在私は以下を持っています:

logme()
{
    FULL_COMMAND=$@

    for EXE in ${FULL_COMMAND}
    do
        case $EXE in
            nohup) continue;;
            time) continue;;
        esac
        break
    done

    mkdir -p logs
    LOGNAME=$(basename ${EXE})_$(date +%Y-%m-%d_%H:%M:%S)

    echo $FULL_COMMAND > logs/${LOGNAME}.e.log
    echo '============' >> logs/${LOGNAME}.e.log
    $FULL_COMMAND > logs/${LOGNAME}.o.log 2>> logs/${LOGNAME}.e.log
}

これは単純なケースで動作するようです。ランニング:

$ touch file1.txt
$ touch file2.txt
$ touch file3.txt

$ logme ls -lh

2つの日付ファイルを含むログディレクトリを作成します。

$ more logs/ls_2017-05-08_16\:05\:36.e.log 
ls -lh
============

$ more logs/ls_2017-05-08_16\:05\:36.o.log 
total 6.5K
-rw-r--r-- 1 aholman compbio  0 May  8 16:05 file1.txt
-rw-r--r-- 1 aholman compbio  0 May  8 16:05 file2.txt
-rw-r--r-- 1 aholman compbio  0 May  8 16:05 file3.txt
drwxr-xr-x 2 aholman compbio 92 May  8 16:05 logs

ただし、コマンドにパイプを追加すると、必要に応じて機能しません。ロギングは最初のコマンドにグループ化されて表示され、logmeの出力がパイプされます。もちろん、logmeの目的はファイルに送信することであるため、出力はありません。

$ logme ls -lh | grep -v file2
$ more logs/ls_2017-05-08_16\:12\:15.e.log 
ls -lh
============

$ more logs/ls_2017-05-08_16\:12\:15.o.log 
total 6.5K
-rw-r--r-- 1 aholman compbio  0 May  8 16:05 file1.txt
-rw-r--r-- 1 aholman compbio  0 May  8 16:05 file2.txt
-rw-r--r-- 1 aholman compbio  0 May  8 16:05 file3.txt
drwxr-xr-x 2 aholman compbio 92 May  8 16:12 logs

コマンド全体がlogmeによって処理されるようにコマンド全体をグループ化する良い方法はありますか?

答え1

スクリプトがコマンドラインを表示する前に、シェルはこれを処理しています。処理後に残ったもの(パイプ前のコマンド)のみ渡します。これらの処理をバイパスするには、コマンド全体を引用する必要があります。

logme 'ls -lh | grep -v file2'

ところで、新しい質問がありました。コマンドは文字列にあるため、直接実行することはできません。 1つの方法はevalを使用することです。

eval "$FULL_COMMAND" > logs/${LOGNAME}.o.log 2>> logs/${LOGNAME}.e.log

ただし、evalは簡単に悪用される可能性があるため、慎重に使用する必要があります。http://mywiki.wooledge.org/BashFAQ/048

関連情報