¿Cómo divido un archivo "/ proc / * / environmental" en líneas separadas?

19

Estoy tratando de obtener el contenido de cualquier /proc/*PID*/environarchivo en un formato más legible. Puedo hacerlo de la manera que se muestra a continuación, pero estoy seguro de que no es la forma correcta.

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

Tal vez deba asignar un valor específico a $IFS, pero ¿qué es? ¿Cuál es la forma correcta de lograr el resultado anterior?

pa4080
fuente

Respuestas:

25

Las entradas están separadas por el carácter nulo, consulte 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.

Entonces, una forma simple es aplicarlo xargs -0 -L1:

$ 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 - leer líneas delimitadas por nulos,
  • -L1 - lee una línea por ejecución de comando
  • -a file leer líneas de file
  • y si no se especifica ningún comando, xargssimplemente imprime la línea.

Varios comandos de GNU tienen opciones para trabajar con datos nulos delimitado: -zpara sed, sort, uniq, grepetc, y para nombres de archivo, -print0con findy -Zcon grep.

Alternativamente, puede usar bash viejo y simple:

while IFS= read -d '' -r line
do
    printf "%q\n" "$line"
done < /proc/.../environ

-d ''le dice readque lea hasta un byte nulo, IFS=y que -revite la división de campos y el escape de barra invertida, de modo que los datos se lean tal como están, entre %qcomillas caracteres especiales en la salida.

Desde que lo usaste sed, podrías haber hecho:

sed -z 's/$/\n/' /proc/.../environ

que simplemente agrega una nueva línea al final de cada línea delimitada por nulos.

muru
fuente
1
+1 para el valor predeterminado de xargsimprimir, no estaba al tanto de eso
Vincent Fourmond
2
Sin embargo, tenga en cuenta que las entradas tienen terminación nula precisamente porque es el único carácter que no puede ser parte de un valor. Si los reemplaza con nuevas líneas, puede introducir una ambigüedad de si dos líneas consecutivas representan dos variables o una variable cuyo valor contiene una nueva línea seguida de lo que parece una asignación.
chepner
13
  • Podrías usar cut:

    cut -d '' -f1- --output-delimiter=$'\n' /proc/$pid/environ

    usando nulo como delimitador y generando un delimitador de nueva línea, opcionalmente seleccionando solo ciertos campos / líneas.

  • O filtre tr, traduciendo nulos a nuevas líneas:

    tr '\0' '\n' </proc/$pid/environ
  • O simplemente quédate con tu sedversión ...

Xen2050
fuente
44
Lo he estado usando tr '\0' '\n'desde que tengo memoria. Esa es la forma más intuitiva para mí de expresar "reemplazar todas las NUL por líneas nuevas" y, por lo tanto, mi solución preferida personal.
egmont
10

Puedes usar stringslo siguiente:

strings /proc/$(pgrep gnome-session -n -U $UID)/environ

Muestra de la salida:

$ 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

cuerdas de hombre

NOMBRE

   strings - print the strings of printable characters in files.

DESCRIPCIÓN

   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.
Yaron
fuente
1
eso es hermoso.
Prisionero