在口译中这个流程图
我在 man bash 中发现:
当 bash 作为交互式登录 shell 或带有 --login 选项的非交互式 shell 被调用时,它首先从文件 /etc/profile 中读取并执行命令(如果该文件存在)。
这表明交互式登录读取 shell /etc/profile
(不带 --noprofile)
还,非交互式带有选项--login
read 的shell/etc/profile
这似乎留下了一些可能登录shell(其中$0
以 a 开头-
)非交互式(运行脚本,可能像这样简单date
)可能无法读取(源)/etc/profile
。
确认或否定这个想法:
首先,我尝试使用su -l -
,它以 a 作为第一个字符启动登录 shell -
,但我未能使其成为非交互式(并且能够提供测试来探测它)。
调用类似的东西
$ bash -c 'date' -bash
不报告为登录 shell(即使第一个字符是 a -
)。
尝试这个来揭示细节:
$ bash -c 'echo "$0 $- ||$(shopt -p login_shell)||";date' -bash -bash hBc ||shopt -u login_shell|| Fri Aug 19 06:32:31 EDT 2016
the 的第一个字符
$0
是 a ,其值中-
没有(交互式) ,但不会将其报告为 a (the -u)。在这种情况下,未读取 /etc/profile,但我不确定这是正确的测试。i
$-
login_shell
还提到了“罕见的非交互式登录 shell”在这个答案中对于这个问题没有足够具体。
这这家伙的结论是/etc/profile
始终被读取的。
读取汇总表:交互式和非交互式登录 shell 都会读取/etc/profile
而如果本页的示例是正确的:
Some examples
$ su bob # interactive non-login shell
$ su - bob # interactive login shell
$ exec su - bob # interactive login shell
$ exec su - bob -c 'env' # non-interactive login shell
$ ssh [email protected] # interactive login shell, `~/.profile`
$ ssh [email protected] env # non-interactive non-login shell, `~/.bashrc`
exec su - bob -c 'env'
对已阅读的报告进行测试/etc/profile
。
简而言之:
是否有可能有一个非交互式登录shell(不使用 --login 或 -l 调用)?
如果为真,它是否正在读取/etc/profile
文件?
如果上述情况为真,我们必须得出结论:全部登录 shell [交互式(或非交互式)] 读取 /etc/profile(无--noprofile
选项)。
注意:要检测 /etc/profile 是否被读取,只需在文件的开头添加以下命令:
echo "'/etc/profile' is being read"
答案1
我见过图形登录环境可以:
exec "$SHELL" -l -c 'exec start-window-or-session-manager'
或等价于:
exec -a "-$SHELL" "$SHELL" <<EOF
exec start-window-or-session-manager
EOF
以便读取并应用会话初始化文件(例如~/.profile
类似 Bourne 的 shell(以及某些 shell 中的相应文件))。/etc
第一个不适用于所有 shell。-l
受大量 shell 支持,但不是全部,并且在某些 shell(例如csh
/ tcsh
)上不能与 一起使用-c
。不过,所有 shell 都可以理解argv[0]
存在的第一个字符-
,因为它login
用来告诉 shell 它们是登录 shell。
在第二种情况下,该 shell 的 stdin 不是设备tty
(<<
由临时常规文件或取决于 shell 的管道实现),因此 shell 不是交互式的(交互的定义是当人类交互时)用它)。
答案2
是的,可以使用非交互式登录 shell
$ head -1 /etc/profile
echo PROFILE BEING READ
$ echo echo hello | su -
PROFILE BEING READ
stdin: is not a tty
hello
$
答案3
非交互式登录 shell 并不常见,但也是可能的。如果您将第零个参数(通常是可执行文件的名称)设置为以 a 开头的字符串来启动 shell -
,则它是一个登录 shell,无论它是否是交互式的。
$ ln -s /bin/bash ./-bash
$ echo 'shopt -p login_shell; echo $-' | HOME=/none PATH=.:$PATH -bash
shopt -s login_shell
hB
您的尝试bash -c date -bash
不起作用,因为这并没有告诉 shell 是登录 shell:第零个参数是bash
,而不是-bash
。 bash 启动后,它将变量设置$0
为 ,-bash
而不是第 0 个参数,但第 0 个参数才是重要的。
su -l
您可以使用或运行非交互式登录 shell su -
,但您需要安排标准输入不是终端,同时仍能够获得授权(无需输入密码,或将密码安排在开头)输入)。使用 sudo: run 来获取存在凭证可能会更容易sudo true
,然后在凭证仍然有效时运行echo 'shopt -p login_shell; echo $-' | sudo -i
。
答案4
是否可以有一个非交互式登录 shell(不使用 --login 或 -l 调用)?
是的。
$ (exec -a '-' bash -c 'shopt -q login_shell && echo login shell')
但是,请注意,除非给出参数,/etc/profile
否则不会用于非交互式登录 shell 。--login
调用非交互式登录 shell 的常见习惯用法是:
$ su - someuser -c somecommand
/etc/profile
但这会遇到一个没有被执行的事实。
可以更改此行为,但它涉及通过取消注释中找到的选项来在编译时自定义 Bash 源代码配置-top.h:
/* Define this to make non-interactive shells begun with argv[0][0] == '-'
run the startup files when not in posix mode. */
/* #define NON_INTERACTIVE_LOGIN_SHELLS */
当我研究了这个su
异常现象,我发现其他shell包括zsh
和dash
没有这个差异。