Bash error [: : integer expression expected" - bash

I'm getting into the error for bash shell [: : integer expression expected" while running below script.
#!/bin/bash
sm=$(ps -e | grep sendmail > /dev/null 2>&1)
pm=$(/etc/init.d/postfix status > /dev/null 2>&1)
check_mail(){
if [ "$sm" -eq 0 ]; then
echo "Service Status: Sendmail is Running!"
elif [ "$pm" -eq 0 ]; then
echo "Service Status: Postfix Service is Running!"
else
echo "Service Status: Both Sendmail & Postfix Service is Not Running On $(uname -n)"
fi
}
check_mail
While running the above script it's simply showing the output of else
condition.
Service Status: Both Sendmail & Postfix Service is Not Running On host
Though, i have tested "==" rather "-eq" for comparison and [[]] but did not worked.

I assume you are trying to assess presence of sendmail in the process list. You should change your code to this :
#!/bin/bash
check_mail(){
if
ps -e | grep sendmail > /dev/null 2>&1
then
echo "Service Status: Sendmail is Running!"
elif
/etc/init.d/postfix status > /dev/null 2>&1
then
echo "Service Status: Postfix Service is Running!"
else
echo "Service Status: Both Sendmail & Postfix Service is Not Running On $(uname -n)"
fi
}
check_mail
The reason your original code fails is that you capture the output of commands using command substitution $(). The standard output, that is, not the exit code. Then, when using the [ -eq ] test, which expects an integer argument (which your variable does not contain), it fails with the message you get. Since both tests always fail, the else clause is entered.
By putting the actual commands inside the conditions of the if statement, you are using the actual numerical return code (0 for true, non-zero for false), which is what you want here.

It seems to me that you are confusing the exit-status of a program with the output.var=$(command) will put the output of command in var. As said in 123's comment, because you redirect everything to /dev/null, there is no output, and therefore, sm and pm are empty.
If you want to see the exit status, use $?:
#!/bin/bash
typeset -i pm
typeset -i sm
ps -e | grep sendmail > /dev/null 2>&1
sm=$?
/etc/init.d/postfix status > /dev/null 2>&1
pm=$?
check_mail(){
if [ $sm -eq 0 ]; then
echo "Service Status: Sendmail is Running!"
elif [ $pm -eq 0 ]; then
echo "Service Status: Postfix Service is Running!"
else
echo "Service Status: Both Sendmail & Postfix Service is Not Running On $(uname -n)"
fi
}
check_mail

Related

wait for the service to be stopped and proceed further in shell script

I am trying a shell script where it needs to wait for the service to be stopped and if its stopped proceed further in script, else it is hung exit from the script.Could someone help me on this. PFB script which I am trying
for i in 13.127.xxx.xxx xx.xxx.xxx.xx
do
echo '############# Stopping the '$i' Apache service ################'
ssh $i echo 'ansible' | sudo -S /etc/init.d/apache2 stop || { echo 'my command failed' ; exit 1 ; }
wait
echo 'service has been stopped'
echo '############# Status of the '$i' Apache service ################'
abc=0
abc=`ps -ef | grep "apache" | grep -v "grep" | wc -l`
if [ $abc -eq 0 ]
then
echo "Boomi process on $i is stopped, proceeding further!!!"
else
echo "Exiting the script as Script could not stop the Boomi process, Please check the issue " ; exit 1;
fi
sleep 10
ssh $i echo 'ansible' | sudo -S /etc/init.d/apache2 status
done
One should warn, that passing unencrypted password using pipe redirection over a simple ssh bash command is unsafe and bad. One that could inspect the script would immediately gain root access to your nodes. The proper way is to add a line sudoers file for executing specified commands (/etc/init.d/apache and pgrep) as a normal, unprivileged user.
for i in 13.127.xxx.xxx xx.xxx.xxx.xx; do
echo '############# Stopping the '"$i"' Apache service ################'
if ! ssh "$i" 'echo ansible | sudo -S /etc/init.d/apache2 stop'; then
echo "ERROR: stopping apache2 on $i failed!" >&2
exit 1
fi
echo 'service has been stopped'
echo '############# Status of the '"$i"' Apache service ################'
ssh "$i" 'echo ansible | sudo -S pgrep apache' && ret=$? || ret=$?
if [ "$ret" -eq 0 ]; then
echo "apache process is not stopped"
elif [ "$ret" -eq 1 ]; then
echo "apache process was successfully stopped"
else
echo "error in executing ssh + pgrep"
exit 1
fi
sleep 10
ssh "$i" 'echo ansible | sudo -S /etc/init.d/apache2 status'
done
You forgot about the quotes. If you run ssh $i echo ansible | .... the part in ... get's executed locally, not on the remote machine. The | character separates commands, just like ; or && or || or &. Except for separating the commands, it also joins the first command stdout to the others stdin.
To run everything on the other host, you need to pass it as an argument to ssh ssh $i "echo ansible | ....". The whole command is passed to ssh, the remote shell then splits the command again into tokens, and executes the echo ansible and ... part as two commands separated with |.
To me the script should looks like:
#!/bin/bash
for i in 13.127.xxx.xxx xx.xxx.xxx.xx
do
echo '############# Stopping the '$i' Apache service ################'
ssh $i echo "ansible | sudo -S /etc/init.d/apache2 stop" || { echo 'my command failed' ; exit 1 ; }
wait
echo 'service has been stopped'
echo '############# Status of the '$i' Apache service ################'
abc=0
abc=$(ssh $i echo "ansible | sudo -S pgrep apache | wc -l")
if [ "$abc" -eq 0 ]
then
echo "Boomi process on $i is stopped, proceeding further!!!"
else
echo "Exiting the script as Script could not stop the Boomi process, Please check the issue " ; exit 1;
fi
sleep 10
ssh $i echo "ansible | sudo -S /etc/init.d/apache2 status"
done
Check quotes and abc var when ssh'ing your hosts

Why does this bash script produce error?

This simple script - to check whether a process is running and then send an email if it's not - works fine:
#!/bin/bash
if pgrep -f "ghost.py" > /dev/null
then
echo "Running" > /dev/null
else
echo "Looks like ghost.py stopped" | mail -s "ghost.py down" shaney.jones#gmail.com
fi
However, my attempt to have an OR operator in there to check two scripts fails:
#!/bin/bash
if [ pgrep -f "ghost.py" ] || [ pgrep -f "ghost2.py" ] > /dev/null
then
echo "Running" > /dev/null
else
echo "Looks like a script stopped" | mail -s "Script down" shaney.jones#gmail.com
fi
The error just says '-bash: [: -f: binary operator expected'
Drop the brackets as it's completely another command (usually equivalent to test):
if pgrep -f "ghost.py" || pgrep -f "ghost2.py" > /dev/null
then
# Your stuff
See help test and man test for more details about the [ command.

shell script handle an error from a command being excuted from echo

Hello I am new to shell script and I need to handle the error coming from a command being excuted inside echo like the following
echo -e "some internal command that I can't share \nq" | nc localhost 10000
I want to say
if [[ there's no error ]]
try
echo "YOUR SUPERSECRET COMMAND" | nc localhost 10000 | grep "Your expected error"
if [[ $? -eq 0 ]]; then
echo "Do something useful with error"
else
echo "Success"
fi
grep return 0 on matching and returns 1 when it doesn't find matching string.
The shell variable $? will give you the exit code. So, you could do:
echo -e "some internal command that I can't share \nq" | nc localhost 10000
rc=$?
if [[ $rc == 0 ]]; then
echo "success"
fi
Or simply,
if echo -e "some internal command that I can't share \nq" | nc localhost 10000; then
echo "success"
fi
Here is a concise way of doing it:
internalcommand &>/dev/null 2>&1 && echo OK || echo FAILED
If internalcommand succeeds OK will be printed to stdout, if it fails FAILED is printed.
Note tested on Bash v4

exit code from ssh command

I'm trying to retrieve the code return from this script:
#!/bin/bash
echo "CM 1"
ssh -i key/keyId.ppk user#X.X.X.X "
grep blabla ddd
if [ ! $? -eq 0 ]; then exit 1; fi
"
echo $?
But the last command echo $? returns 0 instead of 1.
And if try to run separately (not as a script) :
the ssh command: ssh -i key/keyId.ppk user#X.X.X.X
grep blabla ddd => I get the msg "grep: ddd: No such file or directory"
then: if [ ! $? -eq 0 ]; then exit 1; fi
then: echo $? => it returns 1 as expected
Do you have an idea why it doesn't work in my script ?
Thank you
This code
ssh -i key/keyId.ppk user#X.X.X.X "
grep blabla ddd
if [ ! $? -eq 0 ]; then exit 1; fi
"
evaluates $? in your shell and not in the remote one, because the $ is not escaped in single quotes. You should escape that to reach desired behaviour. Once to avoid evaluation in your local shell, for the second time to avoid evaluation when it is passed to the bash on remote side. Or rather put the command into single quotes:
ssh -i key/keyId.ppk user#X.X.X.X '
grep blabla ddd
if [ ! $? -eq 0 ]; then exit 1; fi
'

exit statement will not break while loop in unix shell

The exit statements in each status check if statement do not break the while loop and truly exit the script. Is there something I can do to break the loop and exit with that $STATUS code?
EDIT: I've updated my code and it still isn't working. The status check if statements successfully break the loop but when I try to evaluate the $EXIT_STATUS it's always null, likely having something to do with scope. What am I missing here?
if [ $RESTART -le $STEP ]; then
. tell_step
while read XML_INPUT; do
XML_GDG=`get_full_name $GDG_NAME P`
cp $XML_INPUT $XML_GDG
STATUS=$?
EXIT_STATUS=$STATUS
if [ $STATUS -ne 0 ]; then
break
fi
add_one_gen $XML_GDG
STATUS=$?
EXIT_STATUS=$STATUS
if [ $STATUS -ne 0 ]; then
break
fi
done < $XML_STAGE_LIST
echo $EXIT_STATUS
if [ $EXIT_STATUS -ne 0 ]; then
exit $EXIT_STATUS
fi
fi
I had the same problem: when piping into a while loop, the script did not exit on exit. Instead it worked like "break" should do.
I have found 2 solutions:
a) After your while loop check the return code of the while loop and exit then:
somecommand | while something; do
...
done
# pass the exit code from the while loop
if [ $? != 0 ]
then
# this really exits
exit $?
fi
b) Set the bash script to exit on any error. Paste this at the beginning of your script:
set -e
Not really understand why your script dosn't exits on exit, because the next is works without problems:
while read name; do
echo "checking: $name"
grep $name /etc/passwd >/dev/null 2>&1
STATUS=$?
if [ $STATUS -ne 0 ]; then
echo "grep failed for $name rc-$STATUS"
exit $STATUS
fi
done <<EOF
root
bullshit
daemon
EOF
running it, produces:
$ bash testscript.sh ; echo "exited with: $?"
grep failed for bullshit rc-1
exited with: 1
as you can see, the script exited immediatelly and doesn't check the "daemon".
Anyway, maybe it is more readable, when you will use bash functions like:
dostep1() {
grep "$1:" /etc/passwd >/dev/null 2>&1
return $?
}
dostep2() {
grep "$1:" /some/nonexistent/file >/dev/null 2>&1
return $?
}
err() {
retval=$1; shift;
echo "$#" >&2 ; return $retval
}
while read name
do
echo =checking $name=
dostep1 $name || err $? "Step 1 failed" || exit $?
dostep2 $name || err $? "Step 2 failed" || exit $?
done
when run like:
echo 'root
> bullshit' | bash testexit.sh; echo "status: $?"
=checking root=
Step 2 failed
status: 2
so, step1 was OK and exited on the step2 (nonexisten file) - grep exit status 2, and when
echo 'bullshit
bin' | bash testexit.sh; echo "status: $?"
=checking bullshit=
Step 1 failed
status: 1
exited immediatelly on step1 (bullshit isn't in /etc/passwd) - grep exit status 1
You'll need to break out of your loop and then exit from your script. You can use a variable which is set on error to test if you need to exit with an error condition.
I had a similar problem when pipelining. My guess is a separate shell is started when piplining. Hopefully it helps someone else who stumbles across the problem.
From jm666's post above, this will not print 'Here I am!':
while read name; do
echo "checking: $name"
grep $name /etc/passwd >/dev/null 2>&1
STATUS=$?
if [ $STATUS -ne 0 ]; then
echo "grep failed for $name rc-$STATUS"
exit $STATUS
fi
done <<EOF
root
yayablah
daemon
EOF
echo "Here I am!"
However the following, which pipes the names to the while loop, does. It will also exit with a code of 0. Setting the variable and breaking doesn't seem to work either (which makes sense if it is another shell). Another method needs to be used to either communicate the error or avoid the situation in the first place.
cat <<EOF |
root
yayablah
daemon
EOF
while read name; do
echo "checking: $name"
grep $name /etc/passwd >/dev/null 2>&1
STATUS=$?
if [ $STATUS -ne 0 ]; then
echo "grep failed for $name rc-$STATUS"
exit $STATUS
fi
done
echo "Here I am!"

Resources