Diff出力「バイナリファイル 違います。」しかし、一般的な詳細出力ではありません。

Diff出力「バイナリファイル 違います。」しかし、一般的な詳細出力ではありません。

「orienv」と「currenv」コマンドを使用して2つのファイルを比較したいと思いますdiff

これら2つのファイルを作成する方法は次のとおりです。

  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がNULLバイトを検出すると、ファイルがバイナリであると判断し(定義によると、テキストファイルにNULLバイトが含まれていない)、表示を放棄します。違いは、ほとんどのバイナリ形式ではdiff印刷が役に立たないためです。/proc/PID/environ

diffにファイルをテキストとして処理するよう指示し続けることができますがdiff --text、2つのファイル間でこれを行うと、実際には多くの改行文字が含まれていないため、大幅に変更された1〜2行しか表示されません。 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.

ただし、環境変数を印刷するときに考慮すべき3つの一般的な問題があります。

  1. これANSIカラーエスケープコード値テキストの代わりに「カラー」としてターミナルに印刷されます(たとえば、.diffはexport p_red=$(tput setaf 1)不要な色を出力し、カラーコードの値も失われます。色の中断のため、期待どおりに機能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'。複数行の値を最初に空白に置き換えるので、複数行の値やヌルバイトのあいまいさを心配する必要はありません。
  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カラーコードがすでに変換されているため、カラーコードが差分色を破るのを心配する必要はありません。

関連情報