在 Linux Alpine 3.11 上找不到 $PATH 中的 SH 脚本

在 Linux Alpine 3.11 上找不到 $PATH 中的 SH 脚本

我使用 Alpine Linux 3.11 作为新的 Docker 容器。

我有默认$PATH变量,其内容为:

echo $PATH
/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

当我放置一个脚本wait-for(这是一个以 开头的 shell 脚本#!/bin/sh)时,/usr/local/bin它显示正常:

chmod +x wait-for
mv wait-for /usr/local/bin/wait-for
ls -l /usr/local/bin/wait-for

产生:

-rwxr-xr-x    1 root     root          1451 May  1 16:09 /usr/local/bin/wait-for

sh /usr/local/bin/wait-for当我用来执行它时它也会运行。

然而,当我进去/usr/src/并尝试跑步时wait-for,我得到了sh: wait-for: not found

我的理解是,因为该/usr/local/bin目录位于$PATH该目录中的任何脚本都应该全局调用。

我误解了什么?

/usr/src/如果我使用,我可以运行该文件sh /usr/local/bin/wait-for,但如果我使用/usr/local/bin/wait-for(不带sh前缀),则不能运行该文件,它返回sh: /usr/local/bin/wait-for: not found.

的输出/etc/fstab是:

/dev/cdrom      /media/cdrom    iso9660 noauto,ro 0 0                          
/dev/usbdisk    /media/usb      vfat    noauto,ro 0 0  

答案1

您的交互式 shell 是dash(伪装成sh)。外壳dash

sh: /usr/local/bin/wait-for: not found

当它尝试执行一个脚本时,如果该脚本包含#!指向无法找到的解释器的错误行。它发生与找不到您键入的命令时得到的错误完全相同,因此很容易认为这是一个$PATH问题(在本例中不是)。其他 shell 有更多信息性错误消息(bashzsh显示“错误的解释器:没有这样的文件或目录”,并且还告诉您它尝试执行的解释器)。

自从该文件是 DOS 文本文件#!-line 指示 shell 使用 运行脚本/bin/sh\r,其中\r是回车符的常见表示形式,它是 DOS 文本文件中行终止符的一部分。在 Unix 系统上,回车符是一个“普通字符”,根本不是行终止的一部分,这意味着它尝试开始/bin/sh\r运行脚本,然后由于该文件不存在而失败。因此,它是口译员那是“未找到”,而不是脚本本身。

运行脚本明确的解释器总是绕过#!-line,这就是为什么你这样做时不会收到错误。但是,脚本中的每一行末尾仍会有回车符,这可能会导致脚本在某些情况下出现故障。

只需将文件重新保存为 Unix 文本文件,或使用 进行转换dos2unix,即可解决您的问题。

答案2

对于那些发现这个问题的人,我的具体问题是我的wait-for脚本已转换为 Windows 行结尾。

当使用 unix 行结尾重新保存时,此问题得到解决。

如果有人可以发布更好的答案来解释为什么 Windows 行结尾导致文件仅在使用时才被识别sh /usr/local/bin/wait-for,否则/usr/local/bin/wait-forwait-for会接受。

相关内容