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've got an unusual problem with a segment of script in my Linux rc.local file, which is automatically executed when the system starts up.
The code is shown below:
---- Start ----
echo -n "Testing current SMART status..."
echo
SMARTOUT=`smartctl -H /dev/sda -d ata | grep "SMART overall-health self-assessment test result: PASSED"`
echo
if [ -z "$SMARTOUT" ]
then
echo
echo
echo Smart Test Failed!!!
echo
echo -n "Press Enter to continue to boot: "
read dummy
echo
else
echo "done"
fi
---- End ----
The code itself is fine and runs properly. However, when used in the /etc/rc.local file, it only executes correctly when the string I search for is found. Any other scenarios results in the script exiting at the SMARTOUT=`... line. I found this problem by accident when installing the script on another machine with a different hard disk configuration. This was somewhat fortunate, as any SMART error would not have shown up.
I suspect in cases where the string is not found that grep is outputting an error level other than 0, which is causing the rc.local script to abandon immediately. I haven't been able to determine if you can suppress grep's errorlevel output, it seems not from what I can tell. I also tried to use Bash's string management features, but without grep, the output becomes multi-line and I had all kinds of trouble with it. At the moment, I'm kinda stumped.
Does anybody know how I could achieve the same results without running into these issue?
I believe you'll find that the problem goes away if you put the shell-subfunction in quotes, like so:
Code:
SMARTOUT="`smartctl -H /dev/sda -d ata | \
grep "SMART overall-health self-assessment test result: PASSED"`"
This way, even if the command returns nothing, it is still a string, albeit an empty one. Without quotes, it may be coming back as an integer, possibly from grep.
Not sure what you mean by "suppress grep's errorlevel output", but if you want to make grep be quiet, I believe there's a -q option (check the man page) and also, you could simply dump stderr into the trash, like:
Code:
SMARTOUT="`smartctl -H /dev/sda -d ata | \
grep "SMART overall-health self-assessment test result: PASSED" 2>/dev/null `"
and that should shut up any visible erorr messages from grep.
EDIT: Or, use `grep -c` which will count how many times the string was found, and return that number as an integer, thereby eliminating the need for strings entirely.
Last edited by GrapefruiTgirl; 03-20-2010 at 06:30 PM.
Reason: Broke the lines at \ to make more readable.
Thanks for your reply, my apology for the very late response, I wasn't at home I'll use the code tags as you suggested.
All three of your solutions as well as the original approach work correctly in Bash. Unfortunately none of them had any effect on the problem. However, all three of your solutions relate to what is output to the SMARTOUT variable. However, given the script actually terminates without warning or error at this very line, I had to assume that what is output to SMARTOUT is actually not the issue at all and something else terminates the script. I could only assume that it was the grep non-zero errorlevel output, but I couldn't see why this would exit the script as it did.
Quote:
The code itself is fine and runs properly. However, when used in the /etc/rc.local file
However, I managed to determine the reason for this after reading the above line from my original statement. The code runs fine on the default interpreter, i.e Bash. But the rc.local file calls "/bin/sh -e" as the interpreter. I removed the -e parameter assuming it might relate to exiting at an errorlevel other than 0 and sure enough that fixes the problem. However, I'm not really keen to remove that parameter on the /etc/rc.local file as it shields against script errors.
Anybody have any ideas how I can achieve what I need without removing that parameter?
I removed the -e parameter assuming it might relate to exiting at an errorlevel other than 0 and sure enough that fixes the problem. However, I'm not really keen to remove that parameter on the /etc/rc.local file as it shields against script errors.
Hmm.. Maybe you should be looking at this in a different way. Specifically: it is evident that using the -e option to the interpreter is NOT in fact "shielding you" against any errors, but the opposite: it's making your script exit for no obvious reason.
On my own system at least, on each version of my OS that I've used over a few years, init scripts do not use the -e option to the interpreter (and if you really wanted, you can set/unset -e as you wish in different locations).
Instead, it is probably a better idea to do some proper sanity checking and logging during the execution of the script itself; this way, if something goes awry during execution, you at least have a nice record of what it was doing when it terminated unexpectedly. This logging might include outputting a message to stderr when something returns with a non-zero status.
Also, you might be able to customize how -e performs, though I'm not sure about this; try `help set` in bash, for some options for setting things like -e
grep will exit with rc 1 if it doesn't match the string, which will trigger the -e trap.
If you need $SMARTOUT to refer to later in your script, then doing the following will avoid tripping the set -e trap.
Code:
SMARTOUT=`smartctl -H /dev/sda -d ata | grep "SMART overall-health self-assessment test result: PASSED"||true`
If you don't need to refer to $SMARTOUT again, I'd go for something like the following instead.
Code:
if smartctl -H /dev/sda -d ata | grep "SMART overall-health self-assessment test result: PASSED"
then
# do stuff when it passes
else
# do stuff when it fails
fi
add -q to the grep if you don't want to see the output of the smartctl line on stdout.
I agree with Grapefruitgirl's approach though. set -e is a blunt instrument and it's much better IMO to catch your own errors and take appropriate action.
Hmm.. Maybe you should be looking at this in a different way. Specifically: it is evident that using the -e option to the interpreter is NOT in fact "shielding you" against any errors, but the opposite: it's making your script exit for no obvious reason.
I have to firstly point out that it's not my script, but the one provided by Debian by default I merely edited it to add things I need. However, I just checked and there's nothing else in there not written by me so it's a moot point.
I agree with your thoughts though. I never use the -e parameter or even the sh interpreter for any of my personal scripts. I'll take the approach you suggested and alter my /etc/rc.local file appropriately.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.