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백그라운드에서 두 번째 통화를 추가했습니다. foo공통 파일에 쓰면 내용이 깨질 수 있으므로 각 호출마다 자체 로그 파일을 유지해야 합니다.

노트:런타임 컨텍스트에서 어떤 로깅이 발생하더라도 특정 로그 파일 foo로 이동하고 싶습니다 .foo/path/to/log.$BASHPID 아니요해당 로그 파일의 이름을 전달하거나 백그라운드에서 여러 인스턴스를 실행할 수도 있습니다 foo.foo

답변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.

관련 정보