System Variable set in bash not sticking after i go to an IF statement - bash

apacherelease=$(curl -s "https://httpd.apache.org" | grep Released | awk '{print $4}' | perl -p -e 's/2.4.54/2.4.54-1/g') &&
apacheinstallversion=$(dnf list installed | grep httpd.x86_64|awk '{print $2}') &&
echo $apacherelease
echo $apacheinstallversion
if test "$apacheinstallversion" = "$apacherelease"; then
: variables are the same
else
: variables are different
fi
`
If I run the commands to set variable directly from the command line instead of a script the variables stick however in the script they disappear the moment I move to the if statement.
Any input would extremely help!

Corrected version:
apacherelease=$(curl -s "https://httpd.apache.org" | grep Released | awk '{print $4}' | perl -p -e 's/2.4.54/2.4.54-1/g') &&
apacheinstallversion=$(dnf list installed | grep httpd.x86_64 | awk '{print $2}')
echo "$apacherelease"
echo "$apacheinstallversion"
if [[ $apacheinstallversion == $apacherelease ]]; then
echo "variables are the same"
else
echo "variables are different" >&2
fi
use the full featured bash test [[
use == instead of =

Related

command not found on shell script run [duplicate]

This question already has answers here:
bash command not found when setting a variable
(2 answers)
Closed 6 months ago.
i have a script that compare heapmemory
#!/bin/bash
$a=$(jcmd `jps -l | grep com.adobe.coldfusion.bootstrap.Bootstrap | cut -f1 -d ' '` GC.heap_info | awk 'NR==2 {print $5}')
$b=1000000K
if [[ $a -ge $b ]]
then
echo "The heapmemory used is greater."
else
echo "The heapmemory used is small."
fi
my question is when I am executing this script using ./testscriptforheap.sh, although the output is correct but why I am getting this command not found in line number 2 and 3 I am not able to figure it out.
> ./testscriptforheap.sh: line 2: =1603644K: command not found
> ./testscriptforheap.sh: line 3: =1000000K: command not found
The heapmemory used is greater.
Assignments in bash (and also in sh) don't use the $ in front of them:
a=$(jcmd `jps -l | grep com.adobe.coldfusion.bootstrap.Bootstrap | cut -f1 -d ' '` GC.heap_info | awk 'NR==2 {print $5}')
b=1000000K
Your variable assignment is incorrect, try this:
#!/bin/bash
a=$(jcmd "$(jps -l | grep com.adobe.coldfusion.bootstrap.Bootstrap | cut -f1 -d ' ')" GC.heap_info | awk 'NR==2 {print $5}')
b=1000000K
if [[ $a -ge $b ]]
then
echo "The heapmemory used is greater."
else
echo "The heapmemory used is small."
fi
...also, the bash -gt operator is trying to compare two integers.
From what I can gather:
When you issue the jcmd nnnn GC.heap_info command, it's the sixth field of the second record in the output holds the used heap memory.
It will be of this form nnnnnK, so to be able to compare just the numbers, you could do with piping that through a sed:
Then you could remove K from $b=1000000K.
So, no harm in trying...
#!/bin/bash
a=$( \
jcmd `jps -l | grep com.adobe.coldfusion.bootstrap.Bootstrap | cut -f1 -d ' '` GC.heap_info | awk 'NR==2 {print $6}' | sed -r 's/[^0-9]//g' \
)
b=1000000
if [[ $a -ge $b ]]
then
echo "The heapmemory used is greater."
else
echo "The heapmemory used is small."
fi

how to stop script from running when drives are full

I have a script that will run and fill up a drive without remorse. I want to set a highwater mark of 90%.
I created a cron that will check if the script is installed and if so if running.
#!/bin/sh
COUNTER=$(df -Ph | grep -vE '^tmpfs|cdrom' | sed s/%//g | sed 1d | awk '{ if($5 > 90) print $1;}' | wc -l)
if [[ -e /var/stats/automation/stats-collection.pl ]]; then
_running=$(ps faux | grep stats-collection.pl | grep -v grep | awk '{print $2}')
if [[ $_running -eq 1 ]]; then
echo "Stats running"
if [[ $COUNTER -gr 0 ]]; then
echo "Drive found above highwater mark. Ending Platform stats."
kill $_running
fi
else
echo "Platform stats not running."
else
echo "Platform stats not found"
fi
How would I combine the benefits of a continuously running cron job to run and stop the offending script from running. Would a while loop be the answer?

Bash script: Eqw status

I've been trying to run this code in a server but always send an 'Eqw' status.
I want to process a file that contains three columns, one with a path, and the others are information about that file.
Can anyone please help me to figure out what's wrong in my code?
#!/bin/bash
source $HOME/.bashrc
source /share/apps/Profiles/share-profile.sh
module load compilers/python-2.7.15
MANIFEST=path with the file with three columns
TRIM=trimming program that does work properly
#Run pyadapter_trim.py to trim adapter sequences
COUNTER=0;
#for each file in the input manifest, run tirimming program
while read LINE
do
READ=`echo "$LINE" | awk -F"\t" '{print $1}'`
SAMPLE=`echo "$LINE" | awk -F"\t" '{print $2}'`
GENOME=`echo "$LINE" | awk -F"\t" '{print $3}'`
WDIR=`(dirname $READ1)`
cd $WDIR
QCDIR=$WDIR"/ats"
mkdir -p $QCDIR
echo -e "Processing sample ${SAMPLE}"
echo -e "${READ1}..."
python $TRIM -a $READ
echo ""
COUNTER=`expr $COUNTER + 1`
done < "$MANIFEST"
echo "$COUNTER Files Processed"

Variable loss in redirected bash while loop

I have the following code
for ip in $(ifconfig | awk -F ":" '/inet addr/{split($2,a," ");print a[1]}')
do
bytesin=0; bytesout=0;
while read line
do
if [[ $(echo ${line} | awk '{print $1}') == ${ip} ]]
then
increment=$(echo ${line} | awk '{print $4}')
bytesout=$((${bytesout} + ${increment}))
else
increment=$(echo ${line} | awk '{print $4}')
bytesin=$((${bytesin} + ${increment}))
fi
done < <(pmacct -s | grep ${ip})
echo "${ip} ${bytesin} ${bytesout}" >> /tmp/bwacct.txt
done
Which I would like to print the incremented values to bwacct.txt, but instead the file is full of zeroes:
91.227.223.66 0 0
91.227.221.126 0 0
127.0.0.1 0 0
My understanding of Bash is that a redirected for loop should preserve variables. What am I doing wrong?
First of all, simplify your script! Usually there are many better ways in bash. Also most of the time you can rely on pure bash solutions instead of running awk or other tools.
Then add some debbuging!
Here is a bit refactored script with debugging
#!/bin/bash
for ip in "$(ifconfig | grep -oP 'inet addr:\K[0-9.]+')"
do
bytesin=0
bytesout=0
while read -r line
do
read -r subIp _ _ increment _ <<< "$line"
if [[ $subIp == "$ip" ]]
then
((bytesout+=increment))
else
((bytesin+=increment))
fi
# some debugging
echo "line: $line"
echo "subIp: $subIp"
echo "bytesin: $bytesin"
echo "bytesout: $bytesout"
done <<< "$(pmacct -s | grep "$ip")"
echo "$ip $bytesin $bytesout" >> /tmp/bwacct.txt
done
Much clearer now, huh? :)

Dynamic Patch Counter for Shell Script

I am developing a script on a Solaris 10 SPARC machine to calculate how many patches got installed successfully during a patch delivery. I would like to display to the user:
(X) of 33 patches were successfully installed
I would like my script to output dynamically replacing the "X" so the user knows there is activity occurring; sort of like a counter. I am able to show counts, but only on a new line. How can I make the brackets update dynamically as the script performs its checks? Don't worry about the "pass/fail" ... I am mainly concerned with making my output update in the bracket.
for x in `cat ${PATCHLIST}`
do
if ( showrev -p $x | grep $x > /dev/null 2>&1 ); then
touch /tmp/patchcheck/* | echo "pass" >> /tmp/patchcheck/$x
wc /tmp/patchcheck/* | tail -1 | awk '{print $1}'
else
touch /tmp/patchcheck/* | echo "fail" >> /tmp/patchcheck/$x
wc /tmp/patchcheck/* | tail -1 | awk '{print $1}'
fi
done
The usual way to do that is to emit a \r carriage return (CR) at some point and to omit the \n newline or line feed (LF) at the end of the line. Since you're using awk, you can try:
awk '{printf "\r%s", $1} END {print ""}'
For most lines, it outputs a carriage return and the data in field 1 (without a newline at the end). At the end of the input, it prints an empty string followed by a newline.
One other possibility is that you should place the awk script outside your for loop:
for x in `cat ${PATCHLIST}`
do
if ( showrev -p $x | grep $x > /dev/null 2>&1 ); then
touch /tmp/patchcheck/* | echo "pass" >> /tmp/patchcheck/$x
wc /tmp/patchcheck/* | tail -1
else
touch /tmp/patchcheck/* | echo "fail" >> /tmp/patchcheck/$x
wc /tmp/patchcheck/* | tail -1
fi
done | awk '{ printf "\r%s", $1} END { print "" }'
I'm not sure but I think you can apply similar streamlining to the rest of the repetitious code in the script:
for x in `cat ${PATCHLIST}`
do
if showrev -p $x | grep -s $x
then echo "pass"
else echo "fail"
fi >> /tmp/patchcheck/$x
wc /tmp/patchcheck/* | tail -1
done | awk '{ printf "\r%s", $1} END { print "" }'
This eliminates the touch (which doesn't seem to do much), and especially not when the empty output of touch is piped to echo which ignores its standard input. It eliminates the sub-shell in the if line; it uses the -s option of grep to keep it quiet.
I'm still a bit dubious about the wc line. I think you're looking to count the number of files, in effect, since each file should contain one line (pass or fail), unless you listed some patch twice in the file identified by ${PATCHLIST}. In which case, I'd probably use:
for x in `cat ${PATCHLIST}`
do
if showrev -p $x | grep -s $x
then echo "pass"
else echo "fail"
fi >> /tmp/patchcheck/$x
ls /tmp/patchcheck | wc -l
done | awk '{ printf "\r%s", $1} END { print "" }'
This lists the files in /tmp/patchcheck and counts the number of lines output. It means you could simply print $0 in the awk script since $0 and $1 are the same. To the extent efficiency matters (not a lot), this is more efficient because ls only scans a directory, rather than having wc open each file. But it is more particularly a more accurate description of what you are trying to do. If you later want to count the passes, you can use:
for x in `cat ${PATCHLIST}`
do
if showrev -p $x | grep -s $x
then echo "pass"
else echo "fail"
fi >> /tmp/patchcheck/$x
grep '^pass$' /tmp/patchcheck/* | wc -l
done | awk '{ printf "\r%s", $1} END { print "" }'
Of course, this goes back to reading each file, but you're getting more refined information out of it now (and that's the penalty for the more refined information).
Here is how I got my patch installation script working the way I wanted:
while read pkgline
do
patchadd -d ${pkgline} >> /var/log/patch_install.log 2>&1
# Create audit file for progress indicator
for x in ${pkgline}
do
if ( showrev -p ${x} | grep -i ${x} > /dev/null 2>&1 ); then
echo "${x}" >> /tmp/pass
else
echo "${x}" >> /tmp/fail
fi
done
# Progress indicator
for y in `wc -l /tmp/pass | awk '{print $1}'`
do
printf "\r${y} out of `wc -l /patchdir/master | awk '{print $1}'` packages installed for `hostname`. Last patch installed: (${pkgline})"
done
done < /patchdir/master

Resources