skip to Main Content

Here is my script:

#!/bin/sh
echo "$PATH"
[ "$UID" -eq 0 ] || exec sudo "$0" "$@"
echo "$UID"
echo "$SUDO_USER"

If I run this script by ./test.sh, this is the result:

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin  
./test.sh: 3: [: Illegal number:  
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin  
./test.sh: 3: [: Illegal number:  
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin  
./test.sh: 3: [: Illegal number:  
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin  
...

And it keeps printing the same thing.

If I run by sh test.sh, then the result is:

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin  
test.sh: 3: [: Illegal number:  
sudo: test.sh: command not found  
And just print once. (I've installed sudo.)

As I know, ./ and sh command are the same. And sh is linked to dash. So how to explain this problem?

System info:

Linux version 5.19.0-32-generic (buildd@lcy02-amd64-026) (x86_64-linux-gnu-gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #33~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC

Explain the reason that ./ and sh have different results when executing the same script.

2

Answers


  1. The script is recursively executing itself, because your UID is not set.

    The difference between the methods:

    ./test.sh executes the file itself (if shebang is valid)
    sh test.sh executes shell and passes file name as argument

    The positional parameter $0 reflects the file name of execution
    ./test.sh
    test.sh

    the latter one misses the path in file name, your script is therefore looking for non-existing file in PATH (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin)

    you can use realpath to determine the file path:

    #!/bin/sh
    echo "$PATH"
    [ "$(whoami)" = root ] || { exec sudo "$(realpath "$0")" "$@"; exit $?; }
    echo "USER='$USER'"
    echo "SUDO_USER='$SUDO_USER'"
    
    Login or Signup to reply.
  2. how to explain this problem?

    sudo: test.sh: command not found  
    

    When you run sh test.sh, then $0 is test.sh so then sudo "$0" "$@" command becomes sudo test.sh.

    There is no such command as test.sh in PATH. You can run ./test.sh or sh test.sh like sudo ./test.sh or sudo sh test.sh, but not plain test.sh.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search