Check string and file empty in script shell - linux

I have the script below that makes a query for the String ERROR generated by HTTP queries, I would like it to check all lines and just return me TRUE for when there is an error or file is empty
result.log
Collecting: LINK1 HTTP 200
EXCEPT ERROR - REST API LINK2 returned HTTP Error
Script:
1 cat /healthcheck/bin/gaps/result.log | grep HTTP | while read line
2 do
3 echo "$line" | grep "ERROR" >/dev/null
4 if [ $? = 0 ]; then
5 RESULT = "TRUE"
6 fi
7 done
8
9 echo $RESULT
Output:
./check.sh: line 5: RESULT: command not found
./check.sh: line 5: RESULT: command not found
Shell check:
$ shellcheck myscript
Line 1:
cat /healthcheck/bin/gaps/result.log | grep HTTP | while read line
^-- SC2148: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.
^-- SC2002: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead.
^-- SC2162: read without -r will mangle backslashes.
Line 4:
if [ $? = 0 ]; then
^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
Line 5:
RESULT = "TRUE"
^-- SC2030: Modification of RESULT is local (to subshell caused by pipeline).
^-- SC1068: Don't put spaces around the = in assignments (or quote to make it literal).
Line 9:
echo $RESULT
^-- SC2031: RESULT was modified in a subshell. That change might be lost.
$

Pipe runs in a subshell. Changes from a subshell are not visible to parent shell. The site bashfaq/024 presents possible workarounds.
You can put break the line if | is the last character on the line, no need to build super long lines for pipelines.
Upper case variables are by convention reserved for exported variables.
cat ... | grep is a useless use of cat. Just grep ... or < file grep.
When you check command return value, just if the command; then instead of the command; if [ $? ....
Use greps exit status in an if. In bash just if <<<"$string" grep -q "pattern"; then. In posix shell do if printf "%s\n" "$string" | grep -q "pattern"; then.
Bash is space aware. The RESULT = "TRUE" executes a command named RESULT with two arguments. It's RESULT="TRUE"
Use while IFS= read -r line to read the whole line exactly.
So while you could:
cat /healthcheck/bin/gaps/result.log |
grep HTTP |
{
while read line
do
echo "$line" | grep "ERROR" >/dev/null
if [ $? -eq 0 ]; then
RESULT="TRUE"
fi
done
echo $RESULT
}
In your case, it's just:
if grep "HTTP" /healthcheck/bin/gaps/result.log | grep -q "ERROR"; then
echo TRUE
fi

Related

Bash command check if string match in command output

I have following command output
$ /opt/CrowdStrike/falconctl -g --aid | grep 'aid='
aid="fdwe234wfgrgf34tfsf23rwefwef3".
I want to check if there is any string after aid= (inside ""). If there is any string, command return code should be 0 and if no value return code must be !=0.
Can someone please help to extend this command to get required output?
Idea is to make sure my bash script to fail if aid= doesn't has any value.
You can use regex to check whether one or more characters exist inside the double quotes. And, you can use regex capture group to extract that value:
if [[ $(/opt/CrowdStrike/falconctl -g --aid | grep 'aid=') =~ ^aid=\"(.+)\"$ ]]; then
aid=${BASH_REMATCH[0]}
echo "aid is $aid"
else
echo "aid not found"
fi
Note that the regex I use is .+ which means 1 or more characters, since you require the string to be non-empty. This is in contrast of the usual .* regex which would have be 0 or more characters.
I don't have falconctl on my system so to mimic its output I'll use a couple files:
$ head falcon*out
==> falcon.1.out <==
some stuff
aid="fdwe234wfgrgf34tfsf23rwefwef3".
some more stuff
==> falcon.2.out <==
some stuff
aid=""
some more stuff
One grep idea:
grep -Eq '^aid="[^"]+"' <filename>
Where:
-E - enable extended regex support
-q - run in silent/quiet mode (suppress all output)
the return code can be captured from $?
Taking for a test drive:
for fname in falcon*out
do
printf "\n############# %s\n" "$fname"
cat "$fname" | grep -Eq '^aid="[^"]+"' "$fname"
echo "return code: $?"
done
This generates:
############# falcon.1.out
return code: 0
############# falcon.2.out
return code: 1

Unix using grep with if

This my code
if [[ (grep -x $idle | grep -x $dead | grep -x $busy) || grep -x $idle1 | grep -x $dead | grep -x $busy1 ]] ./Event.log
then
echo "Events are running Successfully" >> ./Event.log
else
echo "One or more Events are down. Check the log and restart the Events." >> ./Event.log
fi
I'm getting the error
0403-057 Syntax error at line 14 : `-x' is not expected.
What's up?
In bash, [[ is syntactically a command which is terminated with the matching ]]. It is not part of the syntax of the if command, whose syntax starts:
if commands ; then
If you want to test whether a command succeeded or not, you just do that:
if grep -q pattern file; then
# grep found pattern in file
else
# grep did not find pattern in file
fi
Within a [[ command, bash expects to find a conditional expression, not another command. That's why grep -x ... is a syntax error. -x is a unary operator in a conditional expression, which is true if its argument is the name of an executable file, but in that expression it is being used as though it were a binary operator.
If you wish to test for more than one pattern with grep, you can use the -e option to specify each option; the grep will succeed (or select) lines matching any of the options:
if grep -q -e pattern1 -e pattern2 file; then
# grep found pattern1 or pattern2 in file
else
# grep did not find either pattern in file
fi
By a long shot, I am guessing that you want Event.log to contain one each of either member of the pairs. This could be done with something like
if awk "/^($idle|$idle1)$/ { ++idle; next }
/^($dead|$dead1)$/ { ++dead; next }
/^($busy|$busy1)$/ { ++busy; next }
idle && dead && busy { exit 0 }
END { exit 1 }' Event.log; then
echo Yes
else
echo no
fi
This collects three variables; if all of them are true, the Awk script exits with a success exit code (that's zero); otherwise, it will return failure (any nonzero value).
It would make more sense to print the result from Awk, too, but there is an awful amount of assumptions and guesswork in this answer already.

How can I obtain command returning status in linux shell

Say, I call grep "blabla" $file in my shell. How could I know whether grep found "blabla" in $file?
I try ret='grep "blabla" $file', will this work by viewing the value of ret? If yes, is ret integer value or string value or something else?
If you do exactly
ret='grep "blabla" $file'
then ret will contain the string "grep "blabla" $file".
If you do (what you meant)
ret=`grep "blabla" $file`
then ret will contain whatever output grep spit out (the lines that matched "blabla" in $file).
If you just want to know whether grep found any lines that matched "blabla" in $file then you want to check the return code of grep -q blabla "$file" (note that you don't need to quote literal strings when they don't contain special characters and that you should quote variable references).
The variable $? contains the return code of the most recently executed command. So
grep -q blabla "$file"
echo "grep returned: $?"
will echo the return code from grep which will be 0 if any lines were output.
The simplest way to test that and do something about it is, however, not to use $? at all but instead to just embed the grep call in an if statement like this
if grep -q blabla "$file"; then
echo grep found something
else
echo grep found nothing
fi
When you run the command
grep blabla "$file"
Status is saved in the variable $?. 0 is good, greater than 0 is bad. So you
could do
grep -q blabla "$file"
if [ $? = 0 ]
then
echo found
fi
Or save to a variable
grep -q blabla "$file"
ret=$?
if [ $ret = 0 ]
then
echo found
fi
Or just use if with grep directly
if grep -q blabla "$file"
then
echo found
fi

bash: grep wildcard start and end with

i have a bash script like this:
TABLE_TO_IGNORE=$(mysql -u $DBUSER -p$DBPASS -h $DBHOST -N <<< "show tables from $DBNAME" | grep "^$i" | xargs);
currently i only able to grep the text starting with. How to write the code that to determine the text ending with?
let say 1:
my $i is:
test1_*
tb2_*
tb3_*
with the * at the back part, it will grep as text starting with those value
let say 2:
my $i is:
*_sometext1
*sometext2
with the * at the front, it will grep as text ending with those value.
i know this:
grep '^sometext1' files = 'sometext1' at the start of a line
grep 'sometext2$' files = 'sometext2' at the end of a line
question is: how do i write the if else to my bash code identify the * is in front or back?
Note: You can ignore my bash code, i just need the if else condition to determine the "*" is in front or at the back of the string.
Any help would be great.
Thanks
You can try this code.
#!/bin/bash
stringToTest="Hello World!*"
echo $stringToTest | grep "^\*.*" > /dev/null
if [ $? -eq 0 ]; then
echo "Asterisk is at the front"
fi
echo $stringToTest | grep "^.*\*$" > /dev/null
if [ $? -eq 0 ]; then
echo "Asterisk is at the back"
fi
As shown in this code, I made use of exit code ($?) to determine whether the regular expression matches the string. As shown in man grep:
Normally, exit status is 0 if selected lines are found and 1
otherwise.
Hope this helps.

shell script error

I have a shell script like this.
line="$#" # get the complete first line which is the complete script path
name_of_file = ${line%.*}
file_extension = ${line##*.}
if [ $file_extension == "php"]
then
ps aux | grep -v grep | grep -q "$line" || ( nohup php -f "$line" > /var/log/iphorex/$name_of_file.log & )
fi
if [ $file_extension == "java"]
then
ps aux | grep -v grep | grep -q "$line" || ( nohup java -f "$name_of_file" > /var/log/iphorex/$name_of_file.log & )
fi
here line variable has values like /var/www/dir/myphp.php or /var/www/dir/myjava.java.
The purpose of shell script is to check if these processes are already running and if not i try to run them.I get the following errors.
name_of_file: command not found
file_extension: command not found
[: missing `]'
[: missing `]'
Any ideas?
Firstly, the shell processor treats the line:
name_of_file = ${line%.*}
as the execution of the command:
name_of_file
with the parameters:
= ${line%.*}
you need to write it as:
name_of_file=${line%.*}
This makes it into a variable=value. You need to repeat this for the file_extension = line as well.
Secondly, the if:
if [ $file_extension == "php"]
has exactly the same parsing problem, you must have a space before the trailing ], because otherwise the parser thinks you're checking if $file_extension is equal to the string: "php]"
if [ $file_extension == "php" ]
delete the spaces first, maybe this will help...
name_of_file=${line%.*}
file_extension=${line##*.}
EDIT
Try this:
if [ $file_extension="php" ]
..
if [ $file_extension="java" ]
The other answers are right that the problem in your script lies in stray spaces in your variable assignments and [ .. ] statements.
(off-topic. FYI)
I took the liberty of refactoring your script (untested!) just to highlight some alternatives, namely:
using pgrep instead of ps aux | grep .....
using case
-
#!/bin/bash
line="$#" # get the complete first line which is the complete script path
name_of_file=${line%.*}
pgrep "$line" > /dev/null && exit # exit if process running
case "${line##*.}" in # check file extension
php)
nohup php -f "$line" > /var/log/iphorex/$name_of_file.log &
;;
java)
nohup java -f "$name_of_file" > /var/log/iphorex/$name_of_file.log &
;;
esac

Resources