Gostaria de comparar dois arquivos - "orienv" e "currenv", usando o comando diff
.
A forma como criei os dois arquivos foi a seguinte:
Criando o arquivo "currenv"
$cat /proc/1/environ >> currenv $cat /pcoc/279/environ >> currenv $cat /proc/295/environ >> currenv //295 is the pid of the current console
Criando o arquivo orienv
$printenv > orienv
Então eu liguei diff
como segue
diff -u orienv currenv
e obtive a seguinte saída
Arquivos binários orienv e currenv diferem
Eu estava esperando uma saída normal diff
com o sinalizador -u
(por exemplo, saída em que mostra as diferenças em hunks , indicando qual arquivo tem quais informações que o outro não tem.
O que deu errado?
O valor de uma variável de ambiente pode conter quebras de linha. Em , as variáveis são separadas por bytes nulos, que não podem aparecer no valor ou no nome de uma variável de ambiente. (Esta é, não por coincidência, como o ambiente é representado na memória.) Quando o diff vê bytes nulos, ele decide que o arquivo é binário (o que é verdade por definição: arquivos de texto não contêm bytes nulos) e desiste de exibir diferenças, porque para a maioria dos formatos binários o que diff seria impresso não é útil.
/proc/PID/environ
Você pode dizer ao diff para ir em frente e tratar os arquivos como texto com
diff --text
, mas se você fizer isso entre dois arquivos, isso provavelmente fornecerá uma exibição consistindo em apenas uma ou duas grandes linhas alteradas, porque na prática o ambiente não contêm muitas quebras de linha. Diff só funciona com linhas separadas por um caractere de nova linha. E se você fizer isso entre o conteúdo de e a saída de , isso dirá que tudo mudou, porque usa novas linhas como separador./proc/PID/environ
/proc/PID/environ
printenv
printenv
Para obter uma saída útil, traduza os bytes nulos em quebras de linha. Dessa forma, cada variável de ambiente começará no início de uma linha.
Para obter uma saída útil e inequívoca, também traduza as quebras de linha em bytes nulos, para que cada variável de ambiente fique em sua própria linha. Então, se houver um byte nulo na saída do diff, isso indica que o arquivo original contém uma nova linha nesta posição.
/proc/*/environ não são arquivos de texto. usar cordas:
O problema é porque
/proc/<pid>/environ
contém byte nulo. Você pode ver o byte não imprimível representado como texto porcat -v
, por exemplo, você pode ver^@
representa o byte nulo na saída abaixo:Apesar disso, há três problemas comuns que precisam ser considerados ao imprimir variáveis de ambiente:
export p_red=$(tput setaf 1)
. Isso faz com que seu diff produza uma cor indesejada e também perca o valor do código de cor.diff --color=always
também não funcionará como esperado por causa das cores interrompidas.A definição de função normalmente contém várias linhas . E também é possível que o valor da variável contenha várias linhas. por exemplo:
$ cat /etc/environment love=" 1st line 2nd line"
sort
primeiro obterá resultado confuso.Você pode resolver todos esses problemas com:
A saída seria assim:
Explicações:
tr '\n\0' ' \n'
significa abreviação detr '\n' ' ' | tr '\0' '\n'
. Substituímos newline (ou seja, valor de várias linhas)\n
para espaço vazio' '
primeiro, depois substituímos byte nulo\0
por newline'\n'
. Não precisamos nos preocupar com a ambiguidade de várias linhas que podem valorar ou byte nulo, porque estamos substituindo o valor de várias linhas por espaço primeiro.printenv
tem-0
a opção de terminar cada linha de saída com NUL, não com nova linha . E a saída deprintenv -0
seria o mesmo comportamento que/proc/<pid>/environ
. E assim podemos fazer a mesma coisatr '\n\0' ' \n'
.sort -u
para ordenar, e também remover linhas duplicadas para evitar>> currenv
manter anexar as mesmas variáveis e difícil ver a diferença.cat currenv orienv | wc -l
para ver todos os valores unificados possíveis.diff
tool realmente chamastrtoumax()
para converter esse valor, então você obterá um valor de lixo se passar um valor negativo.cat -v
para converter códigos de cores em texto imprimível. Não precisamos nos preocupar com acat -v
necessidade de separar o byte nulo e o código de cores porque já fizemostr '\n\0' ' \n'
primeiro para substituir todos os bytes nulos.diff --color=always
para imprimir o diff com bloco de cores (verde/vermelho/branco). Não precisamos nos preocupar com o código de cores interromper a cor do diff porque ocat -v
código de cores já foi convertido.