remove dependencies on daemon and lockfile
This commit is contained in:
@@ -17,48 +17,13 @@ import zlib
|
|||||||
import subprocess
|
import subprocess
|
||||||
import syslog
|
import syslog
|
||||||
|
|
||||||
try:
|
import syslog
|
||||||
import lockfile
|
|
||||||
import daemon
|
|
||||||
import daemon.pidfile
|
|
||||||
except:
|
|
||||||
print """
|
|
||||||
require on Linux
|
|
||||||
python-filelock
|
|
||||||
python-daemon vs 1.61 or >
|
|
||||||
run sudo easy_install-2.7 lockfile python-daemon
|
|
||||||
on *bsd
|
|
||||||
py27-lockfile
|
|
||||||
py27-daemon
|
|
||||||
run sudo pkg install -y py27-lockfile py27-daemon
|
|
||||||
"""
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
# N.B. daemon tries to close resource.RLIMIT_NOFILE file descriptors
|
|
||||||
# which on FreeBSD in close to a million
|
|
||||||
# hack: replace the function in daemon with ths one:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def log(msg):
|
|
||||||
if fdaemon:
|
|
||||||
syslog.syslog(syslog.LOG_ERR, msg)
|
|
||||||
else:
|
|
||||||
print msg
|
|
||||||
|
|
||||||
|
|
||||||
def get_maximum_file_descriptors():
|
|
||||||
return 2048
|
|
||||||
|
|
||||||
daemon.get_maximum_file_descriptors = get_maximum_file_descriptors
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PORT = 50003
|
PORT = 50003
|
||||||
INTERVAL = 10
|
INTERVAL = 10
|
||||||
PIDFILE = '/tmp/hbc.pid'
|
PIDFILE = '/tmp/hbc.pid'
|
||||||
VER = 3
|
VER = 4
|
||||||
MAXRECV = 32767
|
MAXRECV = 32767
|
||||||
|
|
||||||
running = True
|
running = True
|
||||||
@@ -66,8 +31,8 @@ dorestart = False
|
|||||||
warned1 = False
|
warned1 = False
|
||||||
|
|
||||||
class NullDevice:
|
class NullDevice:
|
||||||
def write(self, s):
|
def write(self, s):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Conn:
|
class Conn:
|
||||||
@@ -84,7 +49,7 @@ class Conn:
|
|||||||
self.rtts = [0]
|
self.rtts = [0]
|
||||||
self.sock=socket.socket(af, socket.SOCK_DGRAM)
|
self.sock=socket.socket(af, socket.SOCK_DGRAM)
|
||||||
self.sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, \
|
self.sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, \
|
||||||
self.sock.getsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR) | 1)
|
self.sock.getsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR) | 1)
|
||||||
|
|
||||||
def sendto(self, msg, ID = 'HTB'): # default ID is HearTBeat
|
def sendto(self, msg, ID = 'HTB'): # default ID is HearTBeat
|
||||||
global warned1
|
global warned1
|
||||||
@@ -175,8 +140,9 @@ def syslogtrace(note):
|
|||||||
logm = '%s hbc died: \n%s' % (note, traceback.format_exc())
|
logm = '%s hbc died: \n%s' % (note, traceback.format_exc())
|
||||||
log(logm)
|
log(logm)
|
||||||
for l in logm.split('\n'):
|
for l in logm.split('\n'):
|
||||||
log(' tb: %s' % l)
|
syslog.syslog(syslog.LOG_ERR, ' tb: %s' % l)
|
||||||
|
if verbose:
|
||||||
|
print logm
|
||||||
|
|
||||||
|
|
||||||
conId = 1
|
conId = 1
|
||||||
@@ -185,7 +151,7 @@ def createConnections(hosts):
|
|||||||
for host in hosts:
|
for host in hosts:
|
||||||
if verbose: log("createConnections for %s" % host)
|
if verbose: log("createConnections for %s" % host)
|
||||||
try:
|
try:
|
||||||
rs=socket.getaddrinfo(host, hb_port, 0, 0, socket.SOL_UDP)
|
rs=socket.getaddrinfo(host, hb_port, 0, 0, socket.SOL_UDP)
|
||||||
except socket.gaierror:
|
except socket.gaierror:
|
||||||
logm = '%s hbc died: \n%s' % ('createConnections', traceback.format_exc())
|
logm = '%s hbc died: \n%s' % ('createConnections', traceback.format_exc())
|
||||||
if verbose: log(logm)
|
if verbose: log(logm)
|
||||||
@@ -197,7 +163,7 @@ def createConnections(hosts):
|
|||||||
elif r[0] == 2:
|
elif r[0] == 2:
|
||||||
af=socket.AF_INET
|
af=socket.AF_INET
|
||||||
else:
|
else:
|
||||||
log("dont know this net type: %s" % r[0][0])
|
print "dont know this net type: %s" % r[0][0]
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
addr = r[4][0]
|
addr = r[4][0]
|
||||||
@@ -226,7 +192,7 @@ def doupdate(conn, msgDict):
|
|||||||
code = msgDict['code'].decode('base64')
|
code = msgDict['code'].decode('base64')
|
||||||
csum = msgDict['csum']
|
csum = msgDict['csum']
|
||||||
except:
|
except:
|
||||||
fail = "csum/code missing"
|
fail = "csum/code missing"
|
||||||
if not fail:
|
if not fail:
|
||||||
fail = doupdateone(code, csum)
|
fail = doupdateone(code, csum)
|
||||||
|
|
||||||
@@ -244,10 +210,10 @@ def doupdateone(code, csum):
|
|||||||
m.update(code)
|
m.update(code)
|
||||||
icsum = m.hexdigest()
|
icsum = m.hexdigest()
|
||||||
if icsum != csum:
|
if icsum != csum:
|
||||||
return "checksum error"
|
return "checksum error"
|
||||||
|
|
||||||
fn = sys.argv[0]
|
fn = sys.argv[0]
|
||||||
ofn = "%.sav" % fn
|
ofn = "%.sav" % fn
|
||||||
try:
|
try:
|
||||||
shutil.copy2(fn, ofn)
|
shutil.copy2(fn, ofn)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -264,7 +230,9 @@ def doupdateone(code, csum):
|
|||||||
|
|
||||||
|
|
||||||
def restart():
|
def restart():
|
||||||
log('restart %s' % (sys.argv[0]))
|
if verbose:
|
||||||
|
print "restart: execv %s %s" % (sys.argv[0], [sys.argv[0]]+cmdargs)
|
||||||
|
syslog.syslog(syslog.LOG_ERR, 'restart %s' % (sys.argv[0]))
|
||||||
e = "fallthrough"
|
e = "fallthrough"
|
||||||
try:
|
try:
|
||||||
os.execv(sys.argv[0], [sys.argv[0]]+cmdargs)
|
os.execv(sys.argv[0], [sys.argv[0]]+cmdargs)
|
||||||
@@ -310,14 +278,14 @@ def process():
|
|||||||
if verbose: print "sock.recvfrom: %s (%s) %s" % (addr, len(data), data[:4])
|
if verbose: print "sock.recvfrom: %s (%s) %s" % (addr, len(data), data[:4])
|
||||||
msgDict = stodict(data)
|
msgDict = stodict(data)
|
||||||
if verbose: print "sock.recvfrom: %s (%s) %s" % (addr, len(data), str(msgDict)[:80])
|
if verbose: print "sock.recvfrom: %s (%s) %s" % (addr, len(data), str(msgDict)[:80])
|
||||||
if msgDict['ID'] == "ACK":
|
if msgDict['ID'] == "ACK":
|
||||||
conns[conn].ack(msgDict)
|
conns[conn].ack(msgDict)
|
||||||
elif msgDict['ID'] == "UPD":
|
elif msgDict['ID'] == "UPD":
|
||||||
if doupdate(conn, msgDict) == None:
|
if doupdate(conn, msgDict) == None:
|
||||||
if verbose: print "process: restart after update"
|
if verbose: print "process: restart after update"
|
||||||
dorestart = True
|
dorestart = True
|
||||||
break
|
break
|
||||||
elif msgDict['ID'] == "CMD":
|
elif msgDict['ID'] == "CMD":
|
||||||
doexec(conn, msgDict['cmd'])
|
doexec(conn, msgDict['cmd'])
|
||||||
else:
|
else:
|
||||||
doexec(conn, data) # deprecated until no more VER - hbc
|
doexec(conn, data) # deprecated until no more VER - hbc
|
||||||
@@ -341,7 +309,7 @@ def cleanup():
|
|||||||
global running
|
global running
|
||||||
if verbose: log('cleanup')
|
if verbose: log('cleanup')
|
||||||
running = False
|
running = False
|
||||||
for conn in conns:
|
for conn in conns:
|
||||||
msg={'shutdown': 1, 'acks': conns[conn].ackcount}
|
msg={'shutdown': 1, 'acks': conns[conn].ackcount}
|
||||||
conns[conn].sendto(msg)
|
conns[conn].sendto(msg)
|
||||||
conns[conn].close()
|
conns[conn].close()
|
||||||
@@ -350,15 +318,59 @@ def cleanup():
|
|||||||
|
|
||||||
|
|
||||||
def closeall():
|
def closeall():
|
||||||
if verbose: log('closecall')
|
if verbose: syslog.syslog(syslog.LOG_ERR, 'closecall')
|
||||||
for conn in conns:
|
for conn in conns:
|
||||||
conns[conn].close()
|
conns[conn].close()
|
||||||
|
|
||||||
|
|
||||||
|
def daemonize(working_dir="/", stdin='/dev/zero', stdout='/dev/null', stderr='/dev/null'):
|
||||||
|
"""
|
||||||
|
Does the UNIX double-fork magic, see Stevens' "Advanced Programming in the
|
||||||
|
UNIX Environment" for details (ISBN 0201563177)
|
||||||
|
http://www.yendor.com/programming/unix/apue/proc/fork2.c
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
# first fork
|
||||||
|
pid = os.fork()
|
||||||
|
if pid > 0:
|
||||||
|
# exit from first parent
|
||||||
|
os._exit(0)
|
||||||
|
except OSError, e:
|
||||||
|
sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
|
||||||
|
os._exit(1)
|
||||||
|
|
||||||
|
# decouple from parent environment
|
||||||
|
os.chdir(working_dir)
|
||||||
|
os.setsid()
|
||||||
|
os.umask(0)
|
||||||
|
# second fork
|
||||||
|
try:
|
||||||
|
pid = os.fork()
|
||||||
|
if pid > 0:
|
||||||
|
# exit from second parent
|
||||||
|
os._exit(0)
|
||||||
|
except OSError, e:
|
||||||
|
sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# redirects standard file descriptors
|
||||||
|
sys.stdout.flush()
|
||||||
|
sys.stderr.flush()
|
||||||
|
si = file(stdin, 'r')
|
||||||
|
so = file(stdout, 'a+')
|
||||||
|
se = file(stderr, 'a+', 0)
|
||||||
|
os.dup2(si.fileno(), sys.stdin.fileno())
|
||||||
|
os.dup2(so.fileno(), sys.stdout.fileno())
|
||||||
|
os.dup2(se.fileno(), sys.stderr.fileno())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
msgonly=False
|
msgonly=False
|
||||||
helpflag=False
|
helpflag=False
|
||||||
verbose=False
|
verbose=False
|
||||||
fdaemon=False
|
fdaemon=False
|
||||||
|
daemonized = False
|
||||||
optlist=[]
|
optlist=[]
|
||||||
args=[]
|
args=[]
|
||||||
msgboot={}
|
msgboot={}
|
||||||
@@ -368,9 +380,9 @@ cmdargs = []
|
|||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
optlist, args = getopt.getopt(sys.argv[1:], 'bc:dhm:v')
|
optlist, args = getopt.getopt(sys.argv[1:], 'bc:dhm:v')
|
||||||
except:
|
except:
|
||||||
helpflag=True
|
helpflag=True
|
||||||
|
|
||||||
for o,a in optlist:
|
for o,a in optlist:
|
||||||
if o == '-b':
|
if o == '-b':
|
||||||
@@ -442,7 +454,7 @@ if f:
|
|||||||
if r[0] == 'hb_hosts':
|
if r[0] == 'hb_hosts':
|
||||||
hb_hosts=eval(r[1])
|
hb_hosts=eval(r[1])
|
||||||
if verbose:
|
if verbose:
|
||||||
print "notice: cfg hb_hosts: %s" % hb_hosts
|
print "notice: cfg hb_hosts: %s" % hb_hosts
|
||||||
elif r[0] == 'interval':
|
elif r[0] == 'interval':
|
||||||
interval=eval(r[1])
|
interval=eval(r[1])
|
||||||
elif r[0] == 'hb_port':
|
elif r[0] == 'hb_port':
|
||||||
@@ -487,7 +499,7 @@ if verbose:
|
|||||||
|
|
||||||
if len(msgboot) > 0:
|
if len(msgboot) > 0:
|
||||||
if verbose: print "on boot"
|
if verbose: print "on boot"
|
||||||
msgboot['acks'] = 0
|
msgboot['acks'] = 0
|
||||||
for conn in conns:
|
for conn in conns:
|
||||||
conns[conn].sendto(msgboot)
|
conns[conn].sendto(msgboot)
|
||||||
|
|
||||||
@@ -497,63 +509,20 @@ if msgonly:
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
||||||
syslog.openlog('hbc', syslog.LOG_PID, syslog.LOG_DAEMON)
|
syslog.openlog('hbc', syslog.LOG_PID, syslog.LOG_DAEMON)
|
||||||
if fdaemon:
|
if fdaemon:
|
||||||
|
print "daemoinizing."
|
||||||
|
daemonize()
|
||||||
|
daemonized = True
|
||||||
|
syslog.syslog(syslog.LOG_ERR, 'starting heartbeat to %s' % ','.join(hb_hosts))
|
||||||
|
|
||||||
pidfile = daemon.pidfile.TimeoutPIDLockFile(PIDFILE, acquire_timeout=-1)
|
running = True
|
||||||
try:
|
try:
|
||||||
opid = pidfile.read_pid()
|
process()
|
||||||
except:
|
except:
|
||||||
opid = None
|
syslogtrace('process')
|
||||||
|
if verbose: print "err: process exit: %s" % e
|
||||||
|
|
||||||
if opid:
|
|
||||||
try:
|
|
||||||
os.kill(opid, 0)
|
|
||||||
is_running = True
|
|
||||||
except:
|
|
||||||
is_running = False
|
|
||||||
if verbose: print "is_running %s" % is_running
|
|
||||||
if is_running:
|
|
||||||
print "process still alive %s" % opid
|
|
||||||
sys.exit(1)
|
|
||||||
print "warning: stale pid file removed"
|
|
||||||
os.unlink(PIDFILE)
|
|
||||||
|
|
||||||
print "daemoinizing... %s" % os.getpid()
|
|
||||||
context = daemon.DaemonContext(
|
|
||||||
working_directory='/tmp',
|
|
||||||
umask=0o022,
|
|
||||||
pidfile=pidfile,
|
|
||||||
detach_process=True,
|
|
||||||
# initgroups=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
context.signal_map = {
|
|
||||||
# signal.SIGHUP: cleanup,
|
|
||||||
signal.SIGTERM: 'terminate',
|
|
||||||
# signal.SIGUSR1: reload_program_config,
|
|
||||||
}
|
|
||||||
|
|
||||||
context.files_preserve = []
|
|
||||||
for conn in conns:
|
|
||||||
context.files_preserve += [conns[conn].sock, conns[conn].sock.fileno()]
|
|
||||||
with context:
|
|
||||||
log('starting heartbeat to %s' % ','.join(hb_hosts))
|
|
||||||
running = True
|
|
||||||
try:
|
|
||||||
process()
|
|
||||||
except:
|
|
||||||
syslogtrace('process')
|
|
||||||
|
|
||||||
else:
|
|
||||||
running = True
|
|
||||||
try:
|
|
||||||
if verbose: print "starting loop process"
|
|
||||||
process()
|
|
||||||
except Exception as e:
|
|
||||||
if verbose: print "err: process exit: %s" % e
|
|
||||||
syslogtrace('process')
|
|
||||||
if verbose: log( "main: cleanup")
|
if verbose: log( "main: cleanup")
|
||||||
cleanup()
|
cleanup()
|
||||||
if dorestart:
|
if dorestart:
|
||||||
|
|||||||
Reference in New Issue
Block a user