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

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

登录和非登录shell定义为:

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

/etc/profile 不会被非登录 shell 调用,例如当您启动 konsole (kde) 时。/etc/profile 只会被登录 shell 调用。

这是为什么?请解释一下,因为我想知道其中的原理。

答案1

/etc/profile仅在登录 shell 中被调用,因为这是它的特定用途。

如果你想要一个命令在交互式 shell 中运行,那么不是登录 shell,并且您正在使用bash,请将其放入~/.bashrc或中/etc/bash.bashrc

“配置文件”的目的是包含只应为登录 shell 运行的命令。这些文件是:

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

  • 中的脚本/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存在,则运行 that 而不是.profile

    .bash_profile(但当或.bash_login存在时,通常会写为 *明确调用.profile。)

    shell 特定的好处轮廓文件的区别在于,它们可以包含仅对该 shell 有效的命令或语法。例如,我可以[[.bash_profile/中使用求值运算符.bash_login,但如果我在 中使用它.profile,然后以我的 shell 身份登录dash,则会失败。

“profile”文件中应该包含什么

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

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

  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存在于您的主文件夹中,并且您的用户名jamesPATH最内层的 shell 是这样的:

/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. 即使这不是登录 shell,也应该运行。

例如,无论是否bash是登录 shell,通常都应启用命令行制表符补全。因此,这出现在~/.bashrc

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

那里,12两者都适用:这不会延续到在该 shell 内运行的其他 shell,并且bash即使我使用不同的 shell 登录,制表符补全也应该可以工作。

登录 Shell 和交互式非登录 Shell 的命令放置位置

如果你正在使用bash并希望命令在登录 shell 和交互式 shell 中运行,但这些 shell 不是登录 shell,通常将其放入/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
        source "$HOME/.bashrc"
    fi
fi

(同样,的/etc/profile来源。)/etc/bash.bashrcbash

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

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

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

这可能会导致严重损坏。如果您要这样做,并且系统上除了您正在使用的管理员帐户之外没有其他管理员帐户,您可能需要创建一个;这样可以更轻松地修复错误。

bash“rc”文件实际上运行的是shell 是否是交互式的。然而,在顶部他们说:

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

因此,如果您需要命令自动运行,即使在非交互式 shell 中也是如此,比如运行脚本的 shell,您可以添加命令那些线。

启动登录 Shell

登录后会启动一个登录 shell。如果你想让此后启动的 shell 充当登录 shell,请使用标志-l(代表登录)。 例如:

这是启动登录 shell 的最佳方式(无需登录),除非你想以如下方式启动其他用户。然后,使用:

  • sudo -i为了rootsudo -s用于非登录、交互式 root shell)
  • sudo -u username -i对于任何用户
  • su - username对于非root用户(用于非登录、交互式 root shell)su username

什么是最初的登录 shell?

一个初始登录 shell登录外壳。这个答案中提到“登录 shell”的地方都可以说“初始登录 shell”(本节除外,因为这一部分已经没有任何意义了)。

这个词的一个原因是初始登录 shell就是它登录外壳也有不同的用法——识别哪个程序用作登录时执行的 shell。这是登录外壳以前说:

  • OpenBSD的默认登录 shell 是ksh;在 Ubuntu 上,它是bash。”
  • “你可以改变您的登录 shellchsh“”。

进一步阅读

相关内容