正如标题所示,我希望能够从子进程(通常是脚本)更改父进程(特别是 shell)中的环境变量。从伪终端/dev/pts/id
尝试key=value
从子脚本导出,因此导出的变量必须以某种方式传递给父级(如果可能的话)?
echoingcmd > /proc/$$/fd/0
不执行cmd
,仅在 shell 终端模拟器中查看命令,当然使用$(cmd)
而不是cmd
在子 shell 中执行,并且export
不向父进程添加变量。
我更喜欢所有的工作都在子端完成。
有人在评论中问我,我想实现什么目标?这是一个一般性问题,我试图使用肯定的答案来传递由(父)shell 执行(生成)的脚本中的变量,以便用户可以从添加的变量中受益,而无需任何进一步的工作。例如,我想让一个脚本安装一个应用程序,并且应用程序目录应该添加到父shell路径中。
答案1
答案2
您可以通过文件或命名管道将变量值从子进程传输到其父进程。
这是一个理论上最简单的例子:
子进程:
echo ${variable} >/tmp/file
父进程:
read variable </tmp/file
答案3
如果父进程不期待并与它合作,这将非常棘手。在这种情况下,请参阅改变正在运行的进程的环境 和有没有办法改变另一个进程的环境变量?
如果父进程需要该值并配合传输,简单的方法是使用命令替换:
出口VAR=$(指令)
这假设变量的值为仅有的程序想要写的东西。如果子进程需要能够写入屏幕(特别是父进程的标准输出),我们可以通过将父进程的文件描述符 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.
现在,如果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.
然后正常使用stdout,并用于>&5
写入值。
到目前为止,我一直假设您只想将一个值传递给一个变量。如果您有多个值,则只需使用保证不会出现在任何值中的字符(或字符串)来分隔它们即可。如果我们选择@@
,那么家长可以说
exec 3>&1
temp=$(child_prog)
exec 3>&-
export var1="${temp%%@@*}"
rest="${temp#*@@}"
export var2="${rest%%@@*}"
export var3="${rest#*@@}"
而且孩子可以说 。echo "value1@@value2@@value3" >&5
如果很难找到保证不会出现在任何值中的打印字符字符串,则可以使用换行符。只需将@@
上述命令中更改为换行符即可:
家长:
export var1="${temp%%
*}"
rest="${temp#*
}"
export var2="${rest%%
*}"
export var3="${rest#*
}"
孩子:
printf "%s\n" "值1” “值2” “值3>&5
另一种变化是让孩子喂食命令
回到父母,而不是价值观。如果父进程说. <(child_prog)
,它会运行子进程,捕获输出,并执行它。然后孩子就可以做
printf "导出 var1='值1'\n导出 var2='值2' var3=\"值3\"\n" >&5
(我用一个测试了这个value3
包含一个撇号,所以我必须用 引用它\"…\"
,并且我这样保留它只是为了说明替代语法。)
该技术的一个特点是您可以添加要导出的变量,而无需更改父级中的代码。
这种方法要求父进程运行 bash(或者可能是其他高级 shell 之一?),因为 POSIX 不支持.<(cmd)