Bash中的任务(job)管理
本来不准备写这篇博客的,因为任务管理(job管理)非常非常常用,以至于觉得根本没有必要去写这样一个东西。但想了下,还是记录一下吧,也许有人会用到呢。
不知你是否碰到过这样的情况,当你兴致勃勃的打开VIM,写代码写到正酣时,运营MM或者产品MM气喘吁吁的跑过来:“赶紧帮我跑一下xx的数据,一会做PPT要用”。可是不想直接关闭当前的VIM,而且某些系统下,又不能新开tty(如设置了maxlogins参数)去执行这些任务,这可怎么办?这其实就涉及到了任务(job)管理。
那么什么是任务管理?顾名思义,就是指在Bash中对同一个tty中的多个工作进行添加、删除、处理等。由于Bash中的每个工作实际上是当前Bash的子进程,因此,从根本上说,job管理就是指对进程的管理。注意上述的表述中,使用了“同一个tty”这一字眼,这时因为,我们是无法通过tty1的job管理去管理tty2中的job的。例如,我们在tty3终端通过ctrl+z将vim放置到后台暂停,在当前tty中,通过jobs命令查看到的后台任务列表如下图所示:
而这时登录新的tty,通过jobs命令查看,发现并没有jobs位于后台:
1. 通过ctrl+z方式将job抛到后台
刚才我们已经看到了,在vim编辑的过程中,通过ctrl+z快捷键的方式,可以将当前VIM放入后台暂停,同时tty终端会输出如下字样的提示:
[1]+ Stopped vim
其中[1]指的是job的编号,在之后将工作放置到前台,或者杀死后台进程的时候会用到。
Stopped代表当前进程的状态(实际上,通过ctrl+z方式放置到后台的job默认都是Stopped状态),vim指的是被放置到后台的job。等等,那个加号+是什么意思?如果我们再放置2个job到后台,通过jobs命令查看当前后台的jobs列表,输出如下:
发现不仅有+号,还有-号。其实+号指输入fg命令时,默认会将标识为+号的job取到前台来执行,-号则是+号job被fg之后的备胎。
2. 将命令丢到后台执行 &
在Bash下,经常会做一些比较耗费时间的工作,比如读取log的脚本,可能需要10分钟以上才能完成,总不能一直盯着吧?这时,最好的办法在命令后面加上&,将其放入后台执行
作为测试,我们在test.php中输入如下内容:
<?php $i = 0; while($i++ < 30){ echo $i; sleep(1); }
然后将其抛入后台执行:
我们看到,即使是在后台执行,程序的输出还是会输出到Bash的标准输出,即使你按了CTRL+C也不会有任何作用。这可以通过重定向解决:
php test.php 2>&1 >>test.log &
通过jobs命令查看jobs的状态:
跟刚才的几乎一样,除了这次抛入后台的是Running状态。在任务执行完毕之后,屏幕会输出如下字样:
表明当前工作已经完成。
3. 将后台工作拿到前台来处理 fg (%jobnumber)
前面只讲了如何将工作放置到后台以及如何查看后台jobs状态。现在数据跑完了,运营MM走了,继续打开刚才后台的vim编码吧。这需要用到fg命令
命令格式:fg [%jobnumber] . 其中[]中的内容可省,这时默认取出的是标识为+的job.如果要取出指定的job,需要传入job编号:
fg %1
即可取出编号为1的job
4. 让工作在后台的状态变成运行中 bg (% jobnumber)
我们知道,通过CTRL+Z放置放置到后台的job,默认是Stopped状态的,如果要让进程在后台执行,应该怎么做呢?bg命令就是干这个的。
再次执行2中的脚本,不过这次在执行后,我们立即按下CTRL+Z使之暂停。jobs查看状态:
标号为3的job即是我们刚刚加入的。
执行bg %3
再次查看jobs:
可以看到,job已经由Stopped状态编程Running状态,并且命令后面多了一个&
5. 杀死后台的工作 kill
现在,后台的进程多了起来,如果有些job不需要执行了,放在后台总归是不好的。这时,可以通过kill命令删除后台的jobs. 命令格式:Kill – signal %jobnumber
这与kill杀死一般的进程基本没什么区别,不同的是,这里是job的编号而不是进程的PID.
Signal是传入的信号,常用的有:
-l 列出kill的可用信号
-1 重新读取配置
-9 立即强制终止(不会有清理工作)
-15 正常终止一个job(会有一些后续的清理工作)。
为了保险起见,慎重使用-9参数。
最后,给几个hint:
(1). VIM编辑过程中ctrl+z暂停手头的工作,做一些其他的处理,是经常使用的操作。例如:为了防止修改的代码不小心被同步到线上去,我们常常需要check编辑的文件已经放入了rsync的ignore-list中。
(2). 通过&放置到后台的命令,虽然不会被CTRL+C中断,但是默认所有的输出都会输出到屏幕,这应该通过重定向来解决。如果输出的内容不需要或者忽略看,可以简单的重定向到/dev/null设备。
(3). 如果一个脚本执行的时间较长,简单放入后台不管可能会因为TTY中断而导致job中断(即使是在后台,tty中断的情况下,job也会中断的)。这时可以通过nohup命令将运行脚本放置到系统的后台而不是当前tty的后台,该命令类似于:
nohup php test.php 2>&1 &
现在,享受job管理带来的便利吧。