我想使用命令比较两个文件 - “orienv”和“currenv” diff
。
我创建这两个文件的方式如下:
创建“currenv”文件
$cat /proc/1/environ >> currenv $cat /pcoc/279/environ >> currenv $cat /proc/295/environ >> currenv //295 is the pid of the current console
创建 orienv 文件
$printenv > orienv
然后我打电话diff
如下
diff -u orienv currenv
并得到以下输出
二进制文件 orienv 和 currenv 不同
我期待一个diff
带有标志的正常输出-u
(例如,它显示了hunks差异的输出,指示哪个文件具有另一个文件没有的信息。
什么地方出了错?
环境变量的值可以包含换行符。在中,变量由空字节分隔,空字节不能出现在环境变量的值或名称中。(这并非巧合的是,环境在内存中的表示方式。)当 diff 看到空字节时,它决定文件是二进制文件(根据定义这是真的:文本文件不包含空字节)并放弃显示差异,因为对于大多数二进制格式,打印出来的差异是没有用的。
/proc/PID/environ
您可以使用 告诉 diff 继续并将文件视为文本
diff --text
,但如果您在两个文件之间执行此操作,这可能会给您一个仅包含一两个大更改行的显示,因为实际上环境不会包含许多换行符。Diff 仅适用于用换行符分隔的行。如果您在 的内容和输出之间执行此操作,则表示一切都已更改,因为使用换行符作为分隔符。/proc/PID/environ
/proc/PID/environ
printenv
printenv
要获得有用的输出,请将空字节转换为换行符。这样,每个环境变量都将从行首开始。
为了获得有用且明确的输出,还将换行符转换为空字节,以便每个环境变量都在自己的单行上。然后,如果 diff 输出中有一个空字节,则表明原始文件在此位置包含换行符。
/proc/*/environ 不是文本文件。使用字符串:
问题是因为
/proc/<pid>/environ
包含空字节。您可以查看以文本表示的不可打印字节cat -v
,例如,您可以在下面的输出中看到^@
表示空字节:尽管如此,在打印环境变量时需要考虑三个常见问题:
export p_red=$(tput setaf 1)
. 这会导致您的 diff 输出不需要的颜色,并且还缺少颜色代码值。diff --color=always
由于颜色中断,也不会按预期工作。函数定义通常包含多行。并且变量值也可能包含多行。例如:
$ cat /etc/environment love=" 1st line 2nd line"
sort
没有first 的Diff会得到令人困惑的结果。您可以通过以下方式解决所有这些问题:
输出将是这样的:
说明:
tr '\n\0' ' \n'
表示 的缩写形式tr '\n' ' ' | tr '\0' '\n'
。我们先将换行符(即多行值)替换\n
为空白' '
,然后将空字节替换\0
为换行符'\n'
。我们不必担心多行可以是值或空字节的歧义,因为我们首先用空格替换多行值。printenv
可以-0
选择以NUL 结束每个输出行,而不是 newline。的输出printenv -0
将与/proc/<pid>/environ
. 所以我们可以做同样的事情tr '\n\0' ' \n'
。sort -u
进行排序,并删除重复的行以避免>> currenv
继续附加相同的变量并且很难看到差异。cat currenv orienv | wc -l
以查看所有可能的统一值。diff
工具实际上调用strtoumax()
以转换该值,因此如果您传递负值,您将获得垃圾值。cat -v
将颜色代码转换为可打印文本。我们无需担心cat -v
需要单独的空字节和颜色代码,因为我们已经tr '\n\0' ' \n'
首先替换了所有空字节。diff --color=always
使用色块(绿色/红色/白色)打印差异。我们不必担心颜色代码会中断差异颜色,因为cat -v
已经转换了颜色代码。