为什么不为非登录shell调用/ etc / profile?


51

登录和非登录shell定义为:

su - $USER # will give you a login shell
bash # will give you a non-login shell

对于非登录外壳,例如在启动konsole(kde)时,不会调用/ etc / profile。/ etc / profile仅用于登录shell。

这是为什么?请解释,因为我喜欢理解这一原理。

Answers:


100

/etc/profile 仅针对登录外壳调用此命令,因为这是其特定目的。

如果您要为非登录shell的交互式shell运行命令,并且正在使用bash,请将其放在~/.bashrc或中/etc/bash.bashrc

“配置文件”文件的目的是包含应仅针对登录Shell运行的命令。这些文件是:

  • /etc/profile,作为登录shell启动时,由所有Bourne兼容shell(包括bashdash)运行。

  • 中的脚本/etc/profile.d

    这是针对Bourne风格的shell的,但是没有被编码到shell可执行文件本身中。而是命令中的命令/etc/profile调用它们。例如,在我的Ubuntu 12.04系统上,/etc/profile包括以下几行:

    if [ -d /etc/profile.d ]; then
      for i in /etc/profile.d/*.sh; do
        if [ -r $i ]; then
          . $i
        fi
      done
      unset i
    fi
    
  • .profile 在用户主目录中,当作为登录shell启动时,由Bourne兼容shell运行(除非被覆盖,请参见下文)。

  • .bash_profile.bash_login在用户的主目录中。除了以外的其他shell都会忽略它们bash。但是,如果.bash_profile存在,请bash运行它而不是 .profile。如果.bash_profile不存在但.bash_login存在,则运行而不是.profile

    (但是,通常存在.bash_profile.bash_login(如果存在)被编写为*显式调用.profile。)

    特定于外壳的配置文件的好处是它们可以包含仅对该外壳有效的命令或语法。例如,我可以[[.bash_profile/中使用评估运算符,.bash_login但是如果在中使用它.profile,然后以dashshell身份登录,它将失败。

“配置文件”文件中应该包含什么

“配置文件”文件应包含在登录开始时仅应运行一次的命令。(这也包括图形登录,因为它们也是从登录外壳开始的。)如果外壳是交互式的,则运行该外壳的用户可能已登录,因此它可能有一个祖先(启动它或启动它的东西,或启动等)作为登录外壳。

您可能只想运行一次命令,因为:

  1. 每次登录没有理由多次运行它,这样效率低下,或者
  2. 它将产生不希望的结果,每次登录运行一次以上。

作为第二种情况(可能会产生不良结果)的示例,请考虑以下几行,默认情况下,这些行出现在每个用户的~/.profile

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi

假设您使用SSH进入,运行了另一个shell(例如zsh),在某个时候发现您想暂时返回到bash环境,但又要保留环境(因此在时bash再次运行zsh),然后运行一个像mc这样的程序来运行shell界面。如果bin您的主文件夹中存在用户名james,则您PATH的最内层外壳中的内容将类似于:

/home/james/bin:/home/james/bin:/home/james/bin:/home/james/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

这是低效的,并且(更重要的是)使其难以理解的内容PATH

但是,这绝不是灾难。据我所知,如果每个交互式shell都以“配置文件”作为源文件,则在默认配置下不会发生任何可怕的事情。但是,由于“配置文件”文件的目的是包含每次登录仅运行一次的命令,因此用户或管理员可以将命令添加到仅在启动登录Shell时必须运行的配置文件。

在哪里放置每个交互式Shell即可运行的命令

如果使用bash,则每个交互式shell中都有要运行的命令文件:

  • /etc/bash.bashrc
  • .bashrc 在用户的主目录中。

这最常用于以下命令

  1. 仅影响它们运行所在的shell的环境,甚至不影响子shell,或者
  2. 即使不是登录外壳,也应该运行。

例如,通常应该启用命令行制表符补全功能,无论是否bash是登录外壳程序。因此,它出现在~/.bashrc

if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
    . /etc/bash_completion
fi

此处12都适用:这不会继承到在此外壳程序中运行的其他外壳程序,并且bash即使我使用其他外壳程序登录,制表符补全也应该起作用。

在何处放置用于登录Shell和交互式非登录Shell的命令

如果您正在使用bash并且希望命令在登录外壳程序和交互式外壳程序中运行,而不是在登录外壳程序中运行,则通常将其放在/etc/bash.bashrc或中就足够了~/.bashrc。这是因为,在默认情况下,/etc/profile~/.profile明确地运行它们。例如,~/.profile具有:

# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
        . "$HOME/.bashrc"
    fi
fi

(类似地,/etc/profile来源/etc/bash.bashrcbash)。

因此,当您启动交互式bash外壳程序(无论它是否是登录外壳程序)时,“ profile”和“ rc”文件都会运行。

在非交互式Shell中将命令放置在何处

您可能不想为所有非交互式外壳程序运行指定任何命令。它们将在每次运行脚本时运行(前提是该脚本由您配置为运行它们的外壳程序运行)。

这可能会导致严重损坏。如果要执行此操作,并且系统上除了使用的管理员帐户之外没有其他管理员帐户,则可能要创建一个;这样可以更轻松地纠正错误。

在其中bash无论外壳是否交互式,实际上都将运行“ rc”文件。但是,他们在最上方说:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

因此,如果即使在非交互式外壳(如运行脚本的外壳)中也需要命令自动运行,则可以这些行之前添加命令。

启动登录外壳

登录启动登录外壳程序。如果您希望之后启动的shell充当登录shell,则以-l标志(代表l ogin)启动。例如:

除非您想以另一个用户身份启动,否则这是启动登录外壳程序(无需登录)的最佳方法。然后,使用:

  • sudo -i用于rootsudo -s用于非登录交互式根shell)
  • sudo -u username -i 对于任何用户
  • su - usernameroot用户使用(用于非登录交互式根shell)su username

什么是初始登录外壳?

一个初始登录壳是相同的一个登录shell。这个答案在每个地方都说“ login shell”时,可能会说“ initial login shell”(本节中的内容已经不再有意义了)。

初始登录外壳一词的一个原因是,登录外壳也以不同的方式使用-标识哪个程序用作通过登录执行的外壳。这就是登录shell曾经说过的感觉:

  • OpenBSD的默认登录shell是ksh;在Ubuntu中,它是bash。”
  • “您可以使用更改登录shell chsh。”

进一步阅读


4
任何Stack Exchange网站上任何问题的最佳答案之一。
Mark E. Haase

1
>“配置文件”文件应包含在登录开始时仅应运行一次的命令。(这也包括图形登录,因为它们也从登录外壳开始。)否否否否!绝对没有!所有类似bourne的外壳程序仅在交互式登录外壳程序会话上读取.profile ,即以-i选项启动的外壳程序或连接到控制终端的外壳程序(如果外壳程序由显示管理器启动,则都不是)。之所以如此,是因为该文件的目的是建立用户的终端,而不仅仅是他们的环境。如果显示经理tr

Eliah,我在这里转述了Derek的其余评论但保留了上述观点,因此他会收到您的回复通知,尽管由于声誉要求他将无法对此做出回应。但是,我已经授予他对上述聊天室的写权限。
塞斯

1
In bash, the "rc" files are actually run whether the shell is interactive or not. 是不正确的。/etc/bash.bashrc由/etc/bash.profile触发。
okwap

okwap是正确的,rc文件不会在非交互式shell中被调用,更加简洁准确。
尼克·艾伦
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.