Linux

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

  • May 2, 2020

我使用 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  

您的互動式外殼是dash(偽裝成sh)。貝殼dash

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

當它試圖執行一個腳本,該腳本有一個錯誤的#!-line 指向一個無法找到的解釋器。它恰好與找不到您鍵入的命令時遇到的錯誤完全相同,因此很容易認為這是一個$PATH問題(在這種情況下不是)。其他 shell 有更多資訊豐富的錯誤消息(bashzsh說“錯誤的解釋器:沒有這樣的文件或目錄”,還告訴你它試圖執行的解釋器)。

由於該文件是 DOS 文本文件#!-line 指示 shell 執行腳本/bin/sh\r,其中\r是輸入符的常見表示,它是 DOS 文本文件中行終止的一部分。在 Unix 系統上,輸入是一個“普通字元”,而不是行終止的所有部分,這意味著它嘗試開始/bin/sh\r執行您的腳本,然後由於該文件不存在而失敗。因此,“未找到”的是解釋器,而不是腳本本身。

使用顯式解釋器執行腳本總是會繞過#!-line,這就是為什麼這樣做時不會出現錯誤的原因。但是,腳本中的每一行仍然會在它們的末尾有輸入符,這可能會導致腳本在某些情況下出現故障。

只需將文件重新保存為 Unix 文本文件,或將其轉換為dos2unix,即可解決您的問題。

引用自:https://unix.stackexchange.com/questions/583822