从 Ubuntu 14.04 迁移到 16.04 时,我注意到我的几个 Bash 脚本由于缺少导出的函数而失败。我想知道这是否与Shellshock 错误的修复有关,即使我只是export -f
函数,而不依赖 Bash 内部函数表示。失败不会发生在直接的 Bash 子外壳中,只有在中间有另一个进程时才会发生。例如,Bash 调用 awk / Perl / Vim 调用另一个 Bash。下面是一个 Perl 的例子:
好的
$ foo() { echo "foobar"; }
$ export -f foo
$ export -f; foo
foo ()
{
echo "foobar"
}
declare -fx foo
foobar
$ bash -c "export -f; foo"
foo ()
{
echo "foobar"
}
declare -fx foo
foobar
$ perl -e 'system("bash -c \"export -f; foo\"")'
foo ()
{
echo "foobar"
}
declare -fx foo
foobar
$ echo $BASH_VERSION
4.3.11(1)-release
坏的
$ foo() { echo "foobar"; }
$ export -f foo
$ export -f; foo
foo ()
{
echo "foobar"
}
declare -fx foo
foobar
$ bash -c "export -f; foo"
foo ()
{
echo "foobar"
}
declare -fx foo
foobar
$ perl -e 'system("bash -c \"export -f; foo\"")'
bash: foo: command not found
$ echo $BASH_VERSION
4.3.42(1)-release
我做错了什么,还是这是一个错误?
编辑:@chepner 指出 Bash 使用特殊命名的 shell 标识符来存储函数。当通过dash
(0.5.8-2.1ubuntu2,使用 0.5.7-4ubuntu1)时,这些标识符被删除。与ksh
,他们保持活力。我检查过
$ dash
$ sudo strings /proc/$$/environ | grep foo # Still passed from Bash to Dash
BASH_FUNC_foo%%=() { echo "foobar"
$ bash
$ sudo strings /proc/$$/environ | grep foo # But went missing from Dash to Bash
$ exit
$ exit
$ ksh
$ sudo strings /proc/$$/environ | grep foo
BASH_FUNC_foo%%=() { echo "foobar"
$ bash
$ sudo strings /proc/$$/environ | grep foo # Kept from Ksh to Bash
BASH_FUNC_foo%%=() { echo "foobar"
同样,Vim 的行为可以通过:set shell=/bin/bash
/:set shell=/bin/ksh
所以,是dash
罪魁祸首吗?!