zoukankan      html  css  js  c++  java
  • nohup-长期运行进程

    我们经常会碰到这样的问题,用 telnet/ssh 登录了远程的 Linux 服务器,运行了一些耗时较长的任务, 结果却由于网络的不稳定导致任务中途失败。

    解决办法:
    当用户注销(logout)或者网络断开时,终端会收到 HUP(hangup)信号从而关闭其所有子进程。因此,我们的解决办法就有两种:要么让进程忽略 HUP 信号,要么让进程运行在新的会话里从而成为不属于此终端的子进程。


    模拟一个断开的会话,看一下前台进程是否还会正常运行:

    [root@node1 ~]# cat b.sh 
    #!/bin/bash
    for((;;)) do
            sleep 1
            echo "no" >> /tmp/b.txt
    done
    
    
    第一个会话:
    [root@node1 ~]# bash b.sh   #执行脚本,会占据整个当前会话页面
    
    新打开一个会话:
    [root@node1 ~]# ps -ef | grep b.sh
    root      34693  28170  0 11:32 pts/0    00:00:00 bash b.sh
    ...
    [root@node1 ~]# kill -1 34693    #模拟第一个会话断开的情况,发送SIGHUP信号
    
    再次切换至第一个会话:
    [root@node1 ~]# bash b.sh
    Hangup                   #已经断线
    [root@node1 ~]#
    
    

    nohup

    nohup - run a command immune to hangups, with output to a non-tty

    运行一个忽略hangups(SIGHUP)影响的命令,输出到一个非tty

    格式:
    nohup COMMAND [ARG]...

    示例:

    [root@node1 ~]# nohup bash b.sh          #占据当前会话,使得当前会话不可执行其它命令
    nohup: ignoring input and appending output to ‘nohup.out’   #如不指定日志输出位置,默认输出至当前目录下的nohup.out文件中。
    
    
    重新打开一个会话:
    [root@node1 ~]# ps -ef | grep b.sh
    root      25973  16490  0 09:56 pts/1    00:00:00 bash b.sh
    [root@node1 ~]# kill -1 25973     #向进程发送SIGHUP信号,nohup进程还在运行。关闭上一个session会话,效果和kill -1效果一样
    [root@node1 ~]# 
    

    nohup将标准输出和标准错误缺省会被重定向到nohup.out文件中。一般我们可在结尾加上&来将命令同时放入后台运行,也可用>xxx.log 2>&1(将标准输出和标准错误输出至指定的文件中)来更改缺省的重定向文件名。

    setsid

    setsid - run a program in a new session

    在一个新的会话中运行一个程序。

    格式:
    setsid program [arg...]

    示例:

    [root@node1 ~]# setsid bash b.sh      #使用setsid来代替nohup
    [root@node1 ~]# jobs                  #后台无法查看
    [root@node1 ~]# ps -ef | grep c.sh    #ps查找其进程,可以看到PID是43019,但PPID确为1(systemd)
    root      43593      1  0 14:15 ?        00:00:00 bash b.sh
    root      44473  43385  0 14:22 pts/1    00:00:00 grep --color=auto b.sh
    
    [root@node1 ~]# pstree -H 43593 -p
    systemd(1)─┬─NetworkManager(3403)─┬─{NetworkManager}(3543)
               │                      └─{NetworkManager}(3551)
               ├─agetty(3528)
               ├─auditd(2802)───{auditd}(2806)
               ├─bash(43593)───sleep(44564)             #因为父进程是1,不属于某个终端的子进程,所以也就无法接收到HUP信号。但是不能使用专门指定这个此进程发送HUP信号,这样是会中断的。
               ├─chronyd(3472)
               ├─crond(3490)
    		   ...
               ├─sshd(4154)───sshd(16488)─┬─bash(36542)───less(40656)
               │                          ├─bash(42726)
               │                          └─bash(43385)───pstree(44565)
    		   ...
    

    同样的,在shell也有一种可以使用进程的PPID改成1的方法,使用`()`括起来并加上`&`,也和`setsid`效果一样。 ``` [root@node1 ~]# (bash b.sh &) #后台执行命令 [root@node1 ~]# jobs #jobs无法查看 [root@node1 ~]# ps -ef | grep b.sh root 45631 1 0 14:30 pts/1 00:00:00 bash b.sh #PPID为1 root 45706 43385 0 14:31 pts/1 00:00:00 grep --color=auto b.sh [root@node1 ~]# kill -1 45631 #向进程发送HUP信号 [root@node1 ~]# ps -ef | grep b.sh #进程被中断 root 45784 43385 0 14:31 pts/1 00:00:00 grep --color=auto b.sh [root@node1 ~]#
    
    <br />
    
    
    
    
    ##jobs:
    > 显示当前会话下后台任务列表。也就是说,如果当命令切换至后台和想要显示后台有哪些进程不是同一个会话,那么将查不出来有哪些后台进程。
    
    **格式:**
    `jobs [option]`
    
    **常用选项:**
    * -l:列出进程ID及其它信息
    * -p:仅列出PID
    * -n:仅列出自从上次输出了状态变化提示。run -> stop
    * -r:显示运行中的进程
    * -s:显示停止的进程
    
    <br />
    ##fg:
    > 将命令从后台作业提到前台终端运行。使用格式`fg 任务号`。任务号是由jobs命令获取的第一列。
    
    <br />
    
    ##bg:
    > 使用格式`bg 任务号`。想要使用bg命令,首先对前台命令`ctrl+z`下放置后台成stop模式后,在对其使用bg命令才能像一开始在命令后添加`&`一样后台运行。需要注意的是,如果挂起会影响到当前进程执行的结果,请慎用`ctrl+z`在`bg`。
    
    <br />
    
    **示例:**
    

    [root@node1 ~]# bash b.sh #ctrl+z挂起进程至后台
    ^Z
    [1]+ Stopped bash b.sh
    [root@node1 ~]# jobs
    [1]+ Stopped bash b.sh
    [root@node1 ~]# bg 1 #后台继续运行
    [1]+ bash b.sh &
    [root@node1 ~]# jobs #已经运行
    [1]+ Running bash b.sh &
    [root@node1 ~]#

    [root@node1 ~]# bash #重新打开一个bash
    [root@node1 ~]# jobs #查询后台进程,查询为空,所以jobs只能查询当前会话的后台进程。
    [root@node1 ~]#

    [root@node1 ~]# exit #退出新的bash
    exit
    [root@node1 ~]# jobs #查看jobs
    [1]+ Running bash b.sh &
    [root@node1 ~]# fg 1 #调至前台运行
    bash b.sh

    
    <br />
    
    **总结:**
    `nohup`是使用进程本身忽略HUP信号从而达到可以后台运行不被意外中断。`setsid`和shell中的`( &)`是将进程的父进程改为1,从而达到不受sshd连接的各种情况影响。
    `jobs`,`bg`,`fg`三个命令只能在当前的会话终端上执行,一但会话终端意外剥离,就无法在操作。
    <br />
    
    
    参考资料:[https://www.ibm.com/developerworks/cn/linux/l-cn-nohup/index.html](https://www.ibm.com/developerworks/cn/linux/l-cn-nohup/index.html)
  • 相关阅读:
    JavaScript数组
    JavaScript正则表达式之分组匹配 / 反向引用
    JavaScript函数之作用域 / 作用链域 / 预解析
    JavaScript正则表达式实例汇总
    python+unittets框架
    locust简介
    seleniumselenium各种技巧,滑动,提示框,窗口大小,iframe切换等等
    selenium 定位元素的方式
    jmeter环境配置,配置中文环境,原理-1
    appium环境搭建+真机+获取package和activity来验证是否搭建成功+appium自带的定位元素
  • 原文地址:https://www.cnblogs.com/dance-walter/p/10314402.html
Copyright © 2011-2022 走看看