shell脚本:使用bash命令运行时没有这样的文件或目录

shell脚本:使用bash命令运行时没有这样的文件或目录

尝试运行等待它.sh使用 bash 命令没有 +x 执行权限的脚本。

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:1 秒后 google.com:80 可用

有什么方法可以在不授予脚本执行权限的情况下使用该脚本或调试问题吗?

答案1

如果您检查等待它.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...

相关内容