python进行linux远程控制,创建非root用户和上传和下载文件

来源:互联网 发布:淘宝客户回访好评软件 编辑:程序博客网 时间:2024/06/02 05:10
# !/usr/bin/env python
# coding=utf-8
import os
import datetime
import paramiko
import threading


# 定义一个类,表示一台远端linux主机
class Linux(object):
    # 通过IP, 用户名,密码,超时时间初始化一个远程Linux主机
    def __init__(self, ip, username, password, port=22, timeout=30):
        self.ip = ip
        self.port = port
        self.username = username
        self.password = password
        self.timeout = timeout
        # transport和chanel
        self.t = ''
        self.chan = ''
        # 链接失败的重试次数
        self.try_times = 3


    # 调用该方法连接远程主机
    def create_sshclient(self, myusername, mypasswd):
        sshclient = paramiko.SSHClient() # 得到一个连接的对象
        sshclient.load_system_host_keys()
        sshclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        while True:
            # 连接过程中可能会抛出异常,比如网络不通、链接超时
            try:
                # 连接服务器
                sshclient.connect(hostname=self.ip, port=self.port, username=myusername, password=mypasswd)
                return sshclient
            except Exception:
                if self.try_times != 0:
                    print u'连接%s失败,进行重试' % self.ip
                    self.try_times -= 1
                else:
                    print u'重试3次失败,结束程序'
                    exit(1)


    # 断开连接
    def close(self):
        if self.chan:
            self.chan.close()
        if self.t:
            self.t.close()


    def exec_cmd(self, mysshclient, cmd):
        return mysshclient.exec_command(cmd)


    def create_user(self, mysshclient, new_username, new_passwd, salt='any_str_here'):
        # 如创建用户名为user的用户,并设置密码为123456
        # 其命令为:'useradd -p `openssl passwd -1 -salt "somesalt" 123456` user'
        # somesalt为任意字符串
        cmd = 'useradd -p `openssl passwd -1 -salt \"' + salt + '\" ' + new_passwd + '` ' + new_username
        print '添加用户 %s 的命令为: %s' % (new_username, cmd)
        self.exec_cmd(mysshclient, cmd)


    # get单个文件
    def sftp_get(self, remotefile, localfile):
        self.t = paramiko.Transport(sock=(self.ip, self.port))
        self.t.connect(username=self.username, password=self.password)
        sftp = paramiko.SFTPClient.from_transport(self.t)
        sftp.get(remotefile, localfile)
        self.t.close()
        
    # put单个文件
    def sftp_put(self, localfile, remotefile):
        self.t = paramiko.Transport(sock=(self.ip, self.port))
        self.t.connect(username=self.username, password=self.password)
        sftp = paramiko.SFTPClient.from_transport(self.t)
        sftp.put(localfile, remotefile)
        self.t.close()


def winpath2linuxpath(winpath):
    return winpath.replace('\\', '/')


def linuxpath2winpath(linuxpath):
    return linuxpath.replace('/', '\\')


def isdir(sftp, filename):
    try:
        sftp.listdir(filename)
        return True
    except Exception:
        return False


class Upload_thread(threading.Thread):
    def __init__(self, hostname, username, password, local_dir, remote_dir, port=22):
        threading.Thread.__init__(self)
        self.hostname = hostname
        self.username = username
        self.password = password
        self.local_dir =  local_dir
        self.remote_dir =  remote_dir
        self.port = port


    def run(self):
        try:
            t = paramiko.Transport((self.hostname, self.port))
            t.connect(username=self.username, password=self.password)
            sftp = paramiko.SFTPClient.from_transport(t)
            print 'upload file start %s ' % datetime.datetime.now()
            for root, dirs, files in os.walk(self.local_dir):
                for name in dirs:
                    remote_path = os.path.join(self.remote_dir, name)
                    # 远端为Linux系统,故将路径中的'\'转换为'/'
                    remote_path = winpath2linuxpath(remote_path)
                    try:
                        sftp.mkdir(remote_path)
                        print "mkdir path %s" % remote_path
                    except Exception, e:
                        print e
                for filespath in files:
                    local_file = os.path.join(root, filespath)
                    # 本地为Windows系统,故将路径中的'/'转换为'\'
                    local_file = linuxpath2winpath(local_file)
                    # 将local_file中等于local_dir的部分替换为remote_dir,以此作为remote_file,即作为上传到服务器的目录
                    remote_file = local_file.replace(linuxpath2winpath(self.local_dir), linuxpath2winpath(self.remote_dir))
                    remote_file = winpath2linuxpath(remote_file)
                    try:
                        sftp.put(local_file, remote_file)
                        pass
                    except Exception, e:
                        sftp.mkdir(os.path.split(remote_file)[0])
                        sftp.put(local_file, remote_file)
                        pass
                    print "upload %s to remote %s" % (local_file, remote_file)
            print 'upload file success %s ' % datetime.datetime.now()
            t.close()
        except Exception, e:
            print e


class Download_thread(threading.Thread):
    def __init__(self, hostname, username, password, local_dir, remote_dir, port=22):
        threading.Thread.__init__(self)
        self.hostname = hostname
        self.username = username
        self.password = password
        self.local_dir =  local_dir
        self.remote_dir =  remote_dir
        self.port = port


    def download_dir(self, sftp, remote_dir_param):
        files = sftp.listdir(remote_dir_param)
        print files
        for file_one in files:
            remote_path = os.path.join(remote_dir_param, file_one)
            remote_path = winpath2linuxpath(remote_path)
            if isdir(sftp, remote_path): 
                files2 = sftp.listdir(remote_path)
                print files2
                new_dir = remote_path.replace(winpath2linuxpath(remote_dir_param), winpath2linuxpath(self.local_dir))
                new_dir = linuxpath2winpath(new_dir)
                if not (os.path.exists(new_dir)):
                    os.mkdir(new_dir)
                self.download_dir(sftp, remote_path)
            else:
                print 'download %s' % remote_path
                local_path = remote_path.replace(winpath2linuxpath(self.remote_dir), winpath2linuxpath(self.local_dir))
                local_path = linuxpath2winpath(local_path)
                sftp.get(remote_path, local_path)


    def run(self):
        try: 
            transport = paramiko.Transport((self.hostname, self.port))
            transport.connect(username=self.username, password=self.password)          
            sftp = paramiko.SFTPClient.from_transport(transport)  
            
            print 'download beginning'
            self.download_dir(sftp, self.remote_dir)
            print 'download end'
        except Exception:
            print "error..."




        
if __name__ == '__main__':
    hostname = '10.9.46.118'
    username = 'root'
    password = '123456'
    
    test_adduser = True
    # 测试创建新用户
    if test_adduser:
        host = Linux(hostname, username, password)
        # 获取一个ssh连接客户端对象,这里使用root用户获取,用来创建非root用户
        sshclient = host.create_sshclient('root', '123456')
        if sshclient:
            # 创建用户名为user密码为123456的非root用户
            host.create_user(sshclient, 'user', '123456')
        # 使用刚创建的非root用户登录
        sshclient = host.create_sshclient('user', '123456')
        # 测试是否连接成功
        if sshclient:
            stdin, stdout, stderr = host.exec_cmd(sshclient, 'whoami')
            # 如果上面执行的命令需要后续的输入,可使用如下命令
            # stdin.write('123456')
            # stdin.flush()
            if stderr:
                print stderr.readlines()
            if stdout:
                print 'whoami命令获取当前登录用户:%s' % str(stdout.readlines())
            sshclient.close()
        host.close()
            
    remotefile = r'/tmp/tmp/test_up.txt' # 某文件的绝对路径
    localfile = r'C:\Users\Roc\Desktop\test_path\test_down.txt'
    test_download_onefile = False
    if test_download_onefile:
        host = Linux(hostname, username, password)
        # 测试单个文件下载
        # 将远端的test_up.txt get到本地,并保存为test_down.txt
        host.sftp_get(remotefile, localfile)
        host.close()


    test_upload_onefile = False
    if test_upload_onefile:
        host = Linux(hostname, username, password)
        # 测试单个文件上传
        # 将本地的test_down.txt put到远端,并保持为test_up.txt
        host.sftp_put(localfile, remotefile)
        host.close()
    
    local_dir = r'C:/Users/Roc/Desktop/tmp' # 要上传的文件目录路径
    remote_dir = r'/tmp' # 指定要将所上传文件保存的远程服务器端的目录路径
    test_upload_dir = False
    if test_upload_dir:
        # 上传后,远端的目录结构与本地相同
        upload_thread = Upload_thread(hostname, username, password, local_dir, remote_dir)
        upload_thread.start() 
        if (upload_thread.isAlive()):
            upload_thread.join()
    
    local_dir2 = r'C:/Users/Roc/Desktop/test_path' # 下载保存至该文件目录路径
    remote_dir2 = r'/tmp' # 要下载的文件目录路径
    test_download_dir = False
    if test_download_dir:
        # 下载后,本地的目录结构与远端相同
        download_thread = Download_thread(hostname, 'root', password, local_dir2, remote_dir2)
        download_thread.start() 
        if (download_thread.isAlive()):
            download_thread.join()
    
    
0 0
原创粉丝点击