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

Linux job control

CoderMeng 2021-04-12
388


当我们 ssh 登录上 Linux shell 之后,在此终端下可以同时执行多个命令或脚本,对这些任务的管理就叫做工作管理。比如:想要一边复制文件,一边进行数据查找。


job control 进行管理的进程必须是你 shell 的子进程。



01

&


可以直接将命令丢到后台中运行,比如我们要将 etc/ 整个备份成为 tmp/etc.tar.gz 且不想要等待,那么可以这样做:


    meng➜/tmp» tar -zpcf tmp/home.tar.gz home/meng  &                                                                                                                                              [21:03:46]
    [1] 28270


    [1]:是 job number

    28270:进程 PID


    在后台当中运行的命令,如果有 stdout 及 stderr 时,它的数据依旧是输出到屏幕上面的。所以,最佳的状况就是利用数据流重定向, 将输出数据传送至某个文件中。


      tar -zpcf tmp/home.tar.gz home/meng > /tmp/log.txt 2>&1 &


      02

      job 管理


      jobs:列出当前 shell 中执行的 job


        meng➜/tmp» jobs                                                                                                                                                                                  [21:03:52]
        [1] + running tar -zpcf tmp/home.tar.gz home/meng


        选项与参数:

        -l  :除了列出 job number 与命令串之外,同时列出 PID 的号码;
        -r  :仅列出正在后台 run 的工作;
        -s  :仅列出正在后台当中暂停 (stop) 的工作。


        fg:将后台工作拿到前景来处理


          fg %job_number


          比如上面我们通过 & 将打包命令放在了后台执行,通过 jobs 拿到 job number 1,然后通过 fg %1 即可拿到前台来处理。


          bg:让工作在后台下的状态变成运行中


          比如上面打包命令,忘记加 & 放后台执行了,这个时候要放到后台执行怎么办呢?


          按键 Ctrl + z 将当前工作丢到后台暂停,然后再通过 bg %job_number ,将工作运行。


            meng➜/tmp» sh ./task.sh                                                                                                                                                                          [21:24:51]
            ^Z
            [1] + 28429 suspended sh ./task.sh
            meng➜/tmp» jobs [21:24:55]
            [1] + suspended sh ./task.sh
            meng➜/tmp» bg %1 [21:25:00]
            [1] + 28429 continued sh ./task.sh


            kill:管理后台当中的工作


              meng➜/tmp» kill %1                                                                                                                                                                               [21:25:06]
              [1] + 28429 terminated sh ./task.sh


              03

              脱机管理


              上面我们讲的命令执行都是在当前 shell 中执行,如果退出 shell 命令都会被关闭掉。你在 shell 中执行的命令,这些命令的父进程都是 shell 进程,当你退出 shell 的时候系统会给 jobs 列出的进程发送信号:SIGHUP,这会导致进程关闭。


              通过 ps 可以看到对应进程的父进程(PPID)


                meng➜/tmp» ps -ejf| head                                                                                                                                                                         [21:41:30]
                UID PID PPID PGID SID C STIME TTY TIME CMD
                root 1 0 1 1 0 Aug20 ? 00:00:17 sbin/init splash
                root 2 0 0 0 0 Aug20 ? 00:00:00 [kthreadd]
                root 4 2 0 0 0 Aug20 ? 00:00:00 [kworker/0:0H]


                简单讲下 PGID 和 SID 


                SID:Session Identifier (Session Leader)。当前 shell 进程id,可以通过环境变量输出:


                  echo $$


                  PGID:Process Group Identifier (Process Group Leader)。我一次执行多个命令就可以认为是一个 Process Group,Leader 就是取第一个命令的进程id。


                  nohup:让进程忽略掉 SIGHUP 信号。


                  如下所示,task.sh 的进程对应的父进程是当前 shell 进程。当我们退出终端,重新进入后,父进程就变成了系统的 1 号进程(退出终端后,找不到父进程,这个时候进程就会被挂在 1 号进程下)。


                    meng➜/tmp» nohup sh ./task.sh &                                                                                                                                                                  [21:59:56]
                    [1] 29164
                    meng➜/tmp» ps -lf [22:00:50]
                    F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
                    0 S meng 29063 29062 0 80 0 - 13532 sigsus 21:57 pts/2 00:00:00 -zsh
                    0 S meng     29164 29063  0  85   5 -  1157 wait   22:00 pts/2    00:00:00 sh ./task.sh
                    # 退出终端,重新进入
                    meng➜~» ps -ejf| grep task.sh
                    UID PID PPID PGID SID C STIME TTY TIME CMD
                    meng     29164     1 29164 29063  0 22:00 ?        00:00:00 sh ./task.sh


                    我们已经知道,如果事先在命令前加上 nohup 就可以在你关闭终端后继续运行程序。但是如果我们未加任何处理就已经提交了命令,该如何补救呢。


                    disown 它可以将指定任务从"后台任务"列表(jobs命令的返回结果)之中移除。一个"后台任务"只要不在这个列表之中, 关闭 shell 的时候肯定不会向它发出SIGHUP 信号。


                      # 移出最近一个正在执行的后台任务
                      $ disown


                      # 移出所有正在执行的后台任务
                      $ disown -r


                      # 移出所有后台任务
                      $ disown -a


                      # 不移出后台任务,但是让它们不会收到SIGHUP信号
                      $ disown -h


                      # 根据jobId,移出指定的后台任务
                      $ disown %2
                      $ disown -h %2



                      长按二维码关注,获得更多干货文章


                      文章转载自CoderMeng,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                      评论