If condition with AWK giving incorrect output - shell

Here is a snippet of a code ,I am expecting the result to be printed as Failed but it ends up giving me Ok message instead. I have cross checked and crontab entry does have the string that the code is searching for. NR ==0 should be false as I understand, what is the purpose of $0<1 ?
Crontab entry as seen :
# comment x
00 5 * * * /opt/vol/scripts/volumes.sh -m SOP
Code:
shell: |
crontab -l | grep -v "^#" | grep "/opt/vol/scripts/volumes.sh" | grep "SOP" |
awk 'END { if (NR==0 || $0<1) print "OK - sop job not scheduled"; else print "FAILED - sop job should not be scheduled"; }
Incorrect Output:
OK - sop job not scheduled
Expected Output:
FAILED - sop job should not be scheduled

To simplify:
if crontab -l | grep -Eq "^\s*[^#].*/opt/vol/scripts/volumes\.sh.*SOP"; then
echo "OK - sop job scheduled"
exit 0
else
echo "FAILED - sop job should not be scheduled" >&2
exit 1
fi
If it's not the expected echo's, edit the echo's lines

Related

I am very new to BASH Scripting, How do I keep a running total (count) of the keyword hits (grep) in a file and then display totals in the end?

count= `grep success <fileName.txt>
The above will only give me a total count of the word "success" but I want to keep a running total. For example, if there is a total of 'expected' 25 hits of which only 20 were found. This would mean that there were 5 failures. So I think I need to keep a running total so in the end I can report (echo) as follows:
20 out of 25 expected success found; 5 failures.
You could use awk which will print out the custom output also.
awk '/success/{ success++ ; expected=25 } END { if ( success < expected ) ; print success " out of " expected " success found; " fail " failures"};{fail=expected-success}' input_file
Example Output
$ for i in {1..25}; do echo "success";done |\
> awk '/success/{ success++ ; expected=25 } END { if ( success < expected ) ; print success " out of " expected " success found; " fail " failures"};{fail=expected-success}'
25 out of 25 success found; 0 failures
This should suffice:
~$ count=$(grep -o -i <search_term> <data_source> | wc -l)
e.g.
~$ count=$(grep -o -i computer myfile.txt | wc -l)
~$ echo $count
--- flag explanations ---
-o means only print only the matching part of the line. Can also be written as --only-matching.
-i makes the search case-insensitive. Also written as --ignore-case.
-l means output the number of lines in each datasource/input file. In the above command, that coordinates with grep with the -o flag which counts each match as a unique line found.

Find words in multiple files and sort in another

Need help with "printf" and "for" loop.
I have individual files each named after a user (e.g. john.txt, david.txt) and contains various commands that each user ran. Example of commands are (SUCCESS, TERMINATED, FAIL, etc.). Files have multiple lines with various text but each line contains one of the commands (1 command per line).
Sample:
command: sendevent "-F" "SUCCESS" "-J" "xxx-ddddddddddddd"
command: sendevent "-F" "TERMINATED" "-J" "xxxxxxxxxxx-dddddddddddddd"
I need to go through each file, count the number of each command and put it in another output file in this format:
==== John ====
SUCCESS - 3
TERMINATED - 2
FAIL - 4
TOTAL 9
==== David ====
SUCCESS - 1
TERMINATED - 1
FAIL - 2
TOTAL 4
P.S. This code can be made more compact, e.g there is no need to use so many echo's etc, but the following structure is being used to make it clear what's happening:
ls | grep .txt | sed 's/.txt//' > names
for s in $(cat names)
do
suc=$(grep "SUCCESS" "$s.txt" | wc -l)
termi=$(grep "TERMINATED" "$s.txt"|wc -l)
fail=$(grep "FAIL" "$s.txt"|wc -l)
echo "=== $s ===" >>docs
echo "SUCCESS - $suc" >> docs
echo "TERMINATED - $termi" >> docs
echo "FAIL - $fail" >> docs
echo "TOTAL $(($termi+$fail+$suc))">>docs
done
Output from my test files was like :
===new===
SUCCESS - 0
TERMINATED - 0
FAIL - 0
TOTAL 0
===vv===
SUCCESS - 0
TERMINATED - 0
FAIL - 0
TOTAL 0
based on karafka's suggestions instead of using the above lines for the for-loopyou can directly use the following:
for f in *.txt
do
something
#in order to print the required name in the file without the .txt you can do a
printf "%s\n" ${f::(-4)}
awk to the rescue!
$ awk -vOFS=" - " 'function pr() {s=0;
for(k in a) {s+=a[k]; print k,a[k]};
print "\nTOTAL "s"\n\n\n"}
NR!=1 && FNR==1 {pr(); delete a}
FNR==1 {print "==== " FILENAME " ===="}
{a[$4]++}
END {pr()}' file1 file2 ...
if your input file is not structured (key is not always on fourth field), you can do the same with pattern match.

how do I parse output from ntpq?

I am fairly new to bash scripting... I have an issue with a cronjob where I get too many emails when "ntpq: read: Connection refused" error comes up. I want to create a conditional when this error shows up, DO NOT send the email.
However, I can't seem to parse the output from "nptq -nc peers". I did try to redirect the output of the cronjob to a test.txt file and then create another cronjob that parses that file. However, I feel like there is a better solution.
Thanks for your help!
Here is my code for the cronjob
#!/bin/bash
limit=10101010101010101010000 # Set your limit in milliseconds here
offsets=$(/usr/sbin/ntpq -nc peers | /usr/bin/tail -n +3 | awk 'BEGIN { FS = " " } ; { print $9 }' | /usr/bin/tr -d '-')
for offset in ${offsets}; do
if echo $offset $limit | awk '{exit $1>$2?0:1}'
then
echo "NTPD offset $offset > $limit. Please investigate"
exit 1
fi
done

Prevent script from outputitng status code

I wrote some ugly script of mine and besides giving me what I want in the output it also gives me the status code value.
The script output is below. How do I prevent the script from showing that status code in the output??
P.S. I'll put the script below, hope it wouldn't hurt your eyes too much
Status code = 0
Status code = 0
Status code = 0
job_1_1_1
Status code = 0
Status code = 0
Status code = 0
Status code = 0
Status code = 0
Status code = 0
job_1_1_2
Status code = 0
Status code = 0
START_ID=`dsjob -logsum -type STARTED UPSTREAM_MDM_D4 seq_1_1 | nawk 'ORS=(FNR%2)?FS:RS' | grep Starting | tail -1 | awk '{print $1 }'`; FATAL_IDS=`dsjob -logsum -type INFO UPSTREAM_MDM_D4 seq_1_1 | grep INFO | awk '{print $1 }'`; for TEST_ID in ${FATAL_IDS}; do if [[ "${TEST_ID}" -ge "${START_ID}" ]]; then WARN_DTL=`dsjob -logdetail UPSTREAM_MDM_D4 seq_1_1 ${TEST_ID}`; if `echo $WARN_DTL|grep -q 'has finished, status = 3'`; then message=`echo $WARN_DTL| grep -oP '\w+(?= has finished, status = 3)'`; fatal_errors=$fatal_errors$'\n'$message;fi; fi;done; echo $fatal_errors
You should decide what you want exactly achieve, one of method can be for example:
(
your commands
) 2>&1 | grep -v 'Status code = 0'
Beware - the above is not a good practice - only a quick-hack like solution...

Nagios Plugin not Working

I'm having an issue when i try to port my bash script to nagios.The scripts works fine when I run on console, but when I run it from Nagios i get the msg "(null)" - In the nagios debug log I see that it parse the script well but it returns the error msg..
I'm not very good at scripting so i guess i'll need some help
The objective of the script is to check *.ears version from some servers, md5 them and compare the output to see if the version matches or not.
To do that, i have a json on these servers that prints the name of the *.ear and his md5.
so.. The first part of the script gets that info from the json with curl and stores just the md5 number on a .tempfile , then it compares both temp files and if they match i got the $STATE_OK msg. If they dont , it creates a .datetmp file with the date ( the objective of this is to print a message after 48hs of inconsistence). Then, i make a diff of the .datetmp file and the days i wanna check if the result is less than 48hrs it prints the $STATE_WAR, if the result is more than 48 hrs it Prints the $STATE_CRI
The sintaxis of the script is " $ sh script.sh nameoftheear.ear server1 server2 "
Thanks in advance
#/bin/bash
#Variables For Nagios
cont=$1
bas1=$2
bas2=$3
## Here you set the servers hostname
svr1= curl -s "http://$bas1.domain.com:7877/apps.json" | grep -Po '"EAR File":.*? [^\\]",' | grep $cont | awk '{ print $5 }' > .$cont-tmpsvr1
svr2= curl -s "http://$bas2.domain.com:7877/apps.json" | grep -Po '"EAR File":.*? [^\\]",' | grep $cont | awk '{ print $5 }' > .$cont-tmpsvr2
file1=.$cont-tmpsvr1
file2=.$cont-tmpsvr2
md51=$(head -n 1 .$cont-tmpsvr1)
md52=$(head -n 1 .$cont-tmpsvr2)
datenow=$(date +%s)
#Error Msg
ERR_WAR="Not updated $bas1: $cont $md51 --- $bas2: $cont $md52 "
ERR_CRI="48 hs un-updated $bas1: $cont $md51 --- $bas2: $cont $md52 "
OK_MSG="Is up to date $bas1: $cont $md51 --- $bas2: $cont $md52 "
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
##Matching md5 Files
if cmp -s "$file1" "$file2"
then
echo $STATE_OK
echo $OK_MSG
# I do the rm to delete the date tmp file so i can get the $STATE_OK or $STATE_WARNING
rm .$cont-datetmp
exit 0
elif
echo $datenow >> .$cont-datetmp
#Vars to set modification date
datetmp=$(head -n 1 .$cont-datetmp)
diffdate=$(( ($datenow - $datetmp) /60 ))
#This var is to set the time of the critical ERR
days=$((48*60))
[ $diffdate -lt $days ]
then
echo $STATE_WARNING
echo $ERR_WAR
exit 1
else
echo $STATE_CRITICAL
echo $ERR_CRI
exit 2
fi
I am guessing some kind of permission problem - more specifically I don't think the nagios user can write to it's own home directory. You either fix those permissions or write to a file in /tmp (and consider using mktemp?).
...but ideally you'd skip writing all those files, as far as I can see all of those comparisons etc could be kept in memory.
UPDATE
Looked at your script again - I see some obvious errors you can look into:
You are printing out the exit value before you print the message.
You print the exit value rather than exit with the exit value.
...so this:
echo $STATE_WARNING
echo $ERR_WAR
exit 1
Should rather be:
echo $ERR_WAR
exit $STATE_WARNING
Also I am wondering if this is really the script or if you missed something when pasting. There seems to be missing an 'if' and also a superfluous line break in your last piece of code? Should rather be:
if [ $diffdate -lt $days ]
then
...
else
...
fi

Resources