CUT command doesn't work in crontab - shell

I have written shell script to monitor space
echo "___________" `date` "___________"
df | tr -s ' ' $'\t' | cut -f5 > file.txt
echo `sed 's/Use//g' file.txt` > file.txt
echo `sed 's/%//g' file.txt` > file.txt
expression=`cat file.txt | sed -e 's/ / /g'`
echo $expression
a=($expression)
#echo ${a[0]}
#echo ${a[1]}
#echo ${a[2]}
#echo ${a[3]}
#echo ${a[4]}
#echo ${a[5]}
#echo ${a[6]}
total=`expr ${a[0]} + ${a[1]} + ${a[2]} + ${a[3]} + ${a[4]} + ${a[5]} + ${a[6]}`
echo $total
server=`who`
if [ $total -ge 90 ]
then
echo "greater"
else
echo "Space occupied " $total "%"
fi
When I run this script in terminal, it works fine. tr and cut commands works fine. But when I schedule this script in crontab, tr and cut command doesn't parse output of df command.
Here is output of script when it is terminal
1 1 96 0 0 4 1
103
greater
output of script when it is scheduled in cron
Filesystem$1K-blocks$d$Available$$Mounted$on udev$1945488$4$1945484$1$/dev tmpfs$391332$836$390496$1$/run /dev/sda1$476684304$433659732$18787364$96$/ none$4$0$4$0$/sys/fs/cgroup none$5120$0$5120$0$/run/lock none$1956652$84020$1872632$5$/run/shm none$102400$56$102344$1$/run/user
Help me !

Not sure I follow what you are trying to get, but whenever you use crontab you should use the full path to all commands to be used as the path to all may not be available / set. Your code could be particularly shorter to:
echo "___________$(/usr/bin/date)___________"
total=$(/usr/bin/df | /usr/bin/awk 'NR > 1 && NR < 9{s+=$5}END{print s}')
if (( total >= 90 ))
then
echo "greater"
else
echo "Space occupied $total%"
fi

Related

Issue with Bash variables

I'm trying to make a code for finding the number and type of atoms from a file.
The file B.txt has few names of the atoms in it and is read to go into the specific atom directory. The file input has the values of the positions and atom types in it. But I cannot store the name of atom as atom_1, atom_2, atom_3 etc..
If I change the atom_$i to atom, then the code works perfectly.
I expect the output to be atom_1=X,numberofatoms_1=100, atom_2=Y, numberofatoms_2=200 etc and so on.
The error is something like:
2(total number of types of atoms)
bash: atom_1=x: command not found
cd ~/A/
cat ~/A/B.txt | while read line
do
cd folder_"$line"
sed -n 6p input> temp1.txt
sed -n 7p input > temp2.txt
atoms= wc -w < temp1.txt > junk
#echo ${atoms}
typeset -i atoms=$(cat junk)
i=1
numberofatoms=0
echo ${atoms}
while [ $i -le $atoms ]
do
ptri=$( echo "scale=2; $i" | bc)
atom="$(cat temp1.txt | sed -n '1p'| cut -d' ' -f$ptri)" > junk
echo $atom
# next section is the code for counting the total number of atomsin the system
noa=$(cat temp2.txt | sed -n '1p'| cut -d' ' -f$ptri)
numberofatoms_$i=$(( $numberofatoms + $noa ))
i=`expr $i + 1`
done
echo "number of atoms = " $numberofatoms
cd ..
rm junk
rm temp1
rm temp2
done

Redirection based on variables assigned within while loop setup

I want to access while loop variable out side the loop
while read line
do
...
...
...
done < $file > /home/Logs/Sample_$line_$(date +"%Y%m%d_%H%M%S").log
In the above example whatever the log file is getting generated that doesn't have the value for the line variable. i.e. $line is not working here.
Please let me know how this can be written to make it work.
#!/bin/sh
exec 1> /home/Logs/`basename $0 | cut -d"." -f1 | sed 's/\.sh//g'`_$(date +"%Y%m%d_%H%M%S").log 2>&1
echo "Execution Started : `date` \n"
SQL_DIR=/home/Sql
INFILE=in_file
TEMPFILE=temp_file
RETURN_CODE=0
ls -ltr $SQL_DIR|grep ".sql"|awk -F" " '{print $9}'|awk -F"." '{print $1}' > $INFILE
sed '/^$/d' $INFILE > $TEMPFILE; mv $TEMPFILE $INFILE
while read line
do
{
START_TIME=`date +%s`
printf "\n SQL File Executed Is : $line.sql"
SQL_FILE_NM=$line.sql
SQL_FILE=$SQL_DIR/$SQL_FILE_NM
nzsql -db netezza_db -Atqf $SQL_FILE > /dev/null
RETURN_CODE=$?
if [ $RETURN_CODE -eq 0 ]; then
echo "Time taken to execute sqlfile $SQL_FILE=$TT_HRS:$TT_MINS:$TT_REM_SECS HH:MM:SS" > $TEMPFILE
printf "\n Success: Sql completed successfully at `date` \n"
cat $TEMPFILE|mailx -s "Time taken to execute sqlfile $SQL_FILE=$TT_HRS:$TT_MINS:$TT_REM_SECS HH:MM:SS" 'koushik.chandra#a.com'
else
printf "\n Error: Failed in sql execution at `date`"
exit $RETURN_CODE
fi
END_TIME=`date +%s`
TT_SECS=$(( END_TIME - START_TIME))
TT_HRS=$(( TT_SECS / 3600 ))
TT_REM_MS=$(( TT_SECS % 3600 ))
TT_MINS=$(( TT_REM_MS / 60 ))
TT_REM_SECS=$(( TT_REM_MS % 60 ))
printf "\n"
printf "Total time taken to execute the sql $line="$TT_HRS:$TT_MINS:$TT_REM_SECS HH:MM:SS
printf "\n"
} > /home/Logs/sql_query_time_$line_$(date +"%Y%m%d_%H%M%S").log
done < $INFILE
rm -f $INFILE $TEMPFILE
exit $RETURN_CODE
You actually need redirection inside the while loop:
while read -r line; do
{ cmd1; cmd2; cmd3; } > "/home/Logs/Sample_${line}_$(date +"%Y%m%d_%H%M%S").log"
done < "$file"
When you have > outfile after done then output is redirected to one file only.

shell script not running but just exiting

I am trying to run the following shell script, but its exiting without flashing any error ( I am ignoring the program errors but not shell errors).
#!/bin/bash
export TIMEFORMAT="%E"
rm -f mix_histogram
x=1
d=0
while read y
do
d=$(( $(( $d + 1 )) % 2 ))
(time echo '\n' | /home/pallavi/cudaSamples/3_Imaging/histogram 0 >/dev/null 2>/dev /null) > /dev/null 2>> mix_histogram &
t1=$(echo "l(32768)" | bc -l)
t2=$(echo "l(($y))" | bc -l)
t=$(echo "( $t1 - $t2 )" | bc -l)
t=$(echo "( 25 * $t )" | bc -l)
t=$(echo "($t)" | bc)
if [ $(echo "200 < $t"|bc) -eq 1 ]
then
t=200
fi
sleep $t
done < stream1_50
wait
could anybody tell me why its not executing??
How do you know it is not executing?
In such cases, the following is helpful: Run the script this way
bash -x path/to/your/script
This will show an execution trace on standard error.

count words in a file without using wc

Working in a shell script here, trying to count the number of words/characters/lines in a file without using the wc command. I can get the file broken into lines and count those easy enough, but I'm struggling here to get the words and the characters.
#define word_count function
count_stuff(){
c=0
w=0
l=0
local f="$1"
while read Line
do
l=`expr $line + 1`
# now that I have a line I want to break it into words and characters???
done < "$f"
echo "Number characters: $chars"
echo "Number words: $words"
echo "Number lines: $line"
}
As for characters, try this (adjust echo "test" to where you get your output from):
expr `echo "test" | sed "s/./ + 1/g;s/^/0/"`
As for lines, try this:
expr `echo -e "test\ntest\ntest" | sed "s/^.*$/./" | tr -d "\n" | sed "s/./ + 1/g;s/^/0/"`
===
As for your code, you want something like this to count words (if you want to go at it completely raw):
while read line ; do
set $line ;
while true ; do
[ -z $1 ] && break
l=`expr $l + 1`
shift ;
done ;
done
You can do this with the following Bash shell script:
count=0
for var in `cat $1`
do
count=`echo $count+1 | bc`
done
echo $count

Errors with a shell-script

i found some freaky error. I want to increment a counter, but the variable isnt visible outside the while do.
The script as follows:
## $1 - The file which should be examined
## $2 - The time passed between the checks. If $2 is 5 then all lines from the last 5 minutes are taken
## $3 - The Errormessage to search for
outputOK="OK - nothing happened"
output_logcheck=0;
errlines="";
cat $1 | grep "$3" | while read line
do
linedate=`date -d "$(echo $line | cut -d " " -f 2)" '+%s'`
nowdate=`date '+%s'`
if [ $(( $nowdate - (60 * $2) )) -le $linedate ]
then
$output_logcheck=$[$output_logcheck+1]
$errlines="${errlines} -- ${line}"
fi
done;
if [ $output_logcheck -eq 0 ]
then
echo $outputOK
else
echo "CRITICAL - There are -= ${output_logcheck} =- $3 -- Lines: $errlines"
fi
So i dont know what else to try.
Thanks in advance.
The problem is that pipe create a SubShell.
change
cat $1 | grep "$3" | while read line
do
...
done
to
while read line
do
...
done <(cat $1 | grep "$3")
As noted, the Bash shell, creates a subshell whenever a pipe is opened to a loop. In that case, variables within the loop are local to the loop.
One kludge is to substitute (if possible) a Korn ('ksh') shell for the Bash one.
Try something like:
## $1 - The file which should be examined
## $2 - The time passed between the checks. If $2 is 5 then all lines from the last 5 minutes are taken
## $3 - The Errormessage to search for
outputOK="OK - nothing happened"
outfile="/tmp/result.$$"
trap { rm $outfile } 0 1 2 3
cat $1 | grep "$3" | (output_logcheck=0; errlines=""; while read line
do
linedate=`date -d "$(echo $line | cut -d " " -f 2)" '+%s'`
nowdate=`date '+%s'`
if [ $(( $nowdate - (60 * $2) )) -le $linedate ]
then
$output_logcheck=$[$output_logcheck+1]
$errlines="${errlines} -- ${line}"
fi
done; echo $output_logcheck ":" $errlines > $outfile)
output_logcheck=`cat $outfile| cut -f1 -d:`
errlines=`cat $outfile|cut -f2 -d:`
if [ $output_logcheck -eq 0 ]
then
echo $outputOK
else
echo "CRITICAL - There are -= ${output_logcheck} =- $3 -- Lines: $errlines"
fi
while is executed in a separate process. Variables that are changed in the context of that process still hold their unchanged valus in the parent process.

Resources