Err*_*ror 15 shell process environment-variables
正如标题所说,我希望能够从子进程(通常是脚本)更改父进程(特别是 shell)中的环境变量。从/dev/pts/id
试图key=value
从子脚本导出的伪终端,如果可能的话,导出的变量必须以某种方式传递给父脚本?
echoingcmd > /proc/$$/fd/0
不执行cmd
,只在 shell 终端模拟器中查看命令,当然在 subshell 中使用$(cmd)
而不是cmd
执行,并且export
不向父进程添加变量。
我更喜欢所有的工作都在孩子这边完成。
我在评论中被问到,我想要实现什么?这是一个普遍的问题,我正在尝试使用肯定的答案从(父)shell 执行(生成)的脚本中传递变量,以便用户可以从添加的变量中受益,而无需任何进一步的工作。比如我想用脚本安装一个应用程序,应用程序目录应该添加到父shell路径中。
您可以通过文件或命名管道将变量值从子进程传输到其父进程。
这是一个理论上最简单的例子:
子进程:
echo ${variable} >/tmp/file
Run Code Online (Sandbox Code Playgroud)
父进程:
read variable </tmp/file
Run Code Online (Sandbox Code Playgroud)
如果父进程不期待并与之合作,这将非常棘手。在这种情况下,请参阅更改正在运行的进程的环境 以及是否有办法更改另一个进程的环境变量?
如果父进程期望值并配合传输,简单的方法是使用命令替换:
导出VAR =$( cmd )
这假设变量的值是程序想要写入的唯一内容。如果子进程需要能够写入屏幕(特别是父进程的标准输出),我们可以通过将父进程的文件描述符 1 隐藏在另一个文件描述符中来实现:
exec 3>&1 # Copy our file descriptor 1 into file descriptor 3.
# child_prog will be invoked with file descriptor 1 pointing to a pipe
# for the command substitution, but all other file descriptors intact.
# Specifically, fd3 will point to our stdout.
export var=$(child_prog)
exec 3>&- # (Optionally) close fd3 as cleanup.
Run Code Online (Sandbox Code Playgroud)
现在,如果child_prog
简短而简单,最简单的方法可能是将变量的值写入文件描述符 1 并使用文件描述符 3 ( cmd?>&3
) 作为标准输出。如果它很大和/或复杂,您将需要执行以下操作:
exec 5>&1 # Redirect fd1 (the command substitution pipe) to fd5.
exec 1>&3 # Set our fd1 (stdout) to our parent's stdout (which was passed in as fd3).
exec 3>&- # Close fd3; it’s no longer needed.
Run Code Online (Sandbox Code Playgroud)
然后正常使用stdout,并>&5
用于写入值。
到目前为止,我一直假设您只想将一个值传递给一个变量。如果您有多个值,用一个字符(或字符串)分隔它们很简单,保证不会出现在任何值中。如果我们选择@@
,那么父母可以说
exec 3>&1
temp=$(child_prog)
exec 3>&-
export var1="${temp%%@@*}"
rest="${temp#*@@}"
export var2="${rest%%@@*}"
export var3="${rest#*@@}"
Run Code Online (Sandbox Code Playgroud)
和孩子可以说
。echo "value1@@value2@@value3"?>&5
如果很难找到保证不会出现在任何值中的打印字符字符串,则可以使用换行符。只需@@
在上述命令中更改为换行符:
家长:
export var1="${temp%%
*}"
rest="${temp#*
}"
export var2="${rest%%
*}"
export var3="${rest#*
}"
Run Code Online (Sandbox Code Playgroud)
孩子:
printf "%s\n" " value1 " " value2 " " value3 "?>&5
另一种变化是让孩子将命令
而不是值反馈给父母。如果父进程说.?<(child_prog)
,它运行子进程,捕获输出并执行它。然后孩子可以做
printf "export var1=' value1 '\nexport var2=' value2 ' var3=\" value3 \"\n" >&5
(我用value3
包含撇号的a 测试了这个,所以我不得不用 引用它\"…\"
,我把它留在那里只是为了说明替代语法。)
此技术的一个特点是您可以添加要导出的变量,而无需更改父级中的代码。
这种方法要求父进程运行 bash(或者可能是其他高级 shell 之一?),因为 POSIX 不支持.<(cmd)