-3

env and printenv are both external commands i.e. executable files, not bash builtins. The problem with them is that some environment variables (such as _, and I also wonder if there are more) which they output don't belong to the shell which invokes them, see here.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
Tim
  • 101,790
  • 1
    is export not what you're looking for? If no names are supplied ... a list of names of all exported variables is displayed. – Jeff Schaller Apr 09 '18 at 19:58

4 Answers4

6

declare -x or will list all variables marked for export, as will export:

$ declare -x
declare -x ALTERNATE_EDITOR=""
declare -x COLORFGBG="7;0"
declare -x COMMAND_MODE="unix2003"
...
declare -x VISUAL="gvim"

It will not list any local variables that are not exported, but will include variables inherited from the shell's outer environment.

declare -x -F -p will omit any exported functions.

Michael Homer
  • 76,565
  • Thanks. I was wondering why environment variable _ is not shown in the output of export? – Tim Apr 09 '18 at 20:03
  • Bash sets _ in the environment of executables it calls to the path it found the executable at, but $_ is not exported and represents what you typed instead. – Michael Homer Apr 09 '18 at 20:05
  • Do you mean _ isn't an environment variable in the current bash shell, by "$_ is not exported and represents what you typed instead."? – Tim Apr 09 '18 at 20:17
  • Yes. The environmental _ is set post-fork, pre-exec, unconnected to the local _. – Michael Homer Apr 09 '18 at 20:21
  • Thanks, though still confused due to my lack of knowledge. Your comments inspire my https://unix.stackexchange.com/q/436615/674 – Tim Apr 09 '18 at 21:02
1

Note the wording in the Bash manual: "all variables marked for export". What we think of the "environment" of a process is what's passed in the envp parameter of the execve system call, and only what is passed via this parameter. The rest is just an illusion. The calling process (a shell or any other type of process) can do whatever it wants with the received variables, according to how it is documented to behave. It can pass the variables it received to a subprocess, or it can choose not to.

What I am aiming at with all this is that there is no magical environment variable block that just automatically gets passed in the shades from a parent process to its children. The parent process can do what it wants with its own "environment", hack it to pieces, encrypt it in memory, copy it to some other address in the process space (which Bash does), etc. There can not be any external mechanism, nor a kernel mechanism, to inspect the environment of a process (wait – read the comment on /proc/PID/environ below). The only thing that matters is that the exporting process should collect the pieces and pass an environment to its child processes according to its own rules; in the case of Bash, the rules are listed in the Bash manual.

What this means is that the file /proc/$$/environ is deceptive. It does not reflect any changes to the shell's environment, but just reports what the shell received when it was execed by the parent process.

Johan Myréen
  • 13,168
1

No, there is not.

There are three sets of "variables" here.

  • The Bourne Again shell inherits a set of environment variables from whatever parent process forked and executed it. These remain the environment variables of the Bourne Again shell process throughout its lifetime.
  • These environment variables initialize the second set, the shell variables that the Bourne Again shell lets users see and manipulate with commands such as declare.
  • This second set of shell variables determines, by dint of which shell variables are marked as exportable (alongside a couple of other mechanisms, outwith the scope of this answer), what environment variables child processes forked by the Bourne Again shell themselves inherit after execve to run an external command in that child process.

The first set are "the environment variables of the current shell". The second set are shell variables, and the third set are environment variables of a child process.

Although it is possible for the Bourne Again shell to alter its process environment variables, and make that alteration visible to other processes, as I explained programs can do at https://unix.stackexchange.com/a/432681/5132, in practice the Bourne Again shell does not do this.

Similarly, it is possible for the Bourne Again shell to provide access to its environment variables, but it does not, only providing access to the shell variables derived from those environment variables at shell program startup.

(I mention the Bourne Again shell because of the question, but in fact most shells have similar behaviour and this isn't really specific to the Bourne Again shell.)

And of course external programs like env and printenv display the third set of variables.

To see the environment variables of the current shell process, one has to use an external command:

ps ewwww -p $$
or
hexdump -C /compat/linux/proc/$$/environ
(just /proc on Linux operating systems)

Further reading

JdeBP
  • 68,745
  • Thanks. I am not sure what you meant by "Although it is possible for the Bourne Again shell to alter its process environment variables, and make that alteration visible to other processes, as I explained programs can do at https://unix.stackexchange.com/a/432681/5132, in practice the Bourne Again shell does not do this" and "Similarly, it is possible for the Bourne Again shell to provide access to its environment variables, but it does not, only providing access to the shell variables derived from those environment variables at shell program startup." Could you rephrase and/or elaborate? – Tim Apr 16 '18 at 03:50
-1

declare -p will list everything it seems. Your question is a bit misleading because the "environment variables" are technically those that are exported, those that aren't are merely local shell variables.

xenoid
  • 8,888
  • I don’t understand how this answers the question.  Consider: Question: “How do I kill all the termites in my house?”  Answer: “Use a thermonuclear bomb, which will kill everything within a radius of a few miles.  Your question is misleading because termites are technically just a species of insect that eats wood.  People, birds, cats, dogs, earthworms, foxes, gophers, horses, and other animals that will also be killed are different species.”  … … … … … … … … … … … … … … … … … … … … …  How is the OP’s question misleading? – G-Man Says 'Reinstate Monica' Apr 12 '18 at 15:38