Se eu examinar /proc/1/environ
, posso ver uma sequência delimitada por bytes nulos das 1
variáveis de ambiente do processo . Eu gostaria de trazer essas variáveis para o meu ambiente atual. Existe uma maneira fácil de fazer isso?
A proc
página de manual fornece um trecho que ajuda a imprimir cada variável de ambiente, linha por linha (cat /proc/1/environ; echo) | tr '\000' '\n'
. Isso me ajuda a verificar se o conteúdo está correto, mas o que realmente preciso fazer é originar essas variáveis na minha sessão atual do bash.
Como faço isso?
fonte
. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/nnn/environ)
, que também manipulará variáveis com aspas."$@"
vez de'{}'
. Para aqueles que se perguntam sobre o--
argumento em sua resposta aprimorada: argumentos posicionais abash -c command_string
são atribuídos a partir de$0
, enquanto"$@"
expande para incluir argumentos a partir de$1
. O argumento--
é atribuído a$0
.Em
bash
você pode fazer o seguinte. Isso funcionará para todo o conteúdo possível das variáveis e evitaeval
:Isso declarará as variáveis de leitura como variáveis do shell no shell em execução. Para exportar as variáveis para o ambiente shell em execução:
fonte
Nesta resposta, assumo um sistema em que
/proc/$pid/environ
retorna o ambiente do processo com o PID especificado, com bytes nulos entre as definições de variáveis. ( Então Linux, Cygwin ou Solaris (?) ).Zsh
(O zsh é bastante simples: um redirecionamento de entrada sem comando
<FILE
é equivalente acat FILE
. A saída da substituição de comando passa por expansão de parâmetro com os sinalizadores queps:\000:
significam "divisão em bytes nulos" e@
que "se tudo estiver entre aspas duplas, então trate cada elemento da matriz como um campo separado "(generalização"$@"
).)Bash, mksh
(Nessas shells, um delimitador vazio transmitido
read
resulta em bytes nulos sendo separadores. Eu usoPWD
como um nome de variável temporário para evitar atrapalhar outra variável que pode acabar sendo importada. Embora você também pudesse importar tecnicamentePWD
, ele só ficaria parado até o próximocd
.)POSIX
A portabilidade POSIX não é tão interessante para esta questão, porque se aplica apenas aos sistemas que possuem
/proc/PID/environ
. Portanto, a questão é o que o Solaris sed suporta - ou se o Solaris tem/proc/PID/environ
, mas não estou acostumado, mas estou muito atrasado nos recursos do Solaris, o que pode acontecer nos dias de hoje. No Linux, os utilitários GNU e o BusyBox são seguros para nulos, mas com ressalvas.Se insistirmos na portabilidade do POSIX, nenhum dos utilitários de texto POSIX será necessário para lidar com bytes nulos, portanto, isso é difícil. Aqui está uma solução que assume que o awk suporta um byte nulo como o delimitador de registro (nawk e gawk, assim como o BusyBox awk, mas o mawk não).
O BusyBox awk (que é a versão comumente encontrada nos sistemas Linux embarcados) suporta bytes nulos, mas não está definido
RS
como"\0"
em umBEGIN
bloco e nem a sintaxe da linha de comando acima; no entanto, suporta-v 'RS="\0"'
. Eu não investiguei o porquê, isso parece um bug na minha versão (Debian wheezy).(Quebre todas as
linhasregistros separados por nulo entre aspas simples"\047"
, depois de escapar das aspas simples dentro dos valores.)Ressalvas
Lembre-se de que qualquer uma dessas opções pode tentar definir variáveis somente leitura (se o seu shell tiver variáveis somente leitura).
fonte
Eu voltei e voltei com isso. Fiquei frustrado com a portabilidade de bytes nulos. Não me ocorreu bem que não havia uma maneira confiável de lidar com eles em uma concha. Então eu continuei olhando. A verdade é que encontrei várias maneiras de fazer isso, das quais apenas duas são mencionadas na minha outra resposta. Mas os resultados foram pelo menos duas funções de shell que funcionam assim:
Primeiro vou falar sobre a
\0
delimitação. Na verdade, é muito fácil de fazer. Aqui está a função:Basicamente,
od
levastdin
e grava emstdout
cada byte que recebe em hexadecimal um por linha.Aposto que você pode adivinhar qual é o
\0null
certo? Escrito assim, é fácil lidar com qualquer umsed
.sed
apenas salva os dois últimos caracteres em cada linha até encontrar um nulo; nesse ponto, substitui as novas linhas intermediárias peloprintf
código de formato amigável e imprime a string. O resultado é uma\0null
matriz delimitada de cadeias de bytes hexadecimais. Veja:Eu canalizei o acima para
tee
que você pudesse ver a saída do comando susbstitution e o resultado doprintf
processamento. Espero que você observe que o subshell também não é citado, masprintf
ainda é dividido apenas no\0null
delimitador. Veja:Também não há aspas nessa expansão - não importa se você citou ou não. Isso ocorre porque os valores da mordida são apresentados sem separação, exceto pela linha de
\n
ew gerada para cada vez quesed
uma string é impressa. A divisão de palavras não se aplica. E é isso que torna isso possível:A função acima usa
_zedlmt
para${pcat}
um fluxo preparado de código de bytes para a origem do ambiente de qualquer processo que possa ser encontrado/proc
ou diretamente para.dot
${psrc}
o mesmo no shell atual, ou sem um parâmetro, para exibir uma saída processada do mesmo para o terminal, comoset
ouprintenv
vontade. Tudo que você precisa é de$pid
- qualquer/proc/$pid/environ
arquivo legível fará.Você o usa assim:
Mas qual é a diferença entre humano amigável e fonte ? Bem, a diferença é que faz com que essa resposta seja diferente de todas as outras aqui - incluindo a minha outra. Qualquer outra resposta depende do shell citar de uma maneira ou de outra para lidar com todos os casos extremos. Simplesmente não funciona tão bem. Por favor, acredite em mim - eu tentei. Veja:
NENHUMA quantidade de caracteres descolados ou citações contidas pode quebrar isso porque os bytes de cada valor não são avaliados até o instante em que o conteúdo é originado. E já sabemos que funcionou como um valor pelo menos uma vez - não há proteção de análise ou cotação necessária aqui, porque esta é uma cópia de byte a byte do valor original.
A função primeiro avalia os
$var
nomes e aguarda a conclusão das verificações antes.dot
de fornecer o documento aqui, alimentado pelo descritor de arquivo 3. Antes de fornecê-lo, é assim que parece. É à prova de idiotas. E POSIX portátil. Bem, pelo menos a manipulação \ 0null é POSIX portátil - o sistema de arquivos / process é obviamente específico do Linux. E é por isso que existem duas funções.fonte
Usando
source
e substituindo processo :Em breve:
Usando
eval
e substituição de comando :A
sed
chamada pode ser substituída por umaawk
chamada:Mas não esqueça que ele não limpa as variáveis de ambiente que não estão no pid 1.
fonte
Vale notar que os processos podem ter variáveis de ambiente que não são válidas variáveis Bash / Sh / * sh - o POSIX recomenda, mas não exige que as variáveis de ambiente tenham nomes correspondentes
^[a-zA-Z0-9_][a-zA-Z0-9_]*$
.Para gerar uma lista de variáveis compatíveis com shell do ambiente de outro processo, no Bash:
Da mesma forma, para carregá-los:
Esse problema surge apenas ocasionalmente, mas quando ocorre ...
fonte
Eu acho que isso é POSIX portátil:
Mas o @Gilles faz um bom argumento -
sed
provavelmente manipulará nulos, mas talvez não. Então tem isso (eu realmente acho que dessa vez) método realmente portátil POSIX:Ainda assim, se você possui o GNU,
sed
basta fazer o seguinte:Bem, o POSIX portable, exceto o
/dev/...
que não está especificado, mas você pode esperar que a sintaxe se comporte da mesma maneira na maioria dos Unices.Agora, se isso tem algo a ver com sua outra pergunta , você pode usá-lo assim:
O documento aqui é extremamente útil, pois evita que o shell se estrague com qualquer uma das citações que trabalhamos tão duro para manipular no subshell e também fornece um caminho confiável para um arquivo
.dot
fonte, em vez de, novamente, um subshell ou shell variável. Outros aqui usam o bashismo que funciona da mesma maneira - apenas é definitivamente um anônimo, enquanto o POSIX especifica apenas um para here-docs e, portanto, pode ser qualquer tipo de arquivo, embora, na prática, seja geralmente um arquivo. ( por outro lado, usa informações anônimas<(process substitution)
|pipe
iohere
temp
dash,
|pipes
para documentos aqui) . O lamentável sobre a substituição de processos, no entanto, é que também depende do shell - o que pode ser um problema especialmente irritante se você estiver trabalhandoinit
.Isso também funciona
|pipes
, é claro, mas você perde o ambiente novamente no final, quando o|pipe's
estado evapora com seu subshell. Então, novamente, isso funciona:A
sed
instrução em si funciona mantendo todas as linhas na memória até chegar à última, quando executa uma manipulação global de substituição, citando e inserindo novas linhas, quando apropriado, ancorando nos nulos. Bastante simples, na verdade.Na
dash
foto, você verá que optei por evitar a \ mess e adicionei a opçãoGNU
específica-r
ased
. Mas isso é apenas porque era menos para digitar. Funciona de qualquer maneira, como você pode ver nazsh
imagem.Aqui está
zsh
:E aqui está
dash
a mesma coisa:Até as fugas do terminal passam ilesas:
fonte
/proc/PID/environ
. Portanto, a questão é o que o Solaris sed suporta - ou se o Solaris possui/proc/PID/environ
, não costumava, mas estou por trás da curva nos recursos do Solaris, para que possa nos dias de hoje.)sed
é necessário lidar com ascii hexadecimal, dos quais o byte nulo é um. Além disso, na verdade, eu pensei apenas se uma maneira muito mais fácil de fazer isso ainda.\xNN
sintaxe não é necessária no POSIX, nem mesmo na\OOO
sintaxe octal (nas seqüências de caracteres C e no awk, sim, mas não nos regexps sed)./proc/PID/environ
afinal (ele tem várias outras entradas semelhantes ao Linux/proc/PID
, mas nãoenviron
). Portanto, uma solução portátil não precisa ir além das ferramentas Linux, o que significa GNU sed ou BusyBox sed. Ambos suportam\x00
em uma regexp, portanto, seu código é tão portátil quanto necessário (mas não POSIX). É excessivamente complexo.fonte