回归:导出的 Bash 函数在经过另一个过程后丢失
Regression: Exported Bash function lost after going through another process
从 Ubuntu 14.04 迁移到 16.04 时,我注意到我的几个 Bash 脚本由于缺少导出函数而失败。我想知道这是否与 Shellshock bug 的修复有关,即使我只是 export -f
函数,而不依赖于 Bash- 内部函数表示。失败不会发生在直接 Bash subshell 中,只有在中间有另一个进程时才会发生。例如,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
我是不是做错了什么,或者这是一个错误?
Edit:@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
是罪魁祸首吗?!
TL;DR:已知 dash
问题;灰色区域,可能已修复;最好不要依赖 non-bash parent.
中的出口
这是由于dash 0.5.8的变化引起的; cp。 dash removes exported bash functions from the environment.
是否会修复此问题尚无共识。 POSIX 似乎允许删除无效的环境条目,其他(更晦涩)shells apparent 也这样做,但它会在各种应用程序中引起问题,特别是因为 /bin/sh
在 Ubuntu.
中符号链接到 dash
(因此默认为 shell)
我的个人用例是一些简短的实用程序函数,我已将其放入我的 ~/.profile
,并在一些 shell 脚本中引用。其中一个在自动启动的 Conky 守护程序中运行,并且那个错过了功能,因为自动启动是通过 dash
发生的。我可以解决这个问题。来自 Korn shell 的 FPATH
自动加载机制在 Bash 中也很好......
这并不理想,但您可以在 Dash 中定义您的函数:
$ foo() { echo "foobar"; }
$ dash -c "$(declare -f); foo"
foobar
从 Ubuntu 14.04 迁移到 16.04 时,我注意到我的几个 Bash 脚本由于缺少导出函数而失败。我想知道这是否与 Shellshock bug 的修复有关,即使我只是 export -f
函数,而不依赖于 Bash- 内部函数表示。失败不会发生在直接 Bash subshell 中,只有在中间有另一个进程时才会发生。例如,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
我是不是做错了什么,或者这是一个错误?
Edit:@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
是罪魁祸首吗?!
TL;DR:已知 dash
问题;灰色区域,可能已修复;最好不要依赖 non-bash parent.
这是由于dash 0.5.8的变化引起的; cp。 dash removes exported bash functions from the environment.
是否会修复此问题尚无共识。 POSIX 似乎允许删除无效的环境条目,其他(更晦涩)shells apparent 也这样做,但它会在各种应用程序中引起问题,特别是因为 /bin/sh
在 Ubuntu.
dash
(因此默认为 shell)
我的个人用例是一些简短的实用程序函数,我已将其放入我的 ~/.profile
,并在一些 shell 脚本中引用。其中一个在自动启动的 Conky 守护程序中运行,并且那个错过了功能,因为自动启动是通过 dash
发生的。我可以解决这个问题。来自 Korn shell 的 FPATH
自动加载机制在 Bash 中也很好......
这并不理想,但您可以在 Dash 中定义您的函数:
$ foo() { echo "foobar"; }
$ dash -c "$(declare -f); foo"
foobar