当foo
在后台运行时,BASHPID
of foo
( ) 在vi bashpid_of_foo
a 体内不可用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
将进行四次调用并生成四行输出。正如您所看到的,只有三个唯一的bashpid
数字,每个数字都来自一次foo
调用。
另一种从 传递到 的方法$bashpid
显然foo
是bar
将其作为命令行参数传递并使用local bashpid="$1"
inbar
或类似的东西接收它,但你说你不想这样做。
答案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
shell 脚本来改变这一点:
$ 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
正确导出到子 shell:
$ ./subby.bash
foo: 5014
foo: blipblop
out_1: 5014
out_2: from bar_1: 5014
out_n: blipblop
我们需要export
在这里使用 an 而不仅仅是 a,local
因为否则环境变量将不会导出到任何子级。这里的子 shell 是子 shell。
$ help export
...
Marks each NAME for automatic export to the environment of subsequently
executed commands. If VALUE is supplied, assign VALUE before exporting.