我想知道必须在PATH
环境变量中添加新路径。我知道这可以通过编辑来完成.bashrc
(例如),但不清楚如何做到这一点。
这边走:
export PATH=~/opt/bin:$PATH
或这个?
export PATH=$PATH:~/opt/bin
答案1
简单的东西
PATH=$PATH:~/opt/bin
或者
PATH=~/opt/bin:$PATH
取决于您是否要~/opt/bin
在末尾添加(在所有其他目录之后搜索,以防多个目录中存在同名程序)或在开头添加(在所有其他目录之前搜索)。
您可以同时添加多个条目。PATH=$PATH:~/opt/bin:~/opt/node/bin
或者订购的变化也很好。不要放在export
行的开头,因为它会带来额外的复杂性(请参阅下面的“关于除 bash 之外的 shell 的注释”)。
如果您的PATH
项目是由许多不同的组件构建的,那么您最终可能会得到重复的条目。看如何添加 Unix 哪个命令发现的主目录路径?和使用 awk 命令删除重复的 $PATH 条目以避免添加重复项或删除它们。
~/bin
顺便说一句,有些发行版会自动放入您的 PATH(如果存在)。
放在哪里
将要修改的行放入PATH
,~/.profile
或~/.bash_profile
或 中(如果您有的话)。 (如果您的登录 shell 是 zsh 而不是 bash,请将其放入~/.zprofile
。)
配置文件是由登录 shell 读取的,因此只有在下次登录时才会生效。(有些系统将终端配置为读取登录 shell;在这种情况下,您可以启动一个新的终端窗口,但设置会生效)仅适用于通过终端启动的程序,如何设置PATH
所有程序取决于系统。)
请注意,~/.bash_rc
任何程序都不会读取它,它~/.bashrc
是 bash 交互式实例的配置文件。您不应该在~/.bashrc
.定义环境变量的正确位置是PATH
(~/.profile
或者~/.bash_profile
如果您不关心 bash 以外的 shell)。看它们之间有什么区别,我应该使用哪一个?
不要将其放入/etc/environment
or中~/.pam_environment
:这些不是 shell 文件,您不能像$PATH
其中那样使用替换。在这些文件中,您只能覆盖变量,而不能添加变量。
某些系统脚本的潜在复杂性
如果变量已经在环境中,则不需要export
:变量值的任何更改都会反映在环境中。PATH
几乎总是在环境中;所有 UNIX 系统都很早就设置了它(实际上通常在第一个进程中)。
在登录时,您可以依赖PATH
已经在环境中并且已经包含一些系统目录。如果您正在编写一个可能在设置某种虚拟环境时提前执行的脚本,您可能需要确保该脚本PATH
非空并导出:如果PATH
仍未设置,则类似的内容PATH=$PATH:/some/directory
将设置PATH
为:/some/directory
,并且空组件开头表示当前目录(如.:/some/directory
)。
if [ -z "${PATH-}" ]; then export PATH=/usr/local/bin:/usr/bin:/bin; fi
关于 bash 以外的 shell 的注释
在 bash、ksh 和 zsh 中,export
是特殊的语法,并且两者都PATH=~/opt/bin:$PATH
做export PATH=~/opt/bin:$PATH
正确的事情。在其他 Bourne/POSIX 风格的 shell 中,例如 dash(在/bin/sh
许多系统上),export
被解析为普通命令,这意味着两个区别:
~
仅在单词的开头进行解析,赋值除外(请参阅如何添加 Unix 哪个命令发现的主目录路径?了解详情);$PATH
外部双引号PATH
如果包含空格或则中断\[*?
。
因此,在像 dash 这样的 shell 中,设置export PATH=~/opt/bin:$PATH
PATH
为文字字符串,后跟直到第一个空格
~/opt/bin/:
的值。 (一个裸作业)PATH
PATH=~/opt/bin:$PATH
不需要引号并做正确的事。如果您想export
在可移植脚本中使用,则需要编写export PATH="$HOME/opt/bin:$PATH"
, or PATH=~/opt/bin:$PATH; export PATH
(或者甚至PATH=$HOME/opt/bin:$PATH; export PATH
是为了可移植到不接受export var=value
且不进行波浪号扩展的 Bourne shell)。
1在 Bourne shell 中情况并非如此(就像在实际的 Bourne shell 中,而不是现代 POSIX 风格的 shell),但现在您不太可能遇到这种旧的 shell。
答案2
Appending/Prepending 的防弹方式
附加/前置的常用方法
PATH="$PATH:~/opt/bin" # appending
PATH="~/opt/bin:$PATH" # prepending
可能会带来剧烈的头痛。
这防弹方式将路径(例如,~/opt/bin
)添加到 PATH 环境变量是
PATH="${PATH:+${PATH}:}~/opt/bin" # appending
PATH="~/opt/bin${PATH:+:${PATH}}" # prepending
为什么?
这可以避免最初为空时出现虚假的前导/尾随冒号$PATH
,这可能会产生不良的副作用,并且可能会成为一场噩梦,难以找到(这个答案简单地处理这个案例awk
)。
解释(从外壳参数扩展):
${parameter:+word}
如果为 null 或未设置,则不替换任何内容,否则替换
parameter
的扩展。word
因此,${PATH:+${PATH}:}
被扩展为:
- 什么都没有,如果
PATH
为空或未设置, ${PATH}:
,如果PATH
已设置。
笔记:这是用于 bash 的。
我想知道为什么系统脚本通常不使用它。
编辑:我刚刚发现像这样的脚本devtoolset-6/enable
实际上使用了这个,
$ cat /opt/rh/devtoolset-6/enable
# General environment variables
export PATH=/opt/rh/devtoolset-6/root/usr/bin${PATH:+:${PATH}}
...
答案3
无论哪种方式都有效,但它们不做同样的事情: 的元素PATH
是从左到右检查的。在您的第一个示例中, 中 的可执行文件~/opt/bin
优先于已安装的可执行文件,例如 中/usr/bin
,这可能是您想要的,也可能不是您想要的。
特别是,从安全的角度来看,在前面添加路径是危险的,因为如果有人可以获得对您的 的写访问权限~/opt/bin
,他们可以在其中放置一个不同的路径ls
,然后您可能会使用它的/bin/ls
不经意间。现在想象一下您的浏览器或选择是否相同ssh
...(将 . 放入您的路径中也是如此。)
答案4
Linux 通过环境变量确定可执行文件的搜索路径$PATH
。要将目录 /data/myscripts 添加到环境变量的开头$PATH
,请使用以下命令:
PATH=/data/myscripts:$PATH
要将该目录添加到路径末尾,请使用以下命令:
PATH=$PATH:/data/myscripts
但前面的内容还不够,因为当您在脚本内设置环境变量时,该更改仅在脚本内有效。解决这个限制只有两种方法:
- 如果在脚本中导出环境变量,则该环境变量在脚本调用的任何程序中都有效。请注意,它在调用脚本的程序中无效。
- 如果调用脚本的程序通过包含而不是调用来执行此操作,则脚本中的任何环境更改都会在调用程序中生效。这种包含可以通过 dot 命令或 source 命令来完成。
例子:
$HOME/myscript.sh
source $HOME/myscript.sh
包含基本上将“被调用”脚本合并到“调用”脚本中。它就像 C 中的#include。所以它在“调用”脚本或程序中有效。但当然,它在调用程序调用的任何程序或脚本中都无效。为了使其在调用链中一直有效,您必须使用导出命令来遵循环境变量的设置。
例如,bash shell 程序通过包含来合并文件 .bash_profile 的内容。将以下两行放入 .bash_profile 中:
PATH=$PATH:/data/myscripts
export PATH
有效地将这两行代码放入 bash 程序中。因此,在 bash 中,$PATH 变量包含$HOME/myscript.sh
,并且由于存在导出语句,bash 调用的任何程序都具有更改后的$PATH
变量。由于从 bash 提示符运行的任何程序都由 bash 调用,因此新路径对于从 bash 提示符运行的任何程序都有效。
最重要的是,要将新目录添加到路径中,您必须将该目录追加或添加到 shell 中包含的脚本内的 $PATH 环境变量中,并且必须导出该$PATH
环境变量。
更多信息这里