【问题标题】:"inappropriate ioctl for device"“设备的 ioctl 不合适”
【发布时间】:2010-12-08 23:28:22
【问题描述】:

我有一个在 AIX 机器中运行的 Perl 脚本。

脚本试图从某个目录打开一个文件,但由于文件没有读取权限而无法读取该文件,但我收到另一个错误消息inappropriate ioctl for device

不应该说no read permissions for file之类的东西吗?

这条inappropriate ioctl for device 消息是什么意思?

我该如何解决?

编辑:这是我在strace 时发现的。

open("/local/logs/xxx/xxxxServer.log", O_WRONLY|O_CREAT|O_APPEND|O_LARGEFILE, 0666) = 4 _llseek(4, 0, [77146], SEEK_END) = 0 ioctl(4, SNDCTL_TMR_TIMEBASE 或 TCGETS, 0xbffc14f8) = -1 ENOTTY (设备的 ioctl 不合适)

【问题讨论】:

  • 如果您怀疑权限 - 您是否已尝试设置相关文件的读取权限?
  • 对更新的响应:这是一个可写入/追加的打开,而不是读取,它正在成功。
  • 是的,正如我在帖子中指出的那样,这根本不是错误。好吧,无论如何,这是一个未在您使用的抽象级别公开的预期错误:)
  • 再次,不。阅读我的答案。你可以信任$!如果你使用得当
  • 或者ysth的答案,就此而言。 :)

标签: perl ioctl


【解决方案1】:

很可能意味着打开没有失败

当 Perl 打开一个文件时,它会通过发出 TCGETS ioctl 来检查文件是否是 TTY(以便它可以回答 -T $fh filetest 运算符)。如果文件是常规文件而不是 tty,则 ioctl 失败并将 errno 设置为 ENOTTY(字符串值:“设备不合适的 ioctl”)。正如 ysth 所说,在 $! 中看到意外值的最常见原因是在它无效时检查它——也就是说,在系统调用失败后立即进行检查,因此测试结果代码您的运营至关重要。

如果 open 确实为您返回 false,并且您在 $! 中找到了 ENOTTY,那么我会认为这是一个小错误(给出一个无用的 $! 值)但我也会很好奇它是如何发生的。代码和/或桁架输出会很漂亮。

【讨论】:

  • 在实际使用/需要之前做好记忆。这有点浪费是在繁忙的服务器上打开/关闭套接字...... perl 还测试它们是否是 tty 的
【解决方案2】:

奇怪的错误,如“不适合设备的 ioctl”通常是检查 $! 的结果。在系统调用失败之后的某个时间点。如果你展示你的代码,我敢打赌有人会迅速指出你的错误。

【讨论】:

  • die 是否总是检查$!?例如,die "my bad!\n" 没有明确引用 $!——但我收到了 OP 的错误消息。
  • @wcochran: die 不会显示基于 $1 的消息,但它可以更改进程的错误代码(将是 $! || $? >> 8 || 255
  • 所以使用die 应该只用于我认为由系统调用生成的错误。谢谢。
  • @wcochran:不,一点也不。如果您关心进程给出的退出代码,请避免死亡并明确退出(某个数字)。但如果你不这样做, die 只会尝试使用具有 some 含义的代码,而不仅仅是使用单个默认值。这不是一件坏事。
【解决方案3】:

"inappropriate ioctl for device" 是 ENOTTY 错误的错误字符串。它过去主要是通过尝试在不是终端的文件描述符(但是,比如说,一个常规文件)上配置终端属性(例如回显模式)来触发的,因此是 ENOTTY。更一般地说,它是在不支持该 ioctl 的设备上执行 ioctl 时触发的,因此是错误字符串。

要找出失败的 ioctl 以及在哪个文件描述符上,请在 strace/truss 下运行脚本。您将识别 ENOTTY,然后实际打印错误消息。然后找出使用了哪个文件号,以及哪个 open() 调用返回了该文件号。

【讨论】:

    【解决方案4】:

    由于这是一个致命错误并且也很难调试,也许可以将修复放在某个地方(在提供的命令行中?):

    export GPG_TTY=$(tty)
    

    发件人:https://github.com/keybase/keybase-issues/issues/2798

    【讨论】:

    • 不管你在说什么,好像和这个问题不一样?
    • 是的。这是一个错误,但我没有删除,因为令人惊讶的是它得到了赞成。也许它对在这里迷路的人有用。
    【解决方案5】:

    *nix 类型系统中的“文件”是一个非常抽象的概念。

    它们可以是由文件系统组织的磁盘区域,但它们也可以是网络连接、共享内存、另一个进程的缓冲区输出、屏幕或键盘。

    为了让 perl 真正有用,它非常接近地反映了这个模型,并且不像许多 4gls 那样通过模拟磁带来处理文件。

    因此,它在文件句柄上尝试了“IOCTL”操作“打开写入”,该文件句柄不允许写入操作,这对于该设备/文件来说是不合适的 IOCTL 操作。

    最简单的做法是在打开的末尾添加“or die 'Cannot open $myfile'”声明,然后您可以选择自己有意义的信息。

    【讨论】:

      【解决方案6】:

      我刚刚修复了这个 perl 错误。 见https://rt.perl.org/Ticket/Display.html?id=124232

      当我们将缓冲层推送到 PerlIO 并执行失败的 isatty() 检查时 这显然在所有正常文件上都失败了,忽略错误的 errno ENOTTY。

      【讨论】:

      • 由于 perl5 决定不修复这个错误(像往常一样),你必须使用 cperl,它确实修复了它。
      【解决方案7】:

      尤里卡时刻!

      我以前遇到过这个错误。

      你有没有用类似的东西调用 perl 调试器:-

      perl -d yourprog.pl > log.txt
      

      如果是这样,perl 调试会尝试查询并可能重置终端宽度。 当 stdout 不是终端时,这将失败并显示 IOCTL 消息。

      另一种方法是让您的调试会话永远挂起,因为您没有看到说明提示。

      【讨论】:

        【解决方案8】:

        今天在尝试使用代码删除作为共享安装在 Centos 服务器上的 Windoze 7 盒子上的文件夹/文件时遇到了这个错误。得到了设备错误的不适当 icotl 并尝试了所有想到的东西。阅读网络上与此相关的几乎所有帖子。

        很明显,问题与 Linux 服务器上挂载的 Windoze 共享有关。看着 在 Windoze 框上的文件权限处,并注意到文件的权限设置为只读。

        更改了这些,回到 Linux 服务器,一切都按预期工作。这可能不是大多数人的解决方案,但希望它可以节省一些时间。

        【讨论】:

          【解决方案9】:

          我尝试了以下似乎可行的代码:

          if(open(my $FILE, "<File.txt")) {
              while(<$FILE>){
              print "$_";}
          } else {
              print "File could not be opened or did not exists\n";
          }
          

          【讨论】:

            【解决方案10】:

            最近,当我将带有基于 DBM 文件的数据库的旧 UB2K 论坛迁移到新主机时,我收到了错误 Can't open file for reading. Inappropriate ioctl for device。显然,DBM 有多种不兼容的实现。我有数据库的备份,所以我可以加载它,但似乎还有其他选项,例如moving a perl script/dbm to a new server, and shifting out of dbm?.

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2014-09-17
              • 2015-02-03
              • 2021-11-25
              • 2015-10-30
              • 1970-01-01
              • 1970-01-01
              • 2022-06-27
              • 2013-01-28
              相关资源
              最近更新 更多