/usr/bin/env: zsh -: 没有这样的文件或目录

/usr/bin/env: zsh -: 没有这样的文件或目录

我收到错误

/usr/bin/env: zsh -: No such file or directory

...当我运行zsh以以下 shebang 行开头的可执行脚本时:

#!/usr/bin/env zsh -

另外,FWIW,替换-为打印类似投诉的--原因。/usr/bin/envzsh --

我只在 ubuntu 下看到过​​这个错误,并且只在 shebang hack 的上下文中见过。在达尔文下,相同的脚本运行良好。并且在ubuntu下,运行

% /usr/bin/env zsh -

从命令行成功。 (实际上,“under ubuntu”应该理解为“under ubuntu 12.04 LTS 和”的简写env (GNU coreutils) 8.13。)

我的问题是:我该如何修改上面的shebang以避免这个错误?

当然,我知道删除尾随-会消除错误,但这不是一个可接受的解决方案。这篇文章的其余部分解释了原因。

导致错误的 shebang 行是为了遵守两个完全独立的准则而出现的:

  1. 要使脚本可移植,请使用#!/usr/bin/env <cmd ...>而不是#!/path/to/cmd <...>.

  2. 将其作为zsh 脚本的 shebang 行中的-唯一参数会阻碍某些类型的zsh攻击

因此,我可以更准确地重申我的问题如下:是否可以在 ubuntu 下满足这两个准则而不触发上面显示的错误?

答案1

Linux(您提到“仅在 Ubuntu 下”,但您提到它工作的唯一操作系统是 Darwin)不支持将多个参数传递给“shebang”解释器。它将整个字符串(在您的情况下为"zsh -")作为单个参数传递。

确保您的软件包不依赖于解释器位置的正确方法是,作为安装过程的一部分,找到解释器并修改脚本以包含正确的路径。一些执行此操作的示例代码(对于sh)提供于http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sh.html#tag_20_117_16

答案2

我认为你的问题的答案基本上是“不”。 Shebang 机制并不那么灵活。

#!行仅允许您指定要执行的命令以及(可选)该命令的单个参数。脚本的名称作为另一个参数传递。所以如果foo.zsh开始于:

#!/usr/bin/env zsh

跑步foo.zsh就相当于跑步/usr/bin/env zsh foo.zsh

如果直接指定路径zsh,则可以传递附加参数:

#!/usr/bin/zsh -

但随着#!/usr/bin/env黑客的入侵,zsh 附加参数。

显然,正如您所见,这种行为因系统而异。顺便说一句,我会检查以确保-Ubuntu 上的 没有被忽略。

如果您可以依赖在zsh您关心的所有系统上处于一致的位置,则可以使用#!/usr/bin/zsh -(忽略您的第一个准则)。

如果不能,那么您可以zsh在每个系统上的一致位置创建符号链接,也可以#!在安装脚本时修改脚本中的行。 (在 Perl 并不总是存在的日子里,我自己为 Perl 脚本做过这个/usr/bin/perl。)

或者,您可以编写一个包装器,当不带参数调用时,使用zsh参数调用-,并将 shebang 更改为:

#!/usr/bin/env zsh-wrapper

它只需要zsh-wrapper位于 中的某个位置$PATH,不一定位于一致的位置。

也可以看看这个问题我对此的回答讨论该#!/usr/bin/env黑客的优点和缺点。

并看到这一页有关各种类 Unix 系统上的 shebang 行为的更多信息(感谢 Stephane Chazelas 提供的链接)。

相关内容