LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Tough script (https://www.linuxquestions.org/questions/linux-newbie-8/tough-script-696085/)

mmahulo 01-09-2009 08:30 AM

Tough script
 
hi

i want to write a script in ksh that will print the comma delimited list of Host,IP,FreeMem,averageLoad.

This is what i tried and i get lost:

cd /etc
host=`cat HOSTNAME`
cd ..
I_P=`/sbin/ifconfig`
IP=${I_P#*eth0 * inet addr:} # delete everything to the left of inet addr:
IP=${IP%% *} # delete from the right till you find the last value that variable IP now holds
echo "Host, IP"
echo $host , $IP

TotMem=`free -tm`
Tot_Mem=${TotMem#*Total: }
#Tot_Mem=${$1% *}
echo $Tot_Mem


the above script acheives to get the Host and the IP address. Please help with the remaining elements as to how i can get them. your assistance is much appreciated. thanks!

Agrouf 01-09-2009 08:35 AM

What are the remaining elements you are looking for? Can you please sum it up for me?

makuyl 01-09-2009 09:01 AM

You could experiment with these:
echo `hostname`
echo `ifconfig eth0|awk 'NR==2 {print $2}'|sed 's/^.....//'`
echo `free -t|awk 'NR==5 {print $4}'`
echo `cat /proc/loadavg`

Edit, oops, for a comma delimited something like:
echo `hostname`,`ifconfig eth0|awk 'NR==2 {print $2}'|sed 's/^.....//'`,\
`free -t|awk 'NR==5 {print $4}'`,`cat /proc/loadavg`

slack12ware 01-09-2009 09:06 AM

for averageLoad: do
echo `uname -a | cut -d ' ' -fX`

run uname on your box and check the column number loadtime avarage is in and put it where "X" is in the above command.

for freememory do:
echo `cat /proc/meminfo | grep MemFree | cut -d ' ' -f2`

play around with the value for 2 above
note the (`) they are tilda not commas. Good luck

sorry cant be of too much help aint a guru, I myself experiment and mess around a little before I come up with real scripts and am not not my box right now.

mmahulo 01-12-2009 01:08 AM

Thanks everyone.

and, makuyl is it possible to use another method except using awk as in you reply post: echo `free -t|awk 'NR==5 {print $4}'`. Or could you at least explain to me in a nutshell as to what the statement actually means. I haven't got the grips of AWK as yet. Please...

chrism01 01-12-2009 01:28 AM

@slack12ware:

~ = tilde

` = backquote

colucix 01-12-2009 02:29 AM

Here is how I would do:
Code:

#!/bin/bash
host=$(hostname -s)
ip=$(/sbin/ifconfig eth0 | sed -n '/inet /{s/.*addr://;s/ .*//;p}')
mem=$(free -tm | sed -n '/Total/{s/.* //;p}')
load=$(cat /proc/loadavg)
echo $host,$ip,$mem,$load

The hostname command with the -s option prints out the short hostname, that is without the domain name. Strip out the -s option if you want the complete hostname. To extract the data (or better to remove the unwanted parts) from the ifconfig and free output I used sed in alternative to awk or parameter substitution. Note that the total free memory is comprehensive of the swap memory.

mmahulo 01-12-2009 03:44 AM

Quote:

Originally Posted by colucix (Post 3405381)
Here is how I would do:
Code:

#!/bin/bash
host=$(hostname -s)
ip=$(/sbin/ifconfig eth0 | sed -n '/inet /{s/.*addr://;s/ .*//;p}')
mem=$(free -tm | sed -n '/Total/{s/.* //;p}')
load=$(cat /proc/loadavg)
echo $host,$ip,$mem,$load

The hostname command with the -s option prints out the short hostname, that is without the domain name. Strip out the -s option if you want the complete hostname. To extract the data (or better to remove the unwanted parts) from the ifconfig and free output I used sed in alternative to awk or parameter substitution. Note that the total free memory is comprehensive of the swap memory.


thanks colucix

i really wish to understand what the following means and right now i don't. can you please break it down for me: '/Total/{s/.* //;p}'.
Another thing is that I want total memory and not only free memory. thanks

colucix 01-12-2009 04:41 AM

To understand the sed command consider the following:
Code:

$ free -tm
            total      used      free    shared    buffers    cached
Mem:          1011        653        357          0        55        342
-/+ buffers/cache:        255        755
Swap:        2047        36      2010
Total:        3058        689      2368

from this output you want to extract the total memory from the last line. In my example I extracted just the last field "2368". So I tell to sed: for each line containing "Total" remove anything till the last blank space and print out the rest:
Code:

sed -n '/Total/{s/.* //;p}'
where /Total/ is the sed address (the commands inside brackets are executed only for those lines that match the regular expression). The command is the substitution of any number of characters .* followed by a space with nothing (that is remove this part of the line). Take in mind that a dot matches any single character and the asterisk means any number (zero included) of the preceding expression. The p command (separated by semi-colon) is to print what remains of the line after the substitution.

If you want the total memory, swap included you can do something like
Code:

free -tm | sed -n '/Total/{s/Total: *//;s/ .*//;p}'
that is first remove the first part containing Total and the following blank spaces, then remove the last part from the first blank space to the end. Or just simply use awk
Code:

free -tm | awk '/Total/{print $2}'
if you're interested in the physical memory only, just change Total with Mem in the commands above. Or just parse the content of /proc/meminfo (dividing by 1000 if you want the output in Mb)
Code:

awk '/MemTotal/{printf "%d\n",$2/1000}' /proc/meminfo

mmahulo 01-12-2009 05:30 AM

Quote:

Originally Posted by colucix (Post 3405470)
To understand the sed command consider the following:
Code:

$ free -tm
            total      used      free    shared    buffers    cached
Mem:          1011        653        357          0        55        342
-/+ buffers/cache:        255        755
Swap:        2047        36      2010
Total:        3058        689      2368

from this output you want to extract the total memory from the last line. In my example I extracted just the last field "2368". So I tell to sed: for each line containing "Total" remove anything till the last blank space and print out the rest:
Code:

sed -n '/Total/{s/.* //;p}'
where /Total/ is the sed address (the commands inside brackets are executed only for those lines that match the regular expression). The command is the substitution of any number of characters .* followed by a space with nothing (that is remove this part of the line). Take in mind that a dot matches any single character and the asterisk means any number (zero included) of the preceding expression. The p command (separated by semi-colon) is to print what remains of the line after the substitution.

If you want the total memory, swap included you can do something like
Code:

free -tm | sed -n '/Total/{s/Total: *//;s/ .*//;p}'
that is first remove the first part containing Total and the following blank spaces, then remove the last part from the first blank space to the end. Or just simply use awk
Code:

free -tm | awk '/Total/{print $2}'
if you're interested in the physical memory only, just change Total with Mem in the commands above. Or just parse the content of /proc/meminfo (dividing by 1000 if you want the output in Mb)
Code:

awk '/MemTotal/{printf "%d\n",$2/1000}' /proc/meminfo


thank you very much sir. now i get the picture. thanks again

makuyl 01-12-2009 12:09 PM

Quote:

Originally Posted by mmahulo (Post 3405313)
Thanks everyone.

and, makuyl is it possible to use another method except using awk as in you reply post: echo `free -t|awk 'NR==5 {print $4}'`. Or could you at least explain to me in a nutshell as to what the statement actually means. I haven't got the grips of AWK as yet. Please...

That one's easy to explain. I told awk to print the fourth column of the fifth line.
I didn't mean you should use those echo lines as I wrote them, just wanted to give you some ideas for a possible solution. Much cleaner to use variables like you and colucix already did.

GazL 01-12-2009 12:35 PM

IP=$(hostname -i)

may save you all that messing with ifconfig and sed to pull the ip address out.

colucix 01-12-2009 03:40 PM

Quote:

Originally Posted by GazL (Post 3405989)
IP=$(hostname -i)

may save you all that messing with ifconfig and sed to pull the ip address out.

On my system it does not display the IP of the eth0 interface, but that one of the localhost, e.g. 127.0.0.1

GazL 01-12-2009 04:14 PM

Quote:

Originally Posted by colucix (Post 3406205)
On my system it does not display the IP of the eth0 interface, but that one of the localhost, e.g. 127.0.0.1

It should return whatever the hostname resolves to. It works correctly on my system. I think some distros put the hostname on the loopback entry in /etc/hosts in order to ensure that it can always be resolved, especially if they're using a dhcp setup to get an address, so yes, on reflection, that's something to watch out for. Good spot Colucix.

It's an interesting problem. If you can't rely on 'hostname -i', then you have to parse the output of ifconfig, but then how do you decide which interface to report should you encounter a system with multiple interfaces.

colucix 01-12-2009 04:42 PM

Quote:

Originally Posted by GazL (Post 3406251)
It's an interesting problem. If you can't rely on 'hostname -i', then you have to parse the output of ifconfig, but then how do you decide which interface to report should you encounter a system with multiple interfaces.

Good point. Apparently you have to know a priori which interface to rely on. Unless there is a way to know which is the external interface and which is (are) the internal one(s), other than check the address itself after its extraction, of course. Moreover, there are a lot of different types of network interface. For example having my system at home connected via DSL modem and running OpenSuse I have
Code:

dsl0      Link encap:Point-to-Point Protocol
eth0      Link encap:Ethernet
lo        Link encap:Local Loopback
wlan0    Link encap:Ethernet
wmaster0  Link encap:UNSPEC


makuyl 01-13-2009 06:26 PM

If you have a router/nat you can just grep for 192.168 or which ever of the four natted adress spaces you use.
Without nat, your isp probably has the same first two octets every time, so grep for what you usually have.

jschiwal 01-13-2009 06:55 PM

You could use "getent hosts <hostname>" as well. Even if you use avahi for name resolution. You will still get the localhost IP address for the host you are running on since that is what is in the hosts file.

The freemem value might be useless. There will be memory used for cache that will be freed if the system needs it. Obtaining the load and memory values from a remote host, you probably need to have some kind of client running on those hosts or use ssh to run a command or script that will return the values. And running a client or script to monitor memory and load value will of course reduce the available memory and increase the load. As you would expect.

I find it convenient to use public key encryption for ssh. Using that and "AllowHosts" makes it more secure, I you don't need to deal with using expect to deal with authentication. Sometimes that can interfere with pipes and tees in your script. Having usernames and passwords in scripts is best to avoid as well.

mmahulo 01-14-2009 03:19 AM

Quote:

Originally Posted by GazL (Post 3405989)
IP=$(hostname -i)

may save you all that messing with ifconfig and sed to pull the ip address out.

Thanks Gazyl

That was fairly easy.

GazL 01-14-2009 07:05 AM

Quote:

Originally Posted by colucix (Post 3406281)
Unless there is a way to know which is the external interface and which is (are) the internal one(s), other than check the address itself after its extraction, of course. Moreover, there are a lot of different types of network interface. For example having my system at home connected via DSL modem and running OpenSuse I have
Code:

dsl0      Link encap:Point-to-Point Protocol
eth0      Link encap:Ethernet
lo        Link encap:Local Loopback
wlan0    Link encap:Ethernet
wmaster0  Link encap:UNSPEC


In the absense of an external reference such as dns, the simplest solution I could come up with would be to assume the interface associated with the default route is the correct one,
Code:

ifconfig $(route | grep default | awk '{print $8}')
And then parse that with the sed script you provided in your responses above. It's still not entirely foolproof, but at least you're not hard coding the interface name which is a step in the right direction.

Ofcourse, if the system is configured such that hostname -i returns the correct value, it avoids the need for all this shenanigans, but as you made clear, this cannot be relied upon on all distributions and setups.


This is why I enjoy hanging out on LQ. You can often find interesting insights in threads that you expect to be pretty straightforward on first viewing. Yes... I know, I'm Sad like that. ;)

GazL 01-14-2009 07:07 AM

Quote:

Originally Posted by mmahulo (Post 3408053)
Thanks Gazyl

That was fairly easy.

You're welcome. Just keep in mind the issue that Colucix and I were discussing.

colucix 01-14-2009 07:15 AM

Quote:

Originally Posted by GazL (Post 3408230)
In the absense of an external reference such as dns, the simplest solution I could come up with would be to assume the interface associated with the default route is the correct one

This is a great advice! Well done!
Quote:

Originally Posted by GazL (Post 3408230)
This is why I enjoy hanging out on LQ. You can often find interesting insights in threads that you expect to be pretty straightforward on first viewing.

Totally agree! :)

slack12ware 02-07-2009 02:38 AM

Quote:

Originally Posted by chrism01 (Post 3405343)
@slack12ware:

~ = tilde

` = backquote

ohps my bad, youre right there, was in a bit of a hurry.


All times are GMT -5. The time now is 01:42 AM.