Extract IP address from /etc/hosts file with SED command - shell

I would like to extract the IP v4 address only from my /etc/hosts file with shell sed command.
I managed to isolate those line with localhost at the end of the line with the following command:
$ sed -E '/localhost$/!d ' host_1 | sed -n 1p
which gave me the following output :
# 127.0.0.1 localhost
How can I only extract the IP v4 address alone form the above result?

The test data:
$ cat file
127.0.0.1 localhost
# 127.0.0.2 localhost
127 127.0.0.3 localhost
The sed:
$ sed -n 's/\(.*[^0-9]\|\)\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\).*/\2/p' file
The output:
127.0.0.1
127.0.0.2
127.0.0.3
The sed with the -E switch:
$ sed -nE 's/(.*[^0-9]|)([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*/\2/p' file

I tried this command and it works fine.
$ sed -E '/localhost$/!d' host_1 | sed -n 1p |grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b"
output: 127.0.0.1
Nonetheless I am still curious about how can I substitute the grep by a sed command.

sed -E '/localhost$/!d ' /etc/hosts | awk '{print $1}' | grep -v :

Late but you can try this :
sed -E '/localhost$/!d ' host_1 | sed -n 1p | sed -r 's/\localhost//g'
The last part replaces the grep used by 4everLRG
If you need to extract localhost IP from /etc/hosts make sure to replace host_1 with /etc/hosts

Related

Bash while loop script that runs Nmap with iterating IP and port number

Summary: I'm trying to create a Bash script that selects an IP address and it's associated open ports, then run each IP through Nmap and display/store the results.
The format of the ports file (portsList):
192.168.1.1 53 udp
192.168.1.1 80 tcp
192.168.1.1 1900 tcp
192.168.1.110 135 tcp
192.168.1.115 1080 tcp
The format of the IP file (ipList):
192.168.1.1
192.168.1.110
192.168.1.115
My Bash script:
#!/bin/bash
portsvar="$(cat formattedPorts)"
hostvar="$(cat oneHost)"
while read -r line;
do
echo "$line" > oneHost
grep -wf oneHost portsList | awk '{print $2}' | tr '\n' ',' > formattedPorts
nmap -n -sV -p"$portsvar" "$hostvar" >> scanResults
cat scanResults
done < ipList
I spent several hours, trying multiple variations of this code and tried to find a solution online. But to no avail. The most this script can do is scan and output for the first selected IP and ports.
Additional considerations would be; if a port is UDP, to append 'U:' on the ports option. Also, if there is a way to display the output of Nmap scanning, while it is being redirected '>>' to a file.
Bash is what I'm most familiar with, but I'm open to learning a solution in a different language.
Edit
I tried jhnc's solution below by replacing:
echo "$line" > oneHost
grep -wf oneHost portsList | awk '{print $2}' | tr '\n' ',' > formattedPorts
nmap -n -sV -p"$portsvar" "$hostvar" >> scanResults
cat scanResults
with jhnc's code in the comment below. the resulting output was:
nmap -n -sV -p T:135 192.168.1.110
nmap -n -sV -p T:5985 192.168.1.112
nmap -n -sV -p T:54112,T:60000,T:8009,T:8888 192.168.1.131
nmap -n -sV -p T:5040 192.168.1.132
nmap -n -sV -p T:1041,T:1900,T:20005,T:33344,T:49152,T:49153,T:80 192.168.1.1
This output was echo'ed onto the terminal 5 times. From this I'll try to find a solution to have the input of this group of IP's ran once.

ssh remote command execution quoting and piping awk

I'm working on a script, that should find certain disks and add hostname to them.
I'm using this for 40 servers with a for loop in bash
#!/bin/bash
for i in myservers{1..40}
do ssh user#$i findmnt -o SIZE,TARGET -n -l |
grep '1.8T\|1.6T\|1.7T' |
sed 's/^[ \t]*//' |
cut -d ' ' -f 2 |
awk -v HOSTNAME=$HOSTNAME '{print HOSTNAME ":" $0}'; done |
tee sorted.log
can you help out with the quoting here? It looks like awk gets piped (hostname) from localhost, not the remote server.
Everything after the first pipe is running locally, not on the remote server.
Try quoting the entire pipeline to have it run on the remote server:
#!/bin/bash
for i in myservers{1..40}
do ssh user#$i "findmnt -o SIZE,TARGET -n -l |
sed 's/^[ \t]*//' |
cut -d ' ' -f 2 |
awk -v HOSTNAME=\$HOSTNAME '{print HOSTNAME \":\" \$0}'" ;
done | tee sorted.log
This is a shorter version of your stuff:
findmnt -o SIZE,TARGET -n -l |
awk -v HOSTNAME=$HOSTNAME '/M/{print HOSTNAME ":" $2}'
Applied to the above:
for i in myservers{1..40}
do ssh user#$i bash -c '
findmnt -o SIZE,TARGET -n -l |
awk -v HOSTNAME=$HOSTNAME '"'"'/M/{print HOSTNAME ":" $2}'"'"' '
done |
tee sorted.log
see: How to escape the single quote character in an ssh / remote bash command?

Processing ifconfig and hostname output and frame it in single line for multiple hosts

I'm trying to filter remote machine mac address , IP and hostname from 100 machines. Initially I'm capturing the information using below command.
$for i in `cat IP`;do in ssh root#$IP "ifconfig eth0 && hostname " ;done
eth0 Link encap:Ethernet HWaddr 00:MN:77:TR:XX:ZZ
inet addr:192.168.122.25 Bcast:192.168.122.255
Mask:255.255.224.0
test.com-112304
eth0 Link encap:Ethernet HWaddr 00:TT:77:MM:XX:YY
inet addr:192.168.122.22 Bcast:192.168.122.255
Mask:255.255.224.0
test.com-11035
Initially the output redirect to one file. from their I need to process output which comes in the above format.
I can able to accomplish to print IP and mac by line as follows
$cat input | awk '/HWaddr/{printf $NF;printf " ";getline;print $2;}' | cut -c1-18,24-
00:MN:77:TR:XX:ZZ 192.168.122.25
00:TT:77:MM:XX:YY 192.168.122.22
Actually I want to include hostname along with the output as follows
00:MN:77:TR:XX:ZZ 192.168.122.25 test.com-112304
00:TT:77:MM:XX:YY 192.168.122.22 test.com-11035
test.com will be common name for all hostname. I tried redirect both output in two variable and called as follows , but no luck.
a=`cat input | awk '/HWaddr/{printf $NF;printf " ";getline;print $2;}' | cut -c1-18,24-`
b=`grep test.com input`
echo $a $b | xargs -n2
Please shed some views
I'm trying to filter remote machine mac address , IP and hostname from 100 machines.
Machine mac address, from here: cat /sys/class/net/eth0/address
You have hostname utility, why don't you just hostname -i? You can parse ifconfig | grep inet | awk '{print $2}' | sed 's/addr://' and hope ifconfig versions are the same across all machines (some ifconfig verions return inet <ip> some return inet addr:<ip> like yours).
Hostname with hostname
Putting together:
echo $(cat /sys/class/net/eth0/address) $(ifconfig eth0 | grep inet | awk '{print $2}') $(hostname)
Executing a command for each line in some file is a job for xargs and remember about properly escaping your arguments:
cat IP | xargs -n1 -I{} ssh root#{} 'echo $(cat /sys/class/net/eth0/address) $(ifconfig eth0 | grep inet | awk '\''{print $2}'\'' | sed '\''s/addr://'\'') $(hostname)'
If you really have 100 machines, ansible might interest you.
If you really have that "input" file and you can't change it, you may parse it like this:
sed 's/eth0/#eth0/' input \
| xargs -d'#' -n1 -- bash -c '{ echo "$1" | grep HWaddr | awk "{print \$5}"; echo "$1" | grep inet | awk "{print \$2}" | sed "s/addr://"; echo "$1" | grep "^test.com"; } | tr "\n" " "; echo' --
And this hurts my eyes:
for i in `cat IP`; then

How would you redirect the output of a command into the input of another command

What can I do to redirect the output of a command such as ls to the input of another command such as grep.
In other words:
what would be in the blank in the following?
$ ls /etc ____ grep host #
You can use the pipe | character.
Your command would become: ls /etc | grep host #
This is called piping and you simply use | in that spot.
ls /etc | grep host
Returns:
hosts
hosts.equiv
hosts-orig
Another example:
cat /etc/hosts | grep 127
Returns (for me):
#127.0.0.1 google.ca
127.0.0.1 localhost

use tcpkill command from an ip list

I have got an ip list in a file called ips:
ip1
ip2
I want to tcpkill from this list. I cannot do it from tcpkill command options. I need a script which will write :
tcpkill -i eth0 -9 host ip1 or host ip2
the list can grow in time.
the only thing I know is that I will need a loop to read the list:
for IP in $(cat list) ; do
echo "tcpkill -i eth0 -9 host $IP " (for
the first element of the list)
echo "or host $IP" (for the rest of
the list).
So my questions are:
1. what would be the right syntax for this purpose?
2. Is there a completely different way of doing this?
Any idea folks ?!
thank you very much.
This single line command would append the IP list to tcpkill command to form the complete command:
tcpkill -i eth0 -9 host $(cat list | xargs | sed 's/ / or host /g')
You can put this command after echo to see how the command gets formed.
echo tcpkill -i eth0 -9 host $(cat list | xargs | sed 's/ / or host /g')

Resources