daemonize.py 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import os
  2. import sys
  3. from . import six
  4. buffering = int(six.PY3) # No unbuffered text I/O on Python 3 (#20815).
  5. if os.name == 'posix':
  6. def become_daemon(our_home_dir='.', out_log='/dev/null',
  7. err_log='/dev/null', umask=0o022):
  8. "Robustly turn into a UNIX daemon, running in our_home_dir."
  9. # First fork
  10. try:
  11. if os.fork() > 0:
  12. sys.exit(0) # kill off parent
  13. except OSError as e:
  14. sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror))
  15. sys.exit(1)
  16. os.setsid()
  17. os.chdir(our_home_dir)
  18. os.umask(umask)
  19. # Second fork
  20. try:
  21. if os.fork() > 0:
  22. os._exit(0)
  23. except OSError as e:
  24. sys.stderr.write("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror))
  25. os._exit(1)
  26. si = open('/dev/null', 'r')
  27. so = open(out_log, 'a+', buffering)
  28. se = open(err_log, 'a+', buffering)
  29. os.dup2(si.fileno(), sys.stdin.fileno())
  30. os.dup2(so.fileno(), sys.stdout.fileno())
  31. os.dup2(se.fileno(), sys.stderr.fileno())
  32. # Set custom file descriptors so that they get proper buffering.
  33. sys.stdout, sys.stderr = so, se
  34. else:
  35. def become_daemon(our_home_dir='.', out_log=None, err_log=None, umask=0o022):
  36. """
  37. If we're not running under a POSIX system, just simulate the daemon
  38. mode by doing redirections and directory changing.
  39. """
  40. os.chdir(our_home_dir)
  41. os.umask(umask)
  42. sys.stdin.close()
  43. sys.stdout.close()
  44. sys.stderr.close()
  45. if err_log:
  46. sys.stderr = open(err_log, 'a', buffering)
  47. else:
  48. sys.stderr = NullDevice()
  49. if out_log:
  50. sys.stdout = open(out_log, 'a', buffering)
  51. else:
  52. sys.stdout = NullDevice()
  53. class NullDevice:
  54. "A writeable object that writes to nowhere -- like /dev/null."
  55. def write(self, s):
  56. pass