当 linux 上相同版本的 `install` 工作正常时,为什么 OS X `install` 会在重定向输入上出现错误?

ken*_*orb 7 osx shell executable files process-substitution

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

所以我扩展了这个例子,它创建了一个新的空可执行文件:

install -b -m 755 /dev/null newfile
Run Code Online (Sandbox Code Playgroud)

进入这个:

install -m755 <(echo pwd) newfile
Run Code Online (Sandbox Code Playgroud)

或者:

echo pwd | install -m755 /dev/stdin newfile
Run Code Online (Sandbox Code Playgroud)

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

它适用于 Linux,但在 OS X 上它失败并出现以下错误:

  • BSD install( /usr/bin/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
Run Code Online (Sandbox Code Playgroud)

Kus*_*nda 1

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

if (!S_ISREG(to_sb.st_mode))
    errc(1, EFTYPE, "%s", to_name);
Run Code Online (Sandbox Code Playgroud)

这会发出错误

install: /dev/fd/4: Inappropriate file type or format
Run Code Online (Sandbox Code Playgroud)

当发现这/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);
Run Code Online (Sandbox Code Playgroud)

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

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

(省略几行)

  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));
Run Code Online (Sandbox Code Playgroud)

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

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