程序员瑞士军刀之 Fabric

EdgarTroutm 7年前
   <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>