近日遇到shell后台启动进程,输入ctrl+z被挂起的问题
具体描述如下:
1、现有两个shell脚本,grandfather.sh和father.sh,两个C++程序son1和son2,其中son1为普通程序,son2使用occi连接oracle数据库
调用关系为
2、Father.sh启动son1和son2后,退出到Grandfather.sh,此时在Grandfather.sh中安ctrl+z后,使用ps aux查看son1和son2的进程状态分别为T和S
3、个人认为,既然Father.sh在后台启动son1和son2,那么son1和son2就不应该再受前台shell的影响,不再接收前台shell的信号,更何况Father.sh已经退出了,son1和son2的父进程PID已经为1了。但其实,Grandfather.sh与son1和son2还存在继承关系,共用一些资源和信号,导致son1和son2会收到ctrl+z信号,从而son1被挂起,此时kill掉Grandfather.sh后,son1正常,说明son1与Grandfather.sh确实还有关联。
4、对于son2,为何没被挂起呢?原因是occi会捕获ctrl+z等信号,所以表面上son2没有收到影响,但实际上可能connection已经回滚或出错了。
5、解决方法分为两种,一是在c++程序中屏蔽信号,二是在shell脚本中屏蔽信号
6、在c++程序中屏蔽ctrl+z等信号
//signum为信号的数字表示,其中SIGSTOP=ctrl+c,SIGTSTP=ctrl+z int32_t signum; //callback为信号响应时的回调函数 SignalCallback callback; struct sigaction act, oldact; memset(&act, 0, sizeof(act)); memset(&oldact, 0, sizeof(oldact)); sigemptyset(&act.sa_mask); act.sa_handler = callback; return sigaction(signum, &act, &oldact);
但occi会优先于c++程序捕获信号,所以此方法对son2程序不起作用
7、在shell脚本中屏蔽ctrl+z等信号
trap exit SIGUSR2 trap exit SIGUSR1 trap exit SIGTERM trap exit SIGSTOP trap exit SIGTTIN trap exit SIGTSTP trap exit SIGTTIN trap exit SIGTTOU trap exit SIGCHLD trap exit SIGINT
trap命令需要两个参数,第二个参数为信号的编号,第一个参数为收到信号时,要替换成的动作,若只是屏蔽信号,则可将第一个参数设为‘’
关于后台运行的原理,请参考文章 http://www.cnblogs.com/SuperXJ/archive/2011/10/31/2230314.html