関数のすべてのコマンドをキャプチャ

関数のすべてのコマンドをキャプチャ

私は機能が読み取り専用と見なされる一連のスクリプトで作業しています。これらの関数は単純なコマンドのリストではありません。たとえば、ディレクトリを繰り返し、変更したり、他の関数を呼び出すこともできます。

func() {
    cd folder/
    run command1
    mkdir folder2/ ; cd folder2/
    run command2
}

私が望むものを示すために、次のようにスクリプトを変更できるとしばらく考えてみましょう。

func() {
    cd folder/
    string[0]="command1" ; run command1 |& tee out0.log ; result[0]="$?" ; finished_command_number 0
    mkdir folder2/ ; cd folder2/
    string[1]="command2" ; run command2 |& tee out1.log ; result[1]="$?" ; finished_command_number 1
}

したがって、パイプで接続することはできますが、使用または反復できないコマンドの場合は、cd文字列を保存し、標準出力(stderr)を保存し、終了コードを保存してから別のコマンドを実行したいと思います。ただし、これを追加することはできません。 func() を使用してスクリプトを呼び出すスクリプトで実行する必要があります。

コマンド後に呼び出し機能を別々に取得するには、関数をコピーしてスクリプトを使って実行してみましたが、関数にtrap foo debug伝播されないようです。一行ずつコピーするのはうまくいかないと思います。なぜなら、サブシェルコマンドではなく制御ステートメントなので、実際には分離できないからですcdloops

文字列が単にコマンド自体の関数である場合は、まだ便利です。

答え1

#!/bin/bash
# test.sh
post() {
        echo "post [$BASH_COMMAND] [$?]"
        echo "== $RANDOM =="
}
set -o functrace
trap post debug
func() {
        . check.sh
        tryme |& tee out.txt
}
func

出力は、ランダムにタグ付けされた行に基づいてフィルタリングできます。複数のプロセスでどれだけうまく機能するかを確認するには、これをさらにテストする必要がありますが、短いコマンドではうまく機能するようです。デバッグが最初に呼び出されたので、終了コードは1つのコマンドより遅れます。

#!/bin/bash
# check.sh
tryme() {
        echo "one"
        echo "two"
        mkdir -p hello
        cd hello/
        echo "three"
        false
        echo "four"
}

===

$ bash test.sh 
post [func] [0]
== 22542 ==
post [func] [0]
== 10758 ==
post [. check.sh] [0]
== 9115 ==
post [tryme 2>&1] [0]
== 11979 ==
post [tee out.txt] [0]
== 17814 ==
post [tryme 2>&1] [0]
== 22838 ==
post [echo "one"] [0]
== 5251 ==
one
post [echo "two"] [0]
== 18036 ==
two
post [mkdir -p hello] [0]
== 4247 ==
post [cd hello/] [0]
== 21611 ==
post [echo "three"] [0]
== 24685 ==
three
post [false] [0]
== 8557 ==
post [echo "four"] [1]
== 7565 ==
four

答え2

あなたの質問を正しく読んだら、方法を探しています。

  • 関数呼び出しに関係なく、stdoutとstderrの出力キャプチャ
  • 現在の作業ディレクトリを保存し、関数の実行中の変更を防ぎます。

これは非常に簡単に行うことができます。

#!/bin/bash
stdout=/path/to/output.std
stderr=/path/to/output.err

somefunc() {
    : Do things
}

( somefunc arg1 arg2 ) >> $stdout 2>> $stderr

サブシェルで関数を実行すると、作業ディレクトリの変更、通常どおり stdout および stderr への出力など、任意の操作を実行できます。サブシェルが終了すると、スクリプトの作業ディレクトリは変更されず、すべてのstdout出力とstderr出力がキャプチャされ、ログファイルにリダイレクトされます。

コマンドの終了コードをキャプチャするために配列(グローバルまたはその他)を追加するのは簡単です。

declare -a exitcodes
( exit 0 )
exitcodes+=( $? )
( exit 2 )
exitcodes+=( $? )
( exit 0 )
exitcodes+=( $? )

echo ${exitcodes[@]}

関連情報