为什么bash甚至解析/运行环境变量中的内容?


9

bash中的shellshock错误通过环境变量起作用。老实说,我对这样的功能感到惊讶:

“通过环境变量传递函数定义”

因此,这个问题虽然可能没有完善地表述,但却是要求举个例子或一个案例,说明是否必须具有此功能?

奖金。其他shell zsh,破折号等也具有此功能吗?


它使用env vars传递函数定义。“为什么不简单地使环境变量保持可用/可访问状态?”是什么意思??
Anthon

@Anthon感谢您的评论。也许我应该更清楚并重新措辞。出于什么原因,必须能够通过env vars传递函数定义?
humanityANDpeace

1
我不确定100%,但是我认为这是GNU parallel调用多个bash实例时获取函数定义的方式。如果不是这样,则必须将这些内容写入文件中,每个被调用的实例都将读取该文件,然后您必须处理诸如何时可以删除该文件的问题。
Anthon 2014年

2
这个线程有一些历史。导出的函数虽然很疯狂。如果您希望新的Shell继承旧的Shell可执行命令,则您.dot将获得与旧Shell相同的文件。多数民众赞成在这样做的过程- 是有道理的-或者您在execing 时将新外壳文件作为输入提供。一旦它被读入,文件无论如何都会被内核缓存。
mikeserv

@mikeserv我是否正确理解,shellshock的很大一部分与该功能有关,反正不是那么重要?
humanityANDpeace

Answers:


4

当一个脚本调用另一个脚本时,可以导出父脚本的变量,然后在子脚本中将其可见。导出函数是一个明显的概括:从父级导出函数,使其在子级中可见。

环境是进程可以将任意数据传递给其子级的唯一便捷方式。数据必须编组为不包含空字节的字符串,这对于shell函数而言并不困难。还有其他可能的方法,例如通过文件描述符传递共享内存块或临时文件,但是这些方法可能会导致中间程序出现问题,这些中间程序不知道如何处理或将其关闭。程序希望在包含不知道或不在乎的变量的环境中运行,因此它们不会被覆盖或擦除。

选择使用函数名称作为环境变量的名称是一种奇怪的选择。一方面,这意味着导出的变量与同名的导出函数发生冲突。

导出的功能是旧功能。在SVR2的Bourne外壳添加了功能,并在同年(1984)发布的Version 8外壳中导出了功能。在该Shell中,变量和函数使用相同的名称空间。我不知道函数导出的工作方式。该传家宝外壳是基于其具有的功能,但不会将它们导出一个Bourne变种。

ATT ksh应该支持导出功能,但是从ksh93u开始,我看不到它的来源或正在使用它。

env -i /usr/bin/ksh -c 'f=variable; f () { echo function; }; typeset -fx f; /usr/bin/env; ksh -c f'
_=*25182*/usr/bin/env
PWD=/home/gilles
SHLVL=1
A__z="*SHLVL
ksh: f: not found

Ksh的公共域克隆(pdksh,mksh),破折号和zsh不支持导出功能。


1
谢谢!因此,在没有导出功能的情况下,功能功能丧失了,但是诸如dash,zsh和pdksh等一些外壳缺少这种功能,我读对了吗?
humanityANDpeace

但是,当我在bash中导出函数时,它会进入类似的变量中BASH_FUNC_f%%=() { echo hi }。bash为什么会解析其他环境变量?BASH_FUNC_g%%当我只打电话时,为什么还要解析f?(显然,在shellshock之前,仅调用了环境变量fg-但我仍然想知道g如果我从未g在脚本中调用过,为什么要解析该变量)
变态的

@Met它必须查看所有环境变量,以找出哪些是函数定义。它可以记住这一事实,并避免在第一次需要时就解析函数的代码,但这将带来额外的复杂性,而带来的收益却很小。仅拥有一种类型的函数而不是两种类型(“正常函数”和“需要一点解析的环境变量中的函数”)会更容易。
吉尔斯(Gilles)'所以

不清楚。我建议,当我运行名为的东西时f,(1)检查名为的shell函数f,(2)检查名为的环境变量f,然后尝试解析它,(3)检查每个PATH可执行文件的组件称为f。在shell启动时,如何将每个环境变量解析为shell代码,看起来似乎不太复杂?
变形的

@Metamorphic您建议添加另一个必须在每个命令上执行的步骤。在定义或取消定义函数时,还必须添加另一步骤(之后unset -f foo,bash foo不再在环境中寻找函数定义),在列出函数时(declare -f除了读取所有环境变量之外,您还应如何处理?) ,还有其他我没想到的。您的设计似乎更容易,因为您省去了大部分设计。相比之下,在启动时执行所有操作仅需一段代码,然后一切正常。
吉尔(Gilles)'所以
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.