【问题标题】:file command generating 'invalid argument'文件命令生成“无效参数”
【发布时间】:2014-11-10 10:00:58
【问题描述】:

我有一个遍历一组目录的 perl 脚本,当它遇到其中一个时,它会因无效参数而爆炸,我希望能够以编程方式跳过它。我以为我可以从使用 file 命令找出文件类型开始,但它也像这样爆炸:

$ file /sys/devices/virtual/net/br-ex/speed
/sys/devices/virtual/net/br-ex/speed: ERROR: cannot read `/sys/devices/virtual/net/br-ex/speed' (Invalid argument)

如果我使用 perl 或 python stat 函数打印出文件的模式,它会告诉我 33060,但我不确定所有位的含义,我希望某个特定的位会告诉我不要尝试查看里面。有什么建议吗?

【问题讨论】:

  • 如果您查看带有ls -l/sys/devices/virtual/net/br-ex 目录会发生什么?该文件的权限是什么?我怀疑这不是一个真实的文件(很像 /dev/null 不是 real 文件)。我打赌你会看到类似crw-rw-rwbrw-rw-rw 的东西,这意味着它是一个特殊文件。
  • /sys 是一个虚拟文件系统,通过文件系统提供内核存储的硬件信息。但是,这些条目与真实文件不对应。但是,元数据具有误导性,因为即使 stat 也将此类文件报告为常规文件。
  • 可以安全地假设 /sys 是您将看到用于 sysfs 的唯一名称,因此您可以硬编码您的脚本以忽略它。

标签: linux bash


【解决方案1】:

要了解你得到的统计数字,你需要将数字转换为八进制(在 python 中oct(...))。

然后你会看到33060 解释为100444。您只对最后三位数字 (444) 感兴趣。第一位是文件所有者权限,第二位是组,第三位是其他所有人。

您可以按以下顺序将每个数字(在您的情况下都是 4)视为 3 个二进制位: 读写执行。

由于在您的情况下,所有者、组和其他具有 4,因此(对于所有这些)它被转换为 100(二进制),这意味着只有读取位对所有三个都打开 - 这意味着所有三个都可以只读取文件。

就文件权限而言,您应该已经成功读取/sys/devices/virtual/net/br-ex/speed
读取失败有两个原因:
- speed 是一个目录,(目录需要执行权限才能读取内部)。
- 或者是special file - 可以使用perlbash 中的-f 标志进行测试,或者在python 中使用os.path.isfile(...)


无论如何,您可以使用以下链接根据您提到的 3 种语言的权限来过滤文件和目录:

【讨论】:

  • 我知道 /sys 是一个特殊的文件系统,我正在尝试读取网络接口速度。通常这个文件包含速度,但有时如果没有,我想在执行 cat 之前知道它会失败。我曾希望有一种方法可以分辨,但正如前面提到的,它是一个“特殊”文件,因此不适用正常规则。我想我总是可以只和猫 2>/&1 。只是我从未见过 /sys 条目的猫以这种方式失败。
  • 我明白了。您还可以检查cat 是否返回成功代码并决定是否打印结果,或者使用2> /dev/null 忽略警告。祝你好运。
  • 其实比我第一次报道的要差一些,所以这里有一些更丑陋的细节。如果你熟悉collectl,这就是它的网络发现代码。当一个新网络出现时,collectl 会尝试在如下目录中查找它的速度:/sys/devices/virtual/net/tap5d6261e0-75/speed,它对它进行了查找。但是,如果 /sys/devices/virtual/net/tap5d6261e0-75/operstate 没有“up”或“unknown”的值,则 cat 会爆炸并且 Invalid Arg 直接进入终端并且无法抑制2>&1。真是一团糟……
【解决方案2】:

与这个特殊情况无关,但是当我在恶意 ELF(Linux 可执行文件)文件上运行它时遇到了同样的错误。在这种情况下,这是因为 ELF 的程序头被故意破坏了。查看文件命令的源代码,这很清楚,因为它检查 ELF 标头并在标头损坏的情况下以相同的错误退出:

    /*
     * Loop through all the program headers.
     */
    for ( ; num; num--) {
        if (pread(fd, xph_addr, xph_sizeof, off) <
            CAST(ssize_t, xph_sizeof)) {
            file_badread(ms);
            return -1;
        }

TLDR; file 命令不仅检查魔术字节,还执行其他检查以验证文件类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-15
    • 1970-01-01
    • 2015-05-10
    • 1970-01-01
    相关资源
    最近更新 更多