Paramiko 学习笔记

之前学 Paramiko 学完就没怎么用过,后来就去使用 Ansible 和 Saltstack 了。最近突然要写一个自动部署的工具,要求在本地打包然后上传服务器,我就又想起了 Paramiko。这东西好用是好用,但是每次执行 Shell 命令,如果不需要打印输出的话就会在指定时间后中断操作,于是还得想点骚操作让它执行完,这就有点难受了。

基本操作

  1. 初始化 SSH 和 SFTP
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    transport = paramiko.Transport((ipaddr, int(loginPort)))
    transport.connect(username=username, password=password)
    ssh = paramiko.SSHClient()
    ssh._transport = transport
    sftp = paramiko.SFTPClient.from_transport(transport)
    
  2. 远程执行命令
    stdin, stdout, stderr = ssh.exec_command("chmod +x *.sh && nohup ./deploy.sh >> deploy.log 2>&1 &")
    
  3. 上传与下载文件
    • 上传文件
    def sftp_upload_file(server_path, local_path):
     try:
         t = paramiko.Transport((ip, 22))
         t.connect(username=user, password=pwd)
         sftp = paramiko.SFTPClient.from_transport(t)
         sftp.put(local_path, server_path)
         t.close()
     except Exception as  e:
         print(e)
    
    • 下载文件
    def sftp_down_file(server_path, local_path):
     try:
         t = paramiko.Transport((ip, 22))
         t.connect(username=user, password=pwd)
         sftp = paramiko.SFTPClient.from_transport(t)
         sftp.get(server_path, local_path)
         t.close()
     except Exception as e:
         print(e)
    

示例

  1. 若当前登录用户不为 Root ,则将当前用户密码设置为 Root 密码
    # If the login user is not root, the login permission and password will be changed.
    if (username != 'root'):
     # Modify the Root password to be the same as the current user. It will be stand alone later.
     stdin, stdout, stderr = ssh.exec_command( \
     '''echo '{CPASSWD}' | sudo -S sh -c "echo '{CPASSWD}' | sudo -S passwd --stdin root" >> execlog.log 2>&1 '''
     .format(CPASSWD=password))
    
     stdin, stdout, stderr = ssh.exec_command( \
     '''echo '{CPASSWD}' | sudo -S sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin kafka/g' /etc/ssh/sshd_config && echo '{CPASSWD}' | sudo -S sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication kafka/g' /etc/ssh/sshd_config'''
     .format(CPASSWD=password))
    
  2. 上传整个文件夹
    def put_all(self,localpath,remotepath):
         #  recursively upload a full directory
         os.chdir(os.path.split(localpath)[0])
         parent=os.path.split(localpath)[1]
         for walker in os.walk(parent):
             try:
                 self.sftp.mkdir(os.path.join(remotepath,walker[0]))
             except:
                 pass
             for file in walker[2]:
                 self.put(os.path.join(walker[0],file),os.path.join(remotepath,walker[0],file))
    
  3. 下载整个文件夹
    def get_all(self,remotepath,localpath):
         #  recursively download a full directory
         #  Harder than it sounded at first, since paramiko won't walk
         #
         # For the record, something like this would gennerally be faster:
         # ssh user@host 'tar -cz /source/folder' | tar -xz
    
         self.sftp.chdir(os.path.split(remotepath)[0])
         parent=os.path.split(remotepath)[1]
         try:
             os.mkdir(localpath)
         except:
             pass
         for walker in self.sftp_walk(parent):
             try:
                 os.mkdir(os.path.join(localpath,walker[0]))
             except:
                 pass
             for file in walker[2]:
                 self.get(os.path.join(walker[0],file),os.path.join(localpath,walker[0],file))
    
  4. Python 中 os.system 和 os.popen 区别
    • os.system()的返回值只会有0(成功),1,2;
    • os.popen()会把执行命令的输出作为值返回,可实现一个“管道”,从这个命令获取的值可以继续被调用。

参考资料

评论