foo
백그라운드에서 실행할 때 () BASHPID
는 명령 대체 함수를 통해 호출되기 때문에 vi 본문 내에서 사용할 수 없습니다 .foo
bashpid_of_foo
bar_1
bar_n
$BASHPID
bash
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
스크립트 주요 부분의 각 호출에 대해 bar
4번의 호출이 이루어지고 4줄의 출력이 생성됩니다. 보시다시피, bashpid
각각 단일 foo
통화에서 나오는 고유 번호는 3개뿐입니다.
from to를 전달하는 또 다른 방법 은 $bashpid
분명히 명령줄 인수로 전달하고 in 등을 사용하여 수신하는 것인데, 그렇게 하고 싶지 않다고 하셨습니다.foo
bar
local 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
export
a가 아닌 여기를 사용해야 합니다. local
그렇지 않으면 환경 변수가 하위 항목으로 내보내지지 않기 때문입니다. 여기서 서브쉘은 서브쉘입니다.
$ help export
...
Marks each NAME for automatic export to the environment of subsequently
executed commands. If VALUE is supplied, assign VALUE before exporting.