first commit.
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
14) import queue
15)
16)
17) def pinger(host, delay):
18) """Independent worker thread: repeatedly ping, check, print and sleep."""
19) last_results = None
20) while True:
21) now = time.localtime()
22) success = ping(host)
23) if success != last_results:
24) status = "UP" if success else "DOWN"
25) _print_queue.put([f'{time.strftime("%Y-%m-%d %H:%M:%S", now)} {host} {status}'])
26) last_results = success
27) time.sleep(delay)
28)
29)
30) def ping(host):
31) """Returns True if host (str) responds to a ping request."""
32) return subprocess.call([*_ping_cmd, host], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0
33)
34)
35) def print_manager():
36) """The only thread allowed to write output."""
37) while True:
38) job = _print_queue.get()
39) for line in job:
40) log(line)
41) _print_queue.task_done()
42)
43)
44) def log(*args, **kwargs):
45) """Opens the logfile, writes the log, and closes the logfile."""
46) # I don't leave the log file open for writing because another process needs access too.
47) with open(_logname, 'a') as fp:
48) return print(*args, **kwargs, file=fp)
49)
50)
51) if __name__ == '__main__':
52) parser = ArgumentParser(description="Repeatedly ping sites. Ex: %(prog)s -d 3 192.168.1.1 192.168.1.12")
53) parser.add_argument('-d', '--delay', type=float, default=1.0, help='Delay between pings')
54) parser.add_argument('addresses', nargs='+', help='Addresses to ping')
55) parser_args = parser.parse_args()
56)
57) _logname = os.path.join(os.path.expanduser('~'), 'log', os.path.basename(sys.argv[0]).replace('py', 'txt'))
58)
59) # Choose the ping parameters appropriate for the platform
60) if sys.platform == 'cygwin' or sys.platform == 'win32':
61) _ping_cmd = ('ping', '-n', '1', '-w', '2000')
62) else:
63) _ping_cmd = ('ping', '-c', '1', '-W', '2', '-q')
64)
65) _print_queue = queue.Queue()
66) print_thread = threading.Thread(target=print_manager, daemon=True)
67) print_thread.start()
68)
69) _print_queue.put([f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}'
70) f' PID={os.getpid()} repeat={parser_args.delay}s Starting'])
|