be66a7caed9ebc11e6f30cf9a216047e29a5e4c3
David Blume Add a version that uses a l...

David Blume authored 5 years ago

1) #!/usr/bin/python3
2) #
3) # Since this is meant to be run as a daemon, do not use #!/usr/bin/env python3,
4) # because the process name would then be python3, not based on __FILE__.
5) #
6) # [filename] -d 3 192.168.1.1 192.168.1.12 &
7) # disown [jobid]
8) import os
9) import sys
10) import subprocess
11) import time
12) from argparse import ArgumentParser
13) import threading
David Blume Add notifications for SIGTE...

David Blume authored 5 years ago

14) import signal
David Blume Add a version that uses a l...

David Blume authored 5 years ago

15) 
16) printer_lock = threading.Lock()
17) 
David Blume Rename a parameter instead...

David Blume authored 5 years ago

18) def log_exit(sig, frame):
19)     log(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} '
20)         f'PID={os.getpid()} signal={signal.Signals(sig).name} Exiting.')
David Blume Add notifications for SIGTE...

David Blume authored 5 years ago

21)     sys.exit(0)
22) 
23) 
David Blume Add a version that uses a l...

David Blume authored 5 years ago

24) def pinger(host, delay):
25)     """Independent worker thread: repeatedly ping, check, print and sleep."""
26)     last_results = None
27)     while True:
28)         now = time.localtime()
29)         success = ping(host)
30)         if success != last_results:
31)             status = "UP" if success else "DOWN"
32)             log(f'{time.strftime("%Y-%m-%d %H:%M:%S", now)} {host} {status}')
33)             last_results = success
34)         time.sleep(delay)
35) 
36) 
37) def ping(host):
38)     """Returns True if host (str) responds to a ping request."""
39)     return subprocess.call([*_ping_cmd, host], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0
40) 
41) 
42) def log(*args, **kwargs):
43)     """Opens the logfile, writes the log, and closes the logfile."""
44)     # I don't leave the log file open for writing because another process needs access too.
45)     with printer_lock:
46)         with open(_logname, 'a') as fp:
47)             return print(*args, **kwargs, file=fp)
48) 
49) 
50) if __name__ == '__main__':
51)     parser = ArgumentParser(description="Repeatedly ping sites. Ex: %(prog)s -d 3 192.168.1.1 192.168.1.12")
David Blume Add notifications for SIGTE...

David Blume authored 5 years ago

52)     parser.add_argument('-d', '--delay', type=float, default=3.0, help='Delay between pings')
David Blume Add a version that uses a l...

David Blume authored 5 years ago

53)     parser.add_argument('addresses', nargs='+', help='Addresses to ping')
54)     parser_args = parser.parse_args()
55) 
56)     _logname = os.path.join(os.path.expanduser('~'), 'log', os.path.basename(sys.argv[0]).replace('py', 'txt'))
57) 
58)     # Choose the ping parameters appropriate for the platform
59)     if sys.platform == 'cygwin' or sys.platform == 'win32':
60)         _ping_cmd = ('ping', '-n', '1', '-w', '2000')
61)     else:
62)         _ping_cmd = ('ping', '-c', '1', '-W', '2', '-q')
63) 
64)     log(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}'
David Blume Add notifications for SIGTE...

David Blume authored 5 years ago

65)         f' PID={os.getpid()} repeat={parser_args.delay}s addresses={",".join(parser_args.addresses)} Starting')
66) 
67)     signal.signal(signal.SIGINT, log_exit)
68)     signal.signal(signal.SIGTERM, log_exit)
David Blume Instead of having the proce...

David Blume authored 5 years ago

69) 
70)     # Create worker threads for all but one host address. (Saving one address for this thread.)
71)     for address in parser_args.addresses[:-1]:
David Blume Add a version that uses a l...

David Blume authored 5 years ago

72)         t = threading.Thread(target=pinger, args=(address, parser_args.delay), daemon=True)
73)         t.start()
David Blume Instead of having the proce...

David Blume authored 5 years ago

74)         del t
David Blume Add a version that uses a l...

David Blume authored 5 years ago

75)