Linux下set、env、export的不同
此文转载而来,在工作时对Linux下的各种环境变量设置有所疑惑,以下是对原文的翻译
原文:What's the difference between set, export and env and when should I use each?
让我们考虑以下这个特定的例子,grep命令利用一个GREP_OPTIONS 环境变量(environment variable)来设置默认的选项。
现在,给定一个文件 test.txt 含有以下行:
line one
line two
运行命令 grep one test.xt 将会返回以下内容:
line one
如果你运行 grep 时附带 -v 参数,将会返回所有不匹配的行,所以输出如下:
line two
我们将尝试利用环境变量设定这个选项
不利用 export 设定环境变量 将不会被你调用命令的环境所继承。
GREP_OPTIONS='-v'
grep one test.txt
结果:
line one
很显然,参数 -v 没有成功的传入grep程序中
*只有在你希望设定一个变量仅在当前运行shell内生效时才采用这种形式,例如在for i in \* ; do中你不会希望 export $i.
然而,这个变量将会被传给当前命令的运行环境中,所以你也可以这样做使其生效:
GREP_OPTIONS='-v' grep one test.txt
这样就会返回预期的结果了
line two
当你想临时改变当前运行实例程序的环境时,采用这种方法。
export 一个变量会使得这个变量被继承:
export GREP_OPTIONS='-v'
grep one test.txt
现在返回
line two
这种形式最常见的使用场景是在,在shell中设置变量以供随后启动的进程使用
这里所说的都是在bash中的实现。 export 是bash的内建方法; VAR=whatever 则是bash的语法。 env, 在另一方面来说, 自己就是一个程序。当 env 被调用时, 下列事情将会发生:
- 命令
env被作为新的进程进行执行 env修改环境的同时- 调起作为参数传入的命令,
env进程被command进程替换
Example:
env GREP_OPTIONS='-v' grep one test.txt
这个命令会启动两个进程: (i) env and (ii) grep (实际上,第二个进程会替代第一个进程). 从 grep 进程的角度来看, 运行的结果与运行下面的命令一模一样:
GREP_OPTIONS='-v' grep one test.txt
然而,当你不在bash内或者不希望唤起另一个shell时,你可以使用这个方法 (例如,当你使用 exec() 类似的函数而不是 system() 调用).
关于 #!/usr/bin/env 的附加说明
这也是为什么, 使用#!/usr/bin/env interpreter 而不是 #!/usr/bin/interpreter. env 并不需要完整的程序路径, 因为它使用 execvp() 函数遍历的搜索 PATH 变量,就像shell会做的一样, 然后将运行命令替换自身。 因此,它可以用作寻找解释器 (例如 perl、 python) 的"位置".
这也表示,通过修改当前的PATH变量,你可以影响到哪个python的程序会被调用。这使得下列命令有可能执行成功:
echo -e '#!/usr/bin/bash\n\necho I am an evil interpreter!' > python
chmod a+x ./python
export PATH=.
calibre
会返回如下结果,而不是调起Calibre
I am an evil interpreter!
说明:Calibre是一个自由开源的电子书软件套装,由python编写,需要依赖python解释器才能运行