参考:http://itlab.idcquan.com/linux/administer/963450.html

 

nohup

  nohup 用途:不挂断的运行命令

  语法 : nohup command [arg] &

  描述: 运行命令,忽略所有SIGHUP信号。 输出到当前目录的nohup.out文件中,如果当前目录不可写,就重定向到$HOME/nohup.out中  一般是要和&配合使用。

  &

  用户: 将一个程序放到后台执行。 并linux 的nohup &和daemon进程不会和终端分离

  后台运行只是终端进行了一次fork,让程序在后台执行,这些都没改变。

  daemon

  需要两次fork

  屏蔽终端信号:

  在后台运行: 方法就是fork 然后使父进程终止,在子进程中运行

  脱离终端,登录会话和进程组:方式就是调用setsid()使其成为会话组组长

  有必要先介绍一下Linux中的进程与控制终端,登录会话和进程组之间的关系:进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登录会话可以包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终端。 控制终端,登录会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在第2点的基础上,调用setsid()使进程成为会话组长:

  禁止进程重新打开控制终端 :通过再次fork进程,其子进程就不是会话组组长,从而达到禁止其再打开控制终端。

  现在,进程已经成为无终端的会话组长。但它可以重新申请打开一个控制终端。可以通过使进程不再成为会话组长来禁止进程重新打开控制终端:

  if(pid=fork())

  exit(0);//结束第一子进程,第二子进程继续(第二子进程不再是会话组长)

  关闭打开的文件描述符:

  进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。按如下方法关闭它们(NOFILE在头文件中定义):

  for(i=0;i < NOFILE;i++)

  close(i);

  改变工作目录:进程活动时,其工作目录所在的文件系统不能卸下。一般需要将工作目录改变到根目录。对于需要转储核心,写运行日志的进程将工作目录改变到特定目录如/tmp:chdir("/tmp")

  重设文件创建掩模:进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除: unmask (0)

  处理SIGCHLD信号 : 处 理SIGCHLD信号并不是必须的。但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵 尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将 SIGCHLD信号的操作设为SIG_IGN. signal(SIGCHLD,SIG_IGN);

  守护进程与用&结尾的后台运行程序有什么区别呢?

  最大的区别有几点:

  1)守护进程已经完全脱离终端控制台了,而后台程序并未完全脱离终端,在终端未关闭前还是会往终端输出结果

  2)守护进程在关闭终端控制台时不会受影响,而后台程序会随用户退出而停止,需要在以nohup xxx & 格式运行才能避免影响

  3)守护进程的会话组和当前目录,文件描述符都是独立的。后台运行只是终端进行了一次fork,让程序在后台执行,这些都没改变。

  其实有没有必要一定用nohup方式去启动后台进程呢,我觉得没有必要,当一个会话的终端中断后,系统只会给当前会话的前台进程组发送SIGHUP信号,如果启动进程时,让进程在后台去执行,也是执行的时候后面加一个&,也可以自己去重定向输入输出,会话的终端中断时,后台的进程组是不会收到SIGHUP信号,也就不会被系统kill掉,当然也可以在代码里注册SIGHUP该信号,防止进程被kill.

 

附:

1、linux系统信号

https://segmentfault.com/q/1010000003786932

SIGHUP

本信号在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端不再关联。

登录Linux时,系统会分配给登录用户一个终端(Session)。
在这个终端运行的所有程序,包括前台进程组和后台进程组,一般都属于这个Session
当用户退出Linux登录时,前台进程组和后台有对终端输出的进程将会收到SIGHUP信号。

这个信号的默认操作为终止进程,因此前台进程组和后台有终端输出的进程就会中止。不过可以捕获这个信号,比如wget能捕获SIGHUP信号,并忽略它,这样就算退出了Linux登录,wget也能继续下载。

 

posted on 2016-02-19 11:30  妞溜溜  阅读(1493)  评论(0编辑  收藏  举报