how to join ifconfig output to a line per interface - sed

how do i convert the following output with sed?
from:
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1
inet 127.0.0.1 netmask ff000000
igb0: flags=9040843<UP,BROADCAST,RUNNING,MULTICAST,DEPRECATED,IPv4,NOFAILOVER> mtu 1500 index 2
inet 10.1.1.1 netmask ffffff00 broadcast 10.1.1.255
groupname mnic_data
to:
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1 inet 127.0.0.1 netmask ff000000
igb0: flags=9040843<UP,BROADCAST,RUNNING,MULTICAST,DEPRECATED,IPv4,NOFAILOVER> mtu 1500 index 2 inet 10.1.1.1 netmask ffffff00 broadcast 10.1.1.255 groupname mnic_data
I have tried
sed -n '/^[a-z]/{x;1!s/\n/ /g;1!p;};H'
but no luck! appreciate your help in advance

You can try this:
$ sed -e :a -e '$!N;s/\n / /;ta' -e 'P;D' inputfile
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1 inet 127.0.0.1 netmask ff000000
igb0: flags=9040843<UP,BROADCAST,RUNNING,MULTICAST,DEPRECATED,IPv4,NOFAILOVER> mtu 1500 index 2 inet 10.1.1.1 netmask ffffff00 broadcast 10.1.1.255 groupname mnic_data
EDIT: To get rid of the extra spaces in the output above, you can use:
$ sed -e :a -e '$!N;s/\n\s\+/ /;ta' -e 'P;D' inputfile
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1 inet 127.0.0.1 netmask ff000000
igb0: flags=9040843<UP,BROADCAST,RUNNING,MULTICAST,DEPRECATED,IPv4,NOFAILOVER> mtu 1500 index 2 inet 10.1.1.1 netmask ffffff00 broadcast 10.1.1.255 groupname mnic_data

ifconfig |
awk '
FNR>1 && /^[^[:space:]]/ {print ""}
{printf "%s", $0}
END {print ""}
'

does this help (awk)?
awk '/:/&&f{print ""}{printf "%s", $0;f=1}'
test
kent$ echo "lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1
inet 127.0.0.1 netmask ff000000
igb0: flags=9040843<UP,BROADCAST,RUNNING,MULTICAST,DEPRECATED,IPv4,NOFAILOVER> mtu 1500 index 2
inet 10.1.1.1 netmask ffffff00 broadcast 10.1.1.255
groupname mnic_data"|awk '/:/&&f{print ""}{printf "%s", $0;f=1}'
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1 inet 127.0.0.1 netmask ff000000
igb0: flags=9040843<UP,BROADCAST,RUNNING,MULTICAST,DEPRECATED,IPv4,NOFAILOVER> mtu 1500 index 2 inet 10.1.1.1 netmask ffffff00 broadcast 10.1.1.255 groupname mnic_data

Related

Simplify `tcpdump` output

I want to convert this tcpdump output:
IP 10.10.10.1 > 20.20.20.1: ICMP echo request, id 8312, seq 0, length 64
IP 10.10.10.1.17441 > 20.20.20.1.22: Flags [S], seq 3936449810, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS[|tcp]>
to:
IP 10.10.10.1 > 20.20.20.1: ICMP
IP 10.10.10.1.17441 > 20.20.20.1.22: tcp
I tried a lot to covert them with shell script by using the cutcommand but I can't.
Thanks all for your help.
Using awk (or the GNU gawk), setting field separator FS to ":" and assuming dump is inside test.txt:
gawk 'BEGIN{ FS=":" } { if($0 ~ / ICMP /){ print $1 ": ICMP" }else if($0 ~ /tcp[]]>/){ print $1 ": tcp" } }' test.txt
The expected result:
IP 10.10.10.1 > 20.20.20.1: ICMP
IP 10.10.10.1.17441 > 20.20.20.1.22: tcp
tcpdump output could be piped to gawk as
tcpdump <options> | gawk ' ... '
This is strictly a cut method. It is assuming your output will always be of this format. As mentioned, a sed (or awk) version would probably be more dynamic.
The main piece of this is the -d (delimiter) argument and the -f (field) argument. -f can specify a single field or range of fields that are separated by a specified delimiter (I believe tabs are default).
If your output is in a file called output.txt, you can use this little script.
line1="$(head -1 output.txt | cut -d ' ' -f1-5)"
line2="$(tail -1 output.txt | cut -d ' ' -f1-4) $(tail -1 output.txt | cut -d '|' -f2 | cut -d "]" -f1)"
echo "$line1"
echo "$line2"
If your output is stored in a variable called output, you could use this script with your
variable sent as a parameter like ./script.sh "$output"
arg="$1"
line1="$(echo "$arg" | head -1 | cut -d ' ' -f1-5)"
line2="$(echo "$arg" | tail -1 | cut -d ' ' -f1-4) $(echo "$arg" | tail -1 | cut -d '|' -f2 | cut -d "]" -f1)"
echo "$line1"
echo "$line2"
Output:
IP 10.10.10.1 > 20.20.20.1: ICMP
IP 10.10.10.1.17441 > 20.20.20.1.22: tcp

Comparing 2 columns of 2 different .tsv files and write the output in a new tsv file

I am kinda stuck on a quick script that I wanted to adapt so I thought asking might help me moving forward :)
My first tsv file is a list of servers / hostnames that looks like this (groups.tsv):
Groupname | Servername
group1 server1
group2 server2
group3 server3 server4 server5
group4 server6
group5 server7
group6 server7
Second one is a list of IPs / hostnames (addresses.tsv):
Hostname | IP | Purpose
server1 192.168.1.29 255.255.255.255 application1
server2 172.16.9.38 255.255.255.255
server3 10.50.110.28 255.255.255.255
server4 10.0.0.1 255.255.255.255 application2
server5 192.168.1.1 255.255.255.255
server6 172.16.32.32 255.255.255.255
server7 10.0.0.3 255.255.255.255
server8 1.1.1.1 255.255.255.255 application3
server9 127.0.0.1 255.255.255.255
server10 10.28.28.28 255.255.255.255
With a perl script found elsewhere I am trying to obtain a new tsv file like this:
Hostname | IP | Purpose | Groupname
server1 192.168.1.29 255.255.255.255 application1 group1
...
The perl script is the following:
#!/usr/bin/perl
use strict;
use warnings;
my %programs; #Hash to save groupname => hostname for each program record
open my $fh1, '<', 'groups.tsv' or die "Failed to open groups.tsv: $!";
foreach (<$fh1>) {
chomp; #Remove newline character from end of line
my ( $groupname, $hostname ) = split(/\t/);
$programs{$groupname} = $hostname;
}
close $fh1;
open my $fh2, '<', 'addresses.tsv' or die "Failed to open addresses.tsv: $!";
open my $fh3, '>', 'result.tsv' or die "Failed to open result.tsv: $!"; #Output
foreach (<$fh2>) {
chomp; #Remove newline character from end of line
my $groupname = ( split(/\t/) )[1]; #Groupname
if ( exists $programs{$groupname} ) {
print $fh3 "$_\t$programs{$groupname}\n";
} else {
print $fh3 "$_\t*NA*\n";
}
}
At some point I have partly retrieved groupnames but it was because I have it confused with inverted key / values. I believe I would rather have to check on the values of the hash instead of the key, but I got no success so far.
For now I am having this result.tsv:
server1 192.168.1.29 255.255.255.255 application1 *NA*
server2 172.16.9.38 255.255.255.255 *NA*
server3 10.50.110.28 255.255.255.255 *NA*
....
In the same spirit, I will then have a policy.tsv
Groupname | Service
group1 ALL
group2 HTTP
group3 HTTP HTTPS TCP_3389
group3 group4 SSH
So my final goal would be to have a final tsv file like this:
Hostname | IP | Purpose | Groupname | Service
server1 192.168.1.29 255.255.255.255 application1 group1 ALL
...
http://www46.zippyshare.com/v/30272792/file.html
But I assume it might be easier to adapt as soon as the first part is OK.
Anybody clear with perl / hash could put me on a lead ?
Thanks in advance for the help!
Your hash is backwards. You want to lookup group name by host name. Change
$programs{$groupname} = $hostname;
to
$groupname{$_} = $groupname for split ' ', $hostname;
Then the bottom part becomes
my $hostname = ( split /\t/ )[0];
print $fh3 $_ . "\t" . ( $groupname{$hostname} || '*NA*' ) . "\n";

Get disk space and separate this with most used space but put in one list

Want to get disk space and separate this with most used space but put in one list
Example how get the used space:
df -P | grep -vE 'Filesystem' | awk '{ print $5 " " $6 }'
Output:
89% /
1% /oralog
24% /oradata
0% /dev/shm
Expected view:
[bad] 89% /
[ok] 1% /oralog
[ok]24% /oradata
[ok]0% /dev/shm
You can drop the grep by skipping over the first line in awk with NR>1 as the condition for the block. Just set the value of x to be the limit for good/bad, in the example I set the limit as 80:
$ df -P | awk 'NR>1{print ($5>x)?"[bad]":"[okay]",$5,$6}' OFS='\t' x=80
[bad] 89% /
[ok] 1% /oralog
[ok] 24% /oradata
[ok] 0% /dev/shm
What about this?
awk '{if($5>20) a="[bad]"; else a="[good]";} {print a, $5 " " $6}'
All together:
$ df -P | grep -vE 'Filesystem' | awk '{if($5>20) a="[bad]"; else a="[good]";} {print a, $5 " " $6}'
Test (whith threshold of 20%):
$ df -P | grep -vE 'Filesystem' | awk '{if($5>20) a="[bad]"; else a="[good]";} {print a, $5 " " $6}'
[bad] 25% /
[good] 1% /dev
[good] 1% /run
[good] 0% /run/lock
[good] 1% /run/shm
[good] 1% /run/user
Only disk with highest usage has [bad]
df -P | perl -anE '$F[4]=~s/%//||next;push#r,[#F];$m<$F[4] and $m=$F[4];END{say $m==$$_[4]?"[bad]":"[ok]"," $$_[4]% $$_[5]"for#r}'
output
[ok] 44% /
[ok] 0% /lib/init/rw
[ok] 1% /dev
[ok] 0% /dev/shm
[bad] 61% /ftp

Perl telnet command not sending every command

I have the following program below which telnets into another device and prints serial number and Mac address.
My problem is that for some reason if I send the command once it skips the first command and sends the second, but if I copy the same command twice it will send the command.
What is the correct way to send a command multiple commands successively?
Should the buffer be flushed after every command sent ?
My Env
Eclipse Ide
Ubuntu 12.10
perl 5, version 14, subversion 2 (v5.14.2)
Snippet of my code:
$telnet = Net::Telnet->new($remoteSystem);
$| = 1;
$telnet->buffer_empty();
$telnet->buffer_empty();
$result = $telnet->input_log($errorlog);
#$_ = "#lines";
#TSN =$telnet->cmd('export | grep -e SerialNumber..[A-Z] | cut -d"\"" -f2');
#TSN =$telnet->cmd('export | grep -e SerialNumber..[A-Z] | cut -d"\"" -f2');
#mac = $telnet->cmd('ifconfig | grep eth0 | cut -d" " -f 11');
print "#TSN AND #TSN #mac";
print FH "$remoteSystem\n";
print "Telnetting into $remoteSystem .\n"; # Prints names of the tcd
close(telnet);
}
foreach (#host) {
checkStatus($_);
}
OUTPUT That skips the first command:
bash-2.02 AND bash-2.02 ifconfig | grep eth0 | cut -d" " -f 11
00:11:D9:3C:6E:02
bash-2.02 #
bash-2.02 Telnetting into debug79-109 .
OUTPUT That works but I have to send the same command twice:
export | grep -e SerialNumber..[A-Z] | cut -d"\"" -f2
AE20001901E2FD1
bash-2.02 #
bash-2.02 AND export | grep -e SerialNumber..[A-Z] | cut -d"\"" -f2
AE20001901E2FD1
bash-2.02 #
bash-2.02 ifconfig | grep eth0 | cut -d" " -f 11
00:11:D9:3C:6E:02
bash-2.02 #
bash-2.02 Telnetting into debug79-109
Specify the command prompt in your call to cmd(), e.g.#TSN =$telnet->cmd('export | grep -e SerialNumber..[A-Z] | cut -d"\"" -f2', Prompt => 'bash-2.02 #');
Try opening a connection after creating a object for the module telnet
$telnet->open($host);
After which execute waitFor method:(waits until the pattern bash-2.02 # comes)
$telnet->waitFor(/^(bash-\d+.\d+ #)$/);
and then execute your commands , it would give you proper output.

Rebuild start.sh

Can someone recode this start.sh script based on CentOS?
Its now based on Ubuntu
#!/usr/bin/expect -f
lassign $argv pssword port mod map num hostname rconpassword slots
spawn-fcgi su - et -c cd et -c "./etded.x86 +set s_num=$num +set net_port $port +set dedicated 2 +set fs_game $mod +set logfile 0 +set sv_punkbuster 0 +set sv_hostname \'$hostname\' +set rconpassword $rcon +set g_password '$password' +set sv_maxclients $slots +set map $map"
> /dev/null 2>&1 &
expect "Password:" { send "$pssword\r" }
expect "# " { send "q" }
exit
Thanks!
Your expect is probably built on Tcl 8.4, so change
lassign $argv pssword port mod map num hostname rconpassword slots
to
foreach {pssword port mod map num hostname rconpassword slots} $argv {break}