Bash

使用 bash 命令執行時等待它的腳本超時(沒有這樣的文件或目錄)

  • October 7, 2022

嘗試使用 bash 命令在沒有 +x 執行權限的情況下執行wait-for-it.sh腳本。

bash wait-for-it.sh google.com:80

超時:無法執行命令’wait-for-it.sh’:沒有這樣的文件或目錄

wait-for-it.sh:google.com:80 等待 15 秒後發生超時

(錯誤資訊,第 2 行來自腳本內部,與上述情況相同,即使已授予執行權限)

但它在給定 +x 的情況下直接執行時有效。

./wait-for-it.sh google.com:80

wait-for-it.sh:等待 15 秒等待 google.com:80

wait-for-it.sh:google.com:80 1 秒後可用

有什麼方法可以在不授予執行權限的情況下使用腳本或調試問題?

如果您檢查wait-for-it.sh腳本。您可以看到以下功能:

wait_for_wrapper()
{
   # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
   if [[ $WAITFORIT_QUIET -eq 1 ]]; then
       timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
   else
       timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
   fi
   WAITFORIT_PID=$!
   trap "kill -INT -$WAITFORIT_PID" INT
   wait $WAITFORIT_PID
   WAITFORIT_RESULT=$?
   if [[ $WAITFORIT_RESULT -ne 0 ]]; then
       echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
   fi
   return $WAITFORIT_RESULT
}

如果你看這一行:

timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet ...

現在如果你執行bash wait-for-it.sh google.com:80它會失敗,原因有兩個:

  1. 如果該文件未在環境變數中wait-for-it.sh定義,則無法辨識該文件。$PATH
  2. 該文件wait-for-it.sh沒有執行權限:

嘗試在沒有 +x 執行權限的情況下執行 wait-for-it.sh 腳本

現在,如果你看到這個函式,這個函式正在傳遞 的值$0,其中$0是文件名 ( wait-for-it.sh)。

所以timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0基本上是使用以下timeout命令“執行自身”(但帶有一些參數):

timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT wait-for-it.sh --quiet ...

wait-for-it.sh使用bash執行時,解決方案是使用絕對路徑或相對路徑。您還需要為該文件分配執行權限。

#Using relative path:
bash ./wait-for-it.sh google.com:80
#Using absolute path:
bash /path/to/wait-for-it.sh google.com:80
#e.g.
bash /home/user/wait-for-it.sh google.com:80

為什麼“bash wait-for-it.sh google.com:80”會失敗?

您可以像這樣編輯函式wait_for_wrapper

wait_for_wrapper()
{
  echo Running "$0"
  echo Whereis "$0": $(whereis "$0")
  $0
  echo Exit...
  exit #to avoid running the following code
   # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
   if [[ $WAITFORIT_QUIET -eq 1 ]]; then
       timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
   else
       timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
   fi
   WAITFORIT_PID=$!
   trap "kill -INT -$WAITFORIT_PID" INT
   wait $WAITFORIT_PID
   WAITFORIT_RESULT=$?
   if [[ $WAITFORIT_RESULT -ne 0 ]]; then
       echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
   fi
   return $WAITFORIT_RESULT
}

如果您執行bash wait-for-it.sh google.com:80(使用執行權限),您將收到此錯誤:

Running wait-for.sh at /home/user/...
Whereis wait-for.sh: wait-for.sh:
wait-for.sh: line 56: wait-for.sh: command not found
Exit...

正如我之前所說,該行$0正在嘗試執行wait-for.sh,但該行不在$PATHenv 變數的任何目錄中。

現在我將文件名更改wait-for.shls. ls 命令將被辨識,因為 my$PATH包含通常所在/usr/bin/的目錄。ls所以,如果你執行:

bash ls  google.com:80

你會得到:

Running ls at /home/user/...
Whereis ls ls: /usr/bin/ls /usr/share/man/man1p/ls.1p.gz /usr/share/man/man1/ls.1.gz

#This output is of my $HOME directory:
Postman         Templates        projects        
bin             go               ls  
Public          Videos           Documents         
Downloads       Pictures         temp
Exit...

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