help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: why does </proc/self/environ not work in bash?


From: Greg Wooledge
Subject: Re: why does </proc/self/environ not work in bash?
Date: Sun, 11 Feb 2024 09:16:36 -0500

On Sun, Feb 11, 2024 at 05:00:16AM +0100, Christoph Anton Mitterer wrote:
> I stumbled over something which I cannot really explain:
> 
> Doing e.g.:
>   $ tr '\000' '\n' </proc/self/environ
> in bash gives no output, while e.g. in dash
> it gives the env vars, as I'd have expected it.
> 
> First question here is: whose environment should/would it return? The
> shell's? tr's?
> I'd assume the former, because the shell sets up the redirection

I'm not sure what "/proc/self" actually is.

unicorn:~$ ls -l /proc/self
lrwxrwxrwx 1 root root 0 Feb 10 04:12 /proc/self -> 20906/
unicorn:~$ ls -l /proc/self
lrwxrwxrwx 1 root root 0 Feb 10 04:12 /proc/self -> 20907/

In this case, it seems to be using the PID of "ls" rather than the PID
of the shell.

If you wanted the shell's environment variables, you'd be better off
using $$ instead:

unicorn:~$ tr '\0' '\n' < /proc/$$/environ | head -n5
SHELL=/bin/bash
QT_ACCESSIBILITY=1
LESS=-X
QMAILSHOST=wooledge.org
QMAILHOST=wooledge.org

As far as explaining your result... this is the closest I've got to
a guess:

unicorn:~$ ( sleep 0.3 & exec 3</proc/$!/environ ; sleep 1; cat <&3 )
unicorn:~$ 

Bash forks a subshell to run tr with the redirection being performed
inside the subshell.  For whatever reason, at the time /proc/self is
evaluated, it refers to the PID of a transient process.  The shell
redirection is performed, opening the environ pseudo-file which
belongs to this transient process.

Then, the transient process exits.  Then, tr starts reading from the
open FD.  Since the transient process is gone, tr gets no data, but
also no error message.

What I can't figure out is why there's a transient process in the picture.
My expectation would be that the redirection is performed in the subshell
which goes on to call execve("tr"), and that this would cause tr to
read the environment which was inherited by this subshell, and
subsequently by tr.

But... wait, now I'm even more confused:

unicorn:~$ ( sleep 3 & exec 3</proc/$!/environ ; cat <&3 )
unicorn:~$ 

How come *that* one didn't print anything?

It's not "Linux doesn't let you read another PID's environment", because
if I manually do "cat /proc/1128/environ" (where 1128 is the PID of
another bash process besides the one where I'm typing), it works as
expected.

Is bash clearing the environment of programs that it executes?  It
shouldn't be doing that either.

But... no, it's not just bash either:

unicorn:~$ dash
$ ( sleep 3 & exec 3</proc/$!/environ ; cat <&3 )
$ 

And it's not something like "sleep clears its environment because it
doesn't need it", because:

unicorn:~$ ( sh -c 'sleep 3; echo boo' & exec 3</proc/$!/environ ; cat <&3 )
unicorn:~$ boo


I'm totally stumped here.

All I can tell you is "use $$ if you want the shell's environment".  That
much works.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]