为何./test.sh与sh test.sh执行同Shell脚本结果不同?
两种Shell脚本执行方式结果不同的原因解析
问题背景
测试脚本
#!/bin/sh echo "$PATH" [ "$UID" -eq 0 ] || exec sudo "$0" "$@" echo "$UID" echo "$SUDO_USER"
执行结果差异
- 通过
./test.sh执行:无限循环输出如下内容
/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: ...
- 通过
sh test.sh执行:仅输出一次后终止
/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
环境信息
- 已安装
sudo - 系统默认
sh链接至dash - 系统内核版本:
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
原因解析
1. $0变量取值差异是循环/终止的关键
./test.sh执行场景:$0的值为./test.sh,当执行sudo "$0"时,./明确指定了当前目录的相对路径,sudo能直接找到并执行脚本。但由于后续判断逻辑始终不成立,会反复触发sudo "$0",形成无限循环。sh test.sh执行场景:$0的值为test.sh,执行sudo "$0"时,sudo会在$PATH配置的系统目录中查找该脚本,但你的$PATH未包含当前工作目录(.),因此找不到test.sh,报错后脚本直接终止,不会进入循环。
2. dash不支持$UID是判断逻辑失效的根源
bash内置了$UID变量存储当前用户ID,但你的系统默认sh是dash——dash作为POSIX标准的轻量shell,没有内置$UID变量,所以脚本中$UID的值为空字符串。这就导致[ "$UID" -eq 0 ]变成[ "" -eq 0 ],触发[: Illegal number:的语法错误,条件判断结果为假,进而触发exec sudo "$0"的逻辑,这也是两种执行方式都会出现错误提示的原因。
内容的提问来源于stack exchange,提问作者er3s56
相关产品推荐
相关产品推荐

