今天,我正在使用装有 Debian 12 Bookworm 的 Raspberry Pi 4,我发现一些系统文本文件很奇怪,我需要这两个:
/sys/firmware/devicetree/base/model
/sys/firmware/devicetree/base/serial-number
读取并存储在变量中bash
如下:
rpi_model_name=$(cat /sys/firmware/devicetree/base/model)
rpi_serial_number=$(cat /sys/firmware/devicetree/base/serial-number)
产生以下警告,我无法通过重定向stderr
来消除/dev/null
例如:
warning: command substitution: ignored null byte in input
提到的重定向看起来像这个命令片段;请注意,我们仍然会收到令人讨厌的警告:
rpi_model_name=$(cat /sys/firmware/devicetree/base/model 2>/dev/null)
-bash: warning: command substitution: ignored null byte in input
我刚安装了两个 shell,bash
和dash
。虽然没有那个警告,但dash
行为正常bash
;似乎更拗口。所以,目前,我不确定其他 shell 是否也会发出这个或类似的警告。
我的目标是在所有 shell 中隐藏此警告。我不关心它的来源或值,我只希望它消失。
为了可移植性,解决方案必须以 POSIX 形式编写。
这对我使用 Debian 12 Bookworm 的 Raspberry Pi 4 来说是有效的,它应该是一个可移植的解决方案(遵守 POSIX)。
我们可以将所有 NULL 字符转换为空字符串,从而使用
tr
实用程序(POSIX 手册页)从字符串中有效地删除其出现的所有位置(我们知道在我的情况下,两种情况下都只有一个字符串和一个末尾的 NULL 字符,所以我们不会删除多个 NULL 字符,只删除字符串末尾的一个。)让我们以第一个提到的文件为例(
/proc/device-tree/model
按照Marcus Müller的回答阅读可能会更好):甚至摆脱
cat
:以下内容
printf
可以与 ,.. 互换echo
,只要您觉得舒服即可:应该输出类似这样的内容:
这可能不是唯一的方法,请随意发布您自己的方法,或改进这个答案。
忽略或明确删除未知数量的零字节而不了解它们的来源似乎不是一个好主意!所以,让我们实际看看它们来自哪里,以及在什么情况下我们可能想要删除它。
首先,为什么会出现错误?shell 字符串本身在内部是一个以零结尾的字符串(如果您熟悉该编程语言,则为“C 字符串”)。因此,它不能包含 0 字节;这始终表示字符串的结尾。因此,当您尝试在 bash(或任何其他 POSIX shell)中的字符串中存储带有零字节的内容时,该字符串会“清除”所有 0 字节,否则您会将整个输出保存到该字符串变量中,但无论何时读取它,您只会获得直到(但不包括)第一个0字节的所有字符。Bash 程序员知道这是错误的一大来源,所以他们会警告您。
现在,我们可以安全地从输入中删除这些字节而不破坏它吗?
根据内核文档,这是:
因此,设备树
string
类型属性以 0 字节结尾,而stringlist
类型属性则是多个以 0 结尾的字符串,它们只是连接在一起。因此,在您的例子中,模型字段正确地以零字节结尾;这是精确二进制数据的一部分,因此也存在于 sysfs 条目中。但因为我们知道这是最后一个字节,
可以工作。而且,额外的好处是,如果这实际上不是一个单独的字符串,而是多个连接在一起的字符串(例如,您会在
compatible
条目中看到这种情况!),您仍然会收到警告,而不是一些没有空格的乱七八糟的东西。当然,您可能希望更一般地处理这个问题:如果某个东西是字符串列表,您可能仍然希望读取它,然后按元素方式使用它(例如用于打印)或者将其连接起来,例如与换行符或空格连接。
除此之外,您不应该
/sys/firmware/devicetree/base
直接使用这些路径,而应该将其用作/proc/device-tree/base/
前缀。这保证在下一次内核更新时仍然有效,但可能会消失。(这些实际上/sys/firmware/devicetree/
不是存储在某个地方的文件——这只是 sysfs 中表示的解析的设备树结构。它是在您读取时由内核计算的,而不是存储在磁盘上的某个文件。因此,它们的存在基本上是这里内核的 API——内核开发人员说“请通过 /proc 访问,另一部分是我们当前使用的,但我们不能保证它不会改变。/proc 路径,我们保证。”。)按照我对抑制 echo 命令的执行跟踪?的回答,尝试
或者