我使用 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 有更多信息性错误消息(bash
并zsh
显示“错误的解释器:没有这样的文件或目录”,并且还告诉您它尝试执行的解释器)。
自从该文件是 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-for
我wait-for
会接受。