F内のサブシェルから呼び出されるコマンドのバックグラウンド関数FのPID

F内のサブシェルから呼び出されるコマンドのバックグラウンド関数FのPID

fooバックグラウンドで実行すると()BASHPIDはコマンド置換関数を介して呼び出されるため、vi本体内では使用できません。foobashpid_of_foobar_1bar_n$BASHPIDbash

function foo() {
    local bashpid_of_foo=$BASHPID
    local output

    # desired to be shared by all Command Substitutions
    # in the body of this function.
    local log=/path/to/log.$BASHPID

    ... >> $log

    output=$(bar_1 ...)
      ...
    output=$(bar_n ...)
}

function bar_1() {
   # log only specific (and NOT all) messages
   # to the shared log file of the invoking thread.
    ... >> /path/to/log.$BASHPID
}

foo &
foo &

質問:bashpid_of_foo一時的な環境変数や外部ディスクファイルを介して渡さずに上記の制限を解決するエレガントな方法はありますか?

渡すエレガントbar_*私の言葉は、bashが提供する機能にのみ依存して、関数のインタフェースと本文をきれいに保つことができるということです。 (たとえば、関数BASHPIDですbash。)

BASHPIDこのような値をオーバーライドしようとすると

out_1=$(BASHPID=$BASHPID bar_1 ...)

BASHPID...読み取り専用変数について(正確に)文句を言います。

編集する:(1)上記の定義を追加しましたbar_1。 (2)fooバックグラウンドで2番目の通貨を追加しました。foo共通ファイルに書き込むと内容が壊れる可能性があるため、各呼び出しごとに独自のログファイルを保持する必要があります。

メモ:ランタイムコンテキストでどのログが発生しても、特定のログファイルfooに移動したいと思います。foo/path/to/log.$BASHPID いいえそのログファイルの名前を渡すことも、バックグラウンドで複数のインスタンスを実行することもできますfoofoo

答え1

#!/bin/bash

bar () {
    # bashpid is set in our environment from the calling function
    printf 'bar BASHPID = %d, bar bashpid = %d\n' "$BASHPID" "$bashpid"

    # in your case, you would have...

    local logfile="/some/path/to/log.$bashpid"

    # etc.
}

foo () {
    local bashpid="$BASHPID"
    local message

    local logfile="/some/path/to/log.$BASHPID"

    message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %s\n' "$message"
    message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %s\n' "$message"
    message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %s\n' "$message"
    message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %s\n' "$message"
}

foo &
foo &
foo &

wait

例を実行してください:

$ bash script.sh
Message from bar: bar BASHPID = 71979, bar bashpid = 18461
Message from bar: bar BASHPID = 7420, bar bashpid = 71036
Message from bar: bar BASHPID = 6109, bar bashpid = 18461
Message from bar: bar BASHPID = 27868, bar bashpid = 71036
Message from bar: bar BASHPID = 44547, bar bashpid = 60086
Message from bar: bar BASHPID = 69310, bar bashpid = 71036
Message from bar: bar BASHPID = 37649, bar bashpid = 60086
Message from bar: bar BASHPID = 15999, bar bashpid = 71036
Message from bar: bar BASHPID = 81520, bar bashpid = 18461
Message from bar: bar BASHPID = 92568, bar bashpid = 60086
Message from bar: bar BASHPID = 72438, bar bashpid = 18461
Message from bar: bar BASHPID = 15094, bar bashpid = 60086

fooスクリプトの主要部分の各呼び出しに対してbar4回の呼び出しが行われ、4行の出力が生成されます。ご覧のとおり、bashpidそれぞれ単一のfoo通貨からの固有番号は3つだけです。

from toを渡すもう一つの方法は$bashpid明らかにコマンドライン引数として渡してinなどを使って受け取ることですが、そうしたくないと言われました。foobarlocal bashpid="$1"bar

答え2

メモ: 一般的な質問に関しては、$BASHPIDこれは読み取り専用なので操作できません。これは意図的に設計されています。

私の一般的なアドバイスは、このようなBashスクリプトがある程度複雑になったら、Python、Rubyなどに移動する必要があるということです。


あなたの模範

私はあなたの問題が何であるかを理解していないようです。これは私にとって効果的でした。

$ cat subby.bash
#!/bin/bash

function foo() {
    local bashpid_of_foo=$BASHPID
    local output=blipblop

    echo "foo: $bashpid_of_foo"
    echo "foo: $output"
    out_1=$(echo $bashpid_of_foo)
    out_n=$(echo $output)
    echo "out_1: $out_1"
    echo "out_n: $out_n"
}

foo &


$ ./subby.bash
foo: 4900
foo: blipblop
out_1: 4900
out_n: blipblop

輸出を増やす

bar_1シェルスクリプトを作成してそれを変更した場合:

$ cat bar_1
#!/bin/bash

echo "from bar_1: $bashpid_of_foo"

元のスクリプトを次のように変更します。

#!/bin/bash

function foo() {
    export bashpid_of_foo=$BASHPID
    local output=blipblop

    echo "foo: $bashpid_of_foo"
    echo "foo: $output"
    out_1=$(echo $bashpid_of_foo)
    out_2=$(./bar_1)
    out_n=$(echo $output)
    echo "out_1: $out_1"
    echo "out_2: $out_2"
    echo "out_n: $out_n"
}

foo &

$bashpid_of_fooサブシェルに正しくエクスポートされたことを確認できます。

$ ./subby.bash
foo: 5014
foo: blipblop
out_1: 5014
out_2: from bar_1: 5014
out_n: blipblop

exportaではなくここを使用する必要があります。localそうしないと、環境変数が子としてエクスポートされないためです。ここで、サブシェルはサブシェルです。

$ help export
...
   Marks each NAME for automatic export to the environment of subsequently
    executed commands.  If VALUE is supplied, assign VALUE before exporting.

関連情報