2013-03-27 89 views
2

我想知道如何創建偵聽POST請求一個守護進程。我發現這個代碼來創建這個link一個守護進程,但我不知道如何來填補它。 IM從Android手機發送到commandes它重定向到能夠通過串行通信,一個Arduino蟒蛇一個PHP服務器通過JSON。我想知道是否有您的幫助如何創建一個Python插槽聽者守護進程

這裏沒有更好的辦法,由於是守護程序創建的代碼:

## {{{ http://code.activestate.com/recipes/278731/ (r6) 
"""Disk And Execution MONitor (Daemon) 

Configurable daemon behaviors: 

    1.) The current working directory set to the "/" directory. 
    2.) The current file creation mode mask set to 0. 
    3.) Close all open files (1024). 
    4.) Redirect standard I/O streams to "/dev/null". 

A failed call to fork() now raises an exception. 

References: 
    1) Advanced Programming in the Unix Environment: W. Richard Stevens 
    2) Unix Programming Frequently Asked Questions: 
     http://www.erlenstar.demon.co.uk/unix/faq_toc.html 
""" 

__author__ = "Chad J. Schroeder" 
__copyright__ = "Copyright (C) 2005 Chad J. Schroeder" 

__revision__ = "$Id$" 
__version__ = "0.2" 

# Standard Python modules. 
import os    # Miscellaneous OS interfaces. 
import sys    # System-specific parameters and functions. 

# Default daemon parameters. 
# File mode creation mask of the daemon. 
UMASK = 0 

# Default working directory for the daemon. 
WORKDIR = "/" 

# Default maximum for the number of available file descriptors. 
MAXFD = 1024 

# The standard I/O file descriptors are redirected to /dev/null by default. 
if (hasattr(os, "devnull")): 
    REDIRECT_TO = os.devnull 
else: 
    REDIRECT_TO = "/dev/null" 

def createDaemon(): 
    """Detach a process from the controlling terminal and run it in the 
    background as a daemon. 
    """ 

    try: 
     # Fork a child process so the parent can exit. This returns control to 
     # the command-line or shell. It also guarantees that the child will not 
     # be a process group leader, since the child receives a new process ID 
     # and inherits the parent's process group ID. This step is required 
     # to insure that the next call to os.setsid is successful. 
     pid = os.fork() 
    except OSError, e: 
     raise Exception, "%s [%d]" % (e.strerror, e.errno) 

    if (pid == 0): # The first child. 
     # To become the session leader of this new session and the process group 
     # leader of the new process group, we call os.setsid(). The process is 
     # also guaranteed not to have a controlling terminal. 
     os.setsid() 

     # Is ignoring SIGHUP necessary? 
     # 
     # It's often suggested that the SIGHUP signal should be ignored before 
     # the second fork to avoid premature termination of the process. The 
     # reason is that when the first child terminates, all processes, e.g. 
     # the second child, in the orphaned group will be sent a SIGHUP. 
     # 
     # "However, as part of the session management system, there are exactly 
     # two cases where SIGHUP is sent on the death of a process: 
     # 
     # 1) When the process that dies is the session leader of a session that 
     #  is attached to a terminal device, SIGHUP is sent to all processes 
     #  in the foreground process group of that terminal device. 
     # 2) When the death of a process causes a process group to become 
     #  orphaned, and one or more processes in the orphaned group are 
     #  stopped, then SIGHUP and SIGCONT are sent to all members of the 
     #  orphaned group." [2] 
     # 
     # The first case can be ignored since the child is guaranteed not to have 
     # a controlling terminal. The second case isn't so easy to dismiss. 
     # The process group is orphaned when the first child terminates and 
     # POSIX.1 requires that every STOPPED process in an orphaned process 
     # group be sent a SIGHUP signal followed by a SIGCONT signal. Since the 
     # second child is not STOPPED though, we can safely forego ignoring the 
     # SIGHUP signal. In any case, there are no ill-effects if it is ignored. 
     # 
     # import signal   # Set handlers for asynchronous events. 
     # signal.signal(signal.SIGHUP, signal.SIG_IGN) 

     try: 
     # Fork a second child and exit immediately to prevent zombies. This 
     # causes the second child process to be orphaned, making the init 
     # process responsible for its cleanup. And, since the first child is 
     # a session leader without a controlling terminal, it's possible for 
     # it to acquire one by opening a terminal in the future (System V- 
     # based systems). This second fork guarantees that the child is no 
     # longer a session leader, preventing the daemon from ever acquiring 
     # a controlling terminal. 
     pid = os.fork() # Fork a second child. 
     except OSError, e: 
     raise Exception, "%s [%d]" % (e.strerror, e.errno) 

     if (pid == 0): # The second child. 
     # Since the current working directory may be a mounted filesystem, we 
     # avoid the issue of not being able to unmount the filesystem at 
     # shutdown time by changing it to the root directory. 
     os.chdir(WORKDIR) 
     # We probably don't want the file mode creation mask inherited from 
     # the parent, so we give the child complete control over permissions. 
     os.umask(UMASK) 
     else: 
     # exit() or _exit()? See below. 
     os._exit(0) # Exit parent (the first child) of the second child. 
    else: 
     # exit() or _exit()? 
     # _exit is like exit(), but it doesn't call any functions registered 
     # with atexit (and on_exit) or any registered signal handlers. It also 
     # closes any open file descriptors. Using exit() may cause all stdio 
     # streams to be flushed twice and any temporary files may be unexpectedly 
     # removed. It's therefore recommended that child branches of a fork() 
     # and the parent branch(es) of a daemon use _exit(). 
     os._exit(0) # Exit parent of the first child. 

    # Close all open file descriptors. This prevents the child from keeping 
    # open any file descriptors inherited from the parent. There is a variety 
    # of methods to accomplish this task. Three are listed below. 
    # 
    # Try the system configuration variable, SC_OPEN_MAX, to obtain the maximum 
    # number of open file descriptors to close. If it doesn't exists, use 
    # the default value (configurable). 
    # 
    # try: 
    # maxfd = os.sysconf("SC_OPEN_MAX") 
    # except (AttributeError, ValueError): 
    # maxfd = MAXFD 
    # 
    # OR 
    # 
    # if (os.sysconf_names.has_key("SC_OPEN_MAX")): 
    # maxfd = os.sysconf("SC_OPEN_MAX") 
    # else: 
    # maxfd = MAXFD 
    # 
    # OR 
    # 
    # Use the getrlimit method to retrieve the maximum file descriptor number 
    # that can be opened by this process. If there is not limit on the 
    # resource, use the default value. 
    # 
    import resource  # Resource usage information. 
    maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1] 
    if (maxfd == resource.RLIM_INFINITY): 
     maxfd = MAXFD 

    # Iterate through and close all file descriptors. 
    for fd in range(0, maxfd): 
     try: 
     os.close(fd) 
     except OSError: # ERROR, fd wasn't open to begin with (ignored) 
     pass 

    # Redirect the standard I/O file descriptors to the specified file. Since 
    # the daemon has no controlling terminal, most daemons redirect stdin, 
    # stdout, and stderr to /dev/null. This is done to prevent side-effects 
    # from reads and writes to the standard I/O file descriptors. 

    # This call to open is guaranteed to return the lowest file descriptor, 
    # which will be 0 (stdin), since it was closed above. 
    os.open(REDIRECT_TO, os.O_RDWR) # standard input (0) 

    # Duplicate standard input to standard output and standard error. 
    os.dup2(0, 1)   # standard output (1) 
    os.dup2(0, 2)   # standard error (2) 

    return(0) 

if __name__ == "__main__": 

    retCode = createDaemon() 

    # The code, as is, will create a new file in the root directory, when 
    # executed with superuser privileges. The file will contain the following 
    # daemon related process parameters: return code, process ID, parent 
    # process group ID, session ID, user ID, effective user ID, real group ID, 
    # and the effective group ID. Notice the relationship between the daemon's 
    # process ID, process group ID, and its parent's process ID. 

    procParams = """ 
    return code = %s 
    process ID = %s 
    parent process ID = %s 
    process group ID = %s 
    session ID = %s 
    user ID = %s 
    effective user ID = %s 
    real group ID = %s 
    effective group ID = %s 
    """ % (retCode, os.getpid(), os.getppid(), os.getpgrp(), os.getsid(0), 
    os.getuid(), os.geteuid(), os.getgid(), os.getegid()) 

    open("createDaemon.log", "w").write(procParams + "\n") 

    sys.exit(retCode) 
## end of http://code.activestate.com/recipes/278731/ }}} 
+1

創建UNIX守護進程我通常使用這個包https://pypi.python.org/pypi/python-daemon/ – 2013-03-27 06:06:35

+0

@DenisNikanorov:借調,強烈推薦。 'python-daemon'是[PEP 3143](http://www.python.org/dev/peps/pep-3143)的參考實現。 – abarnert 2013-03-27 06:11:55

+1

爲什麼你需要所有這些單獨的部分?爲什麼你不能只有一臺Python服務器而不是一臺PHP服務器? – abarnert 2013-03-27 06:37:06

回答

8

如果你必須編寫一個守護進程,你一定要使用python-daemon,因爲它的參考實現是PEP 3143。有很多小事你必須得到正確的。

如果你必須編寫一個服務器,並且從未做過,並且不需要處理超過100個左右的同時連接,並且不需要在不同客戶端之間共享數據,那麼threading是迄今爲止最簡單的解決方案

回聲服務器守護程序(這將永遠運行下去,直到你signal它,並且不會嘗試正常關機)看起來是這樣的:

import socket 
import threading 
import daemon 

def handle_client(sock): 
    with sock.makefile() as f: 
     sock.close() 
     for line in f: 
      f.writeline(line) 

def serve_forever(): 
    server = socket.socket() 
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
    server.bind('', 12345)) 
    server.listen(1) 
    while True: 
     conn, address = server.accept() 
     thread = threading.Thread(target=handle_client, args=[conn]) 
     thread.daemon = True 
     thread.start() 

with daemon.DaemonContext(): 
    serve_forever() 

只要把你真正的代碼handle_client循環內。


但確實,即使這比你需要更復雜。一個inetd服務是簡單了很多:

import sys 
for line in sys.stdin: 
    print(line) 

並將其註冊爲12345端口上的服務器,只需添加一行到/etc/inetd.conf

12345 stream tcp nowait nobody /usr/bin/python python /usr/local/bin/myscript.py 

就是這樣。當然,現代的* nix系統幾乎可以肯定不是用老派inetd

,而是xinetdsystemdlaunchd,或其他一些替代品,這樣的配置會有點不同。閱讀適合您系統的文檔。但是,仍然比編寫套接字服務器守護程序簡單得多。


另外...爲什麼你需要編寫一個PHP服務器轉發到Python服務器?有幾個潛在的答案,但如果你沒有,你不需要這樣做。只需使用Python服務/ CGI /而不是PHP,然後讓Web服務器處理所有網絡,守護進程,管理等。

0

在Python代碼試圖實現一個服務器。檢查這個post並從您的PHP創建一個客戶端連接到該Python服務器。

看到這個post當PHP客戶端連接到Python服務器相關信息開始使用串行到Arduino的通信。

post展示了類似的事情,但使用Java服務器,該服務器使用通信串口和連接到Java服務器Python的客戶端Arduino的。