正如@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/sh
Ubuntu 运行,并且在Ubuntu上是与dash
POSIX兼容的最小外壳的符号链接:
$ 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
代替。