Bash script to monitor Mongo db doesn't work - mongodb

I am writing a bash script to monitor my MongoDB status. once it is crash then restart it. the script is as below:
while true
do
ret = $("mongod --config /etc/mongod.conf")
if $ret == 0
then
echo "I am out with code 0."
break
fi
echo "running again"
done
echo "I am out with code $?"
But it seems doesn't work. Return from the system:
running again
./mongo-text: line 3: mongod --config /etc/mongod.conf: No such file or directory
./mongo-text: line 3: ret: command not found
./mongo-text: line 4: ==: command not found
not sure what the problem is. Any help is appreciated.

Your loop can be made much simpler:
while ! mongod --config /etc/mongod.conf; do
echo "running again" >&2
sleep 1
done
if test -n "$VERBOSE"; then echo 'modgod successful'; fi
Note that the if keyword executes a command. So if $ret == 0 attempts to run the command $ret (assuming that variable is non-empty and contains no whitespace) with the arguments == and 0. That is almost certainly not what you intend. It is more typical to write if test "$ret" = 0 or if [ "$ret" = 0 ]. If $ret is empty, then it is attempting to execute the command == with the single argument 0.

There are several issues in your code:
$("mongod --config /etc/mongod.conf") will try to run mongod --config /etc/mongod.conf as a command, with spaces included
the if syntax is wrong
You can rewrite it this way:
while :; do
if mongod --config /etc/mongod.conf; then
echo "I am out with code 0."
break
fi
echo "running again"
# probably sleep for a few seconds here
done
echo "I am out with code $?"
For info about if statements, see:
How to check the exit status using an if statement
How to compare strings in Bash
Compound if statements with multiple expressions in Bash

Related

Why is inotifywait not executing the body of the while loop

I had inotifywait working well, and suddenly it has stopped working as I expected. I'm not sure what's happening. My script:
#!/bin/bash
while inotifywait -e modify foo.txt; do
echo we did it
done
echo $?
When I execute it, I get:
Setting up watches.
Watches established.
When I edit foo.txt, I get:
0
And then the script exits.
Why is the while loop exiting given that the exit code is 0?
Why is it never echoing the content of the while loop?
UPDATE
This version does work. However I still don't get what's wrong with the original (given that, I swear, it was working for some time.)
#!/bin/bash
echo helle
while true; do
inotifywait -e modify foo.txt
echo hello
done

Bourne shell: how should I terminate a script from within a while loop reading from a pipe?

Here is /bin/sh behaviour that surprised me, "exit" failing to exit:
$ cat sh_exit_from_while_pipe
#!/bin/sh
echo foobar | while read blabla
do
echo >&2 "Calling 'exit 2'"
exit 2
echo >&2 "It seems 'exit' did not terminate the while loop?"
done
echo >&2 "It seems 'exit' did not terminate the script?"
$ ./sh_exit_from_while_pipe
Calling 'exit 2'
It seems 'exit' did not terminate the script?
Empirically I notice exit is leaving the while loop, but not the whole script. So my best guess at the moment is that, maybe, the pipe forks a new shell as subprocess, and exit only terminates the subprocess?
What would be a good way to terminate properly? (I might rewrite this entirely to avoid the "echo foobar |" - which might avoid this problem, but I'm still interested in how this might be more directly addressed.)
At the point where you execute exit 2, you can't tell how many "levels" of shell need to exit. The best you can do is use the exit status of the loop to see if that level should exit as well. For example,
echo foobar | while read blabla; do
x=$(foo)
if [ "$x" = bar ]; then
exit 0 # We're done with the loop, success
elif [ "$x" = gulp ]; then
exit 1 # We're done with the loop, failure
else
exit 2 # We're done with the script, abort!
fi
done
case $? in
2) printf 'Fatal error in loop, exiting\n' >&2; exit 1 ;;
*) printf 'Loop result %d, continuing\n' ;;
esac
printf 'Continuing script...'
You can check the value returned by the while loop. eg:
#!/bin/sh
if ! echo foobar | { while read blabla
do
echo >&2 "Calling 'exit 2'"
exit 2
echo >&2 "It seems 'exit' did not terminate the while loop?"
done
exit 0
}; then
echo >&2 "The loop failed"
exit 1
fi
echo >&2 "It seems 'exit' did not terminate the script?"
(Note that the brackets and the exit 0 are not actually necessary, just added to be explicit.)

How to detect an error at the beginning of a pipeline?

In my script I need to work with the exit status of the non-last command of a pipeline:
do_real_work 2>&1 | tee real_work.log
To my surprise, $? contains the exit code of the tee. Indeed, the following command:
false 2>&1 | tee /dev/null ; echo $?
outputs 0. Surprise, because the csh's (almost) equivalent
false |& tee /dev/null ; echo $status
prints 1.
How do I get the exit code of the non-last command of the most recent pipeline?
Bash has set -o pipefail which uses the first non-zero exit code (if any) as the exit code of a pipeline.
POSIX shell doesn't have such a feature AFAIK. You could work around that with a different approach:
tail -F -n0 real_work.log &
do_real_work > real_work.log 2>&1
kill $!
That is, start following the as yet non-existing file before running the command, and kill the process after running the command.

How to capture error message from prompt - shell or perl

I am trying to capture the output of a command. It works fine if the command executes. However when there is an error, i am unable to capture what gets displayed in commandline
Eg.
$ out=`/opt/torque/bin/qsub submitscript`
qsub: Unauthorized Request MSG=group ACL is not satisfied: user abc#xyz.org, queue home
$ echo $out
$
I want $out to have the message
Thanks!
Errors are on stderr, so you need to redirect them into stdout so the backticks will capture it:
out=`/opt/torque/bin/qsub submitscript 2>&1`
if [ $? -gt 0 ] ; then
# By convention, this is sent to stderr, but if you need it on
# stdout, just remove the >&2 redirection
echo "Error: $out" >&2
else
echo "Success: $out"
fi
You should test the exit status of the command to figure out what the output represents (one way shown). It is similar for perl, slightly different syntax of course.
Have you tried doing it like this
$ out=`/opt/torque/bin/qsub submitscript 2>&1 > /dev/null`
$ echo $out

How can I make a shell script indicate that it was successful?

If I have a basic .sh file containing the following script code:
#!/bin/sh
rm -rf "MyFolder"
How do I make this running script file display results to the terminal that will indicate if the directory removal was successful?
You don't really need to make it say it was successful. You could have it say something only on error ✖, and then silence means success ✔.
That's how the Unix philosophy works:
The rule of silence, also referred to as the silence is golden rule, is an important part of the Unix philosophy that states that when a program has nothing surprising, interesting or useful to say, it should say nothing. It means that well-behaved programs should treat their users' attention and concentration as being valuable and thus perform their tasks as unobtrusively as possible. That is, silence in itself is a virtue. http://www.linfo.org/rule_of_silence.html
That's the way rm itself behaves.
If you are asking about the general case, as suggested by your question's title, you can run your script with sh -x scriptname to see what it's doing. It's also quite common to write diagnostic output into the script itself, and control it with an option.
#!/bin/sh
verbose=false
case $1 in -v | --verbose )
verbose=true
shift ;;
esac
say () {
$verbose || return
echo "$0: $#" >&2
}
say "Removing $dir ..."
rm -rf "$dir" || say "Failed."
If you run this script without any options, it will run silently, like a well-behaved Unix utility should. If you run it with the -v option, it will print some diagnostics to standard error.
rm -rf "My Folder" && echo "Done" || echo "Error!"
You can read more on creating a sequence of pipelines in bash manual
In the bash (and other similar shells) the ? environment variable gives you the exit code of the last executed command. So you can do:
#!/bin/sh
rm -rf "My Folder"
echo $?
UPDATE
If once the rm command has been executed the directory doesn't exist (because it has been successfully removed or because it didn't exist when the command was executed) the script will print 0. If the directory exists (which will mean that the command has been unable to remove it) then the script will print an exit code other than 0. If I understand properly the question this is exactly the requested behavior. If it is not, please correct me.
The previous answers was wrong : rm don't exit with error code > 0 when the dir isn't present.
Instead, I recommend to use :
dir='/path/to/dir'
if [[ -d $dir ]]; then
rm -rf "$dir"
fi
If you want rm to return a status, remove -f flag.
Example on Linux Mint (the dir doesn't exists):
$ rm -rf /tmp/sdfghjklm
$ echo $?
0
$ rm -r /tmp/sdfghjklm
$ echo $?
1