Como divido um arquivo "/ proc / * / environ" em linhas separadas?

19

Estou tentando obter o conteúdo de qualquer /proc/*PID*/environarquivo em formato mais legível. Consigo fazer isso da maneira mostrada abaixo, mas tenho certeza de que esse não é o caminho correto.

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

Talvez eu deva atribuir um valor específico a $IFS, mas o que é isso? Qual é a maneira correta de obter o resultado acima?

pa4080
fonte

Respostas:

25

As entradas são separadas pelo caractere 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.

Portanto, uma maneira simples é aplicar 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 - leia linhas delimitadas por nulo,
  • -L1 - leia uma linha por execução de comando
  • -a file leia linhas de file
  • e se nenhum comando for especificado, xargssimplesmente imprima a linha.

Vários comandos do GNU tem opções para trabalhar com dados delimitado por nulos: -zpara sed, sort, uniq, grepetc, e para nomes de arquivos, -print0com finde -Zcom grep.

Como alternativa, você pode usar o bash antigo simples:

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

-d ''manda readler até um byte nulo IFS=e -revita a divisão de campos e a barra invertida, para que os dados sejam lidos como estão, %qcitarão caracteres especiais na saída.

Desde que você usou sed, você poderia ter feito:

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

que adere apenas a uma nova linha no final de cada linha delimitada por nulo.

muru
fonte
1
+1 para o padrão de xargsimpressão, eu não estava ciente disso #
Vincent Fourmond
2
Porém, lembre-se de que as entradas são terminadas com nulo precisamente porque é o único caractere que não pode fazer parte de um valor. Se você substituí-los por novas linhas, é possível introduzir uma ambiguidade de se duas linhas consecutivas representam duas variáveis ​​ou uma variável cujo valor contém uma nova linha seguida pelo que parece uma atribuição.
chepner
13
  • Você poderia usar cut:

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

    usando nulo como delimitador e produzindo um delimitador de nova linha, escolhendo opcionalmente apenas determinados campos / linhas.

  • Ou filtre tr, traduzindo nulos para novas linhas:

    tr '\0' '\n' </proc/$pid/environ
  • Ou apenas fique com sua sedversão ...

Xen2050
fonte
4
Uso tr '\0' '\n'desde que me lembro. Essa é a maneira mais intuitiva de expressar "substituir todas as NULs por novas linhas" e, portanto, minha solução preferida.
Egmont
10

Você pode usar da stringsseguinte maneira:

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

Amostra da saída:

$ 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

cordas de homem

NOME

   strings - print the strings of printable characters in files.

DESCRIÇÃO

   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
fonte
1
Isso é bonito.
Prisioneiro
1

Com base na resposta do @ muru, você pode exportar essas variáveis ​​com o seguinte:

`cat /proc/1/environ | xargs -0 -L1 -I{} echo export {}`
Marcin
fonte
1
Na verdade, estou usando o comando:, export $(xargs -0 -a "/proc/$(pgrep gnome-session -n -U $UID)/environ")reference: Como posso mostrar mensagens de envio de notificação acionadas pelo crontab?
pa4080
1
@ pa4080 Ah nice
Marcin