首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >[ -n "$PS1“]用于bashrc

[ -n "$PS1“]用于bashrc
EN

Unix & Linux用户
提问于 2018-08-15 04:40:38
回答 4查看 4K关注 0票数 14

[ -n "$PS1" ] in [ -n "$PS1" ] && source ~/.bash_profile;的目的是什么?这一行包含在dotfiles的.bashrc 存储库中。

EN

回答 4

Unix & Linux用户

回答已采纳

发布于 2018-08-15 04:57:59

这是检查shell是否是交互式的。在这种情况下,只有在shell是交互式的情况下才能找到~/.bash_profile文件。

参见bash手册中的“这是壳牌互动吗?”,它引用了这个特定的成语。(它还建议通过测试$-特殊变量是否包含i字符来检查shell是否是交互式的,这是解决此问题的更好方法。)

票数 24
EN

Unix & Linux用户

发布于 2018-08-15 06:31:07

这是做什么的

这是一种广泛的测试shell是否是交互式的方法。注意,它只在bash中工作,它不适用于其他shell。因此,对于.bashrc来说,这是可以的(如果愚蠢的话),但是它不能在.profile中工作(通过sh读取,bash只是sh的可能实现之一,而不是最常见的实现之一)。

为什么它能工作(只在bash!)

交互式shell将壳变量PS1设置为默认提示符字符串。因此,如果shell是交互式的,则设置PS1 (除非用户的.bashrc删除了它,这不可能发生在.bashrc顶部,而且您可以认为这样做是愚蠢的)。

相反,在bash中是正确的:在bash未设置PS1的非交互实例启动时。请注意,这个行为是特定于bash的,并且可以说是一个错误(为什么bash -c '… do stuff with $var…'varPS1时不能工作?)但是bash的所有版本,包括4.4 (我写的最新版本)都是这样做的。

许多系统将PS1导出到环境中。这是个坏主意,因为许多不同的shell使用PS1,但语法不同(例如,巴什迅速逃脱兹什迅速逃脱完全不同)。但是它是足够广泛的,在实践中,看到PS1是设置的,并不是一个可靠的指示,表明shell是交互式的。外壳可能继承了环境中的PS1

为什么(Mis)在这里使用

.bashrc是bash在启动时读取的交互式文件。一个鲜为人知的事实是bash也读取.bashrc是一个登录shell,bash的启发式分析得出这是一个远程会话(bash检查它的父会话是rshd还是sshd)。在第二种情况下,不太可能在环境中设置PS1,因为还没有运行点文件。

但是,代码使用这些信息的方式是适得其反的。

  • 如果shell是一个交互式shell,那么它将在该shell中运行.bash_profile。但是.bash_profile是一个登录时脚本。它可能运行某些程序,这些程序的目的是每个会话只运行一次。它可能覆盖用户在运行该shell之前故意设置为不同值的一些环境变量。在非登录shell中运行.bash_profile是破坏性的。
  • 如果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

代码语言:javascript
复制
case $- in
  *i*) echo "This shell is interactive";;
  *) echo "This shell is not interactive";;
esac

如果shell是非交互式的- i.e,那么这在.bashrc中对读取 .profile <#>only是有用的。如果bash是(非交互式的)登录shell,请读取.profile,如果是交互式shell,则不要读取它。

代码语言:javascript
复制
if [[ $- != *i* && -r ~/.profile ]]; then . ~/.profile; fi
票数 22
EN

Unix & Linux用户

发布于 2018-08-15 09:41:10

这个奇怪的概念似乎是由于bash开始时不是POSIX克隆,而是Bourne Shell克隆的结果。

因此,POSIX交互行为($ENV被调用为交互式shell)后来被添加到bash中,并不广为人知。

有一个shell允许类似的行为。这是csh和csh授权,$prompt具有特定的值:

代码语言:javascript
复制
$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的代码放入文件中:

代码语言:javascript
复制
$ENV

它有一个特定于shell的名称。它是。

代码语言:javascript
复制
$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工作,也不要求$-包含用于交互式shell的i。POSIX只是要求sh -i将外壳强制进入交互模式。

因为变量$PS1可以从环境中导入,所以即使在非交互模式下,它也可能有一个值。在任何非交互式shell中,bash unsets PS1并不是由标准授予的,也不是由任何其他shell执行的。

因此,干净的编程(即使使用bash)是将交互shell的命令放入$HOME/.bashrc中。

票数 2
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/462663

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档