0

I cannot make sense of the results below:

/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:.

I expected PATH to be empty.

Actually, in a way it is:

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

So there's no PATH in the environment, but a non-empty PATH variable is still defined, and can be used by the shell to resolve commands:

bash-5.0$ which ls
/bin/ls

I realize that I can force /usr/bin/env to have an empty PATH like this:

/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$ 

I have two problems with this approach: 1) PATH is shows in the output of /usr/bin/printenv; I'd prefer it if it were completely gone; 2)the situation described above is not unique to PATH; after /usr/bin/env -i a lot of variables in the resulting shell session are still defined.

Q: What is the simplest way to start an interactive /bin/bash session with the least possible number of variables defined (whether in the environment or not)? 1

(Though I've phrased this question in terms of bash, I'm also interested in any related info regarding zsh.)


1 I am aware of the fact that many programs will not function normally, or function at all, if some variables are undefined. I do not intend to use such minimal shell sessions for anything other than for troubleshooting, diagnostics, and the like.

4
  • unix.stackexchange.com/questions/614420/…, github.com/zsh-users/zsh/blob/… Commented Oct 14, 2020 at 2:23
  • 1
    which isn't a builtin. that may or may not affect your results, but command -v will at least report what the shell actually thinks Commented Oct 14, 2020 at 2:52
  • @Fox, which is a builtin in zsh (like in tcsh). Commented Oct 14, 2020 at 5:35
  • 1
    See also info zsh 'Parameters Set By The Shell' Commented Oct 14, 2020 at 5:35

2 Answers 2

3

Yes, both bash and zsh (and dash and mksh and fish at least) set $PATH to a default value when not supplied in the environment they received on startup.

The POSIX shells that don't are still required to look up commands in a default search path.

Both bash and zsh (and some of the modules that are loaded automatically or not in the latter) set a number of internal variables some of which are exported to the environment (not PATH though in the case of bash and zsh), some of which are read-only.

env -i zsh -f or env -i bash --norc would run the shell with an empty environ.

To unset the non-readonly ones, you can do unset ${(k)parameters} in zsh or unset -v $(compgen -v) in bash (though I find that I have to run it twice for LINES and COLUMNS to disappear).

In my test, in bash, that still leaves:

<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 -- _="_"

And in 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

Any shell will use a "default" path (usually including at least /bin and /usr/bin) to lookup commands if the PATH envvar isn't defined. That behaviour is also replicated by execvp(2).

Some shells (like bash) will even set the PATH shell variable to their default path in that case.

What is the simplest way to start an interactive /bin/bash session with the least possible number of variables defined (whether in the environment or not)?

env - bash --norc

bash-5.0$ which ls

which is not a bash built-in -- on some systems it's a shell script run by a different shell than bash. So it's completely irrelevant here.

1

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.