正如@dessert所解释的,这里的问题是您的脚本没有shebang行。如果没有shebang,sudo则默认为尝试使用运行文件/bin/sh。我在任何地方都找不到文档,但通过检查sudo在文件中找到以下内容的源代码来确认pathnames.h:
#ifndef _PATH_BSHELL
#define _PATH_BSHELL "/bin/sh"
#endif /* _PATH_BSHELL */
这意味着“如果_PATH_BSHELL未定义变量,则将其设置为/bin/sh”。然后,在configure源压缩包中包含的脚本中,我们有:
for p in "/bin/bash" "/usr/bin/sh" "/sbin/sh" "/usr/sbin/sh" "/bin/ksh" "/usr/bin/ksh" "/bin/bash" "/usr/bin/bash"; do
if test -f "$p"; then
found=yes
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $p" >&5
$as_echo "$p" >&6; }
cat >>confdefs.h <<EOF
#define _PATH_BSHELL "$p"
EOF
break
fi
done
这个循环会寻找/bin/bash,/usr/bin/sh,/sbin/sh,/usr/sbin/sh或/bin/ksh然后设置_PATH_BSHELL要取其首次发现。由于/bin/sh是列表中的第一个,并且存在,_PATH_BSHELL因此设置为/bin/sh。所有这一切的结果是sudo除非另外定义,否则默认外壳程序为/bin/sh。
因此,sudo默认情况下将使用/bin/shUbuntu 运行,并且在Ubuntu上是与dashPOSIX兼容的最小外壳的符号链接:
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Feb 27 2015 /bin/sh -> dash
该[[构造是bash的功能,它不是POSIX标准定义的,也不为dash:
$ bash -c '[[ true ]] && echo yes'
yes
$ dash -c '[[ true ]] && echo yes'
dash: 1: [[: not found
详细地说,您尝试了以下三种调用:
./test.sh
无sudo; 在没有shebang行的情况下,您的shell将尝试执行文件本身。由于您正在运行bash,因此可以有效地运行bash ./test.sh和运行。
sudo su其次是./test.sh。
在这里,您正在为user启动一个新的shell root。这将是在该$SHELL用户的环境变量中定义的任何shell ,在Ubuntu上,root的默认shell是bash:
$ grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
sudo ./test.sh
在这里,您可以sudo直接执行命令。由于其默认外壳程序/bin/sh如上所述,因此这将导致它使用来运行脚本/bin/sh,并且脚本dash失败,因为dash不理解[[。
注意:如何sudo设置默认Shell 的细节似乎更加复杂。我尝试将答案中提到的文件更改为,/bin/bash但sudo仍默认为/bin/sh。因此,在源代码中必须存在定义默认Shell的其他位置。尽管如此,要点(sudo默认为sh)仍然存在。
sudo su。只是运行sudo -i还是sudo -s代替。