我们要结束一个进程时可以通过kill命令来实现,kill的过程简单来说是这样:
- 使用kill将信号发送到进程的task_struct中,task_struct的特定的成员变量里记下这个信号
- 下一次CPU调度到这个进程的时,内核会先执行
do\_signal
,处理信号
使用kill -l
命令可以查看kill能发送的信号
nohup
除了利用工具(tmux,screen等),daemon自守护,systemed系统外,我们还可以用nohup来实现进程守护的需求。
使用方式很简单:在要执行的命令前加个nohup即可,如果要后台执行则在末尾加个&。
回到之前的例子:
#include <stdio.h>
main(void)
{
int d = 1;
while(1){
printf("hello %d \n",d);
fflush(stdout);
sleep(1);
d += 1;
};
return 0;
}
我们通过nohup来把它运行起来:
root@lan-dev-215:~/test# nohup a.out
nohup: ignoring input and appending output to 'nohup.out'
可以看到有句提示: ignoring input and appending output to 'nohup.out
,忽略输入,输出到nohup.out文件。
此时关掉该终端会发现a.out还是在运行。
nohup命令这么简单易用,是怎么实现的呢?
看看nohup.c的源码 https://gist.github.com/kohsuke/0eeb9bb43ca8d62643dd
关键是这两行:
signal (SIGHUP, SIG_IGN);
execvp (*cmd, cmd);
通过signal (SIGHUP, SIG_IGN),把SIGHUP信号忽略,kill 1对它是无效;然后通过execvp (*cmd, cmd) 切换程序背景,nohup把自己变成了a.out,从而实现了我们的守护需求。
来试验下。
先通过nohup 跑起来,然后kill -1一下试试,发现还在运行
root@lan-dev-215:~/test# nohup ./a.out
nohup: ignoring input and appending output to 'nohup.out'
^C
root@lan-dev-215:~/test# nohup ./a.out &
[1] 27668
root@lan-dev-215:~/test# nohup: ignoring input and appending output to 'nohup.out'
root@lan-dev-215:~/test# kill -1 27668
root@lan-dev-215:~/test# ps aux | grep a.out
root 27668 0.0 0.0 4508 712 pts/1 S 18:21 0:00 ./a.out
root 27674 0.0 0.0 14428 1040 pts/1 S+ 18:21 0:00 grep --color=auto a.out
IGNORED
位被置为1了
root@lan-dev-215:~/test# ps -C a.out s
UID PID PENDING BLOCKED IGNORED CAUGHT STAT TTY TIME COMMAND
0 27668 0000000000000000 0000000000000000 0000000000000001 0000000000000000 S pts/1 0:00 ./a.out
标准输入0被定向到了/dev/null
root@lan-dev-215:~/test# lsof -p 27668
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
a.out 27668 root cwd DIR 8,1 4096 2752642 /root/test
a.out 27668 root rtd DIR 8,1 4096 2 /
a.out 27668 root txt REG 8,1 8696 2753343 /root/test/a.out
a.out 27668 root mem REG 8,1 2030544 5767667 /lib/x86_64-linux-gnu/libc-2.27.so
a.out 27668 root mem REG 8,1 170960 5767639 /lib/x86_64-linux-gnu/ld-2.27.so
a.out 27668 root 0w CHR 1,3 0t0 6 /dev/null
a.out 27668 root 1w REG 8,1 3328 2753344 /root/test/nohup.out
a.out 27668 root 2w REG 8,1 3328 2753344 /root/test/nohup.out
感兴趣的话可以去对比下不加nohup
时这些的区别。