signal的运用

第一:给耗时操作增加统一的TimeOut超时处理机制
无论是否启用了Python的多线程机制,只要利用signal模块就可以为耗时操作增加统一的超时处理机制(当然在使用了多线程的情况下还是有一些不一样的地方,只有在主线程里面才可以调用signal.signal函数,而子线程可以调用signal.alarm函数对信号的状态进行设置,具体需参照signal模块自身文档)。单线程情况下,可直接参考如下示例:

Code:


import signal

def handler(signum, frame):
print 'Signal handler called with signal', signum
raise TimeOutError, "TimeOut!"

try:
# Set the signal handler and a 1-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(1)
# This while loop hang indefinitely
while True:
print 'a',
signal.alarm(0) # Disable the alarm
except:
print
print 'Time out caught!'



第二:python kill信号处理(优雅关闭服务器)
我们可能使用nohup或者自己写一个在后台运行的daemon,然后关闭的时候使用kill命令。但是我们有时候需要在关闭服务器之前做一些事情,比如回收一些资源,关闭数据库连接池等,要实现优雅的关闭服务器,就需要对kill的信号进行处理,python的信号处理用到signal模块。看下面的例子:

Code:


import signal
import time
import sys
import threading

#想捕捉的信号编号
signum = int(sys.argv[1])

class ThreadTest(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)

def run(self):
while True:
print "i am ok"
time.sleep(1)

def myhandle(signum=0, e=0):
"""处理信号的函数"""
print 'i will kill myself'
print 'receive signal: %d at %s' % (signum, str(time.ctime(time.time())))
sys.exit()

if __name__ == "__main__":
signal.signal(signum, myhandle)
tt = ThreadTest()
tt.start()
while True:
time.sleep(1)


上面的例子接受一个参数,是要捕捉的信号,里面是模拟一个多线程的服务器。下面用nohup启动:
nohup python signal_test.py 15&
我们监听的是15,也就是kill <进程号>默认的值,然后打开看日志:
tail -f nohup.out
接着3秒后关闭服务器:
kill 91943
日志里面就会打印出记录:
i am ok
i am ok
i am ok
i will kill myself
receive signal: 15 at Thu Aug 5 17:25:35 2010
注意kill -9 <进程号> 程序是不能处理9这个的,9是强制关闭程序。除了15之外,如果15被系统用了,你也可以选择其他的使用。

可以通过 kill -l来列出所有的信号,如下:

Code:


$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGEMT 8 ) SIGFPE
9) SIGKILL 10) SIGBUS 11) SIGSEGV 12) SIGSYS
13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGURG
17) SIGSTOP 18) SIGTSTP 19) SIGCONT 20) SIGCHLD
21) SIGTTIN 22) SIGTTOU 23) SIGIO 24) SIGXCPU
25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH
29) SIGINFO 30) SIGUSR1 31) SIGUSR2


sys.exit()是会清理才退出的,在某些多线程情况下如果不行的话就使用os.abort(),这个是强制退出。
from:http://www.sugarsfree.org/?p=179

补充:

POSIX.1中列出的信号:

信号 值 处理动作 发出信号的原因

----------------------------------------------------------------------

SIGHUP 1 A 终端挂起或者控制进程终止
SIGINT 2 A 键盘中断(如break键被按下)
SIGQUIT 3 C 键盘的退出键被按下
SIGILL 4 C 非法指令
SIGABRT 6 C 由abort(3)发出的退出指令
SIGFPE 8 C 浮点异常
SIGKILL 9 AEF Kill信号
SIGSEGV 11 C 无效的内存引用
SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道 
SIGALRM 14 A 由alarm(2)发出的信号 
SIGTERM 15 A 终止信号 

SIGUSR1 30,10,16 A 用户自定义信号1 

SIGUSR2 31,12,17 A 用户自定义信号2
SIGCHLD 20,17,18 B 子进程结束信号
SIGCONT 19,18,25 进程继续(曾被停止的进程)
SIGSTOP 17,19,23 DEF 终止进程
SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键
SIGTTIN 21,21,26 D 后台进程企图从控制终端读
SIGTTOU 22,22,27 D 后台进程企图从控制终端写

处理动作一项中的字母含义如下: 
A 缺省的动作是终止进程
B 缺省的动作是忽略此信号
C 缺省的动作是终止进程并进行内核映像转储(dump core)
D 缺省的动作是停止进程
E 信号不能被捕获
F 信号不能被忽略

 

键盘和shell的交互:

Ctrl-c Kill foreground process 常用 ;送SIGINT信号,默认进程会结束,但是进程自己可以重定义收到这个信号的行为。
Ctrl-z Suspend foreground process;送SIGSTOP信号,进程只是被停止,再送SIGCONT信号,进程继续运行。
Ctrl-d Terminate input, or exit shell 常用 有时也会使程序退出,例如没有参数的cat命令,从终端读一行显示一行,知道Ctrl+D终结输入并终结进程;不是发送信号,而是表示一个特殊的二进制值,表示 EOF。
Ctrl-s Suspend output
Ctrl-q Resume output
Ctrl-o Discard output
Ctrl-l Clear screen
控制字符都是可以用(stty命令)更改的。可以用stty -a看看终端配置。

有些信号不能被屏蔽,比如中断,还应该有杀死进程的信号,要不然内核怎么做操作系统中的老大。实际上,SIGKILL和SIGSTOP信号是不能被屏蔽或阻止的,他们的默认动作总是会被执行的


python多线程程序的中断(信号)处理
http://www.162cm.com/archives/904.html

linux下的信号
https://files.cnblogs.com/dkblog/Linux%E4%B8%8BSignal%E4%BF%A1%E5%8F%B7.pdf

posted @ 2011-03-07 22:20  dkcndk  阅读(7534)  评论(1编辑  收藏  举报