专栏名称: Python开发者
人生苦短,我用 Python。伯乐在线旗下账号「Python开发者」分享 Python 相关的技术文章、工具资源、精选课程、热点资讯等。
目录
相关文章推荐
Python爱好者社区  ·  124个Python案例,完整源代码! ·  2 天前  
Python中文社区  ·  牛市开户不需要找关系,找我就行! ·  6 天前  
Python爱好者社区  ·  这可能是中国最“恨”地铁的高校,甚至写了篇论 ... ·  3 天前  
Python爱好者社区  ·  应届生炒到66.8w年薪,真心建议冲冲这个新 ... ·  1 周前  
Python中文社区  ·  狂暴大牛市该买点啥?用量化选股抓住机会 ·  1 周前  
51好读  ›  专栏  ›  Python开发者

ShutIt:一个基于 Python 的 shell 自动化框架

Python开发者  · 公众号  · Python  · 2017-06-22 20:03

正文

(点击上方蓝字,快速关注我们)


编译:雁惊寒  英文:ShutIt 

www.iteye.com/news/32482

如有好文章投稿,请点击 → 这里了解详情


译者注:本文通过实例简单介绍了ShutIt这个基于Python的自动化框架的使用方法。除了pexpect,我们又多了这个选择。以下是译文。


ShutIt是一个易于使用的基于shell的自动化框架。它对基于python的expect库(pexpect)进行了包装。你可以把它看作是“没有痛点的expect”。它可以通过pip进行安装。


Hello World


让我们从最简单的例子开始吧。创建一个名为example.py的文件:


import shutit  

session = shutit.create_session('bash')  

session.send('echo Hello World', echo=True)


运行这个文件:


python example.py


输出:


python example.py  

echo "Hello World"  

echo "Hello World"  

Hello World  

Ians-MacBook-Air.local:ORIGIN_ENV:RhuebR2T#


“send”函数的第一个参数是要运行的命令。“echo”的参数将会输出到终端上。默认情况下,ShutIt是静默的。


登录服务器


如果你要登陆一台服务器并执行服务器上的命令。可以将example.py改为:


import shutit  

session = shutit.create_session('bash')  

session.login('ssh [email protected]', user='you', password='mypassword')  

session.send('hostname', echo=True)  

session.logout()


程序将登录到这台服务器上,并输出主机名。


hostname  

hostname  

example.com  

example.com:cgoIsdVv:heDa77HB#


显然,这很不安全!你可以这样运行:


import shutit  

session = shutit.create_session('bash')  

password = session.get_input('', ispass=True)  

session.login('ssh [email protected]', user='you', password=password)  

session.send('hostname', echo=True)  

session.logout()


它会让你输入密码:


Input Secret:  

hostname  

hostname  

example.com  

example.com:cgoIsdVv:heDa77HB#


同样的,“login”方法在登录后改变了提示符。你给了ShutIt一个登录命令,并附带用户名和密码(如果需要的话),然后,ShutIt会完成剩余的事情。


“logout”负责终止“login”,并向屏幕输出发生的任何变化。


登录到多台服务器


假设你有一个集群包含两台服务器,并希望同时登录到这两个服务器上去。则只需要创建两个会话,并运行类似的login和send命令:


import shutit  

session1 = shutit.create_session('bash')  

session2 = shutit.create_session('bash')  

password1 = session1.get_input('Password for server1', ispass=True)  

password2 = session2.get_input('Password for server2', ispass=True)  

session1.login('ssh [email protected]', user='you', password=password1)  

session2.login('ssh [email protected]', user='you', password=password2)  

session1.send('hostname', echo=True)  

session2.send('hostname', echo=True)  

session1.logout()  

session2.logout()


将输出这样的结果:


$ python example.py  

Password for server1  

Input Secret:  

  

Password for server2  

Input Secret:  

hostname  

hostname  

one.example.com  

one.example.com:Fnh2pyFj:qkrsmUNs# hostname  

hostname  

two.example.com  

two.example.com:Gl2lldEo:D3FavQjA#


实例:监控多台服务器


我们可以通过添加一些代码逻辑来检查命令的输出,从而将上述代码变成一个简单的监控工具:


import shutit  

capacity_command="""df / | awk '{print $5}' | tail -1 | sed s/[^0-9]//"""  

session1 = shutit.create_session('bash')  

session2 = shutit.create_session('bash')  

password1 = session.get_input('Password for server1', ispass=True)  

password2 = session.get_input('Password for server2', ispass=True)  

session1.login('ssh [email protected]', user='you', password=password1)  

session2.login('ssh [email protected]', user='you', password=password2)  

capacity = session1.send_and_get_output(capacity_command)  

if int(capacity) < 10:  

    print('RUNNING OUT OF SPACE ON server1!')  

capacity = session2.send_and_get_output(capacity_command)  

if int(capacity) < 10:  

    print('RUNNING OUT OF SPACE ON server2!')  

session1.logout()  

session2.logout()


在这里,我们用了“sendandget_output”方法来获取capacity_command命令的输出。


还有很多更加优雅的方法可以完成上面的操作,但这取决于你想要Python有多聪明。


更复杂的IO – Expecting


假设你需要跟一个命令行程序进行交互,并且要实现自动化操作。在这里,我们使用telnet来举一个简单的例子:


import shutit  

session = shutit.create_session('bash')  

session.send('telnet', expect='elnet>', echo=True)  

session.send('open google.com 80', expect='scape character', echo=True)  

session.send('GET /', echo=True, check_exit=False)  

session.logout()


注意“expect”的参数。你只需要给出telnet提示符的一个子集来进行匹配。


注意“check_exit”的参数,后面我们会讲到这个参数的。上面这段代码将输出:


$ python example.py  

telnet  

telnet> open google.com 80  

Trying 216.58.214.14...  

Connected to google.com.  

Escape character is '^]'.  

GET /  

HTTP/1.0 302 Found  

Cache-Control: private  

Content-Type: text/html; charset=UTF-8  

Referrer-Policy: no-referrer  

Location: http://www.google.co.uk/?gfe_rd=cr&ei=huczWcj3GfTW8gfq0paQDA  

Content-Length: 261  

Date: Sun, 04 Jun 2017 10:57:10 GMT  

  

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">  

<TITLE>302 MovedTITLE>HEAD><BODY>  

<H1>302 MovedH1>  

The document has moved  

<A HREF="http://www.google.co.uk/?gfe_rd=cr&ei=huczWcj3GfTW8gfq0paQDA">  

here  

A>.  

BODY>HTML>  

Connection closed by foreign host.


现在回到“checkexit = false”上来。由于telnet命令会返回一个错误的退出码(1),我们不想让脚本执行失败,这里的“checkexit = false”能让ShutIt知道你并不关注这个退出码。


如果你没有传入这个参数,ShutIt会给你一个交互式的提示,如果你有终端接入的话。这被称为“暂停点”。


暂停点


你可以随便在什么时候通过调用以下方法来设置一个“暂停点”。


[...]  

session.pause_point('This is a pause point')  

[...]


当脚本运行到暂停点时,同时按下“Ctrl”和“]”,则可以让脚本继续执行。这对于调试非常有用:添加一个暂停点,看看周围,然后继续。试试这个:


import shutit  

session = shutit.create_session('bash')  

session.pause_point('Have a look around!')  

session.send('echo "Did you enjoy your pause point?"', echo=True)


程序输出:


$ python example.py  

Have a look around!  

Ians-Air.home:ORIGIN_ENV:I00LA1Mq#  bash  

imiell@Ians-Air:/space/git/shutit   master +      

CTRL-] caught, continuing with run...  

2017-06-05 15:12:33,577 INFO: Sending:  exit  

2017-06-05 15:12:33,633 INFO: Output (squashed):  exitexitIans-Air.home:ORIGIN_ENV:I00LA1Mq#  [...]  

echo "Did you enjoy your pause point?"  

echo "Did you enjoy your pause point?"  

Did you enjoy your pause point?  

Ians-Air.home:ORIGIN_ENV:I00LA1Mq#


更复杂的IO – Backgrounding


回到我们上面的“监控多台服务器”的例子上来。想象一下,我们要在每台服务器上运行一个长时间运行的任务。默认情况下,ShutIt会持续运行很长时间。但是我们可以在后台运行任务来加快ShutIt的运行速度。


在这里,你可以使用简单的命令“sleep 60”来尝试一个例子。


import shutit  

import time  

long_command="""sleep 60"""  

session1 = shutit.create_session('bash')  

session2 = shutit.create_session('bash')  

password1 = session1.get_input('Password for server1', ispass=True)  

password2 = session2.get_input('Password for server2', ispass=True)  

session1.login('ssh [email protected]', user='you', password=password1)  

session2.login('ssh [email protected]', user='you', password=password2)  

start = time.time()  

session1.send(long_command, background=True)  

session2.send(long_command, background=True)  

print('That took: ' + str(time.time() - start) + ' seconds to fire')  

session1.wait()  

session2.wait()  

print('That took: ' + str(time.time() - start) + ' seconds to complete')


我的笔记本电脑说,运行这两个命令只需花费0.5秒,而脚本在一分钟以后才运行结束(使用了’wait’方法)。


虽然这个例子看起来是微不足道的,但是想像一下,如果你有数百台这样的服务器需要管理,那么你可以看到这几行代码和一个python import所带来的强大的力量。


更多信息


ShutIt可以做很多事。更多信息,请参阅:


  • ShutIt (https://ianmiell.github.io/shutit/)

  • GitHub (https://github.com/ianmiell/shutit/blob/master/README.md)


看完本文有收获?请转发分享给更多人

关注「Python开发者」,提升Python技能