Reputation: 35
I am trying to make a bash script to get CPU and Memory information in different Unix servers and pipe them into a single text file in the local server.
The script returns something (result), but the result was not accurate when I check each of the servers CPU and Memory information manually. There might be some error in the scripts since the CPU and Memory commands are correct.
Here is the command to get CPU information in Unix (HPUX) :
machinfo | grep CPUs | awk '{print $5}'
And the result will be :
4
And here is the command to get Memory information in Unix (HPUX) :
machinfo | grep Memory | awk '{print $3}'
And the result will be :
4090
It shows that the commands are correct. Let's go into the full scripts.
#!/bin/ksh
SERVERS='
xxx.xxx.xxx.xxx
xxx.xxx.xxx.xxx'
cpu=$(machinfo | grep CPUs | awk '{print $5}')
mem=$(machinfo | grep Memory | awk '{print $3}')
print "SERVER" "CPU" "RAM (MB)";
for i in $SERVERS
do
ssh -n $i 2>&1 '$cpu | $mem'
print $cpu $mem
done
When the full scripts run, the result will be:
SERVER CPU RAM (MB)
s24bf011 2 4090
s24bf012 2 4090
s24bf013 2 4090
s24bf014 2 4090
s24bf016 2 4090
S24BF104 2 4090
S24BF105 2 4090
10.14.24.158 2 4090
S29BF200 2 4090
S02BF131 2 4090
S02BF104 2 4090
S24BF071 2 4090
S24BF165 2 4090
10.14.24.17 2 4090
Every server has a different CPU and RAM. How come they were all the same? Error in SSHing?
Upvotes: 0
Views: 2307
Reputation: 189337
Your script has multiple problems.
'$cpu | $mem'
is just a literal string. If you want to interpolate the values of $cpu
and $mem
, you need to use double quotes instead of single.
But
"$cpu | $mem"
will basically discard the output from $cpu
because you are piping it to $mem
which is ignoring its standard input. The proper way to run two independent commands is to put a semicolon between them, not a pipe. The function of the pipe is to take the standard output from the command before the pipe and redirect it as standard input into the command after the pipe.
But of course, the variables you declared do not contain the scripts; they contain the output of the Awk scripts, which you ran locally when you put them in process substitutions.
You should have received error messages about all of this; what happened to them?
Anyway, you can simplify processing enormously by refactoring this to just run a single command, anyway.
print "SERVER" "CPU" "RAM (MB)";
for i in $SERVERS
do
ssh -n "$i" "machinfo |
awk -v s='$i' '/CPUs/ { c=\$5 } /Memory/ { m=\$3 }
END { print s, c, m }'"
done
Here, I use double quotes around the remote command so that I can interpolate the server name into the Awk variable s
. The internal single quotes inside the double quotes do not have any significance to the local shell, i.e. they do not prevent the local shell from replacing the dollar signs, so we need to protect the dollar signs by backslash-escaping them.
But unless your local Awk is crippled or something, it doesn't make sense to run Awk remotely.
for i in $SERVERS
do
ssh -n "$i" machinfo |
awk -v s="$i" '/CPUs/ { c=$5 } /Memory/ { m=$3 }
END { print s, c, m }'
done
Putting stuff which isn't variable and which is only used once into a variable is just silly, and sometimes problematic (see http://mywiki.wooledge.org/BashFAQ/050).
Upvotes: 1