telnetlib模块的使用

2019年7月27日 / 52次阅读 / Last Modified 2019年7月27日

telnetlib模块属于Python标准库,实现了一个telnet客户端的功能,可用来自动连接一些设备并进行相应的操作,其使用方式,有点像著名的expect。虽然现在远程连接基本上已经被SSH所取代,但在某些场景下,比如在局域网中连接一些通信设备,telnet还在发挥余热。本文介绍Python的telnetlib模块的使用。

先做点准备工作,我们需要在Linux中安装telnet相关程序,这样才有一个测试环境。默认情况下,现在的Linux发行版本都没有telnet,因为它不是一个安全的通信方式。

引入telnetlib模块

telnetlib模块内主要就是一个Telnet类,因此我们这样来引入:

>>> from telnetlib import Telnet

连接telnet服务器

我已经在Linux中安装了telnet服务器,地址就是本机的环回地址127.0.0.1,telnet服务器默认的端口号是23。

>>> from telnetlib import Telnet
>>> tn = Telnet('127.0.0.1')  # tn=Telnet('127.0.0.1',23,timeout=1)
>>> tn.interact()
Ubuntu 18.04.2 LTS
ubuntu login: xinlin
Password: 123456

Last login: Sat Jul 27 09:09:20 CST 2019 from 183.206.11.143 on pts/1
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.18.0-25-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage


 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:
     https://ubuntu.com/livepatch

233 packages can be updated.
1 update is a security update.

xinlin@ubuntu:~$ ls
ls
Desktop    examples.desktop  Public           snap       test
Documents  Music             repos            source     Videos
Downloads  Pictures          sendslip-in-use  Templates
xinlin@ubuntu:~$ logout
logout
*** Connection closed by remote host ***
>>> tn.close()

创建Telnet对象的时候,就可以填入telnet服务器地址,以及端口号,如果不填端口号,默认是23号端口。还有一个timeout参数,表示在进行连接时,最长的阻塞时间,如果不填,使用socket全局默认的超时时间。

interact() 函数,表示开始于telnet服务器互动,这个函数调用后,就像我们用手telnet客户端手动登录到服务器上一样,所有的往来交互全手动。上面的示例,我输入了一个ls命令,然后输入logout。最后还调用了一个 close() 函数,其实没有用,logout命令输入后,整个telnet连接就中断了。如果不输入logout命令(没有interact的时候),我们就要使用 close() 函数。最好的方式是,无论什么情况,最后都调用 close() 函数。

下面再来一个示例:

>>> tn = Telnet()
>>> tn.open('127.0.0.1',23,timeout=1)
>>> tn.set_debuglevel(1)
>>> tn.interact()
Telnet(127.0.0.1,23): recv b"\xff\xfd\x18\xff\xfd \xff\xfd#\xff\xfd'"
Telnet(127.0.0.1,23): IAC DO 24
Telnet(127.0.0.1,23): IAC DO 32
Telnet(127.0.0.1,23): IAC DO 35
Telnet(127.0.0.1,23): IAC DO 39
Telnet(127.0.0.1,23): recv b'\xff\xfb\x03\xff\xfd\x01\xff\xfd\x1f\xff\xfb\x05\xff\xfd!'
Telnet(127.0.0.1,23): IAC WILL 3
Telnet(127.0.0.1,23): IAC DO 1
Telnet(127.0.0.1,23): IAC DO 31
Telnet(127.0.0.1,23): IAC WILL 5
Telnet(127.0.0.1,23): IAC DO 33
Telnet(127.0.0.1,23): recv b'\xff\xfb\x03'
Telnet(127.0.0.1,23): IAC WILL 3
Telnet(127.0.0.1,23): recv b'\xff\xfb\x01'
Telnet(127.0.0.1,23): IAC WILL 1
Telnet(127.0.0.1,23): recv b'Ubuntu 18.04.2 LTS\r\nubuntu login: '
Ubuntu 18.04.2 LTS
ubuntu login: xinlin
Telnet(127.0.0.1,23): send b'xinlin\n'
Telnet(127.0.0.1,23): recv b'Password: '
Password: 123456
Telnet(127.0.0.1,23): send b'123456\n'
Telnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b'Last login: Sat Jul 27 10:24:10 CST 2019 from loca'
Last login: Sat Jul 27 10:24:10 CST 2019 from locaTelnet(127.0.0.1,23): recv b'lhost on pts/2'
lhost on pts/2Telnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b'Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.18.0-25'
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.18.0-25Telnet(127.0.0.1,23): recv b'-generic x86_64)'
-generic x86_64)Telnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b' * Documentation:  https://help.ubuntu.com'
 * Documentation:  https://help.ubuntu.comTelnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b' * Management:     https://landscape.canonical.com'
 * Management:     https://landscape.canonical.comTelnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b' * Support:        https://ubuntu.com/advantage'
 * Support:        https://ubuntu.com/advantageTelnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b' * Canonical Livepatch is available for installati'
 * Canonical Livepatch is available for installatiTelnet(127.0.0.1,23): recv b'on.'
on.Telnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b'   - Reduce system reboots and improve kernel secu'
   - Reduce system reboots and improve kernel secuTelnet(127.0.0.1,23): recv b'rity. Activate at:'
rity. Activate at:Telnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b'     https://ubuntu.com/livepatch'
     https://ubuntu.com/livepatchTelnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b'233 packages can be updated.'
233 packages can be updated.Telnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b'1 update is a security update.'
1 update is a security update.Telnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b'xinlin@ubuntu:~$ '
xinlin@ubuntu:~$ ls
Telnet(127.0.0.1,23): send b'ls\n'
Telnet(127.0.0.1,23): recv b'ls\r\n'
ls
Telnet(127.0.0.1,23): recv b'Desktop    examples.desktop  Public           snap'
Desktop    examples.desktop  Public           snapTelnet(127.0.0.1,23): recv b'       test'
       testTelnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b'Documents  Music             repos            sour'
Documents  Music             repos            sourTelnet(127.0.0.1,23): recv b'ce     Videos'
ce     VideosTelnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b'Downloads  Pictures          sendslip-in-use  Temp'
Downloads  Pictures          sendslip-in-use  TempTelnet(127.0.0.1,23): recv b'lates'
latesTelnet(127.0.0.1,23): recv b'\r\n'

Telnet(127.0.0.1,23): recv b'xinlin@ubuntu:~$ '
xinlin@ubuntu:~$
Telnet(127.0.0.1,23): send b'\n'
Telnet(127.0.0.1,23): recv b'\r\nxinlin@ubuntu:~$ '

xinlin@ubuntu:~$
Telnet(127.0.0.1,23): send b'\n'
Telnet(127.0.0.1,23): recv b'\r\nxinlin@ubuntu:~$ '

xinlin@ubuntu:~$ exit
Telnet(127.0.0.1,23): send b'exit\n'
Telnet(127.0.0.1,23): recv b'exit\r\nlogout\r\n'
exit
logout
Telnet(127.0.0.1,23): recv b''
*** Connection closed by remote host ***
>>> tn.close()

这段代码,我使用了 open() 函数,这时另一种连接方式。在interact之前,还调用了 set_debuglevel() 函数,这个函数默认的参数时0,以上代码使用的是1,就将交互过程的信息都打印出来了。可以看到来回交互的都是byte stream。最后,使用 exit 退出(exit退出的其实是telnet服务器打开的bash,bash一旦退出,telnet连接就自动中断)。

与telnet服务器自动化交互

自动化交互才是我们使用telnetlib模块的最主要的原因。

下面这段代码示例,功能是自动登录服务器,切换到根目录(/),并拿到根目录的ll -h命令的打印结果后,终端连接:

>>> tn = Telnet('127.0.0.1')
>>> tn.read_until(b'login:')  # tn.read_until(b'login:',timeout=2)
b'Ubuntu 18.04.2 LTS\r\nubuntu login:'
>>> tn.write(b'xinlin\n')
>>> tn.read_until(b'Password:')
b' Password:'
>>> tn.write(b'123456\n')
>>> tn.read_until(b'xinlin@ubuntu:~$')
b' \r\nLast login: Sat Jul 27 10:48:31 CST 2019 from localhost on pts/2\r\nWelcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.18.0-25-generic x86_64)\r\n\r\n * Documentation:  https://help.ubuntu.com\r\n * Management:     https://landscape.canonical.com\r\n * Support:        https://ubuntu.com/advantage\r\n\r\n\r\n * Canonical Livepatch is available for installation.\r\n   - Reduce system reboots and improve kernel security. Activate at:\r\n     https://ubuntu.com/livepatch\r\n\r\n233 packages can be updated.\r\n1 update is a security update.\r\n\r\nxinlin@ubuntu:~$'
>>> tn.write(b'cd /\n')
>>> tn.read_until(b'xinlin@ubuntu:/$')
b' xinlin@ubuntu:/$'
>>> tn.write(b'll -h\n')
>>> result = tn.read_until(b'xinlin@ubuntu:/$')
>>> tn.close()
>>> print(result.decode())
 total 1.9G
drwxr-xr-x  24 root root 4.0K Jul  1 10:33 ./
drwxr-xr-x  24 root root 4.0K Jul  1 10:33 ../
drwxr-xr-x   2 root root 4.0K Jul 25 19:14 bin/
drwxr-xr-x   3 root root 4.0K Jul  2 06:43 boot/
drwxrwxr-x   2 root root 4.0K Jun 11 15:31 cdrom/
drwxr-xr-x  18 root root 4.2K Jul 26 12:35 dev/
drwxr-xr-x 125 root root  12K Jul 22 15:15 etc/
drwxr-xr-x   4 root root 4.0K Jul 15 13:44 home/
lrwxrwxrwx   1 root root   33 Jul  1 10:33 initrd.img -> boot/initrd.img-4.18.0-25-generic
lrwxrwxrwx   1 root root   33 Jul  1 10:33 initrd.img.old -> boot/initrd.img-4.18.0-24-generic
drwxr-xr-x  21 root root 4.0K Jun 11 15:48 lib/
drwxr-xr-x   2 root root 4.0K Feb 10 08:12 lib64/
drwx------   2 root root  16K Jun 11 15:29 lost+found/
drwxr-xr-x   4 root root 4.0K Jul  9 14:25 media/
drwxr-xr-x   2 root root 4.0K Feb 10 08:12 mnt/
drwxr-xr-x   2 root root 4.0K Jun 11 15:51 opt/
dr-xr-xr-x 296 root root    0 Jul 26 12:34 proc/
drwx------   5 root root 4.0K Jul 15 14:34 root/
drwxr-xr-x  28 root root  880 Jul 27 10:59 run/
drwxr-xr-x   2 root root  12K Jul 25 19:14 sbin/
drwxr-xr-x  16 root root 4.0K Jun 24 20:48 snap/
drwxr-xr-x   2 root root 4.0K Feb 10 08:12 srv/
-rw-------   1 root root 1.9G Jun 11 15:29 swapfile
dr-xr-xr-x  13 root root    0 Jul 26 12:34 sys/
drwxrwxrwt  16 root root 4.0K Jul 27 10:34 tmp/
drwxr-xr-x  10 root root 4.0K Feb 10 08:12 usr/
drwxr-xr-x  14 root root 4.0K Feb 10 08:20 var/
lrwxrwxrwx   1 root root   30 Jul  1 10:33 vmlinuz -> boot/vmlinuz-4.18.0-25-generic
lrwxrwxrwx   1 root root   30 Jul  1 10:33 vmlinuz.old -> boot/vmlinuz-4.18.0-24-generic
xinlin@ubuntu:/$
>>>

在创建Telnet对象的时候连接服务器,然后一路都是 read_until()write() 函数,这个过程就是在进行自动化交互。read_until() 函数还有一个timeout参数,以防止死等,超时后,如果telnet连接没有中断,就没有异常,只是将所有队列中的数据全部读出来:

>>> tn = Telnet('127.0.0.1')
>>> tn.read_until(b'LOGIN:',timeout=1)
b'Ubuntu 18.04.2 LTS\r\nubuntu login: '
>>> tn.write(b'xinlin\n')
>>> tn.read_until(b'LOGIN:',timeout=1)
b'Password: '
>>> tn.write(b'123456\n')
>>> tn.read_until(b'LOGIN:',timeout=1)
b'\r\nLast login: Sat Jul 27 10:59:32 CST 2019 from localhost on pts/2\r\nWelcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.18.0-25-generic x86_64)\r\n\r\n * Documentation:  https://help.ubuntu.com\r\n * Management:     https://landscape.canonical.com\r\n * Support:        https://ubuntu.com/advantage\r\n\r\n\r\n * Canonical Livepatch is available for installation.\r\n   - Reduce system reboots and improve kernel security. Activate at:\r\n     https://ubuntu.com/livepatch\r\n\r\n233 packages can be updated.\r\n1 update is a security update.\r\n\r\nxinlin@ubuntu:~$ '
>>> tn.write(b'll -h /\n')
>>> result = tn.read_until(b'LOGIN:',timeout=1)
>>> tn.close()
>>> print(result.decode())
total 1.9G
drwxr-xr-x  24 root root 4.0K Jul  1 10:33 ./
drwxr-xr-x  24 root root 4.0K Jul  1 10:33 ../
drwxr-xr-x   2 root root 4.0K Jul 25 19:14 bin/
drwxr-xr-x   3 root root 4.0K Jul  2 06:43 boot/
drwxrwxr-x   2 root root 4.0K Jun 11 15:31 cdrom/
drwxr-xr-x  18 root root 4.2K Jul 26 12:35 dev/
drwxr-xr-x 125 root root  12K Jul 22 15:15 etc/
drwxr-xr-x   4 root root 4.0K Jul 15 13:44 home/
lrwxrwxrwx   1 root root   33 Jul  1 10:33 initrd.img -> boot/initrd.img-4.18.0-25-generic
lrwxrwxrwx   1 root root   33 Jul  1 10:33 initrd.img.old -> boot/initrd.img-4.18.0-24-generic
drwxr-xr-x  21 root root 4.0K Jun 11 15:48 lib/
drwxr-xr-x   2 root root 4.0K Feb 10 08:12 lib64/
drwx------   2 root root  16K Jun 11 15:29 lost+found/
drwxr-xr-x   4 root root 4.0K Jul  9 14:25 media/
drwxr-xr-x   2 root root 4.0K Feb 10 08:12 mnt/
drwxr-xr-x   2 root root 4.0K Jun 11 15:51 opt/
dr-xr-xr-x 296 root root    0 Jul 26 12:34 proc/
drwx------   5 root root 4.0K Jul 15 14:34 root/
drwxr-xr-x  28 root root  880 Jul 27 11:18 run/
drwxr-xr-x   2 root root  12K Jul 25 19:14 sbin/
drwxr-xr-x  16 root root 4.0K Jun 24 20:48 snap/
drwxr-xr-x   2 root root 4.0K Feb 10 08:12 srv/
-rw-------   1 root root 1.9G Jun 11 15:29 swapfile
dr-xr-xr-x  13 root root    0 Jul 27 11:00 sys/
drwxrwxrwt  16 root root 4.0K Jul 27 10:34 tmp/
drwxr-xr-x  10 root root 4.0K Feb 10 08:12 usr/
drwxr-xr-x  14 root root 4.0K Feb 10 08:20 var/
lrwxrwxrwx   1 root root   30 Jul  1 10:33 vmlinuz -> boot/vmlinuz-4.18.0-25-generic
lrwxrwxrwx   1 root root   30 Jul  1 10:33 vmlinuz.old -> boot/vmlinuz-4.18.0-24-generic
xinlin@ubuntu:~$
>>>

以上代码,一直在 read_until 函数中使用一个错误的字符串,所有函数从来都等不到它想要的,只能等到超时,然后读取所有能读到的内容。

除了 read_until 函数,还有一个 read_all() 函数,我们在下面的示例代码中体会它的用法:

>>> tn = Telnet('127.0.0.1')
>>> tn.read_until(b'login:')
b'Ubuntu 18.04.2 LTS\r\nubuntu login:'
>>> tn.write('xinlin'.encode('ascii')+b'\n')
>>> tn.read_until(b'Password:')
b' Password:'
>>> tn.write('123456'.encode('ascii')+b'\n')
>>>
>>> tn.write('ls'.encode('ascii')+b'\n')
>>> tn.write('logout'.encode('ascii')+b'\n')
>>> print(tn.read_all().decode())

Last login: Sat Jul 27 11:18:33 CST 2019 from localhost on pts/2
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.18.0-25-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage


 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:
     https://ubuntu.com/livepatch

233 packages can be updated.
1 update is a security update.

xinlin@ubuntu:~$ Desktop    examples.desktop  Public           snap       test
Documents  Music             repos            source     Videos
Downloads  Pictures          sendslip-in-use  Templates
xinlin@ubuntu:~$
>>>

以上代码换了一中对write参数的写法,使用了字符串对象的encode函数。在输入密码登录后,连续输入了两个shell命令,ls和logout,然后通过 read_all() 函数,一把全部读出来。注意:读出来的这一大堆字符串里面,没有我们输入的命令字符串。

关于telnetlib模块的使用,本文的内容应该基本够用了。不过还有一些read_*函数,还有一个expect函数可以通过正则表达式来判断字符串是否是需要的,这些内容,请参考Python官方的说明:https://docs.python.org/3/library/telnetlib.html

-- EOF --

本文链接:https://www.pynote.net/archives/649

相关文章

    留言区

    电子邮件地址不会被公开。 必填项已用*标注


    前一篇:
    后一篇:

    More


    ©Copyright 麦新杰 Since 2019 Python笔记

    go to top