翻译:雁惊寒
译者注:本文通过实例简单介绍了 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 you@example.com', 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 you@example.com', 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 you@one.example.com', user='you', password=password1)
- session2.login('ssh you@two.example.com', 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 you@one.example.com', user='you', password=password1)
- session2.login('ssh you@two.example.com', 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 Moved</TITLE></HEAD><BODY>
- <H1>302 Moved</H1>
- 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)
程序输出:
更复杂的 IO - Backgrounding
- $ 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#
回到我们上面的 "监控多台服务器" 的例子上来。想象一下,我们要在每台服务器上运行一个长时间运行的任务。默认情况下,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 you@one.example.com', user='you', password=password1)
- session2.login('ssh you@two.example.com', 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
- GitHub
来源: http://www.tuicool.com/articles/NrEvYbj