/usr/bin/env -i /bin/bash --norc --noprofile 之后 PATH 不为空

/usr/bin/env -i /bin/bash --norc --noprofile 之后 PATH 不为空

我无法理解以下结果:

/tmp/% /usr/bin/env -i /bin/bash --norc --noprofile
bash-5.0$ echo $PATH
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:.

我预计PATH会是空的。

事实上,从某种程度上来说是这样的:

bash-5.0$ /usr/bin/printenv
PWD=/tmp
SHLVL=1
_=/usr/bin/printenv

PATH所以里面没有环境,但仍然定义了一个非空PATH变量,并且 shell 可以使用它来解析命令:

bash-5.0$ which ls
/bin/ls

我意识到我可以强制/usr/bin/env有一个PATH这样的空:

/tmp/% /usr/bin/env -i PATH= /bin/bash --norc --noprofile
bash-5.0$ /usr/bin/printenv
PWD=/tmp
SHLVL=1
PATH=
_=/usr/bin/printenv
bash-5.0$ echo $PATH

bash-5.0$ 

我对这种方法有两个问题:1)PATH显示在/usr/bin/printenv;的输出中我宁愿它完全消失; 2)上述情况并非独有PATH;之后/usr/bin/env -i生成的 shell 会话中的许多变量仍然被定义。

问:/bin/bash以尽可能少的定义变量(无论是否在环境中)启动交互式会话的最简单方法是什么? 1

(虽然我已经用 来表达这个问题bash,但我也对有关 的任何相关信息感兴趣zsh。)


1我知道,如果某些变量未定义,许多程序将无法正常运行,或者根本无法运行。除了故障排除、诊断等之外,我不打算将如此少的 shell 会话用于任何其他用途。

答案1

是的,当在启动时收到的环境中未提供时,bash两者zsh(并且dashmksh至少fish)都设置为默认值。$PATH

不支持的 POSIX shell 仍然需要在默认搜索路径中查找命令。

和(bash以及zsh后者中自动加载或不加载的一些模块)设置了许多内部变量,其中一些变量被导出到环境中(尽管在和PATH的情况下不是),其中一些是只读的。bashzsh

env -i zsh -f或者env -i bash --norc会在空的环境中运行 shell。

要取消设置非只读的,您可以执行unset ${(k)parameters}inzshunset -v $(compgen -v)in bash(尽管我发现我必须运行它两次才能LINES消失COLUMNS)。

在我的测试中,bash仍然剩下:

<noprompt> typeset -p
declare -r BASHOPTS="checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:globasciiranges:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath"
declare -a BASH_ARGC=([0]="0")
declare -a BASH_ARGV=()
declare -a BASH_LINENO=()
declare -a BASH_SOURCE=()
declare -ar BASH_VERSINFO=([0]="5" [1]="0" [2]="17" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu")
declare -ir EUID="1000"
declare -a FUNCNAME
declare -x OLDPWD
declare -a PIPESTATUS=([0]="1")
declare -ir PPID="44873"
declare -r SHELLOPTS="braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor"
declare -ir UID="1000"
declare -- _="_"

并在zsh

<noprompt> printf '%s (%s)\n' ${(kv)parameters}
parameters (association-readonly-hide-hideval-special)
HISTCMD (integer-readonly-special)
! (integer-readonly-special)
# (integer-readonly-special)
$ (integer-readonly-special)
* (array-readonly-special)
- (scalar-readonly-special)
0 (scalar-special)
ZSH_EVAL_CONTEXT (scalar-readonly-tied-special)
ZSH_SUBSHELL (integer-readonly-special)
? (integer-readonly-special)
@ (array-readonly-special)
zsh_eval_context (array-readonly-tied-special)
status (integer-readonly-special)
TTYIDLE (integer-readonly-special)
LINENO (integer-readonly-special)
PPID (integer-readonly-special)
ARGC (integer-readonly-special)

答案2

如果未定义 envvar,任何 shell 都将使用“默认”路径(通常至少包括/bin/usr/bin)来查找命令。PATH这种行为也被复制了execvp(2)

一些贝壳(比如巴什) 在这种情况下甚至会将PATHshell 变量设置为其默认路径。

/bin/bash以尽可能少的定义变量(无论是否在环境中)启动交互式会话的最简单方法是什么?

env - bash --norc

bash-5.0$ which ls

which不是内置的 bash —— 在某些系统上,它是由 bash 运行的 shell 脚本不同的shell 比 bash 好。所以这里完全不相关。

相关内容