zoukankan      html  css  js  c++  java
  • shell直接退出后 后台进程关闭的原因和对处

    在linux上进行测试时发现启动后台进程后,如果使用exit退出登录shell,shell退出后后台进程还是能够正常运行但如果直接关闭登陆的窗口(如直接关掉xshell),那后台进程就会一起终了。都是退出登录为什么前者后台进程会退出,而后者不会退出呢?

    在查看bash的manual时发现有如下一段描述:

    The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP.

    由此可以知道后台进程退出是由于登陆shell收到了SIGHUP信号后在退出前将SIGHUP转发给所有的作业(jobs)。jobs由于收到SIGHUP而终止运行。

    那能不能通过设置,在窗口异常关闭时保持后台进程继续运行呢?

    答案是肯定的,一般有如下4种方法:

    (在此声明,推荐使用exit退出,以下方法不一定管用,网上找的方法,未测试;第一种方法可能对一些进程有效,一些无效吧,至少我测试过,elasticsearch的kibana进程,nohup是无法阻止SIGHUP信号的)

    1. 使用nohup运行命令

    # nohup ./back.sh &
    # nohup ./fore.sh
    ^Z
    [2]+  Stopped                 nohup ./fore.sh
    # jobs 
    [1]-  Running                 nohup ./back.sh &
    [2]+  Stopped                 nohup ./fore.sh
    # ps -o pid,ppid,pgid,sid,cmd
      PID  PPID  PGID   SID CMD
     4766  4716  4766  4716 /bin/bash ./back.sh
     4769  4716  4769  4716 /bin/bash ./fore.sh
    # fg
    nohup ./fore.sh
    
    ### 关闭窗口并重新登录 ###
    
    # ps -eo pid,paid,pgid,sid,cmd |grep -E "back|fore"
     4766     1  4766  4716 /bin/bash ./back.sh
     4769     1  4769  4716 /bin/bash ./fore.sh

    发现重新登录后前台和后台进程都还运行着但父进程变成了init。

    值得注意的是nohup会在当前目录下产生一个nohup.out文件,并把实际命令的标准输出和标准错误重定向为nohup.out

     

    2. 使用setsid运行命令

    # setsid ./back.sh &
    # setsid ./fore.sh
    # jobs 
    # ps -eo pid,ppid,pgid,sid,cmd |grep -E "back|fore"
     4871     1  4871  4871 /bin/bash ./back.sh
     4874     1  4874  4874 /bin/bash ./fore.sh
    
    ### 关闭窗口并重新登录 ###
    
    # ps -eo pid,ppid,pgid,sid,cmd |grep -E "back|fore"
     4871     1  4871  4871 /bin/bash ./back.sh
     4874     1  4874  4874 /bin/bash ./fore.sh

    可以发现在使用setsid后,不能在当前登录shell的jobs中找到back.sh和fore.sh。并且由于在退出前back.sh和fore.sh的父进程已经是init,重新登录后back.sh和fore.sh没有发生任何改变。

     

    3. 使用disown命令

    # ./fore.sh
    ^Z
    [2]+  Stopped 
    # jobs 
    [1]-  Running                 ./back.sh &
    [2]+  Stopped                 ./fore.sh
    # ps -eo pid,ppid,pgid,sid,cmd |grep -E "back|fore"
     5395  5361  5395  5361 /bin/bash ./back.sh
     5396  5361  5396  5361 /bin/bash ./fore.sh
    # disown -h %2
    # disown -a %1
    # jobs 
    [2]+  Stopped                 ./fore.sh
    # fg
    ./fore.sh
    
    ### 关闭窗口并重新登录 ###
    
    # ps -eo pid,ppid,pgid,sid,cmd |grep -E "back|fore"
     5395  5361  5395  5361 /bin/bash ./back.sh

    重新登录后发现fore.sh还是被终止了,并且经过调查发现终了的原因是收到了SIGHUP信号。由此可见disown仅对后台进程起作用。

     

    4.  Catch SIGHUP信号

    如果是shell脚本,则在脚本中加上下面的一条语句就行了。

    # trap "" HUP

    如果是C程序,则使用signal函数对SIGHUP进行屏蔽就行了。

    signal(SIGHUP, SIG_IGN);

    X. 当然相反的我们也可以让shell在exit退出时发送SIGHUP给所有的jobs,具体设置如下:

    # shopt -s huponexit
  • 相关阅读:
    前端技术-PS切图
    Html5资料整理
    Html5知识体系
    Html知识体系
    C语言知识结构
    ASP.NET知识结构
    src和href的区别
    Ajax的简单使用
    学习理论
    求模运算法则
  • 原文地址:https://www.cnblogs.com/jiu0821/p/5649794.html
Copyright © 2011-2022 走看看