Diff 출력 "바이너리 파일 다릅니다." 그러나 일반적인 자세한 출력은 아닙니다.

Diff 출력 "바이너리 파일 다릅니다." 그러나 일반적인 자세한 출력은 아닙니다.

"orienv" 및 "currenv" 명령을 사용하여 두 파일을 비교하고 싶습니다 diff.

이 두 파일을 만드는 방법은 다음과 같습니다.

  1. "currenv" 파일 생성

    $cat /proc/1/environ >> currenv
    $cat /pcoc/279/environ >> currenv
    $cat /proc/295/environ >> currenv
    //295 is the pid of the current console
    
  2. orienv 파일 생성

    $printenv > orienv
    

diff그런 다음 다음과 같이 호출합니다 .

diff -u orienv currenv

다음과 같은 결과를 얻었습니다.

바이너리 orienv와 currenv가 다릅니다.

diff플래그가 있는 정상적인 출력을 기대합니다 -u(예: 차이점을 보여주는 출력).잘 생긴 남자, 다른 파일에는 없는 정보가 있는 파일을 나타냅니다.

무엇이 잘못되었나요?

답변1

환경 변수의 값에는 개행 문자가 포함될 수 있습니다. 에서 변수는 환경 변수의 값이나 이름에 나타날 수 없는 null 바이트로 구분됩니다. (이것은 우연이 아닙니다. 환경이 메모리에 표현되는 방식입니다.) diff가 널 바이트를 발견하면 파일이 바이너리라고 판단하고(정의에 따르면 텍스트 파일은 널 바이트를 포함하지 않음) 표시를 포기합니다. 차이점은 대부분의 바이너리 형식의 경우 diff 인쇄가 쓸모가 없기 때문입니다./proc/PID/environ

diff에게 계속해서 파일을 텍스트로 처리하라고 지시할 수 있지만 diff --text, 두 파일 사이에서 이 작업을 수행하면 환경에 실제로 많은 개행 문자가 포함되어 있지 않기 때문에 크게 변경된 한두 줄만 표시될 수 있습니다. Diff는 개행으로 구분된 줄에서만 작동합니다. 의 내용과 출력 사이에 이 작업을 수행하면 줄 바꿈이 구분 기호로 사용되므로 모든 것이 변경되었음을 의미합니다./proc/PID/environ/proc/PID/environprintenvprintenv

유용한 출력을 얻으려면 널 바이트를 줄 바꿈으로 변환하십시오. 이렇게 하면 각 환경 변수가 줄의 시작 부분에서 시작됩니다.

diff -u orienv --label=currenv <(tr '\0' '\n' <currenv)

유용하고 명확한 출력을 위해 개행 문자도 널 바이트로 변환되어 각 환경 변수가 자체 단일 행에 표시됩니다. 그런 다음 diff 출력에 널 바이트가 있으면 원본 파일의 해당 위치에 개행 문자가 포함되어 있음을 나타냅니다.

diff -u --text --label=currenv <(tr '\0\n' '\n\0' <currenv1) --label=currenv <(tr '\0\n' '\n\0' <currenv2)

답변2

/proc/*/environ은 텍스트 파일이 아닙니다. 문자열을 사용하세요:

strings /proc/{1,279,295}/environ >> currenv
env > orienv
diff -u orienv currenv

답변3

문제는 /proc/<pid>/environ널 바이트가 포함되어 있기 때문입니다. 로 텍스트로 표시되는 인쇄할 수 없는 바이트를 볼 수 있습니다 cat -v. 예를 들어 ^@아래 출력에서 ​​null 바이트가 표시되는 것을 볼 수 있습니다.

$ cat -v /proc/20148/environ 
CLUTTER_IM_MODULE=xim^@COLORFGBG=15;0^@COLORTERM=truecolor^@ ...cont.

그러나 환경 변수를 인쇄할 때 고려해야 할 세 가지 일반적인 문제가 있습니다.

  1. 이것ANSI 색상 이스케이프 코드 값텍스트 대신 "색상"으로 터미널에 인쇄됩니다(예 export p_red=$(tput setaf 1): . 이로 인해 diff가 원치 않는 색상을 출력하고 색상 코드 값도 손실됩니다. diff --color=always또한 색상 중단으로 인해 예상대로 작동하지 않습니다.
  2. 함수 정의에는 종종 여러 줄이 포함됩니다.. 그리고 변수 값에는 여러 줄이 포함될 수도 있습니다. 예를 들어:

    $ cat /etc/environment love=" 1st line 2nd line"

  3. sort먼저 비교하지 않으면 혼란스러운 결과가 나올 수 있습니다.

다음을 통해 이러한 모든 문제를 해결할 수 있습니다.

$ sudo cat /proc/1/environ | tr '\n\0' ' \n' | cat -v > currenv
$ sudo cat /proc/279/environ | tr '\n\0' ' \n' | cat -v >> currenv
$ sudo cat /proc/295/environ | tr '\n\0' ' \n' | cat -v >> currenv
$ sort -u currenv -o currenv
$ printenv -0 | tr '\n\0' ' \n' | cat -v | sort -u > orienv
$ diff --unified="$(cat currenv orienv | wc -l)" orienv currenv --color=always

출력은 다음과 같습니다:

...
 LOGNAME=xiaobai
 love= 1st line 2nd line
..
 PKG_CONFIG_PATH=:/usr/lib/pkgconfig:/usr/local/lib/pkgconfig
 p_lblue=^[[38;5;50m
 p_lgreen=^[[38;5;118m
 p_lred=^[[38;5;196m
 p_orig=^[(B^[[m
 p_red=^[[31m
 PROFILEHOME=
...
 QT_IM_MODULE=ibus
+recovery=
+rootmnt=/root
 S_COLORS=auto

설명하다:

  1. tr '\n\0' ' \n'약어 형식을 나타냅니다 tr '\n' ' ' | tr '\0' '\n'. 먼저 개행 문자(예: 여러 줄 값)를 \nnull로 바꾼 ' '다음 null 바이트를 \0개행 문자로 바꿉니다 '\n'. 여러 줄 값을 먼저 공백으로 바꾸기 때문에 여러 줄 값이나 null 바이트의 모호성에 대해 걱정할 필요가 없습니다.
  2. printenv-0선택 할수있다각 출력 줄은 개행 문자가 아닌 NUL로 끝납니다.. 의 출력은 printenv -0와 동일하게 동작합니다 /proc/<pid>/environ. 그래서 우리도 같은 일을 할 수 있습니다 tr '\n\0' ' \n'.
  3. sort -u>> currenv동일한 변수를 반복해서 추가하여 차이를 확인하기 어렵게 만드는 것을 방지하려면 중복 행을 정렬하고 제거하세요 .
  4. cat currenv orienv | wc -l가능한 모든 균일 값을 보려면 균일 값을 value로 설정합니다 . diff이 도구는 실제로 strtoumax()값을 변환하기 위해 호출되므로 음수 값을 전달하면 쓰레기 값을 얻게 됩니다.
  5. cat -v색상 코드를 인쇄 가능한 텍스트로 변환합니다. 이미 모든 null 바이트를 먼저 교체 cat -v했으므로 별도의 null 바이트 및 색상 코드가 필요한 것에 대해 걱정할 필요가 없습니다 .tr '\n\0' ' \n'
  6. 마지막으로 diff --color=always색상 블록(녹색/빨간색/흰색)으로 차이점을 인쇄합니다. cat -v색상 코드가 이미 변환되었으므로 색상 코드가 차등 색상을 깨뜨리는 것에 대해 걱정할 필요가 없습니다 .

관련 정보