在.bashrc,.profile,.bash_profile等之间进行选择


197

这个问题已经在这里有了答案:

这是令人尴尬的,但经过多年的使用POSIX系统充分的时间,我仍然有一个很难搞清楚,如果一个shell定制应该进去.bashrc.profile或者别的地方。更不用说某些特定于OS的配置文件了.pam_environment

是的,我知道如何困惑文档并了解何时加载或不加载每个文件。我想知道的是,是否有人将如何确定将给定类型的自定义内容放入哪个文件的综合指南综合在一起。


6
此问题不应被标记为重复,原因是添加的问题中没有.profile。
2015年

Answers:


222

TL; DR:

  • ~/.bash_profile应该是非常简单的,并且只需按以下顺序加载.profile.bashrc

  • ~/.profile具有与bash无关的东西,例如环境变量(PATH和朋友)

  • ~/.bashrc在交互式命令行中具有您想要的任何内容。命令提示符,EDITOR变量,bash别名供我使用

其他一些注意事项:

  • 图形应用程序应该可用的任何东西或sh(或bash调用为sh)必须存在~/.profile

  • ~/.bashrc 不得输出任何东西

  • 任何仅适用于登录Shell的内容都应放入 ~/.profile

  • 确保~/.bash_login不存在。


3
+1,这可以~/.profile为显式运行/ bin / sh的GDM / LightDM / LXDM等服务正确设置环境。
grawity 2014年

12
我的.bashrc输出很多东西,您能对此发表评论吗?特别是,应将问候语输出放在哪里?
Calimo 2014年

14
@Calimo:使其仅以交互方式输出内容。您可以使用进行测试[[ $- == *i* ]],即在特殊$-变量中寻找“ i” 。当然,仅在将bash编译为.bashrc以非交互模式读取的系统上,它才是最重要的。(也就是说,Debian的,但不是凯旋门。),但它尝试使用连接时,神秘的错误消息的常见原因sftpscp或类似的工具。
grawity 2014年

4
现在我知道了-为什么.bash_login不存在?它有什么作用?
tedder42 2014年

11
@ tedder42:它与.bash_profile和相同.profile。但是bash只读取三分之一中的第一个。意思是,如果您有一个.bash_login,则.profile.bash_profile都将被神秘地忽略。
grawity 2014年

54

在过去的几年中,我有很多的时间可以浪费,所以我已经研究了这个比仅有10分钟多一点。我不知道这是否是最好的布局,它只是在几乎所有情况下都能正常工作的布局。

要求:

  • ~/.profile 必须与任何/ bin / sh兼容-包括bash,dash,ksh以及发行版可能选择使用的其他任何东西。

  • 环境变量必须放在控制台登录名(即“登录” shell)和图形登录名(即,诸如GDM,LightDM或LXDM之类的显示管理器)均可读取的文件中。

  • 同时拥有 ~/.profile和几乎没有意义~/.bash_profile。如果缺少后者,bash将很乐意使用前者,并且可以使用$BASH或来保护任何特定于bash的行$BASH_VERSION

  • *profile和之间的区别*rc是,前者用于“登录” shell,后者在您每次打开终端窗口时使用。但是,“登录”模式下的bash无法提供~/.bashrc,因此~/.profile需要手动进行。

最简单的配置是:

  • 有一个~/.profile设置所有环境变量(特定于bash的变量除外)的,也许打印一行或两行,然后~/.bashrc如果由bash运行则打印源,否则坚持使用与sh兼容的语法。

    出口TZ =“欧洲/巴黎”
    导出EDITOR =“ vim”
    如果[“ $ BASH”]; 然后
        。〜/ .bashrc
    科幻
    正常运行时间
    
  • 有一个~/.bashrc可以执行任何特定于外壳程序的安装程序,并通过检查交互模式来避免破坏sftpDebian(在Debian上编译bash并提供~/.bashrc即使对于非交互外壳程序也可以加载的选项):

    [[$-== * i *]] || 返回0
    
    PS1 ='\ h \ w \ $'
    
    start(){sudo服务“ $ 1” start; }
    

但是,还有一个问题是某些非交互式命令(例如ssh <host> ls)会跳过~/.profile,但是环境变量对它们非常有用。

  • 某些发行版(例如Debian)会编译其bash,并提供源于~/.bashrc此类非交互式登录的选项。在这种情况下,我发现将所有环境变量(各export ...行)移动到单独的文件~/.environ,并从和两者中获取 它很有用,可以避免两次执行:.profile.bashrc

    如果![“ $ PREFIX”]; 那么    #$或编辑,或$ TZ,还是...... 
        。〜/ .environ            #通常,.environ本身会设置的任何变量
    科幻
    
  • 不幸的是,对于其他发行版(例如Arch),我还没有找到一个很好的解决方案。一种可能性是使用(默认情况下启用的)pam_env PAM模块,方法如下~/.pam_environment

    BASH_ENV =。/。environ         #不是错字;它必须是一条道路,但〜无效
    

    然后,当然,更新~/.environunset BASH_ENV


结论?贝壳是一种痛苦。环境变量很痛苦。特定于发行版的编译时选项给您带来极大的痛苦。


2
+1的最后一段,但我更喜欢采购.profile.bashrc.bash_profile并保持.profile清洁。
nyuszika7h 2014年

@ nyuszika7h:我.profile 很干净,谢谢。
grawity 2014年

1
注意再每次你打开一扇窗是另一种方式轮OSX时间评论
马克

1
“同时拥有~/.profile和几乎没有意义~/.bash_profile”:我不同意。有关原因,请参见丹的答案。
rubenvb 2014年

@rubenvb您能引用相关部分吗?我认为只有a .profilebash用条件保护特定部分是很好的。
开尔文

36

看看ShreevatsaR撰写的这篇优秀博客文章。这是摘录,但转至博客文章,其中包括对“登录外壳”等术语的解释,流程图和类似的Zsh表。

对于Bash,它们的工作方式如下。读取适当的列。执行A,然后执行B,然后执行C,依此类推。B1,B2,B3表示仅执行找到的那些文件中的第一个。

+----------------+-----------+-----------+------+
|                |Interactive|Interactive|Script|
|                |login      |non-login  |      |
+----------------+-----------+-----------+------+
|/etc/profile    |   A       |           |      |
+----------------+-----------+-----------+------+
|/etc/bash.bashrc|           |    A      |      |
+----------------+-----------+-----------+------+
|~/.bashrc       |           |    B      |      |
+----------------+-----------+-----------+------+
|~/.bash_profile |   B1      |           |      |
+----------------+-----------+-----------+------+
|~/.bash_login   |   B2      |           |      |
+----------------+-----------+-----------+------+
|~/.profile      |   B3      |           |      |
+----------------+-----------+-----------+------+
|BASH_ENV        |           |           |  A   |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|~/.bash_logout  |    C      |           |      |
+----------------+-----------+-----------+------+

很好 需要注意的是,通常是很重要的/etc/profile电话/etc/bash.bashrc,和~/.profile电话~.bashrc。如此有效,/etc/bash.bashrc并且~/.bashrc也正在针对交互式登录执行。
wisbucky

请注意,某些发行版似乎覆盖了该方案(带来了奇怪的后果)-例如,请参见我对opensuse的错误报告:bugzilla.opensuse.org/show_bug.cgi?
id

顺便说一句。至少使用bash没有这些文件时在bash经由被称为正被执行/bin/sh
JepZ

@JepZ是的,这就是第三栏“脚本”的解释。
Flimm

1
@Flimm好吧,“脚本”列描述了当您通过bash(例如/ bin / bash)启动非交互式脚本时发生的情况。但是,如果通过sh启动脚本(/ bin / sh是到/ bin / bash的符号链接),则不会执行上述任何操作(甚至不会执行BASH_ENV)。可以通过搜索找到bash手册页的相关段落If bash is invoked with the name sh
JepZ

21

我为您提供“综合”指南:

  • 制作.bash_profile.profile加载(.bashrc如果存在),例如 [ -r $HOME/.bashrc ] && source $HOME/.bashrc
  • 把其他东西都放进去.bashrc
  • 别担心
  • 每四年左右,花十分钟研究这个问题,然后放弃并回到“不用担心”。

编辑:在“全面”中添加了恐吓引号,以防万一有人想相信它。;)


3
同时拥有.bash_profile.profile有点多余;您只需要后者。不过,您确实需要使其具有/ bin / sh-proof的能力,if [ "$BASH" ] && [ -r ~/.bashrc ]; then . ~/.bashrc; fi因为有些程序(即gdm / lightdm)可以从/ bin / sh脚本手动获取文件。这也意味着保持环境.bashrc无效。不得不为-1,因为您的“综合”准则在许多系统上均不起作用,正如我多次发现的困难方式。
grawity 2014年

没问题,我很乐意付出-1来获得答案,这不仅是merely舌的“综合”,而且您当然也赢得了该头衔。
机械鱼

0

我放弃了尝试弄清楚这一点的想法,~/.shell-setup而是制作了一个脚本(),我从所有其他脚本中获取了该脚本。

此方法需要~/.shell-setup具有两个功能:

  1. 即使重复获得,也只能运行一次(使用Include guards
  2. 不要产生任何不需要的输出(检测输出何时正常)

#1是相当标准的,尽管可能在shell脚本中使用不多。

#2比较棘手。这是我在bash中使用的:

if [ "" == "$BASH_EXECUTION_STRING" -a "" == "$DESKTOP_SESSION" ]; then
    echo "Hello user!" # ... etc
fi

不幸的是,我不记得我是怎么想出来的,或者为什么仅仅检测交互式shell是不够的。


-2

放入所有内容.bashrc,然后.bashrc从中获取.profile

从bash手册页(在OS X 10.9上):

启动不是登录外壳程序的交互式外壳程序时,如果该文件存在,则bash从〜/ .bashrc读取并执行命令。使用--norc选项可以禁止这种情况。--rcfile file选项将强制bash从文件而不是〜/ .bashrc中读取并执行命令。

以上是所有内容都放入其中的原因.bashrc。但是,在处理登录Shell时会有一些不同的行为。再次引用手册页:

当bash作为交互式登录shell或具有--login选项的非交互式shell被调用时,它首先从文件/ etc / profile中读取并执行命令(如果该文件存在)。读取该文件后,它将按该顺序查找〜/ .bash_profile,〜/ .bash_login和〜/ .profile,并从存在且可读的第一个命令中读取并执行命令。启动外壳程序时,可以使用--noprofile选项禁止此行为。

.profile为登录外壳读取,但.bashrc不是。复制所有内容.bashrc都是bad™,因此我们需要提供其来源.profile以使行为保持一致。

但是,你不想源.bashrc.profile无条件。请查看评论和其他答案以获取更多详细信息。


4
-1,请勿.bashrc从来源.profile。请参阅@DanRabinowitz的答案。
nyuszika7h 2014年

至少不是无条件的。
nyuszika7h 2014年

[ -n "$BASH" -a -f ~/.bashrc ] && . ~/.bashrc会是一个不错的选择.profile
约翰·史密斯

@ nyuszika7h,为什么不呢?每个人似乎都建议这样做。
Pacerier's
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.