暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

nohup、&、setsid 、disown 区别

潍鲸 2020-08-15
2663

在linux中,经常会碰到这样的问题,用ssh登录了远程的Linux服务器,运行了一些耗时较长的任务,结果却由于网络等的不稳定导致任务中途失败。这是由于在用户注销(logout)或者网络断开时,终端会收到 HUP(hangup)信号从而关闭其所有子进程。

解决办法有两种:

  • 进程忽略HUP信号,如 nohup、screen

  • 让进程运行在新的会话里执行,从而不属于此终端的子进程,如 setsid、(cmd &)

 

nohup


不挂断地运行命令,即退出了终端仍然会在后台运行,常配合&使用。

    # 语法:
    nohup Command [ Arg … ] [ & ]

    无论是否将 nohup 命令的输出重定向到终端,输出都将附加到当前目录的 nohup.out 文件中。

    1)如果当前目录的 nohup.out 文件不可写,输出重定向到 $HOME/nohup.out 文件中。

    2)如果没有文件能创建或打开以用于追加,那么 Command 参数指定的命令不可调用。

    退出状态,则该命令返回下列出口值: 

    126 可以查找但不能调用 Command 参数指定的命令。 

    127 nohup 命令发生错误或不能查找由 Command 参数指定的命令。 

    否则,nohup 命令的退出状态是 Command 参数指定命令的退出状态。

    nohup 命令,会将标准输出和标准错误默认重写向到nohup.out中,所以可以在命令之后添加上">filename 2>&1",例如把输出重新定向到/mimvp-nohup.log文件中。

      nohup ~/mimvp-shell.sh > ~/weijing-nohup.log 2>&1 &

       

      & 和 ()


      在后台运行,但有一个问题ssh窗口关闭或网络断开,此后台程序也会停止运行。由于当用户注销(logout)或者网络断开时,终端会收到 HUP(hangup)信号从而关闭其所有子进程。所以让进程忽略HUP信号或者将对应脚本程序设置为不属于此终端的子进程。

      一般 nohup 和 & 两者一起配合使用,例如:

        nohup command &

        &可以结合括号()一起使用,产生一个新的子shell并在此子shell中将任务放置到后台运行,从而不受当前shell终端的HUP信号影响,此用法类似与 setsid,且通过 jobs -l无法查看,即提交的作业不在作业列表里。

        使用格式:(COMMAND [ARG]... &) ps -ef | grep weijing

          ps -ef |grep weijing
          homer 10955 1 0 18:04 pts/5 00:00:00 sh weijing-shell.sh
          homer 10956 10955 0 18:04 pts/5 00:00:00 ping weijing.co
          homer    10992 10957  0 18:04 pts/24   00:00:00 grep --color=auto weijing

          可见,其父进程id=1,并非当前的终端id,从而不受当前终端影响,关闭并重启终端后,命令会仍然在后台运行,非常类似于 setsid,通常的使用方式为:

            nohup ./filename.sh > filename.log 2>&1 &
            nohup ./filename.sh &> filename.log &


            nohup 优于 & 的三点理由:
            1) nohup保障进程不会被hangup信号异常中断;
            2) 将任务放置到后台运行,不占用当前的终端;
            3) 将错误输出也打印到log中,默认>只有标准输出,错误输出没有。

             

            jobs


            使用格式:jobs [-lnprs] [jobspec ...] or jobs -x command [args]

            jobs 用于查看当前进程,且只看当前终端生效的,关闭终端后在另一个终端jobs已经无法看到后台跑的程序了,那时需利用ps

            控制进程(disown 中经常使用)

            查看当前终端下的后台进程:
            直接执行:jobs -l

            切换到前台,将查看到的某个后台进程放回到前台:
            直接输入:fg {jobid}  // 这里的{jobid}是通过jobs命令中看到的进程前[]中的数字

            切换到后台,将当前正在前台运行的进程放到后台运行:
            先敲下快捷键:ctrl +z      暂停当前正在运行的进程
            再执行:bg

            终止当前正在前台运行的进程:
            直接敲下快捷键:ctrl +c

             

            应用实例:

              /usr/bin/Xvfb :7 -ac -screen 0 1280x1024x8 > /dev/null 2>&1 &
              export DISPLAY=:7
              nohup java -jar selenium-server-standalone-3.8.0.jar -port 8888 &


              # 运行查看日志 
              nohup java -jar selenium-server-standalone-3.8.0.jar -port 8888 &
              [1] 10020
              nohup: ignoring input and appending output to ‘nohup.out’


              ll
              -rw-r--r-- 1 homer homer 3730403 1224 23:18 chromedriver_linux64_v2.34.zip
              -rw-rw-r-- 1 homer homer 90 1226 22:26 composer.json
              -rw-rw-r-- 1 homer homer 41340 1226 22:31 composer.lock
              -rwxr-xr-x 1 homer homer 1855013 1226 22:25 composer.phar*
              -rw-rw-r-- 1 homer homer 2259579 12 12:10 geckodriver-v0.19.0-linux64.tar.gz
              -rw-r--r-- 1 homer homer 2301226 1225 22:56 geckodriver-v0.19.1-linux64.tar.gz
              -rw------- 1 homer homer 22448 12 16:52 nohup.out
              -rw-rw-r-- 1 homer homer 22844105 12 11:53 selenium-server-standalone-3.8.0.jar
              -rw-rw-r-- 1 homer homer 22844868 1228 13:31 selenium-server-standalone-3.8.1.jar
              drwxrwxr-x 12 homer homer 4096 1226 22:31 vendor/


              jobs -l
              [1]+ 10020 Running nohup java -jar selenium-server-standalone-3.8.0.jar -port 8888 &


              日志可见,自动在当前目录下,创建了日志文件 nohup.out 

              关闭当前终端,然后再打开终端,查看 nohup 是否仍然在运行(没有被挂断)


                ps -ef | grep java
                homer 10020 1 0 16:59 ? 00:00:04 java -jar selenium-server-standalone-3.8.0.jar -port 8888

                确认了,nohup 和 & 配合使用,关闭终端后再重启终端,java 仍然一直在后台运行,没有被挂断

                 

                setsid


                setsid 是让提交的命令归属一个新会话,即新开一个终端,其用法与nohup类似。

                  $ setsid java -jar selenium-server-standalone-3.8.0.jar -port 8888 &   
                  [2] 10269
                  $ 17:23:40.735 INFO - Selenium build info: version: '3.8.0', revision: '924c4067df'


                  不同的是 setsid 是新开一个终端会话,nohup是在当前的终端会话

                  例如:对比下进程父ID(PPID)

                    ps -ef | grep java
                    homer 10020 9859 0 17:05 pts/1 00:00:02 java -jar selenium-server-standalone-3.8.0.jar -port 8888
                    homer 10270 1 22 17:23 ? 00:00:01 java -jar selenium-server-standalone-3.8.0.jar -port 8888
                    homer 10291 9859 0 17:23 pts/1 00:00:00 grep --color=auto java

                    通过对比可看出,使用setsid提交的命令父进程id为1,并不是当前终端进程id;而 nohup提交的命令父进程id为当前终端id=9859

                     

                    disown


                    使用格式:disown [-h] [-ar] [jobspec ...]

                    如果未加任何处理就已经提交了命令,可使用disown补救,为没有使用nohup与setsid的进程加上忽略HUP信号的功能,例如提交的命令可用&放入后台运行

                    如果执行的命令想在前台和后台切换,也可以使用disown进行控制切换。

                    应用实例:

                      # 创建一个ping脚本进行运行模拟


                      vim mimvp-shell.sh
                      #!/bin/bash
                      ping mimvp.com
                      # 一般后台运行


                      sh mimvp-shell.sh &
                      [1] 12189


                      jobs -l
                      [1]+ 12189 Running sh mimvp-shell.sh &
                      # 当前终端关闭后,此进程会随之关闭,终止

                      disown 后台运行


                        sh weijing-shell.sh &
                        [1] 12357


                        jobs -l
                        [1]+ 12357 Running sh weijing-shell.sh &


                        disown -h %1


                        jobs -l
                        [1]+ 12357 Running sh weijingp-shell.sh &
                        $
                        $ ps -ef | grep weijing
                        homer 12357 12279 0 19:15 pts/24 00:00:00 sh weijing-shell.sh
                        homer 12358 12357 0 19:15 pts/24 00:00:00 ping weijingp.com
                        homer 12385 12279 0 19:18 pts/24 00:00:00 grep --color=auto mimvp


                        # # 如上,执行 disown -h %1 后,通过 jobs -l 查看进程号前后几乎没有变化,ps 查看进程号也几乎没有变化


                        # # 接着,关闭终端,并重启终端后,通过 ps 查看进程 sh mimvp-shell.sh


                        ps -ef | grep mimvp
                        homer 12357 1 0 19:15 ? 00:00:00 sh mimvp-shell.sh
                        homer 12358 12357 0 19:15 ? 00:00:00 ping mimvp.com
                        homer 12534 12498 0 19:22 pts/5 00:00:00 grep --color=auto weijing


                        # # 发现进程 sh mimvp-shell.sh 仍然在运行,且其父进程id=1


                        #  # 即执行 disown -h %1 命令后,让作业号为1的进程,转为了后台nohup进程,即成功实现了亡羊补牢
                        # # 实现了功能:后台命令 —> nohup 后台运行

                        disown


                          sh weijing-shell.sh 
                          PING weijing.co (47.95.6.112) 56(84) bytes of data.
                          64 bytes from 47.95.6.112: icmp_seq=1 ttl=53 time=8.87 ms
                          64 bytes from 47.95.6.112: icmp_seq=2 ttl=53 time=8.94 ms
                          64 bytes from 47.95.6.112: icmp_seq=3 ttl=53 time=11.9 ms
                          ^Z (Ctrl + z 挂起前台进程)
                          [1]+ Stopped sh mimvp-shell.sh


                          bg 1 (bg 1 切换到后台进程;fg 切换到前台进程)
                          [1]+ sh mimvp-shell.sh &
                          64 bytes from 47.95.6.112: icmp_seq=4 ttl=53 time=9.07 ms


                          disown -h %1
                          jobs -l
                          [1]+ 12800 Running sh mimvp-shell.sh &
                          # 说明:
                          1) 一开始在前台运行命令 sh mimvp-shell.sh
                          2) Ctrl + z 挂起前台进程
                          3) bg 1 (bg 1 切换到后台进程; fg 切换到前台进程)
                          4) disown -h %1  后台进程挂起
                          5) 关闭终端,重启终端后,仍然在后台执行


                          ps -ef | grep weijing
                          homer    12800     1  0 19:30 ?        00:00:00 sh weijing-shell.sh
                          homer 12801 12800 0 19:30 ? 00:00:00 ping weijing.co
                          homer    12971 12927  0 19:37 pts/24   00:00:00 grep --color=auto weijing
                          # 实现了功能: 前台命令 —> 后台命令 —> nohup 后台运行


                          # 补充说明:
                          jobs -l 查看当前作业一般接-l,用于显示其作业号
                          bg %作业号,将作业在后台运行,例如 bg 1, bg %1
                          fg %作业号,将作业在前面处理,例如 fg 1, fg %1
                          CTRL-z,将当前程序挂起
                          文章转载自潍鲸,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                          评论