fabric2.0 使用說明
fabric框架腰懂,主要的目的就是用來遠(yuǎn)程自動化部署项秉。在最近,作者將fabric框架重寫了一遍怖喻,升級到了2.0版本岁诉。在我學(xué)習(xí)過程中,遇到了不少的坑哗蜈,最坑的一次就是python編譯器老是給我提示,fabric 導(dǎo)入 api失敗候生,沒有fabric.api绽昼。我不斷的懷疑自己是不是腦子瓦特了的時候须蜗,我pip list 查看了一下版本明肮,再看了一下github版本。
我謝謝作者嘔心瀝血的更新框架循未。
本說明秫舌,結(jié)合官方文檔,使用效果更佳嫂粟。
安裝
pip install fabric
查看一下pip安裝fabric的版本號:
fabric 2.1.3
一切OK墨缘,開始練習(xí)镊讼。
初步的使用
準(zhǔn)備兩臺機(jī)器。一個pc护糖,一個虛機(jī)就行嚼松。我的是兩個虛機(jī),ip地址如下:
虛機(jī)1: 192.168.11.11 系統(tǒng):ubuntu
虛機(jī)2: 192.168.11.111 系統(tǒng):centos
確保兩個虛機(jī)都能使用SSH連接寝受。
我的操作都是在(虛機(jī)1)上進(jìn)行罕偎。。甩苛。
from fabric import Connection
In [3]: c = Connection('192.168.11.111', port=22, user='root', connect_kwargs={'password':'1'})
In [4]: result = c.run('uname -s')
Linux
代碼說明:
我們一切的遠(yuǎn)程shell命令的執(zhí)行都是基于Connection來實現(xiàn)的讯蒲。實現(xiàn)的原理,也就是SSH赁酝。
Connection中一些參數(shù):
- host 主機(jī)地址
- port 端口號
- user 用戶名
連接的一些其他參數(shù)都放到connect_kwargs中旭等。我這使用了密碼連接搔耕。(試了半天,查看api手冊才試對)
當(dāng)我們獲取到了Connection對象之后弃榨,我們就可以使用它來進(jìn)行一些命令惭墓。
result是執(zhí)行的結(jié)果,包含了許多屬性值划咐,如下:
In [8]: result.
result.command result.connection result.encoding result.env result.exited result.failed result.hide result.ok result.pty result.return_code result.shell result.stderr result.stdout
關(guān)于c.run()命令:
Connection objects’ methods (like run) usually return instances of invoke.runners.Result (or subclasses thereof) exposing the sorts of details seen above: what was requested, what happened while the remote action occurred, and what the final result was.
-----引用 http://docs.fabfile.org/en/2.1/getting-started.html
也就是 Connection 對象的方法(例如run) 常常返回invoke.runners.Result的實例钧萍,這個實例暴露了一些細(xì)節(jié):
我們請求了什么风瘦,我們遠(yuǎn)程操作發(fā)生了什么,最終的結(jié)果又是什么胡桨。
以上是fabric的初步使用瞬雹。
自動回復(fù)
當(dāng)我們需要sudo操作的權(quán)限的時候酗捌,遠(yuǎn)程服務(wù)器會阻塞在那涌哲,直到我們輸入密碼尚镰,這肯定是不行的。如果這么low初烘,那我們使用這個框架做啥子敞曹?
我們開始試驗:(我centos是root權(quán)限澳迫,所以來個騷操作)
手動輸入版本:
In [13]: c.run('ssh tly@192.168.11.11', pty=True)
The authenticity of host '192.168.11.11 (192.168.11.11)' can't be established.
ECDSA key fingerprint is SHA256:vDOg8wbz0RSFDPGJGEmMc6lT32eR13xW9NxOPxRO2t0.
ECDSA key fingerprint is MD5:f7:77:c8:bf:e0:ba:bd:8b:4d:48:6a:86:f0:3a:dc:31.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.11.11' (ECDSA) to the list of known hosts.
tly@192.168.11.11's password:
Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-130-generic x86_64)
* Documentation: https://help.ubuntu.com/
350 packages can be updated.
0 updates are security updates.
Last login: Wed Jul 11 14:11:36 2018 from 192.200.41.46
tly@tly-dev:~$ exit
logout
Connection to 192.168.11.11 closed.
Out[13]: <Result cmd='ssh tly@192.168.11.11' exited=0>
pty=True橄登,我的理解就是將遠(yuǎn)程終端的stdout輸出到本地讥此。如果不添加會報錯。
上面卒稳,我們連接了192.168.11.111 他巨,然后又用ssh連接到了192.168.11.11(要不是測試染突,我想我腦子瓦特了),之后也榄,命令返回了終端需要我們輸入密碼的字眼司志。我手動的輸入密碼,操作成功囚霸。
自動輸入的版本:
In [14]: from invoke import Responder
In [15]: sudopass = Responder(
....: pattern=r"'s password:",
....: response='1\n',
....: )
In [16]: c.run('ssh tly@192.168.11.11', pty=True, watchers=[sudopass])
tly@192.168.11.11's password:
Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-130-generic x86_64)
* Documentation: https://help.ubuntu.com/
350 packages can be updated.
0 updates are security updates.
Last login: Wed Jul 11 15:11:53 2018 from 192.168.11.111
tly@tly-dev:~$ exit
logout
Connection to 192.168.11.11 closed.
Out[16]: <Result cmd='ssh tly@192.168.11.11' exited=0>
分析如下:
引入了invoke中的Responder庫邮辽。這個庫將用來匹配字符串,并自動回復(fù)吨述。
從終端發(fā)回來的數(shù)據(jù)來看揣云,我們阻塞的地方就是我們需要填寫密碼的地方。即:
tly@192.168.11.11's password:
所以在創(chuàng)建Responder對象的時候刘莹,匹配的字符串就選擇“ 's password:” 來匹配焚刚。
response參數(shù)也就是我們需要自動回復(fù)的文本矿咕。
sudo幫手
我遠(yuǎn)程終端是centos 根用戶運行的。不需要root, 所以我切換到centos下使用fabric捡絮。
使用如下:
In [1]: import getpass
In [3]: sudo_pass = getpass.getpass("What's your sudo password?")
What's your sudo password?
In [5]: from fabric import Config
In [6]: from fabric import Connection
In [7]: sudo_pass = getpass.getpass("What's your sudo password?")
What's your sudo password?
In [8]: config = Config(overrides={'sudo': {'password': sudo_pass}})
In [11]: c = Connection('192.168.11.11', port=22, user='tly', config=config, connect_kwargs={'password':'1'})
In [12]: c.sudo('whoami', hide='stderr')
root
Out[12]: <Result cmd="sudo -S -p '[sudo] password: ' whoami" exited=0>
分析如下:
getpass 只是用來獲取密碼使用的福稳。(私密處理了一下吧)
sudo_pass中就是你輸入的文本值。
傳輸文件
遠(yuǎn)程部署的最常用的命令了吧瑞侮。 (巨坑爹的來了)
命令如下:
In [20]: c
Out[20]: <Connection host=192.168.11.11 user=tly>
In [21]: result = c.put('mysql-rc.yaml', '/home/tly/mysql-rc.yaml')
只要使用put命令就能將文件推送過去了的圆。
參數(shù):
- 為本機(jī)路徑
- 為遠(yuǎn)程路徑
現(xiàn)在這個版本一定要指定遠(yuǎn)程文件名!G凇略板!不然會報錯
本機(jī)默認(rèn)目錄就是你執(zhí)行腳本的目錄。如果要切換怎么辦慈缔?
暫時還沒有找到比較方便的方式叮称。所以先建議使用絕對路徑。
如果只是在本地運行命令藐鹤,可以使用
In [27]: from invoke import run
In [28]: run('ls')
anaconda-ks.cfg
mysql-rc.yaml
test_dir
Out[28]: <Result cmd='ls' exited=0>
如何去配置configure文件瓤檐,官方文檔例子問題太大,看完還是不太明白娱节。