Python基于socket\subprocess编写远程命令执行

简介写socket通讯过程
服务端

1. 初始化socket对象
2. 绑定IP/PORT
3. 监听端口
4. 等待客户链接
    1. 等待消息
    2. 发送消息
5. 关闭客户端链接

客户端

1. 初始化socket对象
2. 链接服务端
    1. 发送消息
    2. 等待消息
3. 关闭与服务器链接

Server端


#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import socket,sys,subprocess


def excute_cmd(temp_cmd):
    temp_res = subprocess.Popen(temp_cmd,shell = True,stdout = subprocess.PIPE,stderr = subprocess.PIPE)
    temp_res1 = subprocess.Popen(temp_cmd,shell = True,stdout = subprocess.PIPE,stderr = subprocess.PIPE)
    if temp_res.stderr.read(): #如果执行结果没有错,则返回执行结果,否则返回错误信息
        return temp_res1.stderr.read()
    else:
        return temp_res1.stdout.read()


def main(ip_add = '127.0.0.1',ip_port = 23323):
    Bash_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #实例化socket对象,使用IP/TCP协议
    Bash_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #设置socket对象描述符,打开地址复用,防止端口冲突
    Bash_server.bind((ip_add,int(ip_port))) #绑定IP和端口号
    try:
        Bash_server.listen() #启动监听
    except Exception as e :
        print("Server start failed: %s" %e)
        exit()
    print("server start at %s : %s" %(ip_add,ip_port))
    while True: #进入循环不断接受客户端链接
        Con_client,Con_addr = Bash_server.accept() #等待客户端链接,获取链接客户端,和客户端ip端口
        print("client %s connected" %Con_addr[0])
        while True: #进入循环接受命令
            try:
                recv_data = Con_client.recv(1024).decode('utf-8')
                if not recv_data : continue #如果收到命令为空则进入下一次循环
                print('%s  :  %s' %(Con_addr[0],recv_data)) #如果接受到客户端命令,则打印[ip - 执行命令]
                res = excute_cmd(recv_data) #执行命令获取执行结果
                length = str(len(res)) #获取返回结果长度
                Con_client.send(length.encode('utf-8')) #将长度返回给客户端
                recv_data = Con_client.recv(1024).decode("utf-8") #获取客户端返回的信息,以便确认传输
                if recv_data == 'recv_ready': #如果返回结果为recv_ready,则开始传输全部内容
                    Con_client.sendall(res)
                else:
                    Con_client.send("error".encode('utf-8'))
            except Exception: #防止客户端中途结束链接,在上面代码出现通讯中断时主动中断与客户端的链接,退出循环进入下一次等待客户端链接
                Con_client.close()
                break
    Bash_server.close() #关闭服务器


if __name__ == "__main__":
    if len(sys.argv) == 3:
        main(sys.argv[1],sys.argv[2])
    if len(sys.argv) == 1:
        main()
    else:
        print(''' 
server.py [ipaddr] [port]
        ''')

Client端


#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import socket,sys


def main(ip_add = '127.0.0.1',ip_port = 23323):
    ''' main program '''
    Bash_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #建立socket对象走tcp协议
    Bash_client.connect((ip_add,int(ip_port))) #与服务端建立链接
    while True: #进入不断发送命令的循环
        user_cmd = input("# >") #请求用户输入命令
        if not user_cmd: continue #如果输入为空直接跳过本次循环
        Bash_client.send(user_cmd.encode('utf-8')) #客户端发送命令
        length = Bash_client.recv(1024).decode('utf-8') #接受返回值长度
        Bash_client.send("recv_ready".encode("utf-8")) #发送recv_ready消息,确认接受结果
        count = 0 #初始化计数器
        while count < int(length): #用收到结果的长度作为退出循环的条件,防止黏包
            data = Bash_client.recv(1024).decode("utf-8") #客户端不断接受命令结果
            print(data) #输出命令结果
            count += len(data) #每次循环结束都给计数器加上接受结果的长度
    Bash_client.close()

if __name__ == "__main__":
    if len(sys.argv) == 3:
        main(sys.argv[1],sys.argv[2])
    if len(sys.argv) == 1:
        main()
    else:
        print(''' 
client.py [ipaddr] [port]
        ''')

One thought on “Python基于socket\subprocess编写远程命令执行”

Leave a Reply

Your email address will not be published. Required fields are marked *