如何在条件语句中退出脚本?


50

我正在编写一个bash脚本,如果用户不是root用户,我想在其中退出。有条件的工作正常,但脚本不会退出。

[[ `id -u` == 0 ]] || (echo "Must be root to run script"; exit)

我尝试使用&&代替,;但是都没有用。

Answers:


50

您可以这样进行:

[[ $(id -u) -eq 0 ]] || { echo >&2 "Must be root to run script"; exit 1; }

(第一条语句中带有算术二进制运算符的“普通”条件表达式),或:

(( $(id -u) == 0 )) || { echo >&2 "Must be root to run script"; exit 1; }

(第一次测试的算术评估)。

注意更改()-> {}-大括号不会产生子外壳。(搜索man bash“ subshel​​l”。)


1
请使用非零的代码退出,例如:exit 1为了使父进程了解发生了问题。
SamK 2011年

1
您不应该使用[[进行数字比较,请使用((
克里斯·

1
[[只要您使用-eq而不是,@ChrisDown 都可以==
Let_Me_Be 2011年

修复条件,添加了算术版本@ChrisDown。

2
@Mat顺便说一句,您可以将其缩短为(( EUID )) && ...
Chris Down

21

这些命令的括号创建一个subshel​​l。您的子shell回显“必须是root用户才能运行脚本”,然后您告诉该子shell退出(尽管已经这样做了,因为没有更多命令了)。解决该问题的最简单方法可能是使用if

if [[ `id -u` != 0 ]]; then
    echo "Must be root to run script"
    exit
fi

因此,没有办法采用单缸衬管吗?
加勒特音乐厅

1
你的逻辑倒退了。在您的示例中,如果为id -u == 0,则表示您 root。你要[[ $(id -u) != 0 ]]; then
蒂姆·肯尼迪

4
如果您/必须/有一个内衬,请尝试以下尺寸:[ "$UID" != 0 ] && echo 'You have to be root.' && exit 1;还要注意$UID,它节省了产生进程的时间。我想您可能甚至更喜欢$EUID
janmoesen 2011年

1
@janmoesen,很好。尽管有一个带有数字值的变量:((UID)) && echo 'You have to be root.' && exit 1
manatwork

3
@janmoesen:请注意,使用这种逆逻辑将导致脚本set -e中止。解决该问题的一种方法是[ "$UID" != 0 ] && echo 'You have to be root.' && exit 1 || true
sam hocevar 2011年

2

bash

[ $UID -ne 0 ] && echo "Must be root to run script" && exit 1

如果echo失败(例如因为stdout不可写),那将无法退出。
斯特凡Chazelas

1

不需要括号||&&因为它们是右关联的。以下两个表达式是等效的:

expr1 || expr2 && expr3
expr1 || { expr2 && expr3 }

因此&&;如果echo返回true ,则不是可以正常工作。

[[ $(id -u) == 0 ]] || echo "Must be root to run script" && exit 1

1
尽管您说的一切都是正确的,但是这是一个不好学习的模式,因为您依赖于expr2的返回值。您确定echo总是返回0退出状态吗?用大括号和分号对语句进行分组是一个更好的主意。这是它在BashPitfalls其自己的条目这样一个共同的缺陷:mywiki.wooledge.org/BashPitfalls#cmd1_.26.26_cmd2_.7C.7C_cmd3
Flimm

1
@Flimm:我不同意这是一个坏模式。显然,它的使用取决于大小写,并且还取决于您对获得的返回值的了解。在这种情况下,我确定echo会在99.999%的时间内返回0,并且如果在写入错误时脚(唯一的情况是它不会返回0),则存在比此expr大的问题。在某些情况下,您正在生成返回值,所以不,对于我来说,这本身并不是一个“坏模式”。
ata

我也将添加,就像Wiki中所说的那样,如果一定要了解C评估,就应该使用它。无论如何,稍作测试就能消除任何歧义。
ata

0

这可能会对您有所帮助

[oracle@rac1 ~]$ which bash
/bin/bash
[oracle@rac1 ~]$ cat test1.sh
if [ `id -u` != 0 ]
then
echo "Must be root to run the script
 "
exit
fi

3
这已经得到回答和接受。另外,您的答案几乎与已发布的答案相同。
maulinglawns

@maulinglawns,这个答案与其他答案相反,具有可移植到所有类似Bourne的shell的优点(最好是在stderr上输出错误,退出状态为非零,并用引号代替命令) )
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.