Simplify `tcpdump` output - sh

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

Related

Sh script to output unused interfaces on linux

I asked the dark side and here's what it printed.....
#!/bin/bash
for interface in $(ip addr show | awk '/^[0-9]+:/ {print $2}' | tr -d :)
do
if ! ip addr show $interface | awk '/inet / {print $2}' | grep -q . ; then
echo $interface
fi
done
I want to add n+ variable directly so the output will be the interfaces that is not used by the system,
Done
I have these two scripts, one for Linux and one for Mac, I hope they serve you because I have tested them on Linux Ubuntu and Mac.
on linux
#!/bin/bash
# This script will output unused interfaces on Linux
# Get list of all interfaces
interfaces=$(ifconfig -a | grep -o '^[^ ]*:' | tr -d :)
# Loop through each interface
for interface in $interfaces; do
# Check if interface is up
if [[ $(ifconfig $interface | grep -c 'UP') -eq 0 ]]; then
# Output interface name
echo "$interface is unused"
fi
done
on mac
#!/bin/bash
# Get list of all network interfaces
interfaces=$(networksetup -listallnetworkservices | tail -n +2)
# Loop through each interface
for interface in $interfaces; do
# Get the IP address of the interface
ip=$(ipconfig getifaddr "$interface")
# If the IP address is empty, the interface is unused
if [ -z "$ip" ]; then
echo "$interface is unused"
fi
done
#!/bin/bash
count=0
for interface in $(ip addr show | awk '/^[0-9]+:/ {print $2}' | tr -d :)
do
if ! ip addr show $interface | awk '/inet / {print $2}' | grep -q . ; then
free_interfaces[$count]=$interface
count=$((count + 1))
fi
done
case $count in
0)
echo "No usable interface found."
exit 1
;;
1)
DEFIF=${free_interfaces[0]}
echo "The interface $DEFIF will be used."
;;
*)
echo "Available interfaces to select: "
PS3="Press a number to select an interface to use (1-$count): "
select interface in "${free_interfaces[#]}"; do
DEFIF=$interface
break
done
echo "The interface $DEFIF will be used."
;;
esac

Mongo DB command via SSH [duplicate]

I have this following shell command:
ssh user#host "df | grep /dev/ | \
awk 'BEGIN{print "DISK", "%USAGE", "STATUS"} {split($5, a, "%"); \
var="GREEN"; print $1, $5, var}' | column -t"
I need to run this over ssh but I get syntax error due to the presence of nested double and single quotes.
I tried the escape characters for before the beginning and ending of the quotes but it did not solve the problem.
However, on local system running this will give the following output:
$ df | grep /dev/ | \
awk 'BEGIN{print "DISK", "%USAGE", "STATUS"} {split($5, a, "%"); \
var="GREEN"; print $1, $5, var}' | column -t
DISK %USAGE STATUS
/dev/sda1 95% GREEN
A quoted heredoc allows you to omit the outer quotes:
ssh user#host <<'END'
df | grep /dev/ | awk 'BEGIN{print "DISK", "%USAGE", "STATUS"} {split($5, a, "%"); var="GREEN"; print $1, $5, var}' | column -t
END
This is the case where here document comes handy:
ssh -t -t user#host<<'EOF'
df | awk 'BEGIN{print "DISK", "%USAGE", "STATUS"} /dev/{split($5, a, "%"); var="GREEN"; print $1, $5, var}' | column -t
EOF
It's much simpler to just run df | grep remotely, and process the output locally with awk:
ssh user#host 'df | grep /dev' | awk '
BEGIN{print "DISK", "%USAGE", "STATUS"}
{split($5, a, "%"); var="GREEN"; print $1, $5, var}' | column -t

Split results of du command by new line

I have got a list of the top 20 files/folders that are taking the most amount of room on my hard drive. I would like to separate them into size path/to/file. Below is what I have done so far.
I am using: var=$(du -a -g /folder/ | sort -n -r | head -n 20). It returns the following:
120 /path/to/file
115 /path/to/another/file
110 /file/path/
etc.
I have tried the following code to split it up into single lines.
for i in $(echo $var | sed "s/\n/ /g")
do
echo "$i"
done
The result I would like is as follows:
120 /path/to/file,
115 /path/to/another/file,
110 /file/path/,
etc.
This however is the result I am getting:
120,
/path/to/file,
115,
/path/to/another/file,
110,
/file/path/,
etc.
I think awk will be easier, can be combined with a pipe to the original command:
du -a -g /folder/ | sort -n -r | head -n 20 | awk '{ print $1, $2 "," }'
If you can not create a single pipe, and have to use $var
echo "$var" | awk '{ print $1, $2 "," }'

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.

get list of sections from ini-file using shell (sed/awk)

I want to create a var from the section names of an ini file like:
[foo]
; ...
[bar]
; ...
[baz:bar]
;...
now I need a var like
SECTIONS="foo bar baz"
thanks in advance
One line solution could be:
export SECTIONS=`grep "^\[" test.ini |sort -u | xargs | tr '\[' ' ' | tr '\]' ' ' `
SECTIONS=$(crudini --get your.ini | sed 's/:.*//')
I'm now using this construct, don't need to know if a section exists. just read it, if it's empty it does not exist.
INI_FILE=test.ini
function ini_get
{
eval `sed -e 's/[[:space:]]*\=[[:space:]]*/=/g' \
-e 's/;.*$//' \
-e 's/[[:space:]]*$//' \
-e 's/^[[:space:]]*//' \
-e "s/^\(.*\)=\([^\"']*\)$/\1=\"\2\"/" \
< $INI_FILE \
| sed -n -e "/^\[$1\]/,/^\s*\[/{/^[^;].*\=.*/p;}"
echo ${!2}
}
IP=$(ini_get 50001 ip)
PORT=$(ini_get 50001 port)
echo $IP:$PORT