[ -n "$PS1" ]
in 的目的是什么[ -n "$PS1" ] && source ~/.bash_profile;
?该行包含在.bashrc
点文件中回购协议。
答案1
这是检查 shell 是否是交互式的。在这种情况下,只有~/.bash_profile
在 shell 是交互式的情况下才获取文件。
看“这是 Shell Interactive 吗?”在 bash 手册中,引用了特定的习惯用法。 (还建议通过测试$-
特殊变量是否包含该字符来检查 shell 是否是交互式的i
,这是解决此问题的更好方法。)
答案2
这是做什么的
这是测试 shell 是否交互式的一种广泛使用的方法。请注意,它仅适用于 bash,不适用于其他 shell。所以对于 来说是可以的(如果愚蠢的话).bashrc
,但是对于 来说它不起作用.profile
(由 sh 读取,bash 只是 sh 的可能实现之一,而不是最常见的实现)。
为什么它有效(仅在 bash 中!)
交互式 shell 设置外壳变量PS1
到默认的提示字符串。因此,如果 shell 是交互式的,PS1
则设置(除非用户.bashrc
已将其删除,这在 的顶部还不可能发生.bashrc
,并且您可以认为这是一件愚蠢的事情)。
bash 中的情况正好相反:bash 的非交互式实例PS1
在启动时会被取消设置。请注意,此行为特定于 bash,并且可以说是一个错误(为什么当isbash -c '… do stuff with $var…'
时不起作用?)。但是 bash 的所有版本(包括 4.4)(我写的最新版本)都是这样做的。var
PS1
许多系统都会导出PS1
到环境中。这是一个坏主意,因为许多不同的 shell 使用PS1
不同的语法(例如bash 的提示转义完全不同于zsh 的提示转义)。但它的应用非常广泛,以至于在实践中,看到它PS1
已设置并不能可靠地表明 shell 是交互式的。 shell 可能是PS1
从环境继承的。
为什么它在这里被(错误)使用
.bashrc
是 bash 在交互时启动时读取的文件。一个不太为人所知的事实是,bash 还读取.bashrc
is 一个登录 shell,并且 bash 的启发式结论是这是一个远程会话(bash 检查其父级是否是rshd
或sshd
)。在第二种情况下,不太可能PS1
在环境中设置,因为还没有运行点文件。
然而,代码使用此信息的方式会适得其反。
- 如果 shell 是交互式 shell,则它
.bash_profile
在该 shell 中运行。但.bash_profile
它是一个登录时脚本。它可能会运行一些原本每个会话仅运行一次的程序。它可能会覆盖用户在运行该 shell 之前故意设置为不同值的某些环境变量。.bash_profile
在非登录 shell 中运行会造成破坏。 - 如果 shell 是非交互式远程登录 shell,则不会加载
.bash_profile
.但在这种情况下,加载.bash_profile
可能会很有用,因为非交互式登录 shell 不会自动加载/etc/profile
和~/.profile
。
我认为人们这样做的原因是针对通过 GUI 登录的用户(一种非常常见的情况)并将环境变量设置放入.bash_profile
而不是.profile
.大多数 GUI 登录机制会调用.profile
但不会调用.bash_profile
(读取时.bash_profile
需要运行 bash 作为会话启动的一部分,而不是 sh)。通过此配置,当用户打开终端时,他们将获得环境变量。然而,用户将无法在 GUI 应用程序中获取其环境变量,这是一个非常常见的混乱来源。这里的解决方案是使用.profile
而不是.bash_profile
设置环境变量。在.bashrc
和之间添加桥梁.bash_profile
会产生比它解决的问题更多的问题。
该怎么办
有一种简单、可移植的方法来测试当前 shell 是否是交互式的:测试该选项是否-i
已启用。
case $- in
*i*) echo "This shell is interactive";;
*) echo "This shell is not interactive";;
esac
这.bashrc
对于.profile
仅当 shell 非交互式时才读取——即与代码的作用相反!.profile
如果 bash 是(非交互式)登录 shell,则读取它;如果它是交互式 shell,则不要读取它。
if [[ $- != *i* && -r ~/.profile ]]; then . ~/.profile; fi
答案3
看来这个奇怪的概念是由于它bash
不是作为 POSIX shell 克隆而是作为Bourne Shell
克隆开始的。
因此,POSIX 交互行为($ENV
交互 shell 被调用)是后来添加的,bash
但并不广为人知。
有一种 shell 可以实现类似的行为。这是csh
csh 授予$prompt
的特定值:
$prompt not set non-interactive shell, test $?prompt.
$prompt set but == "" .cshrc called by the which(1) command.
$prompt set and != "" normal interactive shell.
但这既不适用于 Bourne Shell,也不适用于 POSIX shell。
对于 POSIX shell,唯一授予的方法是将交互式 shell 的代码放入文件中:
$ENV
具有 shell 特定名称。它是例如
$HOME/.kshrc for the korn shell
$HOME/.bashrc for bash
$HOME/.mkshrc for mksh
$HOME/.shrc for the POSIX Bourne Shell
其他人提到了 shell 标志-i
,但这不适用于可靠的编程。 POSIX 既不要求它set -i
有效,也不$-
包含i
交互式 shell。 POSIX 仅要求sh -i
强制 shell 进入交互模式。
由于变量$PS1
可以从环境中导入,因此即使在非交互模式下它也可能具有值。事实上,任何非交互式 shell 中的bash
unset
sPS1
都不是由标准授予的,也不是由任何其他 shell 执行的。
因此,干净的编程(即使使用bash
)是将交互式 shell 的命令放入$HOME/.bashrc
.
答案4
我首先要谈谈 Debian 以及大多数情况下 Ubuntu 为 bash 设置的内容。后者涉及其他系统。
在shell启动文件的设置上有很多意见。
我也有我的意见,但我会尝试展示正确设置的现有示例。
我将使用 debuan,因为很容易找到其文件的示例。
而且debian被大量使用,所以设置都经过了很好的测试,
检查 PS1 是否已设置的目的是什么?
只是为了查明 shell 是否是交互式的。
这默认/etc/profile
debian 中的和 ubuntu(来自 /usr/share/base-files/profile):
if [ "${PS1-}" ]; then
if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
if 的读法是:如果是交互式的(PS1 默认设置)并且它是一个 bash shell(但不充当默认外壳sh
),则将 PS1 更改为特定的新外壳(不是默认外壳)。
这默认/etc/bash.bashrc
debian 中的还包含:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
它的作用非常清楚:如果交互式不来源(其余)。
然而,在/etc/skel/.bashrc
一个例子测试交互式 shell 的正确方法(使用$-
):
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
这应该清楚地表明了 PS1 的原因和一种替代方案。
正确的顺序
应避免您报告的设置。
顺序(从系统设置到更具体的用户设置(对于 bash))是/etc/profile
、/etc/bash.bashrc
,~/.profile
最后是~/.bashrc
。这将最广泛的影响(以及更多 shell)放在/etc/profile
(由 root 拥有)中,其次是/etc/bash.bashrc
(也由 root 拥有),但只影响 bash。然后是 中的个人设置$HOME
,第一个~/.profile
适用于大多数 shell ~/.bashrc
(几乎相当于~/.bash_profile
),仅特定于 bash。
~/.bashrc
因此,来源是错误的~/.profile
,它将 bash 的特定用户设置转换为更通用的设置,即影响更多炮弹。除非如果这样做:
# ~/.profile: executed by the command interpreter for login shells
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
它检查 bash 是否正在运行,并且仅.bashrc
在运行时才加载。
这是来自 Debian 的上游决定。其原理解释如下。
事实上,相反,(或)~/.profile
中的采购只是重新应用应该已经加载到特定用例的一般规则,因此“还不错”(我不是说“好”)。我并不是说好,因为这可能会导致文件来源循环。就像子目录加载父目录一样,这是一个目录循环。~/.bash_profile
~/.bashrc
在这种交叉源中,检查交互式 shell 才有意义。仅当 shell 是交互式的时才会~/.bashrc
加载,但它反过来可能会加载~/.profile
(或相反),并且在这种情况下,可以使用检查交互式 shell。