4

Trying to run the wait-for-it.sh script without +x execution permission using bash command.

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

timeout: failed to run command ‘wait-for-it.sh’: No such file or directory

wait-for-it.sh: timeout occurred after waiting 15 seconds for google.com:80

(The error message, 2nd line of which comes from inside the script, is same for above case even if execution permission is given)

But it works when directly executed given +x.

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

wait-for-it.sh: waiting 15 seconds for google.com:80

wait-for-it.sh: google.com:80 is available after 1 seconds

Any way I can use the script without giving it execution permission, or debug the issue?

1 Answer 1

3

If you inspect wait-for-it.sh script. You can see the following function:

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
}

If you look at this line:

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

Now if you run bash wait-for-it.sh google.com:80 this will fail for two reasons:

  1. The file wait-for-it.sh will not be recognized if this one is not defined inside the $PATH environment variable.
  2. The file wait-for-it.sh has no execution permissions:

Trying to run the wait-for-it.sh script without +x execution permission

Now, if you see the function, this one is passing the value of $0, where $0 is the filename (wait-for-it.sh).
So what timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 does is basically "run itself" (but with some args) using the timeout command:

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

The solution is using an absolute path or relative path when you run wait-for-it.sh with bash. You also need to assign the execution permissions to that file.

#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

Why does "bash wait-for-it.sh google.com:80" fail?

You can edit the function wait_for_wrapper like this:

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
}

If you run bash wait-for-it.sh google.com:80 (with execution perms) you will get this error:

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...

As I said before, the line $0 is trying to execute wait-for.sh but this one is not in any of directories of the $PATH env variable.

Now I will change the filename wait-for.sh to ls. The ls command will be recognized because my $PATH contains the dir /usr/bin/ which is where ls is usually located. So, if you run:

bash ls  google.com:80

You will get:

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...
2
  • 1
    Thanks for your in-depth explanation, that helped man!
    – Farshid
    Commented Oct 7, 2022 at 4:19
  • 1
    @AshNazg a pleasure! Every day is a learning experience :) Commented Oct 7, 2022 at 4:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .