ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I feel a bit embarrassed to ask this having been a Linux user for over 10 years - but I've never really dug deep into shell scripting.
One of the log rotate scripts on a small gateway contains this:
Code:
prerotate
test ! -x /usr/sbin/sarg-reports || /usr/sbin/sarg-reports
endscript
postrotate
test ! -e /var/run/squid.pid || /usr/sbin/squid -k rotate
endscript
Is my understanding flawed?
I'm assuming that if the prerotate line returns true that the postrotate section will run. If not the 'endscript' will terminate it?
I'm assuming the truth of prerotate is negated with ! and what that line basically says is if /usr/sbin/sarg-reports is not executable ... then I struggle to get the logical || or with just the file name.
If I could understand the purpose of the || or, I think I'd 'get it' and the postrotate line.
Be gentle with me, I'm ashamed enough that I don't know. Google has been little help to me (|| seems to upset it)
test ! -x /usr/sbin/sarg-reports || /usr/sbin/sarg-reports
checks if /usr/sbin/sargs-reports is executable by you and, if so, executes it.
Quote:
Originally Posted by `man bash'
An OR list has the form
command1 || command2
command2 is executed if and only if command1 returns a non-zero exit status. The return status of AND
and OR lists is the exit status of the last command executed in the list.
What you're seeing is the original developer taking advantage of "short circuit" boolean evaluation.
You have two basic boolean operations where this comes into play: logical AND (&&) and logical OR (||).
If you have a statement such as "alpha && beta" then alpha must evaluate to true and beta must evaluate to true for the whole expression to evaluate to true. The point is that for logical AND, both alpha and beta must be evaluated to determine the overall expression.
Compare that with a statement such as "alpha || beta." There are three cases where the overall statement evaluates to true: (1) alpha = true; beta = false, (2) alpha = true; beta = true, (3) alpha = false; beta = true. Notice that if alpha evaluates to true, then it does not matter what beta evaluates to--the overall expression will still be true.
That's "short circuit" evaluation. The shell will evaluate only so much of the expression as is necessary to determine the overall result.
So, back to your code snippets, because they use ||, the second half of the statement will be ignored if the first half is true. Only when the first half evaluates to false will the second half get evaluated (which in this case is launching a new process).
EDIT:
It seems I was fashionably late to the party
Last edited by Dark_Helmet; 03-03-2012 at 04:04 AM.
So, back to your code snippets, because they use ||, the second half of the statement will be ignored if the first half is true. Only when the first half evaluates to false will the second half get evaluated (which in this case is launching a new process).
So let me see if I've got this clear when the left hand side of the or is false (that is I can't execute it).
Code:
test ! -x /usr/sbin/sarg-reports || /usr/sbin/sarg-reports
The right hand side would evaluate, but because I have no permissions to execute I presume it would dump an error to stderr. So in effect it does nothing. However, I'm guessing the exit code won't be zero meaning that 'endscript' will fire and postrotate won't ever run. Does that sound like I've got it? I think I'll have a play and see - just to be clear.
Quote:
Originally Posted by Dark_Helmet
EDIT:
It seems I was fashionably late to the party
Hell, how can you be late? the DJ hasn't even turned up yet!
If my virtue be a dancer's virtue, and if I have often sprung with both feet into golden-emerald rapture, and if it be my Alpha and Omega that every thing heavy shall become light, every body a dancer and every spirit a bird: verily, that is my Alpha and Omega.
And this is the cue for the entrance of the double-negative that is Unix process exit codes.
.....
What you have to remember is, for Unix process exit codes, 0 is "success" or "true." A non-zero value is "failure" or "false."
That's the exact opposite of programming languages like C.
That clears something up for me as I tend to think in C true 1 /false 0 in my head. But I'm really confused now! I figured 'experiment will solve this for me', but hell no! Let me step through, perhaps someone will spot my logic flaw and bomb.
I created a simple 'hello world' shell script and did NOT add execute to it. Testing with the example firstfire gave (modified) it seems to be the exact opposite of what I would expect.
Code:
$ test -x `/home/leslie/scripts/hello.sh` && echo yes || echo no
-bash: /home/leslie/scripts/hello.sh: Permission denied
yes
I don't have execute permissions and I read this evaluation using true = 0 and false =1 for shell, AND, I'm guessing that the exit code of 'echo yes' would be true/0. This may be a fatal flaw, but I'd expect an echo to complete with a return code of zero (true in shell).
If I don't have execute permissions test -x the result should be 1/false in shell speak. The other side of the AND is echo yes and fires because the return code 1 (a double bluff here) is logically 'true' and evaluation of the && clause continues - firing the echo. However, as I see it the shell would return '0' (true) for the echo statement, meaning the && as a whole should fail??? 1&&0 is not true???? Therefore the whole clause fails and the || or should be evaluated printing the 'no' to the screen - but this does not happen?
Clearly I'm wrong as 'no' never prints. If I invert the test
Code:
$ test ! -x `/home/leslie/scripts/hello.sh` && echo yes || echo no
-bash: /home/leslie/scripts/hello.sh: Permission denied
no
Am I right to be confused here?? I know that outside of logical malarky:
Code:
#!/bin/sh
if [ -x /home/leslie/scripts/hello.sh ]
then
echo "is executable"
else
echo "is not executable"
fi
Works as any sane rookie would expect it to work.
Somewhere, something in my brain is broken, can you help me fix it!
Quote:
Originally Posted by Dark_Helmet
EDIT:
And as for my being late, I must be, because firstfire and cin_ were already on the dance floor
Magic, I can't trump that :-) Only to say for a good conga you need lots of people!
If I don't have execute permissions test -x the result should be 1/false in shell speak. The other side of the AND is echo yes and fires because the return code 1 (a double bluff here) is logically 'true' and evaluation of the && clause continues - firing the echo. However, as I see it the shell would return '0' (true) for the echo statement, meaning the && as a whole should fail??? 1&&0 is not true???? Therefore the whole clause fails and the || or should be evaluated printing the 'no' to the screen - but this does not happen?
Of course it wont. 1&&0 is not true, sure. But the exit code will be a big fat 1 for shell (it's false) not a zero (this is not C). Hence the or IS satisfied.
If you have a statement such as "alpha && beta" then alpha must evaluate to true and beta must evaluate to true for the whole expression to evaluate to true. The point is that for logical AND, both alpha and beta must be evaluated to determine the overall expression.
Only if alpha is true. From http://www.gnu.org/software/bash/man...nal-Constructs: "The && and || operators do not evaluate expression2 if the value of expression1 is sufficient to determine the return value of the entire conditional expression".
prerotate
test ! -x /usr/sbin/sarg-reports || /usr/sbin/sarg-reports
endscript
postrotate
test ! -e /var/run/squid.pid || /usr/sbin/squid -k rotate
endscript
AFAIK, under bash test ! -x /usr/sbin/sarg-reports || /usr/sbin/sarg-reports is functionally identical to the more natural test -x /usr/sbin/sarg-reports && /usr/sbin/sarg-reports.
I cannot think why the programmer chose the more convoluted form.
I just KNEW somebody was going to call me on that!
Yes, my original description was incomplete.
If the first/left half of a logical AND evaluates to false, the second/right half will not be evaluated--because there is no value for that portion which could make the entire statement evaluate to true.
Sorry to anyone if my haphazard response caused confusion.
And I gotta say, this is turning out to be a decent conga line.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.