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()