Adding value to global variable in a subshell is not working - bash

I am trying to get the total disk usage of my machine. Below is the script code:
#!/bin/sh
totalUsage=0
diskUse(){
df -H | grep -vE '^Filesystem|cdrom' | awk '{ print $5 " " $1 }' | while read output;
do
diskUsage=$(echo $output | awk '{ print $1}' | cut -d'%' -f1 )
totalUsage=$((totalUsage+diskUsage))
done
}
diskUse
echo $totalUsage
While totalUsage is a global variable, I have tried to sum the individual disk usage to totalUsage in the line:
totalUsage=$((totalUsage+diskUsage))
An echo of totalUsage between do and done shows the correct value,
but when I try to echo it after my call diskUse, it stills prints a 0
Can you please help me, what is wrong here?

The variable totalUsage in a sub-shell doesn't change the value in the parent shell.
Since you tagged bash, you can use here string to modify your loop:
#!/bin/bash
totalUsage=0
diskUse(){
while read output;
do
diskUsage=$(echo $output | awk '{ print $1}' | cut -d'%' -f1 )
totalUsage=$((totalUsage+diskUsage))
done <<<"$(df -H | grep -vE '^Filesystem|cdrom' | awk '{ print $5 " " $1 }')"
}
diskUse
echo $totalUsage

I suggest to insert
shopt -s lastpipe
as new line after
#!/bin/bash
From man bash:
lastpipe: If set, and job control is not active, the shell runs the last command of a pipeline not executed in the background in the current shell environment.

Related

`df' unexpected' checking for diskspace inside a function using a while loop bash script

I am getting an issue where if I call this function below, I get the error line 89: syntax error at line 117: 'df' unexpected.
If I take the code out of the function it works fine.
Is there any reason for the error above?
This is a bash script on RHEL.
function testr{
df -H | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{ print $5 " " $1 }' | while read output;
do
usep=$(echo $output | awk '{ print $1}' | cut -d'%' -f1)
partition=$(echo $output | awk '{ print $2 }')
(.. Sends alert via mail after)
done
}
Maybe a little easier to read this way?
testr_zsh () {
# This (only) works with zsh.
for usep partition in $( df -H | awk 'NR>1 && !/tmpfs|cdrom/{print $5,$1}' | sed -n '/%/s/%//p' )
do
echo "\$usep: $usep, \$partition: $partition"
done
}
testr () {
for fs in $( df -H | awk 'NR>1 && !/tmpfs|cdrom/{print $5"|"$1}' | sed -n '/%/s/%//p' )
do
usep="$(echo "${fs}" | sed 's/|.*//' )"
partition="$(echo "${fs}" | sed 's/.*|//' )"
echo "\$usep: $usep, \$partition: $partition"
done
}
On my computer not all lines that pass through the awk filter have % in them hence adding the sed filter. zsh allows two vars in the for loop which is pretty slick.

Variable value not set in ssh -X [duplicate]

This question already has an answer here:
Executing ssh command in a bash shell script within a loop [duplicate]
(1 answer)
Closed 9 years ago.
I am Oracle DBA and i am doing some scripting to check if database is live or not on our large number of servers.
I am trying to set value to variable in ssh -X e.g
[oracle#proddb02]$ DB_STAT=`ssh -X proaddb01 'ps -ef | grep pmon | grep -v grep' | awk '{ print $8 }'`
[oracle#proddb02]$ echo $DB_STAT
ora_pmon_pconn01
Above example works perfectly but as i am using ssh command i cannot loop using while as it exit at the first line file which include list of the servers.
so i have to add /dev/null to the command so that it should not exit the loop. but this does not set the variable value.
When i echo the variable it gives nothing.
[oracle#proddb02]$ DB_STAT=`ssh -X proddb01 'ps -ef | grep pmon | grep -v grep' | awk '{ print $8 }'</dev/null`
[oracle#proddb02]$ echo $DB_STAT
[oracle#proddb02]$ echo $DB_STAT
The loop code is
[oracle#proddb02]$cat test.sh
while read line
do
INST_VAR=`echo $line | awk '{ print $1 }'`
HOST_VAR=`echo $line | awk '{ print $2 }'`
SERVER_NAME=$HOST_VAR
INSTANCE_NAME=$INST_VAR
DB_STAT=`ssh -X proaddb01 'ps -ef | grep pmon | grep -v grep' | awk '{ print $8 }'`
echo $DB_STAT
done < host_list.lst
Any help would be much appreciated.
Just do:
DB_STAT=`ssh -X proaddb01 "ps -ef | awk '/[p]mon/'{ print $8 }"`
Here you use:
// to filter the input stream (like grep but witj awk);
the trick with [p]grep to exclude the same line from ps (because [p]grep string will not be found with [p]grep template).

Bash variable from command with pipes, quotes, etc

I have a command I'm using to get the hostname.localdomain:
dig axfr #dc1.localdomain.com localdomain.com | grep -i Lawler | awk '{ getline ; $1=substr($1,1,length($1)-1); print $1 ; exit }'
This nicely returns a result like:
michael.lawler.localdomain.com
I'd like to further use that result as a variable in a Bash script.
It seems I'm having trouble getting past the first pipe.
If I VAR="dig axfr #dc1.localdomain.com localdomain.com | grep -i Lawler | awk '{ getline ; $1=substr($1,1,length($1)-1); print $1 ; exit }'"
...I get back the entire zone transfer. I've also tried many minor changes, adding $ before the dig command, without quotes, but nothing seems to work. How can I fix this?
VAR=$( dig axfr #dc1.localdomain.com localdomain.com |
grep -i Lawler |
awk '{ getline ; $1=substr($1,1,length($1)-1); print $1 ; exit }' )
Use backtics instead of quotes:
VAR=`dig axfr #dc1.localdomain.com localdomain.com | grep -i Lawler | awk '{ getline ; $1=substr($1,1,length($1)-1); print $1 ; exit }'`
Backtics actually mean "run whatever is in here and return standard out as the expression's value", but quotes don't do that.

No output when using awk inside bash script

My bash script is:
output=$(curl -s http://www.espncricinfo.com/england-v-south-africa-2012/engine/current/match/534225.html | sed -nr 's/.*<title>(.*?)<\/title>.*/\1/p')
score=echo"$output" | awk '{print $1}'
echo $score
The above script prints just a newline in my console whereas my required output is
$ curl -s http://www.espncricinfo.com/england-v-south-africa-2012/engine/current/match/534225.html | sed -nr 's/.*<title>(.*
?)<\/title>.*/\1/p' | awk '{print $1}'
SA
So, why am I not getting the output from my bash script whereas it works fine in terminal am I using echo"$output" in the wrong way.
#!/bin/bash
output=$(curl -s http://www.espncricinfo.com/england-v-south-africa-2012/engine/current/match/534225.html | sed -nr 's/.*<title>(.*?)<\/title>.*/\1/p')
score=$( echo "$output" | awk '{ print $1 }' )
echo "$score"
Score variable was probably empty, since your syntax was wrong.

Pass variable to nawk in bash?

I'm trying to pass a variable to nawk in a bash script, but it's not actually printing the $commentValue variable's contents. Everything works great, except the last part of the printf statement. Thanks!
echo -n "Service Name: "
read serviceName
echo -n "Comment: "
read commentValue
for check in $(grep "CURRENT SERVICE STATE" $nagiosLog |grep -w "$serviceName" | nawk -F": " '{print $2}' |sort -u ) ; do
echo $check | nawk -F";" -v now=$now '{ printf( "[%u]=ACKNOWLEDGE_SVC_PROBLEM;"$1";"$2";2;1;0;admin;$commentValue"\n", now)}' >> $nagiosCommand
done
$commentValue is inside an invocation to nawk, so it is considered as a variable in nawk, not a variable in bash. Since you do not have such a variable in nawk, you won't get anything there. You should first pass the variable "inside" nawk using the -v switch just like you did for the now variable; i.e.:
... | nawk -F";" -v now=$now -v "commentValue=$commentValue"
Note the quotes - they are required in case $commentValue contains whitespace.

Resources