/usr/lib/python2.7/dist-packages/cylc/daemonize.py is in python-cylc 7.6.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | #!/usr/bin/env python
# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
# Copyright (C) 2008-2017 NIWA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Turn a cylc scheduler into a Unix daemon."""
import os
import sys
from time import sleep, time
from cylc.suite_logging import SuiteLog
SUITE_SCAN_INFO_TMPL = r"""
To view suite daemon contact information:
$ cylc get-suite-contact %(suite)s
Other ways to see if the suite is still running:
$ cylc scan -n '\b%(suite)s\b' %(host)s
$ cylc ping -v --host=%(host)s %(suite)s
$ ssh %(host)s "pgrep -a -P 1 -fu $USER 'cylc-r.* \b%(suite)s\b'"
"""
_INFO_TMPL = r"""
*** listening on %(host)s:%(port)s ***""" + SUITE_SCAN_INFO_TMPL
_TIMEOUT = 300.0 # 5 minutes
def daemonize(server):
"""Turn a cylc scheduler into a Unix daemon.
Do the UNIX double-fork magic, see Stevens' "Advanced Programming in the
UNIX Environment" for details (ISBN 0201563177)
ATTRIBUTION: base on a public domain code recipe by Jurgen Hermann:
http://code.activestate.com/recipes/66012-fork-a-daemon-process-on-unix/
"""
logd = SuiteLog.get_dir_for_suite(server.suite)
log_fname = os.path.join(logd, SuiteLog.LOG)
try:
old_log_mtime = os.stat(log_fname).st_mtime
except OSError:
old_log_mtime = None
# fork 1
try:
pid = os.fork()
if pid > 0:
# Poll for suite log to be populated
suite_pid = None
suite_port = None
timeout = time() + _TIMEOUT
while time() <= timeout and (
suite_pid is None or suite_port is None):
sleep(0.1)
try:
log_stat = os.stat(log_fname)
if (log_stat.st_mtime == old_log_mtime or
log_stat.st_size == 0):
continue
# Line 1 of suite log should contain start up message, host
# name and port number. Format is:
# LOG-PREIFX Suite starting: server=HOST:PORT, pid=PID
# Otherwise, something has gone wrong, print the suite log
# and exit with an error.
log_line1 = open(log_fname).readline()
if server.START_MESSAGE_PREFIX in log_line1:
server_str, pid_str = log_line1.rsplit()[-2:]
suite_pid = pid_str.rsplit("=", 1)[-1]
suite_port = server_str.rsplit(":", 1)[-1]
else:
try:
sys.stderr.write(open(log_fname).read())
sys.exit(1)
except IOError:
sys.exit("Suite daemon exited")
except (IOError, OSError, ValueError):
pass
if suite_pid is None or suite_port is None:
sys.exit("Suite not started after %ds" % _TIMEOUT)
# Print suite information
sys.stdout.write(_INFO_TMPL % {
"suite": server.suite,
"host": server.host,
"port": suite_port,
"pid": suite_pid,
"logd": logd,
})
# exit parent 1
sys.exit(0)
except OSError, exc:
sys.stderr.write(
"fork #1 failed: %d (%s)\n" % (exc.errno, exc.strerror))
sys.exit(1)
# decouple from parent environment
os.chdir("/")
os.setsid()
os.umask(0)
# fork 2
try:
pid = os.fork()
if pid > 0:
# exit parent 2
sys.exit(0)
except OSError, exc:
sys.stderr.write(
"fork #2 failed: %d (%s)\n" % (exc.errno, exc.strerror))
sys.exit(1)
# reset umask, octal
os.umask(022)
# Redirect /dev/null to stdin.
# Note that simply reassigning the sys streams is not sufficient
# if we import modules that write to stdin and stdout from C
# code - evidently the subprocess module is in this category!
dvnl = file(os.devnull, 'r')
os.dup2(dvnl.fileno(), sys.stdin.fileno())
|