近日遇到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但occi会优先于c++程序捕获信号,所以此方法对son2程序不起作用
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);
7、在shell脚本中屏蔽ctrl+z等信号
trap exit SIGUSR2trap命令需要两个参数,第二个参数为信号的编号,第一个参数为收到信号时,要替换成的动作,若只是屏蔽信号,则可将第一个参数设为‘’
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
关于后台运行的原理,请参考文章 http://www.cnblogs.com/SuperXJ/archive/2011/10/31/2230314.html