How do I split a "/proc/*/environ" file in separate lines?
I'm trying to get the content of any /proc/*PID*/environ
file in more readable format. I'm able to do that in the way shown below, but I'm sure this isn't the proper way.
$ cat "/proc/$(pgrep gnome-session -n -U $UID)/environ"
USER=spasTEXTDOMAIN=im-configXDG_SEAT=seat0XDG_SESSION_TYPE=waylandSHLVL=1QT4_IM_MODULE=ximHOME=/home/spasDESKTOP_SESSION=ubuntuGNOME_SHELL_SESSION_MODE=ubuntuDBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/busIM_CONFIG_PHASE=2LOGNAME=spasGTK_IM_MODULE=ibusJOURNAL_STREAM=9:147845_=/usr/bin/gnome-sessionUSERNAME=spasXDG_SESSION_ID=70PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/binXDG_RUNTIME_DIR=/run/user/1000LANG=en_US.UTF-8XDG_CURRENT_DESKTOP=ubuntu:GNOMEXDG_SESSION_DESKTOP=ubuntuXMODIFIERS=@im=ibusSHELL=/bin/bashGDMSESSION=ubuntuTEXTDOMAINDIR=/usr/share/locale/XDG_VTNR=2QT_IM_MODULE=ximPWD=/home/spasCLUTTER_IM_MODULE=ximXDG_DATA_DIRS=/usr/share/ubuntu:/usr/local/share:/usr/share:/var/lib/snapd/desktopXDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg
$ cat -e "/proc/$(pgrep gnome-session -n -U $UID)/environ"
USER=spas^@TEXTDOMAIN=im-config^@XDG_SEAT=seat0^@XDG_SESSION_TYPE=wayland^@SHLVL=1^@QT4_IM_MODULE=xim^@HOME=/home/spas^@DESKTOP_SESSION=ubuntu^@GNOME_SHELL_SESSION_MODE=ubuntu^@DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus^@IM_CONFIG_PHASE=2^@LOGNAME=spas^@GTK_IM_MODULE=ibus^@JOURNAL_STREAM=9:147845^@_=/usr/bin/gnome-session^@USERNAME=spas^@XDG_SESSION_ID=70^@PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin^@XDG_RUNTIME_DIR=/run/user/1000^@LANG=en_US.UTF-8^@XDG_CURRENT_DESKTOP=ubuntu:GNOME^@XDG_SESSION_DESKTOP=ubuntu^@XMODIFIERS=@im=ibus^@SHELL=/bin/bash^@GDMSESSION=ubuntu^@TEXTDOMAINDIR=/usr/share/locale/^@XDG_VTNR=2^@QT_IM_MODULE=xim^@PWD=/home/spas^@CLUTTER_IM_MODULE=xim^@XDG_DATA_DIRS=/usr/share/ubuntu:/usr/local/share:/usr/share:/var/lib/snapd/desktop^@XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg^@
$ cat -e "/proc/$(pgrep gnome-session -n -U $UID)/environ" | sed 's/\^@/\n/g'
USER=spas
TEXTDOMAIN=im-config
XDG_SEAT=seat0
XDG_SESSION_TYPE=wayland
...
Maybe I must assign a specific value to $IFS
, but what is it? What is the proper way to achieve the above result?
Solution 1:
The entries are separated by the null character, see man 5 proc
:
/proc/[pid]/environ
This file contains the environment for the process. The entries
are separated by null bytes ('\0'), and there may be a null byte
at the end.
So a simple way is to apply xargs -0 -L1
on it:
$ xargs -0 -L1 -a /proc/self/environ
LC_CTYPE=UTF-8
USER=muru
LOGNAME=muru
HOME=/home/muru
MAIL=/var/mail/muru
SHELL=/bin/zsh
...
-
-0
- read null-delimited lines, -
-L1
- read one line per execution of command -
-a file
read lines fromfile
- and if no command is specified,
xargs
simply prints the line.
Various GNU commands have options to work with null-delimited data: -z
for sed
, sort
, uniq
, grep
etc, and for filenames, -print0
with find
and -Z
with grep.
Alternatively, you can use plain old bash:
while IFS= read -d '' -r line
do
printf "%q\n" "$line"
done < /proc/.../environ
-d ''
tells read
to read until a null byte, IFS=
and -r
prevent field-splitting and backslash-escaping, so that the data is read as-is, %q
will quote special characters in output.
Since you did use sed
, you could have done:
sed -z 's/$/\n/' /proc/.../environ
which just tacks on a newline at the end of each null-delimited line.
Solution 2:
-
You could use
cut
:cut -d '' -f1- --output-delimiter=$'\n' /proc/$pid/environ
using null as a delimiter, and outputting a newline delimiter, optionally picking only certain fields/lines.
-
Or filter through
tr
, translating nulls to newlines:tr '\0' '\n' </proc/$pid/environ
Or just stick with your
sed
version...
Solution 3:
You can use strings
as follows:
strings /proc/$(pgrep gnome-session -n -U $UID)/environ
Sample of the output:
$ strings /proc/$(pgrep gnome-session -n -U $UID)/environ
GNOME_KEYRING_PID=
LANGUAGE=en_US
J2SDKDIR=/usr/lib/jvm/java-8-oracle
LC_TIME=en_US.UTF-8
XDG_SEAT=seat0
XDG_SESSION_TYPE=x11
COMPIZ_CONFIG_PROFILE=ubuntu
SESSION=ubuntu
man strings
NAME
strings - print the strings of printable characters in files.
DESCRIPTION
For each file given, GNU strings prints the printable character sequences that are at least 4 characters long (or the number given with the options below) and are followed by an unprintable character. By default, it only prints the strings from the initialized and loaded sections of object files; for other types of files, it prints the strings from the whole file. strings is mainly useful for determining the contents of non-text files.
Solution 4:
Building on @muru's answer, you can then export those variables with the following:
`cat /proc/1/environ | xargs -0 -L1 -I{} echo export {}`