如何通过Shell脚本导出变量?

28

a.sh

#! /bin/sh
export x=/usr/local

我们可以在命令行中执行 source ./a。但我需要通过 shell 脚本来进行导出。

b.sh

#! /bin/sh
. ~/a.sh

没有错误,但在命令行中输入$x时不会显示任何内容。因此,它没有被导出。

有什么办法让它工作吗?


a.sh

#! /bin/sh
export x=/usr/local
-----------
admin@client: ./a.sh
admin@client: echo $x

admin@client:  <insert ....>

related: http://superuser.com/questions/176783/what-is-the-difference-between-executing-a-bash-script-and-sourcing-a-bash-scrip#176788 - Lesmana
如果可以的话,您可以将a.sh的内容放在一个Bash函数中(例如在.bash_profile或其他shell文件中)。 - Seraf
6个回答

119

您可以将导出语句放入shell脚本中,然后使用“source”命令在当前进程中执行:

source a.sh

9
这个答案应该有一个对勾。 - chicharito
3
这个回答应该有一个勾 +1。 - Hui-Yu
继续前进。这应该是正确的答案 ;) - RoadRunner
需要一个社区覆盖来接受答案呵呵。 - Srinath Ganesh

31

你无法通过一个shell脚本进行导出,因为shell脚本在子shell进程中运行,只有子shell的子进程才能继承该导出。

使用source命令的原因是让当前的shell执行命令

将export命令放入类似于.bashrc这样的文件中是非常常见的,bash会在启动时读取该文件(或其他shell的类似文件)

另一个想法是创建一个shell脚本,可以生成一个导出命令作为输出:

shell$ cat > script.sh
#!/bin/sh
echo export foo=bar
^D
chmod u+x script.sh

然后让当前的Shell执行该输出

shell$ `./script.sh`

shell$ echo $foo
bar

shell$ /bin/sh
$ echo $foo
bar

(请注意上面的脚本调用被反引号包围,以使shell执行脚本的输出)


输入 ctrl-D 然后回车,以完成使用 cat 创建的文件的编写。 - Chris Stratton
谢谢。我更新了我的帖子。我尝试过,但是当我打印出来时,它只给了我一行空白。什么也没发生? - CppLearner
我不确定你具体做了什么,但这不是我所做的。请注意在执行shell脚本时使用反引号,并且该脚本会回显一个导出命令而不是自己执行。 - Chris Stratton
是的,虽然我不确定它是否有用。 - Chris Stratton

6
回答上面的问题,如果我有多个相关变量需要导出,这些变量在每次导出时使用相同的值,我可以这样做:
#!/bin/bash
export TEST_EXPORT=$1
export TEST_EXPORT_2=$1_2
export TEST_EXPORT_TWICE=$1_$1

并将其保存为例如~/桌面/TEST_EXPORTING

最后执行$chmod +x ~/Desktop/TEST_EXPORTING

--

之后,使用source ~/Desktop/TEST_EXPORTING bob运行它

然后使用export | grep bob检查应该显示您期望的内容。


2
找了四个多小时,终于找到了这个答案,我真的太高兴了,现在可以清理一下血迹,贴上创可贴了哈哈哈。 - Tadej Gašparovič
3
source 只需要读取权限,对于你实际想要执行的文件,你只需要 chmod +x 权限。 - tripleee

3
将变量导出到环境中只会使该变量对子进程可见。子进程无法修改其父进程的环境。

1
另一种方法(基于上述想法)是将脚本放在~/bin中,并确保~/bin在您的PATH中。然后,您可以全局访问变量。这只是我用来编译需要将GOPATH变量指向当前目录的Go源代码的示例(假设您在需要从中编译源代码的目录中):
从~/bin/GOPATH:
#!/bin/bash

echo declare -x GOPATH=$(pwd) 

然后你只需执行以下操作:
#> $(GOPATH)

所以现在您可以在其他脚本中使用$(GOPATH),比如自定义的构建脚本,可以通过$(pwd)自动调用此变量并在运行时声明它。

0

script1.sh

shell_ppid=$PPID
shell_epoch=$(grep se.exec_start "/proc/${shell_ppid}/sched" | sed 's/[[:space:]]//g' | cut -f2 -d: | cut -f1 -d.)
now_epoch=$(($(date +%s%N)/1000000))
shell_start=$(( (now_epoch - shell_epoch)/1000 ))
env_md5=$(md5sum <<<"${shell_ppid}-${shell_start}"| sed 's/[[:space:]]//g' | cut -f1 -d-)
tmp_dir="/tmp/ToD-env-${env_md5}"
mkdir -p "${tmp_dir}"
ENV_PROPS="${tmp_dir}/.env"
echo "FOO=BAR" > "${ENV_PROPS}"

script2.sh

shell_ppid=$PPID
shell_epoch=$(grep se.exec_start "/proc/${shell_ppid}/sched" | sed 's/[[:space:]]//g' | cut -f2 -d: | cut -f1 -d.)
now_epoch=$(($(date +%s%N)/1000000))
shell_start=$(( (now_epoch - shell_epoch)/1000 ))
env_md5=$(md5sum <<<"${shell_ppid}-${shell_start}"| sed 's/[[:space:]]//g' | cut -f1 -d-)
tmp_dir="/tmp/ToD-env-${env_md5}"
mkdir -p "${tmp_dir}"
ENV_PROPS="${tmp_dir}/.env"
source "${ENV_PROPS}"
echo $FOO

./script1.sh
./script2.sh
BAR

它在相同父 shell 运行的脚本中持续存在,并防止冲突。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接