Python get IP address from telnetlib output

Using telnetlib I am pulling routing information from my router and want to extract the WAN IP using a template. The result of the telnet session is in a variable with lines separated by \ n.

Material from telnet session.

l= tn.read_all()
>>> l
'\r\nip -f inet addr\r\nexit\r\nadmin4asus@RT-AC68U:/tmp/home/root# ip -f inet addr\r\n1: lo: <LOOPBACK,MULTICAST,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN \r\n    inet 127.0.0.1/8 brd 127.255.255.255 scope host lo\r\n2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\r\n    inet 24.6.29.214/21 brd 24.6.31.255 scope global eth0\r\n7: br0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN \r\n    inet 192.168.11.1/24 brd 192.168.11.255 scope global br0\r\n8: tun21: <POINTOPOINT,MULTICAST,NOARP,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 100\r\n    inet 10.8.0.1 peer 10.8.0.2/32 scope global tun21\r\nadmin4asus@RT-AC68U:/tmp/home/root# exit\r\n'
>>> 

      

Now my code.

l= tn.read_all()
for line in l.split('\n'):
    match= re.findall( r'([0-9]+(?:\.[0-9]+){3}).*scope global eth0', line)
    if match is not None:
        print('Found ' + line)

      

I would expect one line to match print. In the meantime, there is no need to worry about it.

Found     inet 24.6.29.214/21 brd 24.6.31.255 scope global eth0

      

But I find it everywhere.

Found 
Found ip -f inet addr
Found exit
Found admin4asus@RT-AC68U:/tmp/home/root# ip -f inet addr
Found 1: lo: <LOOPBACK,MULTICAST,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
Found     inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
Found 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
Found     inet 24.6.29.214/21 brd 24.6.31.255 scope global eth0
Found 7: br0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN 
Found     inet 192.168.11.1/24 brd 192.168.11.255 scope global br0
Found 8: tun21: <POINTOPOINT,MULTICAST,NOARP,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 100
Found     inet 10.8.0.1 peer 10.8.0.2/32 scope global tun21
Found admin4asus@RT-AC68U:/tmp/home/root# exit
Found 

      

I cannot figure out why my code is not working. If the experts have a better method (with an explanation), that would be great.

Edit:

Ian's answer is definitely more pythonic, but my lack of knowledge about python makes me prefer vks, which is easier for me to understand. I gave both "^" and will mark the vks as preferred (in the sense of "preferred over me").

I ended up using '\ r \ n' in the 'split' cmd and the following code.

def get_asus_wan_ip():
    "Gets WAN IP from ASUS router"

    import telnetlib
    import re

    ASUS_IP=   '192.168.1.1'
    ASUS_USER= 'xxxxxxxx'
    ASUS_PASS= 'yyyyyyyy'
    tn = telnetlib.Telnet(ASUS_IP)

    tn.read_until("login: ")
    tn.write(ASUS_USER + "\n")
    tn.read_until("Password: ")
    tn.write(ASUS_PASS + "\n")
    tn.write("ifconfig eth0\n")
    tn.write("exit\n")
    l= tn.read_all()
    for line in l.split('\r\n'):
        match= re.findall( r'^\s+inet addr:([0-9]+(?:\.[0-9]+){3}).*', line)
        if match:
            break

    wan_ip= match[0]
    return wan_ip

      

+3


source to share


2 answers


import re
x="""'\r\nip -f inet addr\r\nexit\r\nadmin4asus@RT-AC68U:/tmp/home/root# ip -f inet addr\r\n1: lo: <LOOPBACK,MULTICAST,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN \r\n    inet 127.0.0.1/8 brd 127.255.255.255 scope host lo\r\n2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\r\n    inet 24.6.29.214/21 brd 24.6.31.255 scope global eth0\r\n7: br0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN \r\n    inet 192.168.11.1/24 brd 192.168.11.255 scope global br0\r\n8: tun21: <POINTOPOINT,MULTICAST,NOARP,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 100\r\n    inet 10.8.0.1 peer 10.8.0.2/32 scope global tun21\r\nadmin4asus@RT-AC68U:/tmp/home/root# exit\r\n'"""
for line in x.split('\n'):
    match= re.findall(r'(?:[0-9]+(?:\.[0-9]+){3}).*scope global eth0', line)
    if match:
        print('Found ' + line)

      

Output: Found inet 24.6.29.214/21 brd 24.6.31.255 scope global eth0

Problems with your code:



1) re.findall

returns list

, so it can't be None

, it can be empty. Use this in if

.

2) re.findall

only returns the groups, if any. If you want the entire row, make the first group uncaptured.

+3


source


You can greatly reduce your combo code:

import re

string = """
1: lo: <LOOPBACK,MULTICAST,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
    inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
    inet 24.6.29.214/21 brd 24.6.31.255 scope global eth0
7: br0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN 
    inet 192.168.11.1/24 brd 192.168.11.255 scope global br0
8: tun21: <POINTOPOINT,MULTICAST,NOARP,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 100
    inet 10.8.0.1 peer 10.8.0.2/32 scope global tun21
"""

rx = re.compile(r'\b(\d+(?:\.\d+){3})\b.*scope global eth0')
matches = [line
            for line in string.split("\n")
            for match in [rx.search(line)]
            if match]
print(matches)
# ['    inet 24.6.29.214/21 brd 24.6.31.255 scope global eth0']

      



Or, if you prefer filter()

and lambda()

:

matches = list(filter(lambda x: rx.search(x), string.split("\n")))
print(matches)

      

+2


source







All Articles