python脚本 实现批量远程执行命令,传输文件功能

python脚本 实现批量远程执行命令,传输文件功能

  • 前言
    • 服务端(被远程操控端)
    • 客户端(操控端)

前言

由于一些不可抗力因素,公司生产上的机器封了ssh的端口,无可奈何只能自己写了一个python 程序来实现批量远程控制和传输文件脚本。

服务端(被远程操控端)

  • server.py 放在被控制的主机上 需要修改的地方为ip_pat中的正值表达式,默认是筛选本机的192开头的地址,可根据实际情况调整,端口默认为11115,日志默认打印在当前目录的server.log中

  • 执行方法

python server.py #前端运行
nohup python server.py & #后端运行
import socket
import time
import json
import struct
import subprocess
import os
import re
import datetime


def write_log(data, cmd=''):
    with open('server.log', 'a') as f2:
        now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        if cmd:
            f2.write(now + '\n' + json.dumps(data) + '\n' + cmd + '\n')
        else:
            f2.write(now + '\n' + json.dumps(data) + '\n')


def getip(patten):
    ip_text = subprocess.check_output(["ip", "a"])
    ip_search = re.search(patten, ip_text)
    return ip_search.groups()[0]


def return_cl(data):
    clientSocket.send((ip.center(30, '-') + "\n" + data))
    time.sleep(0.2)
    clientSocket.send('$end$')


def execute_cmd(cmd):
    write_log(head_dict, cmd)
    return_data = ''
    res = subprocess.Popen(
        cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
    nomal_text = res.stdout.read().rstrip()
    error_text = res.stderr.read().rstrip()
    if nomal_text:
        return_data += nomal_text
    if error_text:
        return_data += error_text
    return_cl(return_data)


def wirte_file(data, filename):
    write_log(head_dict)
    dir_path = os.path.dirname(filename)
    if not os.path.exists(dir_path):
        return_data = 'dir %s not exists' % dir_path
        return_cl(return_data)
        return False
    if os.path.isdir(filename):
        return_data = '%s is dir' % filename
        return_cl(return_data)
        return False
    try:
        with open(filename, 'wb') as f2:
            f2.write(data)
            return_cl('file %s transport successfully' % filename)
    except IOError:
        return_cl('Permission denied: wirte ' + filename)


if __name__ == '__main__':

    ip_pat = r"inet (192.[0-9\.]*?)/24 brd"
    ip = getip(ip_pat)

    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind((ip, 11115))

    print('server started')
    server.listen(1)
    fulldata = ''

    while True:
        clientSocket, clientAddress = server.accept()
        fulldata = ''
        head_len_byte = clientSocket.recv(1024)
        try:
            head_len = struct.unpack('i', head_len_byte)[0]
        except struct.error:
            write_log('bad request')
            clientSocket.close()
            continue
        head_dict = json.loads(clientSocket.recv(head_len))

        while True:
            data = clientSocket.recv(1024)
            if data == b'$end$':
                break
            else:
                fulldata += data

        if head_dict['type'] == 'cmd':
            execute_cmd(fulldata.decode('utf-8'))
        if head_dict['type'] == 'file':
            wirte_file(fulldata, head_dict['dest'])

客户端(操控端)

  • client.py 连接默认端口为11115,只需修改iplist即可
  • 执行方法
python client.py cmd '命令'  #操控远程主机执行命令,并返回结果
python client.py file 本地文件地址 远端文件地址
import socket
import sys
import os
import struct
from time import sleep
import json

promote = '''Useage :
python  (cmd 'context' | file 'context' 'dest_filename')
'''


def check_file(file_path):
    if not os.path.isfile(file_path):
        exit(file_path + ' not exists')
    return True


def check_params():
    params = [i.rstrip() for i in sys.argv[1:]]

    if len(params) == 2 and params[0] == 'cmd' or (
            len(params) == 3 and params[0] == 'file' and check_file(params[1])):
        send_data(params)
        exit()

    exit(promote)


def send_data(args):
    tran_dict = {
        'type': args[0]
    }
    if args[0] == 'cmd':
        data = args[1].encode('utf-8')

    if args[0] == 'file':
        tran_dict['dest'] = args[2]
        with open(args[1], 'rb') as f:
            data = f.read()

    head_info = json.dumps(tran_dict)
    head_info_len = struct.pack('i', len(head_info))

    socket.setdefaulttimeout(4)

    for ip in iplist.rstrip().split():
        try:
            sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sk.connect((ip, 11115))
            sk.send(head_info_len)
            sleep(0.2)
            sk.send(head_info.encode('utf-8'))
            sk.sendall(data)
            sleep(0.2)
            sk.send(b'$end$')

            res_data = ''
            while True:
                temdata = sk.recv(1024)
                if temdata == b'$end$':
                    break
                else:
                    res_data += temdata.decode('utf-8')
            print res_data
        except socket.timeout:
            print '%s connection time out'.center(30, '-') % ip
            continue
        except:
            print '%s is DOWN'.center(30, '-') % ip
            continue
        sk.close()


if __name__ == '__main__':
    iplist = '''192.168.58.128
    192.168.58.129
    '''
    check_params()
    exit()

你可能感兴趣的:(python)