Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm writing a bash script where I want to exit if the user is not root. The conditional works fine, but the script does not exit.

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

I've tried using && instead of ; but neither work.

share|improve this question

4 Answers 4

up vote 22 down vote accepted

You could do that this way:

[[ `id -u` -eq 0 ]] || { echo "Must be root to run script"; exit 1; }

("ordinary" conditional expression with an arithmetic binary operator in the first statement), or:

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

(arithmetic evaluation for the first test).

Notice the change () -> {} - the curly brackets do not spawn a subshell. (Search man bash for "subshell".)

share|improve this answer
    
That was what I was looking for, thanks! –  Garrett Hall Nov 4 '11 at 15:20
1  
Please exit with a code other than zero, example: exit 1 in order to make understand the parent process that a problem occured. –  SamK Nov 4 '11 at 16:32
1  
You shouldn't use [[ for numeric comparison, use ((. –  Chris Down Nov 4 '11 at 19:59
1  
@ChrisDown [[ is fine, as long as you use -eq instead of ==. –  Let_Me_Be Nov 24 '11 at 10:10
2  
@Mat By the way, you can shorten it to (( EUID )) && ... –  Chris Down Nov 24 '11 at 11:14

The parentheses around those commands creates a subshell. Your subshell echos "Must be root to run script" and then you tell the subshell to exit (although it would've already, since there were no more commands). The easiest way to fix it is probably to just use an if:

if [[ `id -u` != 0 ]]; then
    echo "Must be root to run script"
    exit
fi
share|improve this answer
    
So there is no way to do this with a one-liner? –  Garrett Hall Nov 4 '11 at 15:16
1  
your logic is backwards. in your example, if id -u == 0, which would mean that you are root. You want [[ $(id -u) != 0 ]]; then. –  Tim Kennedy Nov 4 '11 at 17:32
3  
If you /must/ have a one-liner, try this on for size: [ "$UID" != 0 ] && echo 'You have to be root.' && exit 1; Also note the $UID, which saves spawning a process. I think you might even prefer $EUID. –  janmoesen Nov 4 '11 at 18:19
1  
@janmoesen, good point. And while wee have a variable with a numeric value: ((UID)) && echo 'You have to be root.' && exit 1. –  manatwork Nov 4 '11 at 18:25
2  
@janmoesen: note that using such inverse logic will cause a script that set -e to abort. One solution to that problem is [ "$UID" != 0 ] && echo 'You have to be root.' && exit 1 || true. –  Sam Hocevar Nov 4 '11 at 22:14

With bash:

[ $UID -ne 0 ] && echo "Must be root to run script" && exit 1
share|improve this answer

You don't even need brackets here as || and && are right-associative, this two expressions are equivalent:

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

So && instead of ; would work just fine, as echo will return true.

[[ `id -u` == 0 ]] || echo "Must be root to run script" && exit 1
share|improve this answer
1  
While everything you said is correct, this is a bad pattern to learn, because you're relying on the return value of expr2. Are you certain that echo will always return a 0 exit status? It's much better idea to group the statements with curly braces and semi-colons. This is such a common pitfall that it has its own entry in BashPitfalls: mywiki.wooledge.org/BashPitfalls#cmd1_.26.26_cmd2_.7C.7C_cmd3 –  Flimm Nov 10 '11 at 23:10
1  
@Flimm: I don't agree it's a bad pattern. Evidently, it use is case-dependant, and also depends on your knowledge of the return values you'll get. In this case I'm sure echo will return 0 the 99.999% of times, and if it stomps on a write error (the only case it won't return 0) there's a bigger problem than this expr. There's also the case where YOU are generating the return values, so no, it isn't a "bad pattern" per se for me. –  ata Nov 11 '11 at 0:18
    
I'll add too, like it says in the wiki, that you should use it if sure to understand C evaluation. Anyway, a little testing should clear any ambiguities. –  ata Nov 11 '11 at 0:26

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.