get hostname from string using bash script - bash

In my bash script I need to extract all hostnames from output of command for further ping:
for host in `echo $MXrecords | awk '{ printf "%s", $0; }'` ; do
ping -c1 $host 2> /dev/null > /dev/null
if [ "$?" -eq "0" ] ; then
answ="OK"
else
answ="BAD"
fi
echo "\t$host [$answ]"
done
But I have some extra string:
40 [BAD]
alt2.aspmx.l.google.com. [OK]
30 [BAD]
alt3.aspmx.l.google.com. [OK]
I get var MXrecords by means of dig:
MXrecords=`dig #$DNSserver $domainName IN MX +short +multiline | awk '{ printf "\t%s\n", $0; }'`

From the output it looks like $MXrecords contains the MX records including their priority:
40 alt2.aspmx.l.google.com.
30 alt3.aspmx.l.google.com.
Try replacing this:
`echo $MXrecords | awk '{ printf "%s", $0; }'`
with this:
$(echo "$MXrecords" | awk '{print $2}')

Try this instead :
for host in ${MXrecords##* }; do
if ping -c1 $host &>/dev/null; then
answ="OK"
else
answ="BAD"
fi
echo "\t$host [$answ]"
done
Note
${MXrecords##* } is a parameter expansion bash trick (a buil-tin)
&>/dev/null is a bash shorthand for >/dev/null 2>&1
The backquote (`) is used in the old-style command substitution. The foo=$(command) syntax is recommended instead. Backslash handling inside $() is less surprising, and $() is easier to nest. See http://mywiki.wooledge.org/BashFAQ/082
no need to test the special variable $?, you can use boolean logic like I do in my snippet

Related

echo "$var" prints blank space

I was basically trying to compare two files and as part of that I assigned the cksum of the file to a variable . But when I try to compare it, it did not work. I realized that when I tried to read the variable nothing gets printed out
The below commands worked just fine
s.joseph#VA-S-JOSEPH-900 /cygdrive/c/users/Anuprita
$ test=`cksum interface2 | awk -F" " '{ print $1 }'`
s.joseph#VA-S-JOSEPH-900 /cygdrive/c/users/Anuprita
$ echo "$test"
3021988741
But when these are part of a script and I try to echo $var, nothing gets printed
$ for i in `ls interface*`;
do chksum1=`cksum $i | awk -F" " '{ print "'$1'" }'`;
echo "$chksum1";
done
s.joseph#VA-S-JOSEPH-900 /cygdrive/c/users/Anuprita
$
I am using bash shell
Without assigning it to any variable, the output is as shown below
for i in interface*; do echo "interface=\"$i\""; cksum "$i"; done
interface="interface11"
4113442291 111 interface11
interface="interface17"
1275738681 111 interface17
interface="interface2"
3021988741 186 interface2
Looks like it is an issue only with bash on cygwin. The script seems to be working just fine on unix
for i in ls interface*; do chksum1=cksum $i | awk -F" " '{ print $1 }'; echo $i, $chksum1; done
interface1, 4294967295
interface2, 4294967295
Try this;
for i in ls interface*; do echo "interface=$i"; chksum1=$(cksum $i | awk -F" " '{ print "'$1'" }'); echo "$chksum1"; done
I like adding the echo statement to verify your getting what you think with the ls statement and the variable assignment should use $(cmd) or `cmd`
Cheers
What you have in your 2nd script:
print "'$1'"
is a completely different statement from what you have in your first one:
print $1
Think about it and ask yourself why you changed it and what it is you're trying to achieve. Also man awk and see g at http://cfajohnson.com/shell/cus-faq-2.html#Q24 for what print "'$1'" does.
Best I can tell without and provided sample input your script should be written:
for i in interface*; do chksum1=$(cksum "$i" | awk '{ print $1 }'); echo "$chksum1"; done

Integer Expression Expected

Code sample :
declare -i a=1
echo "The number of NMON instances running in Performance VM"
ps -ef | grep nmon | awk '{ print $2 }' | wc -l
echo "---------------------------------------------"
num2= ps -ef | grep nmon | awk '{ print $2 }' | wc -l
#num1=${num2%%.*}
#num2 = $(ps -ef | grep nmon | awk '{ print $2 }' | wc -l)
echo "---------------------------------------------"
echo "${num2}"
while [ "$a" -lt "$num2" ]
do
kill -USR2 $(ps -ef | grep nmon | awk '{ print $2 }' | head -1)
a=`expr $a + 1`
done
In the Output i am getting the following error
[: : integer expression expected
in the debug it shows
++ '[' 1 -lt '' ']'
that num2 is empty but when i echo the num2 value i am getting the value correctly.
Output:
The number of NMON instances running in Performance VM
1
1
thanks in advance
The 1 you see in the output is not from echo "${num2}". Like the diagnostics already tell you, this variable is empty.
The general syntax of shell scripts is
[ variable=value ...] command parameters ...
which will assign value to variable for the duration of command, then restore its original value. So the pipeline you are running temporarily sets num2 to the empty string (which apparently it already contained anyway), then runs the pipeline without storing the output anywhere (such as, I imagine you expected, in num2).
Here is a fixed version of your script, with the additional change that the Awk scripts handle stuff you used grep and head and wc for. Because the functionality of these commands is easily replaced within Awk, using external utilities is doubtful (especially so for grep which really is useless when you just run it as a preprocessor for a simple Awk script).
countnmon () {
ps -ef | awk '/[n]mon/ { ++n } END { print n }'
}
declare -i a=1
echo "The number of NMON instances running in Performance VM"
countnmon
echo "---------------------------------------------"
num2=$(countnmon)
#num1=${num2%%.*}
#num2 = $(countnmon)
echo "---------------------------------------------"
echo "${num2}"
while [ "$a" -lt "$num2" ]
do
kill -USR2 $(ps -ef | awk '/[n]mon/ { print $2; exit }')
a=`expr $a + 1`
done
The repeated code could be refactored even further to avoid all code duplication but that will somewhat hamper the readability of this simple script so I have not done that.
Whitespaces matter in bash.
The syntax for command execution is:
command arg1 arg2 ...
So,
var = value # command: var, arg1: =, arg2: value
There's are two exceptions to this rule
exporting variables to an executed command (the variables vanish after the command finishes):
var1=value1 var2=value2 .. command arg1 arg2 ...
assigning a variable (you want this one):
var=value

Bash function arguments

My problem is that prepinace_grepu, which is $3 inside of function, evaluates to -i instead of -i -n as I expected it to be .
How can I change it to work? And I cant put it in two variables, because I want it to be flexible and just take it as a string , so it will work even if prepinace_grepu="-c -v -i -f" etc...
compare()
{
semka $2 $1 /etc/passwd /etc/shadow | sort > result1.txt
grep $3 $1 /etc/passwd /etc/shadow | sort > result2.txt
diff result2.txt result1.txt > diff.txt
if [[ -s diff.txt ]] ;
then echo "FAIL"
else echo "OK"
fi ;
}
pattern=Hojny
prepinace_moje="-vi"
prepinace_grepu="-i -n"
compare $pattern $prepinace_moje $prepinace_grepu
Quote the variables in shell as much as you can:
pattern="Hojny"
prepinace_moje="-vi"
prepinace_grepu="-i -n"
compare "$pattern" "$prepinace_moje" "$prepinace_grepu"
Since prepinace_grepu contains space you must send it in quotes otherwise called function will only get -i and $3 and -n as $4.

awk command variable NF not working on NULL input

I run my safe shell script to make sure a binary is running
to check a binary is running I do following command
pidof prog.bin | awk '{print NF}'
is some system it gives me 0 when binary not running
and
in some systems it gives me NULL(nothing)
I can check the NULL using -z option but why awk command acting this way ??
Instead of pidof you can use:
pgrep -qf prog.bin
And check its exit status.
As per man pgrep:
-f Match against full argument lists. The default is to match against process names.
-q Do not write anything to standard output.
You can use this,
if [ `pidof 'NetworkManager'` ]; then
echo "Running"
else
echo "Not Running"
fi
One way to handle this sort of thing (undefined variables) in awk is like this:
echo hi | awk '{print a}'
compared with:
echo hi | awk '{print a || 0}'
0
One Liner for If else
[[ $(pidof 'NetworkManager') ]] && echo "Running" || echo "Not Running"
Try this:
pidof prog.bin | awk '{ if (NF!=0) print NF }'
Here's some tests with awk and NF:
$ # regular line of input
$ echo foo | awk '{print NF}'
1
$ # empty line
$ echo | awk '{print NF}'
0
$ # a word on input with no newline
$ printf "%s" nonewline | awk '{print NF}'
1
$ # no input, not even a newline
$ printf %s | awk '{print NF}'
# no output from awk
I suspect the pidof case is the last: not even a newline. To force a newline:
echo $(pidof prog) | ...
printf "%s\n" "$(pidof prog)" | ...

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.

Resources