常用的信號值如下:
信號值 事件 處理方式 SIGHUP 終止進程 終端線路掛斷 SIGINT 終止進程 中斷進程 SIGQUIT "建立CORE文件終止進程,並且生成core文件" SIGILL 建立CORE文件 非法指令 SIGTRAP 建立CORE文件 跟蹤自陷 SIGBUS 建立CORE文件 總線錯誤 SIGSEGV 建立CORE文件 段非法錯誤 SIGFPE 建立CORE文件 浮點異常 SIGIOT 建立CORE文件 執行I/O自陷 SIGKILL 終止進程 殺死進程 SIGPIPE 終止進程 向一個沒有讀進程的管道寫數據 SIGALARM 終止進程 計時器到時 SIGTERM 終止進程 軟件終止信號 SIGSTOP 停止進程 非終端來的停止信號 SIGTSTP 停止進程 終端來的停止信號 SIGCONT 忽略信號 繼續執行一個停止的進程 SIGURG 忽略信號 I/O緊急信號 SIGIO 忽略信號 描述符上可以進行I/O SIGCHLD 忽略信號 當子進程停止或退出時通知父進程 SIGTTOU 停止進程 后台進程寫終端 SIGTTIN 停止進程 后台進程讀終端 SIGXGPU 終止進程 CPU時限超時 SIGXFSZ 終止進程 文件長度過長 SIGWINCH 忽略信號 窗口大小發生變化 SIGPROF 終止進程 統計分布圖用計時器到時 SIGUSR1 終止進程 用戶定義信號1 SIGUSR2 終止進程 用戶定義信號2 SIGVTALRM 終止進程 虛擬計時器到時
1、接收信號綁定處理對應的事件

#!/usr/bin/env python # -*- coding: utf-8 -*- import signal import os import time def receive_signal(signum, stack): """用於接收信號,對signum的值區分信號,實現不同的信號做對應的處理""" print('接收的signum', signum) #注冊處理信號的事件,此處對用戶定義信號1、用戶定義信號2,綁定事件 signal.signal(signal.SIGUSR1, receive_signal) signal.signal(signal.SIGUSR2, receive_signal) print('我的PID: %s' % os.getpid()) #開啟循環監聽信號 while True: print('Waiting...') time.sleep(3)
運行效果
#終端1 [root@ mnt]# python3 signal_signal.py 我的PID: 14718 Waiting... #==>每3秒打印一次 Waiting... Waiting... 接收的signum 10 #==>接收到kill -USR1 14718的命令,作出的動作 Waiting... 接收的signum 12 #==>接收到kill -USR2 14718的命令,作出的動作 Waiting... Waiting... Traceback (most recent call last): #==>接收到kill -INT 14718命令的動作 File "signal_signal.py", line 22, in <module> time.sleep(3) KeyboardInterrupt #終端2 [root@ ~]# kill -USR1 14718 [root@ ~]# kill -USR2 14718 [root@ ~]# kill -INT 14718
2、獲取已注冊信號處理器事件

#!/usr/bin/env python # -*- coding: utf-8 -*- import signal def alarm_received(n, stack): return signal.signal(signal.SIGALRM, alarm_received) # 字典格式:{<Signals.SIGABRT: 6>: 'SIGIOT', <Signals.SIGALRM: 14>: 'SIGALRM'...} signals_to_names = { getattr(signal, n): n for n in dir(signal) if n.startswith('SIG') and '_' not in n } for s, name in sorted(signals_to_names.items()): handler = signal.getsignal(s) # 獲取信號的有沒有綁定信號事件 if handler is signal.SIG_DFL: # 判斷有沒有綁定信號事件,沒有的話,設置為SIG_DFL或SIG_IGN handler = 'SIG_DFL' elif handler is signal.SIG_IGN: handler = 'SIG_IGN' print('{:<10} ({:2d}):'.format(name, s), handler)
運行效果
[root@ mnt]# python3 signal_getsignal.py SIGHUP ( 1): SIG_DFL SIGINT ( 2): <built-in function default_int_handler> SIGQUIT ( 3): SIG_DFL SIGILL ( 4): SIG_DFL SIGTRAP ( 5): SIG_DFL SIGIOT ( 6): SIG_DFL SIGBUS ( 7): SIG_DFL SIGFPE ( 8): SIG_DFL SIGKILL ( 9): SIG_DFL SIGUSR1 (10): SIG_DFL SIGSEGV (11): SIG_DFL SIGUSR2 (12): SIG_DFL SIGPIPE (13): SIG_IGN SIGALRM (14): <function alarm_received at 0x7f2bc1002e18> SIGTERM (15): SIG_DFL SIGCLD (17): SIG_DFL SIGCONT (18): SIG_DFL SIGSTOP (19): SIG_DFL SIGTSTP (20): SIG_DFL SIGTTIN (21): SIG_DFL SIGTTOU (22): SIG_DFL SIGURG (23): SIG_DFL SIGXCPU (24): SIG_DFL SIGXFSZ (25): SIG_IGN SIGVTALRM (26): SIG_DFL SIGPROF (27): SIG_DFL SIGWINCH (28): SIG_DFL SIGPOLL (29): SIG_DFL SIGPWR (30): SIG_DFL SIGSYS (31): SIG_DFL SIGRTMIN (34): SIG_DFL SIGRTMAX (64): SIG_DFL
3、發送信號

#!/usr/bin/env python # -*- coding: utf-8 -*- import os import signal import sys os.kill(int(sys.argv[1]),signal.SIGUSR1)
4、告警信號

import signal import time def receive_alarm(signum, stack): print('告警時間 :', time.ctime()) signal.signal(signal.SIGALRM, receive_alarm) signal.alarm(2) #2秒后調用SIGALRM信號的事件 print('之前運行時間:', time.ctime()) time.sleep(4) print('之后運行時間: :', time.ctime())
運行效果
[root@ mnt]# python3 signal_alarm.py 之前運行時間: Thu Dec 5 16:02:11 2019 告警時間 : Thu Dec 5 16:02:13 2019 之后運行時間: : Thu Dec 5 16:02:15 2019
5、怱略信號

import signal import os def do_exit(sig, stack): raise SystemExit('Exiting') # 退出程序並打印顯示 # 注冊使用SIGINT發送信號,做忽略處理 signal.signal(signal.SIGINT, signal.SIG_IGN) # 注冊使用SIGUSR1發送信號,交給do_exit函數處理 signal.signal(signal.SIGUSR1, do_exit) print('我的PID: %s' % os.getpid()) signal.pause() # 暫停
運行效果
#終端1 #Ctrl+C,失效,因為Ctrl+C發送的信號是SIGINT,已經被怱略 [root@ mnt]# python3 signal_ignore.py 我的PID: 15042 ^C^C^C^C^C^C^C #終端2 #方法1、殺死不了進程 [root@ mnt]# kill -INT 15042 #方法2、可以殺死進程 [root@ mnt]# kill -USR1 15042
6、開啟兩個線程相互接收信號

#!/usr/bin/env python # -*- coding: utf-8 -*- import signal import threading import os import time def signal_handler(num, stack): print('接收信號 SIG值{} 線程名字{}'.format(num, threading.currentThread().name)) # 給SIGUSR1注冊處理事件 signal.signal(signal.SIGUSR1, signal_handler) #等待接收信號 def wait_for_signal(): print('等待信號進來', threading.currentThread().name) signal.pause() print('完成等持') # 啟動不會接收信號的線程 receiver = threading.Thread( target=wait_for_signal, name='receiver', ) receiver.start() time.sleep(0.1) #給主進程發送SIGUSR1信號 def send_signal(): print('發送SIGUSR1信號', threading.currentThread().name) os.kill(os.getpid(), signal.SIGUSR1) sender = threading.Thread(target=send_signal, name='sender') sender.start() sender.join() # 等待線程看到信號 print('Waiting for', receiver.name) signal.alarm(2) #2秒后,發出告警信號,終止程序,如果沒有加入此代碼,會導致無限阻塞 receiver.join()
運行效果
[root@ mnt]# python3 signal_threads.py 等待信號進來 receiver 發送SIGUSR1信號 sender 接收信號 SIG值10 線程名字MainThread Waiting for receiver Alarm clock
7、多進程與告警信號配合使用

#!/usr/bin/env python # -*- coding: utf-8 -*- import signal import time import threading def signal_handler(num, stack): print(time.ctime(), '處理告警的線程名字', threading.currentThread().name) # 注冊SIGALRM信號的事件 signal.signal(signal.SIGALRM, signal_handler) def use_alarm(): t_name = threading.currentThread().name print(time.ctime(), '設置1秒后觸發告警', t_name) signal.alarm(1) print(time.ctime(), '睡眠3秒', t_name) time.sleep(3) print(time.ctime(), '完成睡眠', t_name) # Start a thread that will not receive the signal alarm_thread = threading.Thread( target=use_alarm, name='alarm_thread', ) alarm_thread.start() time.sleep(0.1) # Wait for the thread to see the signal (not going to happen!) print(time.ctime(), '等待執行完成', alarm_thread.name) alarm_thread.join() print(time.ctime(), '正常退出')
運行效果
[root@ mnt]# python3 signal_threads_alarm.py Thu Dec 5 16:37:05 2019 設置1秒后觸發告警 alarm_thread Thu Dec 5 16:37:05 2019 睡眠3秒 alarm_thread Thu Dec 5 16:37:05 2019 等待執行完成 alarm_thread Thu Dec 5 16:37:06 2019 處理告警的線程名字 MainThread Thu Dec 5 16:37:08 2019 完成睡眠 alarm_thread Thu Dec 5 16:37:08 2019 正常退出