Shell script for generating HTML out put - shell

The following script is generating the desired out put but not redirecting the result to /home/myuser/slavedelay.html
#!/bin/bash
host=<ip>
echo $host
user=usr1
password=mypass
threshold=300
statusok=OK
statuscritical=CRITICAL
for i in ert7 ert9
do
echo "<html>" > /home/myuser/slavedelay.html
if [ "$i" == "ert7" ]; then
slvdelay=`mysql -u$user -p$password -h<ip> -S /backup/mysql/mysql.sock -e 'show slave status\G' | grep Seconds_Behind_Master | sed -e 's/ *Seconds_Behind_Master: //'`
if [ $slvdelay -ge $threshold ]; then
echo "<tr><td>$i</td><td>CRITICAL</td>" >> /home/myuser/slavedelay.html
echo "<tr><td>$i</td><td>CRITICAL</td>"
else
echo "<tr><td>$i</td><td>OK</td>" >> /home/myuser/slavedelay.html
echo "<tr><td>$i</td><td>OK</td>"
fi
fi
done
echo "</html>" >> /home/myuser/slavedelay.html
If I cat the output file /home/myuser/slavedelay.html it gives.
<html>
</html>
Execution result :
sh slave_delay.sh
<tr><td>sdb7</td><td>OK</td>

Each time through the loop you're emptying the output file because of the command
echo "<html>" > /home/myuser/slavedelay.html
So the first iteration writes the <tr> row to the file, then the next iteration overwrites the file and doesn't write those lines because $i isn't ert7.
Change it to:
for i in ert7 ert9
do
if [ "$i" == "ert7" ]; then
echo "<html>" > /home/myuser/slavedelay.html
slvdelay=`mysql -u$user -p$password -h<ip> -S /backup/mysql/mysql.sock -e 'show slave status\G' | grep Seconds_Behind_Master | sed -e 's/ *Seconds_Behind_Master: //'`
if [ $slvdelay -ge $threshold ]; then
echo "<tr><td>$i</td><td>CRITICAL</td>"
else
echo "<tr><td>$i</td><td>OK</td>"
fi | tee -a /home/myuser/slavedelay.html
echo "</html>" >> /home/myuser/slavedelay.html
fi
done

Replace :
if [ "$i" == "ert7" ];
with:
if [ "$i" = "ert7" ];
You use = operator in test also.

Related

bash function dont recognize input

I seem to have some problems executing this bash function from the terminal,
function sort () {
if [ "$#" -ne 1 ];
then
word="$arg1"
isolated="$arg2"
file="output/$word _ $isolated_matches"
else
word="$arg1"
file="output/$word_matches"
fi
echo "$word"
echo "$file"
cat "$file" | while read line;
do
output=$(awk 'BEGIN{IGNORECASE=1} /"$word"/ {print NR, $0}' "$line");
if [ $[#output] -ne 0 ];
then
echo "File: " "$line";
echo "----------------------------------------------------";
echo "$output";
fi
echo $'\n';
done
I source the script in the terminal, and when i execute
sort a a
My output becomes :
output
cat: output/ Is a directory
Why does it not recognize the input I am given it?
Just check this change.
#!/bin/bash
function sort () {
if [ "$#" -ne 1 ];
then
word=$1
isolated=$2
file="output/${word}_${isolated}_matches"
else
word="$1"
file="output/${word}_matches"
fi
touch "$file"
echo "word : $word"
echo "file : $file"
cat "$file" | while read line;
do
output=$(awk -v word="$word"; BEGIN{IGNORECASE=1} /"$word"/ {print NR, $0}' "$line");
if [ -n "$output" ];
then
echo "File: " "$line";
echo "----------------------------------------------------";
echo "$output";
fi
echo $'\n';
done
}
OUTPUT
smily#Machine MINGK64 /d/test
$ sh testbash.sh
word : a
file : output/a_a_matches

sed throwing sed: -e expression #(number), char (number): unknown command: `(letter)'

I wrote a shell script which reads some files and copy all the data from these files to other consolidated file.
This happens multiple times and previously copied data will not be copied again. For this i am saving the last copied line in a separate file and comparing it from the second time.
Flow of logic :
For the first time, read individual files and copy the whole data except last line into the consolidated file. Saving the last copied line into a temporary file.
sed '$d' $file >> $consolidatedCSVFile
tail -2 $file | head -1 > $consolidatedCSVFile$lastLines/$(basename $file)$lastLine
From second time, read last line from the temporary file and search for that line in individual file. When found, take all the lines from the next line and append to consolidated file.
Full script:
#!/bin/bash
consolidatedCSVFile=$1
endTime=$2
curdate=$(date +%s)
CSVFiles=${#:3}
CSVFiles=${CSVFiles[#]}
lastLines=_LASTLINES
lastLine=_LASTLINE
newMerge=false
# Returns 1 if Consolidated file is empty
[ -s $consolidatedCSVFile ]
if [ $? == 1 ]
then
mkdir $consolidatedCSVFile$lastLines
newMerge=true
fi
testInProcess=false
if [ $endTime -ge $curdate ]
then
testInProcess=true
fi
for file in $CSVFiles
do
if $newMerge ;
then
touch $consolidatedCSVFile$1astLines5(basename $file)$lastLine
sed $d $file >> $consolidatedCSVFile
tail -2 $file | head -1 > $consolidatedCSVFile$1astLines5(basename $file)$lastLine
else
availableLastLine="`cat $consolidatedCSVFile$1astLines/$(basename $file)$lastLine`"
if $testInProcess
then
sed '1,/^'"$availableLastLine"'$/d' $file | sed '$d' >> $consolidatedCSVFile
tail -2 $file | head -1 > $consolidatedCSVFile$1astLines5(basename $file)$lastLine
else
sed '1,/^'"$availableLastLine"'$/d' $file >> $consolidatedCSVFile
fi
fi
done
if ! $testInProcess ;
then
rm -rf $consolidatedCSVFile$lastLines
fi
Sometimes, i get error as sed: -e expression #1, char 26: unknown command: 'X'
My guess
I am trying to combine the files generated by JMeter.
Sometimes, the files are generating data like 1439459065780,5,SOAP/XML-RPC Request,200,OK,ws test 1-3,text,true,267,3,3,5
I think the problem is while sed '1,/^'"$availableLastLine"'$/d' $file | sed '$d' >> $consolidatedCSVFile at SOAP/XML. Slash(/) could be problem here.
Without having gone through all your code, your intuition about that line seems spot on to me. The variable is going to be expanded before the sed command is executed, so if you have / in the expansion it will terminate the pattern in sed. You can use other characters than / as your separators, so if, say _ is not going to show up in your data you could use that like
sed '1,_^'"$availableLastLine"'$_d' $file | sed '$d' >> $consolidatedCSVFile
or you could skip the second sed with
sed -e '1,_^'"$availableLastLine"'$_d' -e '$d' $file >> $consolidatedCSVFile
worked after modifying availableLastLine
to availableLastLine=$(sed 's/\//\\\//' $consolidatedCSVFile$lastLines/$(basename $file)$lastLine).
Working Script :
#!/bin/bash
consolidatedCSVFile=$1
endTime=$2
curdate=$(date +%s)
CSVFiles=${#:3}
CSVFiles=${CSVFiles[#]}
lastLines=_LASTLINES
lastLine=_LASTLINE
newMerge=false
# Returns 1 if Consolidated file is empty
[ -s $consolidatedCSVFile ]
if [ $? == 1 ]
then
mkdir $consolidatedCSVFile$lastLines
newMerge=true
fi
testInProcess=false
if [ $endTime -ge $curdate ]
then
testInProcess=true
fi
for file in $CSVFiles
do
if $newMerge ;
then
touch $consolidatedCSVFile$1astLines5(basename $file)$lastLine
sed $d $file >> $consolidatedCSVFile
tail -2 $file | head -1 > $consolidatedCSVFile$1astLines5(basename $file)$lastLine
else
## Replaced below line
#availableLastLine="`cat $consolidatedCSVFile$1astLines/$(basename $file)$lastLine`"
availableLastLine=$(sed 's/\//\\\//' $consolidatedCSVFile$lastLines/$(basename $file)$lastLine)
if $testInProcess
then
sed '1,/^'"$availableLastLine"'$/d' $file | sed '$d' >> $consolidatedCSVFile
tail -2 $file | head -1 > $consolidatedCSVFile$1astLines5(basename $file)$lastLine
else
sed '1,/^'"$availableLastLine"'$/d' $file >> $consolidatedCSVFile
fi
fi
done
if ! $testInProcess ;
then
rm -rf $consolidatedCSVFile$lastLines
fi
Possible error cases handled while merging of multiple files
#!/bin/bash
echo -e "\n******* $(date) *******"
echo "Arguments :: $#"
consolidatedCSVFile=$1
echo "consolidatedCSVFile :: $1"
endTime=$2
curdate=$(date +%s)
echo -e "endTime :: $2\n"
CSVFiles=${#:3}
CSVFiles=${CSVFiles[#]}
echo -e "Individual Files : ${CSVFiles[#]}\n"
lastLines=_LASTLINES
lastLine=_LASTLINE
newMerge=false
# Returns 1 if Consolidated file is empty
[ -s $consolidatedCSVFile ]
if [ $? == 1 ]
then
newMerge=true
fi
echo "newMerge? :: $newMerge"
if $newMerge ;
then
if [ ! -d $consolidatedCSVFile$lastLines ]
then
echo "creating LASTLINES directory"
mkdir $consolidatedCSVFile$lastLines
fi
fi
testInProcess=false
if [ $endTime -ge $curdate ]
then
testInProcess=true
fi
echo -e "testInProcess? :: $testInProcess\n"
for file in $CSVFiles
do
echo -e "\nCurrent file in loop :: $(basename $file)"
if $newMerge ;
then
# Returns 1 if file is empty
[ -s $file ]
if [ $? == 1 ]
then
echo "File empty !!"
continue
fi
echo "creating LASTLINE file"
touch $consolidatedCSVFile$lastLines/$(basename $file)$lastLine
#sed '$d' $file >> $consolidatedCSVFile
sed '1d' $file | sed '$d' >> $consolidatedCSVFile
echo "Last line to save :: $(tail -1 $consolidatedCSVFile)"
tail -1 $consolidatedCSVFile > $consolidatedCSVFile$lastLines/$(basename $file)$lastLine
else
# Returns 1 if file is empty
[ -s $file ]
if [ $? == 1 ]
then
echo "File empty !!"
continue
fi
if [ ! -f $consolidatedCSVFile$lastLines/$(basename $file)$lastLine ]
then
echo "creating LASTLINE file"
touch $consolidatedCSVFile$lastLines/$(basename $file)$lastLine
#sed '$d' $file >> $consolidatedCSVFile
sed '1d' $file | sed '$d' >> $consolidatedCSVFile
echo "Last line to save :: $(tail -1 $consolidatedCSVFile)"
tail -1 $consolidatedCSVFile > $consolidatedCSVFile$lastLines/$(basename $file)$lastLine
continue
else
availableLastLine=$(sed 's/\//\\\//' $consolidatedCSVFile$lastLines/$(basename $file)$lastLine)
echo "Last line from file :: $availableLastLine"
fi
if $testInProcess
then
tempVar=`sed '1,/^'"$availableLastLine"'$/d' $file | sed '$d'`
#echo -e "\ntempVar ::\n$tempVar\n"
[ -z "$tempVar" ]
if [ $? == 1 ]
then
#sed '1,/^'"$availableLastLine"'$/d' $file | sed '$d' >> $consolidatedCSVFile
echo -e "$tempVar" >> $consolidatedCSVFile
echo "Last line to save :: $(tail -1 $consolidatedCSVFile)"
tail -1 $consolidatedCSVFile > $consolidatedCSVFile$lastLines/$(basename $file)$lastLine
else
echo "No last line to save"
fi
else
sed '1,/^'"$availableLastLine"'$/d' $file >> $consolidatedCSVFile
fi
fi
done
if ! $testInProcess ;
then
echo -e "\nRemoving LASTLINES folder"
rm -rf $consolidatedCSVFile$lastLines
fi
echo -e "\n*************"

Suggestions how to check for presence of a audio CD-ROM before continuing the script

I have found a nice solution to check if an audio cd is present. It works with a While loop which I like to end after the audio rip is done and the disc is ejected.
while true; do
sleep 10
cdparanoia -Q 2>&1 | grep 'audio only'
RET=$?
if [ $RET = "0" ] ; then
abcde -c ~/Music/abcde.conf -o flac,mp3,ogg -p -x
fi
done
I believe I found a solution to my wishes, hereby my code
#!/bin/bash
echo "voer componist in"
read componist
echo ingevoerde "$componist"
echo "voer het aantal CD's in"
read aantaldiscs
echo aantal discs $aantaldiscs
mkdir ~/Music/"$componist"
for a in $(seq -f %02g 01 $aantaldiscs);
do
mkdir ~/Music/"$componist"/$a
echo "OUTPUTDIR='~/Music/"$componist"/$a'" > ~/Music/abcde.conf
echo "OUTPUTFORMAT='\${TRACKNUM}.\${TRACKFILE}'" >> ~/Music/abcde.conf
echo "LAMEOPTS='-V 0'" >> ~/Music/abcde.conf
echo "FLACOPTS='-f --verify --best'" >> ~/Music/abcde.conf
echo "OGGENCOPTS='-q 8'" >> ~/Music/abcde.conf
echo "MAXPROCS=2" >> ~/Music/abcde.conf
echo "mungefilename ()" >> ~/Music/abcde.conf
echo "{" >> ~/Music/abcde.conf
echo "echo "$#" | sed s,:,\ -,g | tr / _ | tr -d \’\"\?\[:cntrl:\]" >> ~/Music/abcde.conf
echo "}" >> ~/Music/abcde.conf
while true; do
sleep 10
cdparanoia -Q 2>&1 | grep 'audio only'
RET=$?
if [ $RET = "0" ] ; then
abcde -c ~/Music/abcde.conf -o flac,mp3,ogg -p -x
break
fi
done
done

Bash - sometimes creates only empty output

I am trying to create a bash dictionary script that accepts first argument and creates file named after that, then script accepts next arguments (which are files inside same folder) and outputs their content into file (first argument). It also sorts, deletes symbols etc., but main problem is, that sometimes ouptut file is empty (I am passing one non empty file and one non existing file), after deleting and running script few more times it is sometimes empty sometimes not.
#!/bin/bash
numberoffileargs=$(( $# - 1 ))
exitstat=0
counterexit=0
acceptingstdin=0;
> "$1";
#check if we have given input files given
if [ "$#" -gt 1 ]; then
#for cycle going through input files
for i in "${#:2}"
do
#check whether input file is readable
if [ -r "${i}" ]; then
cat "${i}" >> "$1"
#else redirect to standard output
else
exitstat=2
counterexit=$((counterexit + 1))
echo "file does not exist" 1>&2
fi
done
else
echo "stdin code to be done"
acceptingstdin=1
#stdin input to output file
#stdin=$(cat)
fi
#one word for each line, alphabetical sort, alphabet only, remove duplicates
#all lowercase
#sort -u >> "$1"
if [ "$counterexit" -eq "$numberoffileargs" ] && [ "$acceptingstdin" -eq 0 ]; then
exitstat=3
fi
cat "$1" | sed -r 's/[^a-zA-Z\-]+/ /g' | tr A-Z a-z | tr ' ' '\n' | sort -u | sed '/^$/d' > "$1"
echo "$numberoffileargs"
echo "$counterexit"
echo "$exitstat"
exit $exitstat
Here is your script with some syntax improvement. Your trouble came from the fact that the dictionary was both on input and output on your pipeline; I added a temp file to fix it.
#!/bin/bash
(($# >= 1)) || { echo "Usage: $0 dictionary file ..." >&2 ; exit 1;}
dict="$1"
shift
echo "Creating $dict ..."
>| "$dict" || { echo "Failed." >&2 ; exit 1;}
numberoffileargs=$#
exitstat=0
counterexit=0
acceptingstdin=0
if (($# > 0)); then
for i ; do
#check whether input file is readable
if [ -r "${i}" ]; then
cat "${i}" >> "$dict"
else
exitstat=2
let counterexit++
echo "file does not exist" >&2
fi
done
else
echo "stdin code to be done"
acceptingstdin=1
fi
if ((counterexit == numberoffileargs && acceptingstdin == 0)); then
exitstat=3
fi
sed -r 's/[^a-zA-Z\-]+/ /g' < "$dict" | tr '[:upper:]' '[:lower:]' | tr ' ' '\n' |
sort -u | sed '/^$/d' >| tmp$$
mv -f tmp$$ "$dict"
echo "$numberoffileargs"
echo "$counterexit"
echo "$exitstat"
exit $exitstat
The pipeline might be improved.

Grep inside bash script not finding item

I have a script which is checking a key in one file against a key in another to see if it exists in both. However in the script the grep never returns anything has been found but on the command line it does.
#!/bin/bash
# First arg is the csv file of repo keys separated by line and in
# this manner 'customername,REPOKEY'
# Second arg is the log file to search through
log_file=$2
csv_file=$1
while read line;
do
customer=`echo "$line" | cut -d ',' -f 1`
repo_key=`echo "$line" | cut -d ',' -f 2`
if [ `grep "$repo_key" $log_file` ]; then
echo "1"
else
echo "0"
fi
done < $csv_file
The CSV file is formatted as follows:
customername,REPOKEY
and the log file is as follows:
REPOKEY
REPOKEY
REPOKEY
etc
I call the script by doing ./script csvfile.csv logfile.txt
Rather then checking output of grep command use grep -q to check its return status:
if grep -q "$repo_key" "$log_file"; then
echo "1"
else
echo "0"
fi
Also your script can be simplified to:
log_file=$2
csv_file=$1
while IFS=, read -r customer repo_key; do
if grep -q "$repo_key" "$log_file"; then
echo "1"
else
echo "0"
fi
done < "$csv_file"
use the exit status of the grep command to print 1 or 0
repo_key=`echo "$line" | cut -d ',' -f 2`
grep -q "$repo_key" $log_file
if [ $? -eq 1 ]; then
echo "1"
else
echo "0"
fi
-q supresses the output so that no output is printed
$? is the exit status of grep command 1 on successfull match and 0 on unsuccessfull
you can have a much simpler version as
grep -q "$repo_key" $log_file
echo $?
which will produce the same output

Resources