在连续运行的python脚本中保持端口打开

时间:2017-11-25 05:51:24

标签: python linux cron

我正在尝试使用永久运行的python 3.4开发服务器脚本,并在最多5个独立端口上响应客户端请求。我首选的平台是Debian 8.0。该平台当前在云中的虚拟机上运行。当我从命令行运行它时,我的脚本工作正常 - 我现在需要(1)在我注销服务器后保持运行,(2)通过脚本保持几个端口打开,以便Windows客户端可以连接到它们。

对于(1),

尝试了几个选项后[我尝试使用upstart,将脚本添加到rc.local,使用nohup和&从终端等运行它似乎不起作用,我最终发现似乎确实保持脚本运行的东西,即使它不是很优雅 - 我写了一个每小时的cron脚本,检查是否有脚本正在进程列表中运行,如果没有,则执行它。

每当我现在登录虚拟机时,当我输入'ps -ef'时,我会看到以下输出:

root 22007 21992 98 Nov10 14-12:52:59 /usr/bin/python3.4 /home/userxyz/cronserver.py

我假设脚本是基于系统中存在活动进程的事实而运行的。我提到这一部分是因为我怀疑可能与我的问题的第(2)部分存在关联。

对于(2),

脚本应该打开端口49100 - 49105并侦听连接请求等。当我从终端运行脚本时,来自客户端计算机的zenmap会验证这些端口是否已打开。但是,当cron作业启动脚本时,这些端口似乎不会保持打开状态。我的Windows客户端程序也无法连接到脚本。

我用来监听端口的python代码:

(precedes 'e 'c '(d b e a c g f)) = #t

非常感谢任何见解或帮助!

1 个答案:

答案 0 :(得分:0)

你要问的并不容易,因为它取决于多种因素:

  • 收到的数据的频率是多少?
  • 预计会有多少客户端连接到此服务器?
    • 两个客户是否有可能同时尝试连接?
  • 处理一些收到的数据需要多长时间?
  • 您需要对数据做什么?
    • 写入数据库?
    • 写入文件?
    • 计算一些东西?

根据您的回答,您将为解决方案做出一些设计决策。

但是既然你需要一个答案,这里就是一个代表一种做事方式的黑客:

import socketserver
import threading
import datetime

class SleepyGaryReceptionHandler(socketserver.BaseRequestHandler):

    log_file_name = "/tmp/sleepygaryserver.log"

    def handle(self):

        # self.request is defined in BaseRequestHandler
        data_received = self.request.recv(1024)
        # self.client_address is also defined in BaseRequestHandler
        sender_address = self.client_address[0]

        # This is where you are supposed to do something with your data
        # This is an example
        self.write_to_log('Someone from {} sent us "{}"'.format(sender_address,
                                                                data_received))

        # A way to stop the server from going on forever
        # But you could do this other ways but it depends what condition
        # should cause the shutdown
        if data_received.startswith(b"QUIT"):
            finishing_thread = threading.Thread(target=self.finish_in_another_thread)
            finishing_thread.start()

    # This will be called in another thread to terminate the server
    # self.server is also defined in BaseRequestHandler
    def finish_in_another_thread(self):
        self.write_to_log("Shutting down the server")
        self.server.shutdown()

    # Write something (with a timestamp) to a text file so that we
    # know something is happenning
    def write_to_log(self, message):
        timestamp = datetime.datetime.now()
        timestamp_text = timestamp.isoformat(sep=' ', timespec='seconds')
        with open(self.log_file_name, mode='a') as log_file:
            log_file.write("{}: {}\n".format(timestamp_text, message))

service_address = "localhost"
port_number = 49101

server = socketserver.TCPServer((service_address, port_number),
                                SleepyGaryReceptionHandler)
server.serve_forever()

我在这里使用socketserver模块而不是直接在套接字上监听。编写此标准库模块是为了简化服务器的编写。所以使用它!

我在这里所做的就是写一个文本文件收到的内容。您必须根据自己的使用情况进行调整。

但要让它连续运行,请使用cron作业,但要在计算机启动时启动它。由于此脚本将阻塞,直到服务器停止,我们必须在后台运行它。它看起来像那样:

 @reboot /usr/bin/python3 /home/sleepygary/sleppys_server.py &

我测试了它,5小时后它仍然可以做到。

就像我说的那样,这是一个黑客攻击。如果您想要一路走下去并在计算机上执行任何其他服务,您必须以某种方式对其进行编程。您可以在此页面上找到更多信息:https://www.freedesktop.org/software/systemd/man/daemon.html

我真的很累,所以这里和那里可能会有一些错误。