为什么在 Linux 上相同版本的“install”运行正常时,OS X“install”在重定向输入时会出现错误?

为什么在 Linux 上相同版本的“install”运行正常时,OS X“install”在重定向输入时会出现错误?

我想使用install命令来创建一个具有预填充内容的新可执行文件(例如,pwd其中包含单个命令)。

所以我延长了创建一个新的空可执行文件的示例:

install -b -m 755 /dev/null newfile

进入这个:

install -m755 <(echo pwd) newfile

或者:

echo pwd | install -m755 /dev/stdin newfile

我希望创建一个新的newfile可执行文件,其中包含内容pwd

它在 Linux 上运行良好,但是在 OS X 上会失败并出现以下错误:

  • BSD install( /usr/bin/install)

    install: /dev/fd/63: 不适当的文件类型或格式

  • GNU install( /usr/local/opt/coreutils/libexec/gnubin/install)

    安装:跳过文件/dev/fd/63,因为它在复制时被替换

为什么这在 Unix 上不起作用,但在 Linux 上却可以?我缺少什么吗?有没有办法通过使用不同的语法来绕过上述警告(没有在单独的命令中创建一个文件,然后使用chmod)?


在两种环境(Linux 和 OS X)上我都有相同的版本install

$ install --version
install (GNU coreutils) 8.23

答案1

OpenBSD 系统上的 BSD 安装中有这段代码(来自src/usr.bin/xinstall/xinstall.c):

if (!S_ISREG(to_sb.st_mode))
    errc(1, EFTYPE, "%s", to_name);

这会发出错误

install: /dev/fd/4: Inappropriate file type or format

当发现这/dev/df/4不是一个普通文件时。 (有一个单独的早期检查/dev/null

这相当简单。

GNUinstall有以下代码(src/install.ccoreutils):

  /* Allow installing from non-regular files like /dev/null.
     Charles Karney reported that some Sun version of install allows that
     and that sendmail's installation process relies on the behavior.
     However, since !x->recursive, the call to "copy" will fail if FROM
     is a directory.  */

  return copy (from, to, false, x, &copy_into_self, NULL);

发出错误的代码来自src/copy.c

  source_desc = open (src_name,
                      (O_RDONLY | O_BINARY
                       | (x->dereference == DEREF_NEVER ? O_NOFOLLOW : 0)));

(省略几行)

  if (fstat (source_desc, &src_open_sb) != 0)
    {
      error (0, errno, _("cannot fstat %s"), quoteaf (src_name));
      return_val = false;
      goto close_src_desc;
    }

  /* Compare the source dev/ino from the open file to the incoming,
     saved ones obtained via a previous call to stat.  */
  if (! SAME_INODE (*src_sb, src_open_sb))
    {
      error (0, 0,
             _("skipping file %s, as it was replaced while being copied"),
             quoteaf (src_name));

这是copy_reg()复制常规文件的地方。该宏的计算结果为 false,因为两个结构体和SAME_INODE中的 inode 不同。来自对源文件名的 or 调用以及如上所示的新打开的描述符。stat*src_sbsrc_open_sb*src_sbstat()lstat()src_open_sbfstat()

我可以理解为什么打开一个新的文件描述符并将其 inode 与 shell 给出的文件描述符的 inode 进行比较(/dev/fd/4在我的例子中)会失败,但不幸的是我无法用明确的词来表达。

相关内容