【问题标题】:Multithreaded socket gets closed before remote script execution over多线程套接字在远程脚本执行结束之前关闭
【发布时间】:2017-11-19 21:20:41
【问题描述】:

使用 Python 2.6.6,我无法从客户端脚本获取完整数据,因为我怀疑套接字在客户端脚本执行结束之前已关闭,而如果我手动触发远程服务器上的脚本,客户端脚本工作正常.

脚本的作用-

触发脚本

仅用于传输客户端脚本[agent.py]并使用多线程远程触发。

客户端脚本

  • agent.py 将被传输到目标服务器 [1000+]
  • 在 (1000+) 个远程服务器 [linux] 上运行以收集数据并返回 从每台远程机器返回服务器的字典列表

服务器脚本

  • 接收数据并转换为 CSV

客户端脚本 - agent.py

 s = socket.socket()             # Create a socket object
 host = "<SERVER_HOST>"          # server ip
 port = 12345                    # Reserve a port for your service.
 try:
    s.connect((host, port))
    instlist = []
    infoCollect = processInfo()  #get the info in dictionary object
    instlist.append(infoCollect)
    data_string = str(instlist)
    s.sendall(data_string)
    s.send(",")
    s.shutdown(socket.SHUT_WR)
    print('Sent ',(instlist))
    s.close()

服务器脚本 [DataCollector]:

class ThreadedServer(object):
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind((self.host, self.port))

    def listen(self):
        self.sock.listen(5)
        print 'Started Listening....'
        while True:
            client, address = self.sock.accept()
            print 'Got connection from', address
            client.settimeout(60)
            threading.Thread(target = self.listenToClient,args = (client,address)).start()

    def listenToClient(self, client, address):
        size = 1024
        while True:
           try:
              l = client.recv(size)
              while (l):
                 print ("Receiving...%s" % l)
                 f.write(l)
                 l = client.recv(size)
                 print "Instance Details Recieved"
              client.send('Thank you for connecting')

           except:
                client.close()
                return False

if __name__ == "__main__":
    while True:
        port_num = input("Port? ")
        try:
            port_num = int(port_num)
            break
        except ValueError:
            pass
    f = open(array_data,'wb')
    ThreadedServer('',port_num).listen()

触发脚本 - 该脚本的目的是启动所有过程并将客户端脚本 [agentScript] 放置在 1000 多个服务器上并远程执行

 cmd = "python agent.py"

 takeLock = threading.Lock()

 def worker(host):
     ssh = paramiko.SSHClient() # Initiate SSH Object
     ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
     try:
        ssh.connect(host, username='user', password='pass' )

        sftp = ssh.open_sftp()   #sedning files to parellaly to all listed servers
        sftp.put(__file__, 'excludelist')
        sftp.close()

        stdin, stdout, stderr = ssh.exec_command(cmd)
        while not stdout.channel.exit_status_ready():
           # Print Only data when available
           if stdout.channel.recv_ready():
              alldata = stdout.channel.recv(1024)
              prevdata = b"1"
              while prevdata:
                prevdata = stdout.channel.recv(1024)
                alldata += prevdata
                print alldata
              return (str(alldata))
        ssh.close()

     except socket.error, v:
           print "Connection Refused"

 def main():

     with open('IPlist.txt') as ip:
         hosts = ip.read().splitlines()

     threads = []
     for h in hosts:
         t = threading.Thread(target=worker, args=(h,))
         t.start()
         threads.append(t)
     for t in threads:
         t.join()

 if __name__ == "__main__":
     main()

注意:客户端脚本 [agent.py] 需要 1-5 秒,具体取决于服务器的 生成输出和返回值的配置

问题 - 在服务器端填充不完整的数据,例如 -

当我在远程机器上手动触发脚本以测试它时,它会发送完整的字典对象,如 [{commonServerData},{a,b,c,d},{Engine02Data},{tempData,tempData02}] 等服务器接收相同数据

当使用触发脚本调用 agent.py 时,它会发送不完整的数据,例如 - [{commonServerData},{a,b,c,d}] 适用于所有 1000 多个服务器。

我怀疑我的触发脚本有问题,它甚至在 agent.py 完成之前就关闭了远程服务器的套接字会话。

【问题讨论】:

    标签: python


    【解决方案1】:

    从客户端脚本中删除了多余的逗号 s.send(',') 并将其添加到 s.sendall(data_string + ',') 可以完成预期的工作 -

    s = socket.socket()             # Create a socket object
     host = "<SERVER_HOST>"          # server ip
     port = 12345                    # Reserve a port for your service.
     try:
        s.connect((host, port))
        instlist = []
        infoCollect = processInfo()  #get the info in dictionary object
        instlist.append(infoCollect)
        data_string = str(instlist)
        s.sendall(data_string + ',')
        s.shutdown(socket.SHUT_WR)
        print('Sent ',(instlist))
        s.close()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-27
      • 2015-08-17
      • 2021-12-02
      • 2015-08-10
      • 2016-03-07
      相关资源
      最近更新 更多