Дифференциальные выходы "двоичные файлы отличаются", но не обычный детальный вывод

Создайте файл с именем custom.zsh в ~ / .oh-my-zsh / custom / и поместите в этот файл свои псевдонимы. Они загружаются в последнюю очередь в "oh-my-zsh".

1
17.09.2018, 09:21
3 ответа

/proc/ */environ не являются текстовыми файлами. использовать строки:

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

Значение переменной среды может содержать разрывы строк. В /proc/PID/environпеременные разделяются нулевыми байтами, которые не могут появляться в значении или имени переменной среды. (Это не случайно то, как окружающая среда представлена ​​в памяти. )Когда diff видит нулевые байты, он решает, что файл является двоичным (что верно по определению :текстовые файлы не содержат нулевые байты )и отказывается от отображения различий, потому что для большинства двоичных форматов то, что diff будет распечатывать, бесполезно.

Вы можете сказать diff, чтобы он продолжал и обрабатывать файлы как текст с помощью diff --text, но если вы сделаете это между двумя файлами /proc/PID/environ, это, вероятно, даст вам отображение, состоящее всего из одной или двух больших измененных строк., потому что на практике среда не содержит большого количества разрывов строк. Diff работает только со строками, разделенными символом новой строки. И если вы сделаете это между содержимым /proc/PID/environи выводом printenv, это будет означать, что все изменилось, потому что printenvиспользует символы новой строки в качестве разделителя.

Чтобы получить полезный вывод, преобразуйте нулевые байты в разрывы строк. Таким образом, каждая переменная среды будет начинаться с начала строки.

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
27.01.2020, 23:42

Проблема связана с тем, что /proc/<pid>/environсодержит нулевой байт. Вы можете просмотреть непечатаемый байт, представленный в виде текста cat -v, например. вы можете видеть, что ^@представляет нулевой байт в приведенном ниже выводе:

$ 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. Diff без 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'. Сначала мы заменяем новую строку (, то есть значение нескольких строк )\n, на пустое пространство ' ', а затем заменяем нулевой байт \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, чтобы увидеть все возможные унифицированные значения. Инструмент diffна самом деле вызывает strtoumax()для преобразования этого значения, поэтому вы получите мусорное значение, если передадите отрицательное значение.
  5. cat -vдля преобразования цветовых кодов в печатный текст. Нам не нужно беспокоиться о том, что cat -vнужен отдельный нулевой байт и код цвета, потому что мы уже сделали tr '\n\0' ' \n'сначала, чтобы заменить все нулевые байты.
  6. И, наконец, diff --color=alwaysдля печати различий с цветовым блоком (зеленый/красный/белый ). Нам не нужно беспокоиться о том, что цветовой код прерывает различный цвет, потому что cat -vуже преобразовал цветовой код.
0
27.01.2020, 23:42

Теги

Похожие вопросы