程序员瑞士军刀之 Fabric
EdgarTroutm
8年前
<p>Fabric是一个Python库, 也是一个命令行工具, 通过 SSH 来做应用程序的部署和系统管理任务</p> <p>它可以执行本地的远程的系统命令, 上传下载文件, 以及其他能用Python编程完成的任务</p> <p>其实它一个工具框架, 执行一个默认的 python 文件 fabfile.py</p> <p>简单写个小例子</p> <pre> <code class="language-python">$vi fabfile from fabric.api import * env.hosts = ['10.224.64.106'] env.user = "root" env.password = "pass" def freedisk(param='-h'): cmd = 'df ' + param run(cmd) def listfile(folder='~'): cmd = 'ls -l ' + folder run(cmd) def pullcodes(folder='/workspace/cpp/snippets'): with cd(folder): run("git pull origin master") # 察看远程服务器上的磁盘剩余空间 $ fab listfile:folder=/home/walter</code></pre> <ul> <li> <p><strong>为安全起见, 不用在文件中存放密码, 在命令行提示输入</strong></p> <p>$ fab -u root -I -H 10.224.64.106 freedisk</p> </li> <li> <p><strong>更好的做法是把本机私钥预先拷贝到目标服务器上, 这样就不用输入密码了</strong></p> </li> </ul> <pre> <code class="language-python">1. 在本机上生成公钥 ~/.ssh/id_rsa.pub ssh-keygen -t rsa 2. 拷贝此公钥到目标服务器 10.224.64.106 上 scp id_rs.pub root@10.224.64.106:/root 3. 目标服务器 10.224.64.106 上 cat id_rsa.pub >> ~/.ssh/authorized_keys chmod 700 ~/.ssh/authorized_keys</code></pre> <h2><strong>常用方法</strong></h2> <ul> <li>run (fabric.operations.run)</li> <li>sudo (fabric.operations.sudo)</li> <li>local (fabric.operations.local)</li> <li>get (fabric.operations.get)</li> <li>put (fabric.operations.put)</li> <li>prompt (fabric.operations.prompt)</li> <li>reboot (fabric.operations.reboot)</li> </ul> <h2><strong>常用函数</strong></h2> <ul> <li>cd (fabric.context_managers.cd)</li> <li>lcd (fabric.context_managers.lcd)</li> <li>path (fabric.context_managers.path)</li> <li>settings (fabric.context_managers.settings)</li> <li>prefix (fabric.context_managers.prefix)</li> </ul> <h2><strong>例子:批量上传下载文件</strong></h2> <pre> <code class="language-python">from fabric.api import * from fabric.context_managers import * from fabric.contrib.console import confirm env.user='root' env.hosts=['10.224.64.106'] env.passwords = { 'root@10.224.64.106:22': 'password' } local_dir='/workspace/cpp/codelab' remote_dir = '/home/walter/cpp/codelab' file_list = [ 'src/FileUtils.cpp', 'src/FileUtils.h', 'src/Makefile.am', 'src/StringUtils.cpp' ] @task def hostinfo(): run('uname -s') @task def upload(): #upload file task with cd(remote_dir) : for filename in file_list: local_file = local_dir + "/" + filename remote_file = remote_dir + "/" + filename #print local_file, " to ", remote_file with settings(warn_only=True): #when upload error,continue result = put(local_file, remote_file) if result.failed and not confirm("put file failed,Continue[Y/N]?"): abort("Aborting file put task!") @task def download(): #upload file task with cd(remote_dir) : for filename in file_list: local_file = local_dir + "/" + filename remote_file = remote_dir + "/" + filename #print local_file, " to ", remote_file with settings(warn_only=True): #when upload error,continue result = get(remote_file,local_file) if result.failed and not confirm("put file failed,Continue[Y/N]?"): abort("Aborting file put task!")</code></pre> <h2><strong>高阶用法</strong></h2> <p>设置角色role来指定远程的服务器范围</p> <p>或者直接用字典由输入参数指定, 例如:</p> <pre> <code class="language-python"># usage: # fab localpull:rtc # fab checkfiles:hf2 from fabric.api import * from fabric.context_managers import * from fabric.contrib.console import confirm env.user = 'root' env.roledefs = { 'qa': ['root@10.224.57.202:22'], 'dev': ['root@10.224.64.106:22'] } env.passwords = { 'root@10.224.57.202:22': 'pass', 'root@10.224.64.106:22': 'pass', 'root@10.224.64.107:22': 'pass' } @roles('dev') @task def localpull(app='web'): if app == 'web': code_dir = '/workspace/walter/hfweb' with lcd(code_dir): local("git pull origin master") elif app == 'rtc': code_dir = '/workspace/walter/hfrtc' with lcd(code_dir): local("git pull origin master") local("git branch -l") test_servers = {'hf1':['root@10.224.64.46:22'], 'hf2':['root@10.224.64.106:22'], 'hf3':['root@10.224.64.107:22']} @task def listfiles(): run("ls -l") @task def checkfiles(target_env='hf2'): execute("listfiles", hosts=test_servers[target_env])</code></pre> <h2><strong>FAQ</strong></h2> <h3><strong>问题: fab put error: paramiko.ssh_exception.SSHException: Channel closed</strong></h3> <p><strong>解决方法:</strong></p> <ul> <li> <p>编辑 /etc/ssh/sshd_config:</p> <pre> <code class="language-python">vi /etc/ssh/sshd_config</code></pre> </li> <li> <p>加上一行 Subsystem sftp internal-sftp</p> <pre> <code class="language-python">Port 22 Protocol 2 LogLevel INFO X11Forwarding no MaxAuthTries 4 IgnoreRhosts yes HostbasedAuthentication no PermitRootLogin yes PermitEmptyPasswords no PermitUserEnvironment no Ciphers aes128-ctr,aes192-ctr,aes256-ctr ClientAliveInterval 600 Banner /etc/issue Subsystem sftp internal-sftp</code></pre> </li> <li> <p>保存并重启 SSH server:</p> <p>service sshd restart</p> </li> </ul> <h2>参考链接</h2> <ul> <li><a href="/misc/goto?guid=4959714921568510922" rel="nofollow,noindex">Fabric site</a></li> <li><a href="/misc/goto?guid=4959622156502828506" rel="nofollow,noindex">Fabric Tutorial</a></li> <li><a href="/misc/goto?guid=4959714921721521680" rel="nofollow,noindex">Fabric options</a></li> </ul> <p> </p> <p> </p> <p>来自:http://www.jianshu.com/p/e7623533e886</p> <p> </p>