244

I need to troubleshoot some problems related to environment variables on a Unix system.

On Windows, I can use a tool such as ProcessExplorer to select particular a process and view values of each environment variable.

How can I accomplish the same thing on Unix? echoing and env cmd just show values at present time, but I want to view what values the running process is using currently.

Desperatuss0ccus
  • 252
  • 1
  • 4
  • 9
Gant
  • 2,585
  • 2
  • 16
  • 8
  • 3
    Even though /proc//environ has a size of 0, there's still information in there. "It makes more sense if you think of it as a window into the kernel. The file doesn't actually contain any data; it just acts as a pointer to where the actual process information resides." [[source](http://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/proc.html)] – nevets1219 Jun 10 '11 at 17:45

13 Answers13

316
cat /proc/<pid>/environ

If you want to have pid(s) of a given running executable you can, among a number of other possibilities, use pidof:

AlberT$ pidof sshd   
30690 6512 

EDIT:

I totally quote Dennis Williamson and Teddy comments to achieve a more readable output. My solution is the following:

tr '\0' '\n' < /proc/<pid>/environ
drAlberT
  • 10,871
  • 7
  • 38
  • 52
  • 50
    To make it readable, convert the nulls to newlines: `cat /proc/17330/environ | tr \\0 \\n` – Dennis Williamson Sep 17 '09 at 19:14
  • 34
    I always do `xargs --null --max-args=1 echo < /proc/PID/environ` – Teddy Oct 29 '09 at 13:08
  • 8
    better use strings, its fast. Cat is still faster :-) – Nikhil Mulley Jan 14 '12 at 19:37
  • `grep -z ^PATH /proc/25631/environ` is another way to handle the nulls and find the variable you want. – GKFX Sep 13 '16 at 14:32
  • `-z` is not available everywhere (not portable solution) .. for example on OS X `grep` does not support it – drAlberT Sep 19 '16 at 08:27
  • 3
    The whole `/proc` filesystem isn’t portable. – Daniel H Dec 16 '16 at 16:49
  • 6
    I don't understand why using `xargs` to convert nulls to newlines is better than using `tr`. Can someone lay it out for me? Thanks. – Jonathan Hartley May 09 '17 at 13:55
  • 2
    @DanielH Even if you consider only Linux **it is still wise to follow POSIX and portability**. Linux is only the kernel of the system (which provides the `/proc` interface) but the tools like `tr`, `xargs`, `grep`, `strings` etc. are part of the userland and though in most cases they can be [GNU tools](https://www.gnu.org/software/software.html) (the `xargs` and `grep` cases here) they can be also for example [BusyBox](https://busybox.net/) in which the GNU extensions will not work. --- So I agree with Jonathan Hartley that there is no good reason to use nonstandard `xargs` instead of `tr`. – pabouk - Ukraine stay strong Jul 20 '17 at 08:49
  • 1
    In busybox, can use 'xargs -0 -n 1 < /proc/self/environ' get better output. – PokerFace Mar 27 '18 at 08:19
  • Note that it only works if the caller is same user who controls this process (PID), or if the caller is `root`. – VasyaNovikov May 14 '19 at 14:19
  • Tautological observation IMHO – drAlberT May 14 '19 at 18:36
63

Since this question has a unix tag and everyone else has done such a great job addressing linux tag, you can get this information on OS X and other BSD-derived systems using

ps -p <PID> -wwwe

or

ps -p <PID> -wwwE

and on Solaris with

/usr/ucb/ps -wwwe <PID>

Solaris also supports the /proc directory if you don't want to remember the obscure ps commmand.

Mark Stewart
  • 103
  • 8
Gerald Combs
  • 6,331
  • 23
  • 35
  • 4
    I I run _ps -p -wwwe_ on OS X 10.6 I get the list of all running processes. the right command is with _-E_ flag, not -e. – drAlberT Sep 18 '09 at 08:17
  • I realized that _-e_ is equal to _-E_ only if ps is in _legacy mode_ – drAlberT Sep 18 '09 at 08:21
  • 1
    I tested on OS X 10.4, but not 10.5. Updated accordingly. – Gerald Combs Sep 18 '09 at 15:23
  • 4
    This is not perfect. The -E option only reports the _initial_ environment variables. If the variables have been changed by the running process itself (e.g. through the use of the POSIX putenv() function), the changes are not reflected in the output of `ps -p -wwE`. – Kal Mar 01 '13 at 07:11
  • I just checked on OS X 10.11 and I cannot see the environment variables of processes not owned by me (except for setuid programs such as `login` and `ps` itself). – huyz Mar 18 '17 at 02:57
  • 1
    Not seeing env vars of processes not owned by you sounds like a desirable feature. It is also the case for @drAlberT's Linux-oriented answer using `/proc/PID/environ`. Those files are only readable by the owner of the process. – Jonathan Hartley May 09 '17 at 13:58
  • For Solaris use `pargs -ae ` – Madars Vi May 26 '18 at 09:57
  • @Kal - Do you know if it is possible to get the correct info after a `putenv` call? – Yani Jun 26 '18 at 05:21
  • 1
    @yani It's possible, but it's much harder, it requires attaching a debugger to the running process. See this answer: https://unix.stackexchange.com/a/70636 – Kal Jun 26 '18 at 07:54
  • Question asks about "Environment variables of a running process on Unix". Since macOS is built on FreeBSD Unix, point goes to this cross-platform answer. – Tony Barganski Nov 09 '19 at 09:51
26

As others have mentioned, on Linux, you can look in /proc but there are, depending on your kernel version, one or two limits:

First of all, the environ file contains the environment as it looked when the process was spawned. That means that any changes the process might have made to its environment will not be visible in /proc:

$ cat /proc/$$/environ | wc -c
320
$ bash
$ cat /proc/$$/environ | wc -c
1270
$ 

The first shell is a login shell and initially has a very limited environment but grows it by sourcing e.g. .bashrc but /proc does not reflect this. The second shell inherits the larger environment from the start, which it why it shows in /proc.

Also, on older kernels, the contents of the environ file is limited to a page size (4K):

$ cat /proc/$$/environ | wc -c
4096
$ env | wc -c
10343
$ 

Somewhere between 2.6.9 (RHEL4) and 2.6.18 (RHEL5) this limit was removed...

Lasse
  • 416
  • 3
  • 6
  • 1
    Is it possible to get the environmental variables of a remote process that were set after the process is spawned? I understand that on VFS, it is showed with /proc/self/environ but only if we are inside the process. But how to get this for a remote process? – GP92 Jan 04 '18 at 02:36
  • Whew! Thanks for this answer hopefully still holds true. So environment variables on startup are visible to other users and processes on the system via /proc//environ/. Run-time changes to the environment are not accessible via /proc/, but if it spawns another process the env var will end up visible in its /proc/. I guess that's why secrets should not be configured via environment variables when using containers and instead via secret files coordinated by the orchestration system or vault api. – jamshid Jul 04 '20 at 00:55
12

correct usage of BSD options to do this (at least on linux):

ps e $pid

or

ps auxe  #for all processes

and yes, ps manpage is pretty confusing. (via)

raincrumb
  • 221
  • 2
  • 2
  • My Ubuntu smashes the environment variables right up against the command line, without even so much as a space between them, and also truncates to one line on the terminal window. I found `ps eww $pid` fixes the 2nd problem. – user18911 Dec 03 '13 at 14:42
  • 1
    @user18911: The env vars have a null character separator. Other answers on this page show ways to use `xargs` or `tr` to convert these to newlines for readability. You probably realised this in the intervening four years. – Jonathan Hartley May 09 '17 at 14:01
11

While rather sparsely documented, the contents of /proc/<pid>/environ will only contain the environment that was used to start the process.

If you need to inspect the current state of a process' environment, one way to do that is by using gdb.

# Start gdb by attaching it to a pid or core file
gdb <executable-file> <pid or core file>

# Run the following script to dump the environment
set variable $foo = (char **) environ
set $i = 0
while ($foo[$i] != 0)
print $foo[$i++]
end
Michael Renner
  • 1,750
  • 13
  • 17
  • 1
    It could be better by putting those commands, plus a `quit` command in the end into a `.gdb` file, such as `~/penv.gdb`; then starts `gdb(1)` with this GDB script any time when you want to exam the environment of a process, by running `gdb -x ~/penv.gdb -p []`. – Low power Nov 29 '19 at 04:41
7

Taken from the Archlinux wiki:

You can create a temporary function to parse the values in /proc/<pid>/environ. At the terminal prompt:

envof() { sed 's/\x0/\n/g' /proc/${1}/environ; }

Then with the pid of the process you want, just use:

envof <pid>
mwotton
  • 171
  • 1
  • 2
7
cat /proc/PID/environ

replace PID with the PID of the process you want to see. Every information about a running process is under /proc/PID/ directory

example: cat /proc/32512/environ

kargig
  • 316
  • 1
  • 2
6

For Solaris 5.10, this works:

pargs -e <PID>
Chris S
  • 77,337
  • 11
  • 120
  • 212
Nikolai Novik
  • 61
  • 1
  • 3
6

Under Linux, I'd try having a look at

/proc/<pid>/environ
Joril
  • 1,513
  • 1
  • 19
  • 27
4

And since my job makes me be an AIX fan boy, let us not forget:

ps eww [pid]

Or as the man page calls it, "Berkeley Standards".

For whatever reason, /proc/PID/environ does not exist in AIX.

Corey S.
  • 2,379
  • 1
  • 18
  • 23
4

If you want to create formatted env like output of the environment variables for an arbitrary process (PID), you can create a convenient bash penv <pid> command (tailored to your OS) and add it to your .bashrc:

Linux add this to your ~/.bashrc:

penv () { 
    xargs --null --max-args=1 < /proc/$1/environ
}

macOS / BSD add this to your ~/.bashrc:

penv() {
   ps eww -o command $1  | tr ' ' '\n'
}

Solaris add this to your ~/.bashrc:

penv() {
   pargs -e $1
}

Usage:

$ source $HOME/.bashrc
$ pgrep VBoxSVC
10268
$ penv 10268
SSH_CONNECTION=1.1.1.242 53960 1.1.1.91 22
GREP_COLORS=sl=49;39:cx=49;39:mt=49;38;5;167;1:fn=49;39;1:ln=49;39:bn=49;39:se=50;39
LANG=en_US.UTF-8
EDITOR=vim
XDG_SESSION_ID=106
USER=root
PWD=/root
HOME=/root
SSH_CLIENT=1.1.1.242 53960 22
SSH_TTY=/dev/pts/3
MAIL=/var/mail/root
TERM=xterm-256color
SHELL=/bin/bash
SHLVL=1
LOGNAME=root
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus
XDG_RUNTIME_DIR=/run/user/0
PATH=/root/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:.
VBOX_LOG_FLAGS=thread tsc
VBOX_LOG=-all+dev_vmm_backdoor.e.l.f+dev_vmm.e.l.f
clearlight
  • 153
  • 5
0

A mac solution, probably other BSDs as well could be something like

pid=28369; ps e $pid | cut -c$(expr 1 + $(ps p $pid|tail +2|wc -c))-

The environment variables are appended to the command line, this removes the command line and we only have the environment variables left.

It is not perfect because they are space separated not LF separated

Erik Martino
  • 113
  • 4
-1

/proc/PID/environ

for this, first we need to identify the PID of the process. for this you can use ps command

varun
  • 1