Why does my bash if fail? - bash

The command
grep shutting log.log
returns nothing.
My script is as follows
#!/bin/bash
FAIL=`grep shutting log.log`
if [ "$FAIL"="Binary file log.log matches" ]; then
echo FOUND
else
echo NOT FOUND
fi
I'm expecting NOT FOUND but get FOUND

You have to put spaces around the = operator in an [ ... ] expression; what you have written is being interpreted as [ string ], which tests whether string is nonempty.
But you don't need backticks nor string comparison at all here. Try this instead:
if grep -q shutting log.log
then echo FOUND
else echo NOT FOUND
fi
(Thankfully, the systems that did not have the -q option to grep have long since gone to the great bit bucket in the sky.)

In your test you need spaces around the =:
#!/bin/bash
FAIL=`grep shutting log.log`
if [ "$FAIL" = "Binary file log.log matches" ]; then
echo FOUND
else
echo NOT FOUND
fi
See http://tldp.org/LDP/abs/html/comparison-ops.html

Related

Bash string comparison not working on BusyBox

I don't understand why this bash script won't work on BusyBox v1.29.3 () built-in shell (ash).
Here's the code:
#!/bin/sh
MODE=$(cat /etc/config/wireless | grep 'option mode') #not working
#MODE="option mode 'sta'" ==> this works
echo $MODE
MCHECK="option mode 'sta'"
echo $MCHECK
if [ "$MCHECK" = "$MODE" ];then
ping -c3 www.google.com > /dev/null
a=$?
echo $a
if [ $a -eq 0 ];then
echo "ok"
else
echo "fail"
fi
else
echo "no sta mode"
fi
It works correctly if I "force" the string with a variable.( the #MODE)
I imagine there are some characters in the cat returned variable that create a different string.
I always got "no sta mode" so the if won't return true.
The option mode in etc/config/wireless is the same as the string to compare.
Cannot find what am I missing..?
The problem was following gives a string with leading zeros.
MODE="$(cat /etc/config/wireless | grep 'option mode')"
Following gives the same result without leading spaces.
MODE="$(cat /etc/config/wireless | sed -n 's/\s*\(option mode.*\)/\1/p'"

Bash script for searching a specific word in terminal output

I'm trying to implement a bash script who supposed to search for a word in a Python script terminal output.
The Python script doesn't stop so "&" in the end of the command is needed but the "if [ $? == 0 ] ; then" condition doesn't work.
How it can be solved?
Thanks, Gal.
#!/bin/bash
#Check if Pixhawk is connected
PORT=/dev/ttyPixhawk
end=$((SECONDS+3))
not_exists=f
/usr/local/bin/mavproxy.py --daemon --non-interactive --master=$PORT | grep 'Failed' &> /dev/null &
while [ $SECONDS -lt $end ] ; do
if [ $? == 0 ] ; then
not_exists=t
fi
sleep 1
done
if [ $not_exists=t ] ; then
echo "Not Exists"
else
echo "Exists"
fi
kill $(pgrep -f '/usr/local/bin/mavproxy.py')
Bash doesn't know anything about the output of background commands. Check for yourself with [ 5444 -lt 3 ] & echo $?.
your if statement wouldn't work in any case because $? checks for the return value of the most recent previous command, which in this case is your while loop.
You have a few different options. If you're waiting for some output, and you know how long it is in the output until whatever target you're looking for occurs, you can have the python write to a file and keep checking on the file size with a timeout for failure.
You can also continue with a simple timed approach as you have where you just check the output after a few seconds and decide success or failure based on that.
You can make your python script actually end, or provide more error messages, or write only the relevant parts to file that way.
Furthermore, you really should run your script through shellcheck.net to notice more problems.
You'll need to define your goal and use case more clearly to get real help; all we can really say is "your approach will not work, but there are definitely approaches which will work"
You are checking the status of grep command output inside while loop using $?. This can be done if $? is the next command to be fired after grep and if grep is not a back-group process . But in your script, $? will return the status of while [$SECONDS -lt $end ]. You can try to re-direct the output to a temp file and check it's status
/usr/local/bin/mavproxy.py --daemon --non-interactive --master=$PORT | grep 'Failed' &> tmp.txt &
sleep 3
# If file exists and it's size is greater than 0, [ -s File] will return true
if [ -s tmp.txt ]; then
echo 'pattern exists'
else
echo 'pattern not exists'
fi

ps command in sh script not include the top command

I have written a script to check process is running or not,it work fine but while testing it, i have found that it not include top command count running in other terminal
check-process.sh
#!/bin/sh
OK=1
CRITICAL=0
PROCESS_NUM=$( ps -ef | grep $1 | grep -v "grep "|grep -v "sh"|wc -l )
#echo $PROCESS_NUM
if [ $PROCESS_NUM = $OK ]
then
echo "OK"
elif [ $PROCESS_NUM = $CRITICAL ]
then
echo "CRITICAL"
elif [ $PROCESS_NUM > $OK ]
then
echo "MULTIPLE process are runing"
else
echo "error"
fi
And i run top command in two terminals and run this script as follow:
./check-process.sh top
and out put is 0 CRITICAL , but when i run normal command ps -ef |grep -v "grep "| wc -l it gives two counts.
That mess of greps just has to go.
One "trick" for finding processes by name without finding your grep is to use a regular expression. That is, after all, what the Global Regular Expression Print command is for. You can use parameter expansion to construct a safe regular expression based on your input string, perhaps like this:
#!/bin/sh
if [ -z "$1" ]; then
echo "I'd love me an option." >&2
exit 1
fi
OK=1
CRITICAL=0
x="${1#?}" # make a temporary string missing the 1st chararcter,
re="[${1%$x}]$x" # then place the 1st character within square brackets.
PROC_COUNT=$( ps -ef | grep -w -c "$re" ) # yay, just one pipe.
if [ "$PROC_COUNT" -eq "$OK" ]; then
echo "OK"
elif [ "$PROC_COUNT" -eq "$CRITICAL" ]; then
echo "CRITICAL"
elif [ "$PROC_COUNT" -gt "$OK" ]; then
echo "MULTIPLE process are running"
else
echo "error"
fi
There are a few notable changes here:
I added something to fail with better explanation if no option is given.
The pipeline, of course. And the lines that create $re.
We're using -gt and -eq to test numeric values. man test for details.
I renamed your count variable to be clearer. What is a "PROCESS_NUM" really? Sounds like a PID to me.
All variables are quoted. I don't need to tell you why, you have the Google.
That said, you should also consider using pgrep instead of any sort of counting pipe, if it's available on your system. Try running pgrep and see what your OS tells you.

Error with shell scripting

!#/bin/bash
svnadmin dump /path/to/repo | gzip -9 > /path/to/backup.bak-$(date +"%d\%m\%Y--%T").dump.gz
if ( `echo $?` -eq 0)
then
echo "hello world" | mail -s "a subject" someone#wherever.com
else
echo "sorry, no way out" | mail -s "a subject" someone#wherever.com
exit 1
fi
there is an edit with the question
Any help is appreciated. Thanks
The output i get is the else part " sorry no way out! but what i expect to get is a hello world as the dump command works perfectly
Your IF clause should be: if [ $? -eq 0 ]. Notice the square brackets and the whitespaces around them.
Here is how I solved it:
!#/bin/bash
ls;
if [ $? -eq 0 ]
Your shebang is wrong. It should be #!. Also,
do not bother explicitly checking $?. Just do:
if ls; then
...
else
...
fi

Shell Script Syntax Error: Unexpected End of File [duplicate]

This question already has answers here:
Bash syntax error: unexpected end of file
(21 answers)
Closed 3 years ago.
In the following script I get an error:
syntax error: unexpected end of file
What is this error how can I resove it? It is pointing at the line whee the function is called.
#!/bin/sh
expected_diskusage="264"
expected_dbconn="25"
expected_httpdconn="20"
expected_cpuusage="95"
#expected_fd="100"
httpdconn=`ps -ef|grep -i httpd|grep -v grep|wc -l` #httpd connections
cpu_usage=`ps aux|awk 'NR > 0 { s +=$3 }; END {print s}'`
disk_usage=`df -h|awk {'print $2'}|head -n3|awk 'NF{s=$0}END{print s}'`
#db_connections=`mysql -uroot -pexxxxxx -s -N -e "show processlist"|wc -l`
db_connections=6
cld_alert()
{
nwconn=$1
cpu_usage=$2
disk_usage=$3
db_connections=$4
message=$5
`touch /tmp/alert.txt && > /tmp/alert.txt`
date=`date`
echo -e "$date\n" > /tmp/alert.txt
echo -e "$message" >> /tmp/alert.txt
path="/proc/$httpd/fd/";
cd $path
tfd=`ls -l|wc -l`;
sfd=`ls -ltr|grep sock|wc -l`;
echo "Total fds: $tfd" >> /tmp/alert.txt
echo "Socket fds: $sfd" >> /tmp/alert.txt
echo "Other fds: $[$tfd - $sfd]" >> /tmp/alert.txt
freememory=`vmstat | awk '{if (NR == 3) print "Free Memory:"\$4}'`;
echo "Free memory :$freememory" >> /tmp/alert.txt
Bufferedmemory=`vmstat | awk '{if (NR == 3) print "Buffered Memory:"\$5}'`;
echo "Buffered memory $Bufferedmemory" >> /tmp/alert.txt
CacheMemory=`vmstat | awk '{if (NR == 3) print "Cache Memory:"\$6}'`;
echo "Cache memory : $CacheMemory" >> /tmp/alert.txt
sshconn=`netstat -an|grep 22|wc -l` #ssh connections
httpsconn=`netstat -an|grep 443|wc -l` #https connections
wwwconn=`netstat -an|grep 80|wc -l` #www connections
echo "Disk usage is $disk_usage" >> /tmp/alert.txt
echo "DB connections $db_connections" >> /tmp/alert.txt
echo "Network connections $nwconn" >> /tmp/alert.txt
echo "CPU Usage: $cpu_usage" >> /tmp/alert.txt
topsnapshot=`top -n 1 -b`
echo "===========================TOP COMMAND SNAPSHOT====================================================";
echo "$topsnapshot" >> /tmp/alert.txt
echo"==================PS COMMAND SNAPSHOT=============================================================="
entireprocesslist=`ps -ef`
echo "$entireprocesslist" >> /tmp/alert.txt
echo Hello hi"";
}
message=""
if [ ${disk_usage%?} -le $expected_diskusage ] ##{x%?} Removes last character
then
echo "disk usage exceeded";
message="Disk usage limit exceeded \nCurrent disk usage is $disk_usage\nConfigured disk usage is $expected_diskusage\n\n\n\n\n";
#Checking for CPU usage
if [ $cpu_usage -ge $expected_cpuusage] ##{x%?}
then
echo "CPU usage exceeded";
if [ $message -ne "" ]
then
message="$message\n\nCPU usage exceeded configured usage limit \nCurrent CPU usage is $cpu_usage\nConfigured CPU usage is $expected_cpuusage\n\n\n\n\n";
else
message="CPU usage exceeded configured usage limit \nCurrent CPU usage is $cpu_usage\nConfigured CPU usage is $expected_cpuusage\n\n\n\n\n";
fi ;
fi
#Checking for httpd connections
if [ $httpdconn -ge $expected_httpdconn] ##{x%?}
then
echo "HTTPD connections exceeded";
if [ $message -ne "" ]
then
message="$message\n\nHTTPD connections exceeded configured usage limit \nCurrent HTTPD connections is $httpdconn\nConfigured HTTPD connection is $expected_httpdconn";
else
message="HTTPD connections exceeded configured usage limit \nCurrent HTTPD connections is $httpdconn\nConfigured HTTPD connection is $expected_httpdconn";
fi ;
fi ;
message="$message\n\n\n\n\n";
value=$(cld_alert $message $httpdconn $cpu_usage $disk_usage $db_connections)
Edit: Note that the original post has been edited since this answer was written and has been reformatted. You should look at the history to see the original formatting to understand the context for this answer.
This error occurs often when you have mismatched structure - that is, you do not have matching double quotes, matching single quotes, have not closed a control structure such as a missing fi with an if, or a missing done with a for.
The best way to spot these is to use correct indentation, which will show you where you have a broken control structure, and syntax highlighting, which will show you where quotes are not matched.
In this particular case, I can see you are missing a fi. In the latter part of your code, you have 5 ifs and 4 fis. However you also have a number of other problems - your backquoted touch /tmp/alert.txt... command is syntactically invalid, and you need a space before the closing bracket of an if test.
Clean up your code, and errors start to stand out.
in my case the issue was in the EOL Conversion. (End Of Line).
i created the file on windows and only after i converted the EOL from windows(CR LF) to unix(LF), everything went well.
I did the conversion with Notepad++ very easily from: Edit -> EOL Conversion -> Unix(LF)
Unrelated to the OP's problem, but my issue was that I'm a noob shell scripter. All the other languages I've used require parentheses to invoke methods, whereas shell doesn't seem to like that.
function do_something() {
# do stuff here
}
# bad
do_something()
# works
do_something
In my case, I found that placing a here document (like sqplus ... << EOF) statements indented also raise the same error as shown below:
./dbuser_case.ksh: line 25: syntax error: unexpected end of file
So after removing the indentation for this, then it went fine.
Hope it helps...
Indentation when using a block can cause this error and is very hard to find.
if [ ! -d /var/lib/mysql/mysql ]; then
/usr/bin/mysql --protocol=socket --user root << EOSQL
SET ##SESSION.SQL_LOG_BIN=0;
CREATE USER 'root'#'%';
EOSQL
fi
=> Example above will cause an error because EOSQL is indented. Remove indentation as shown below. Posting this because it took me over an hour to figure out the error.
if [ ! -d /var/lib/mysql/mysql ]; then
/usr/bin/mysql --protocol=socket --user root << EOSQL
SET ##SESSION.SQL_LOG_BIN=0;
CREATE USER 'root'#'%';
EOSQL
fi
I have found that this is sometimes caused by running a MS Dos version of a file. If that's the case dos2ux should fix that.
dos2ux file1 > file2
I had this problem when running some script in cygwin. Fixed by running dos2unix on the script, with proper description of problem and solution given in that answer
You've got an unclosed quote, brace, bracket, if, loop, or something.
If you can't see it just by looking (I'd recommend a syntax colouring editor and a neat indentation style), take a copy of the script, and delete half of it, cutting it of somewhere that ought to be valid. If the script runs, as far as it can, then the problem is in the other half. Repeat until you've narrowed down the problem.
echo"==================PS COMMAND SNAPSHOT=============================================================="
needs to be
echo "==================PS COMMAND SNAPSHOT=============================================================="
Else, a program or command named echo"===... is searched.
more problems:
If you do a grep (-A1: + 1 line context)
grep -A1 "if " cldtest.sh
you find some embedded ifs, and 4 if/then blocks.
grep "fi " cldtest.sh
only reveals 3 matching fi statements. So you forgot one fi too.
I agree with camh, that correct indentation from the beginning helps to avoid such errors. Finding the desired way later means double work in such spaghetti code.
Helpful post, I found that my error was using else if instead of elif like so:
if [ -z "$VARIABLE1" ]; then
# do stuff
else if [ -z "$VARIABLE2" ]; then
# do other stuff
fi
Fixed it by changing to this:
if [ -z "$VARIABLE1" ]; then
# do stuff
elif [ -z "$VARIABLE2" ]; then
# do other stuff
fi
It can also be caused by piping out of a pair of curly braces on a line.
This fails:
{ /usr/local/bin/mycommand ; outputstatus=$? } >> /var/log/mycommand.log 2>&1h
do_something
#Get NOW that saved output status for the following $? invocation
sh -c "exit $outputstatus"
do_something_more
while this is allowed:
{
/usr/local/bin/mycommand
outputstatus=$?
} >> /var/log/mycommand.log 2>&1h
do_something
#Get NOW that saved output status for the following $? invocation
sh -c "exit $outputstatus"
do_something_more
I have encountered the same error while trying to execute a script file created in windows OS using textpad. so that one can select proper file format like unix/mac etc.. or recreate the script in linux iteself.

Resources