{"id":520,"date":"2011-09-27T17:22:20","date_gmt":"2011-09-27T17:22:20","guid":{"rendered":"http:\/\/tech.avant.net\/q\/?p=520"},"modified":"2019-06-01T01:53:19","modified_gmt":"2019-06-01T01:53:19","slug":"python-daemon","status":"publish","type":"post","link":"https:\/\/tech.avant.net\/q\/python-daemon\/","title":{"rendered":"python daemon"},"content":{"rendered":"<p>I would like to create a python daemon, completely detaching from the terminal or parent process, and yet retaining any log handlers through the python logging module.  There is a wonderful example at <a href=\"http:\/\/code.activestate.com\/recipes\/278731-creating-a-daemon-the-python-way\/\">cookbook-278731<\/a> of a well-behaved daemon, and see <a href=\"http:\/\/www.python.org\/dev\/peps\/pep-3143\/\">PEP 3143<\/a>.<\/p>\n<p>Borrowing from these examples, here is a simple daemonize function that will retain thread-safe logging handlers that were setup through the logging module. This is also available via <a href=\"https:\/\/github.com\/timwarnock\/daemonize\">github<\/a>.<\/p>\n<pre class=\"sh_python\"># vim: set tabstop=4 shiftwidth=4 autoindent smartindent:\n'''\nDaemon (python daemonize function)\n\nDetach process through double-fork (to avoid zombie process), close all\nfile descriptors, and set working directory to root (to avoid umount problems)\n'''\n\nimport os, resource\nimport logging\n\n# target environment\nUMASK = 0 \nWORKINGDIR = '\/' \nMAXFD = 1024\nif (hasattr(os, \"devnull\")):\n    REDIRECT_TO = os.devnull\nelse:\n    REDIRECT_TO = \"\/dev\/null\"\n\ndef daemonize():\n    '''Detach this process and run it as a daemon'''\n\n    try:\n        pid = os.fork() #first fork\n    except OSError, e:\n        raise Exception, \"%s [%d]\" % (e.strerror, e.errno)\n\n    if (pid == 0): #first child\n        os.setsid()\n        try:\n            pid = os.fork() #second fork\n        except OSError, e:\n            raise Exception, \"%s [%d]\" % (e.strerror, e.errno)\n\n        if (pid == 0): #second child\n            os.chdir(WORKINGDIR)\n            os.umask(UMASK)\n        else:\n            os._exit(0)\n    else:\n        os._exit(0)\n\n    #close all file descriptors except from non-console logging handlers\n    maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]\n    if (maxfd == resource.RLIM_INFINITY):\n        maxfd = MAXFD\n    filenos = []\n    for handler in logging.root.handlers:\n        if hasattr(handler, 'stream') and hasattr(handler.stream, 'fileno') and handler.stream.fileno() &gt; 2:\n            filenos.append( handler.stream.fileno() )\n    for fd in range(0, maxfd):\n        try:\n            if fd not in filenos:\n                os.close(fd)\n        except OSError:\n            pass\n\n    #redirect stdin, stdout, stderr to null\n    os.open(REDIRECT_TO, os.O_RDWR)\n    os.dup2(0, 1)\n    os.dup2(0, 2)\n\n    return(0)\n<\/pre>\n<p>Simply call the daemonize() function within your application, e.g.,<\/p>\n<pre class=\"sh_python\">import logging\nimport Daemon\n\nlogging.info('daemonize?')\nDaemon.daemonize():\nlogging.info('daemonized! we are now safely detached')\n<\/pre>\n<p>From a shell, console logging will only appear before daemonize() was called, e.g.,<\/p>\n<pre># python test\/daemon.py \nINFO:daemon.py:4 -- daemonize?\n#\n<\/pre>\n<p>And the logfile output:<\/p>\n<pre># cat test.log\n2011-09-27 13:26:02,712 INFO:daemon.py:4 -- daemonize?\n2011-09-27 13:26:02,717 INFO:daemon.py:6 -- daemonized! we are now safely detached\n#\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I would like to create a python daemon, completely detaching from the terminal or parent process, and yet retaining any log handlers through the python logging module. There is a wonderful example at cookbook-278731 of a well-behaved daemon, and see PEP 3143. Borrowing from these examples, here is a simple daemonize function that will retain [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[6],"tags":[],"_links":{"self":[{"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/posts\/520"}],"collection":[{"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/comments?post=520"}],"version-history":[{"count":10,"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/posts\/520\/revisions"}],"predecessor-version":[{"id":989,"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/posts\/520\/revisions\/989"}],"wp:attachment":[{"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/media?parent=520"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/categories?post=520"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/tags?post=520"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}