当前位置:首页 > 资讯 > 热门博客 > 正文

【Linux探索之旅】第三部分第四课:后台运行及合并多个终端

发表于: 2015-09-20   作者:frogoscar   来源:转载   浏览次数:
摘要: 内容简介1、第三部分第四课:后台运行及合并多个终端2、第三部分第五课预告:延时执行,唯慢不破后台运行及合并多个终端上一课(《【Linux探索之旅】第三部分第三课:监视系统活动,滴水不漏》)中,我们简单介绍了进程,也学习了如何列出系统中的进程,如何过滤列表结果,还有如何结束进程。这一课我们继续乘胜追击,一路向北,来学习进程的后台运行。我们使用的终端让我们难免有一种感觉:我们每次只能在一个终端中运行一

0?wx_fmt=jpeg

内容简介

1第三部分第四课:后台运行及合并多个终端

2、第三部分第五课预告:延时执行,唯慢不破


后台运行及合并多个终端


上一课(《【Linux探索之旅】第三部分第三课:监视系统活动,滴水不漏》)中,我们简单介绍了进程,也学习了如何列出系统中的进程,如何过滤列表结果,还有如何结束进程。


这一课我们继续乘胜追击,一路向北,来学习进程的后台运行。


我们使用的终端让我们难免有一种感觉:我们每次只能在一个终端中运行一个进程。但其实这是大错特错的。


终端还可以运行后台进程。要使进程一个在后台运行,有几种方法,我们都将学习。


这一课的第三节还将学习screen这个程序,用于同时开多个终端窗口。


&符号和nohup命令:后台运行进程


我们到目前为止用终端做的事情都是眼目所能及的,也就是说:我们运行的命令都是在前台可见的。


这样有一个好处是我们可以看到命令运行的过程,有什么问题可以及时发现。但是也有缺陷,例如有的命令运行耗时良久,我们又不想无所事事,怎么办呢?难道我开一个终端专门执行一个耗时命令,然后为了能做其他事情,我再启动一个终端,那也很不方便。而且,这样的规避方法在非图形界面的终端(还记得我们的tty1~tty6吗?)中是难以实现的,因为只有一个终端窗口。


所以这课显得尤为重要。


事实上,我们可以在同一个终端中同时运行好几个命令。怎么做呢?就需要用到后台进程的概念。


前台进程和后台进程


默认情况下,用户创建的进程都是前台进程。前台进程从键盘读取数据,并把处理结果输出到显示器。


我们可以看到前台进程的运行过程。例如,使用 ls 命令来遍历当前目录下的文件。


这个程序就运行在前台,它会直接把结果输出到显示器。如果 ls 命令需要数据(实际上不需要),那么它会等待用户从键盘输入。


当程序运行在前台时,由于命令提示符($)还未出现,用户不能输入其他命令;即使程序需要运行很长时间,也必须等待程序运行结束才能输入其他命令。


后台进程与键盘没有必然的关系。当然,后台进程也可能会等待键盘输入。


后台进程的优点是不必等待程序运行结束就可以输入其他命令。


那么怎么使一个进程(程序的实例)运行在后台呢?


&符号:在后台运行进程


前面说过,让一个进程在后台运行有几种方法,我们带大家来学习第一种,很简单:就是在你要运行的命令最后加上&这个符号。


我们可以用熟悉的cp命令做例子,例如,我运行cp命令来拷贝文件:emacs的软件包。


cp emacs-24.4.tar.gz emacs-24.4-copy.tar.gz &


0?wx_fmt=png


上图中,因为命令最后加了&符号,运行时此进程就成为了后台进程。终端输出了一些信息:[1] 16525


  1. [1]:这是此终端的后台进程的标号。因为这是第一个后台进程,所以标号为1。

  2. 16525:这是进程号(PID),如果你想要结束这个后台进程,你可以用我们上一课学习的kill命令:kill 16525


我们虽然看不到这个拷贝进程的《所作所为》,但它确实在后台默默进行着文件的拷贝。


如果我们用其他命令试一下,例如find命令,你会吃惊的。


例如我们运行:


find / -name "*log" &


意思是:在根目录/下查找所有以log结尾的文件名的文件,并且在后台运行此进程。


但是你会发现,find命令虽然在后台运行了,但是终端还是会不断显示所有找到的内容或错误信息。虽然我们还可以在终端中输入其他命令,但是一直会跳出find搜索的结果还是很让人感到厌烦的。最后小编不得不把它停止(用kill命令)。


0?wx_fmt=jpeg


幸好,我们之前学过重定向,我们可以把find的输出结果重定向到文件里,就不会再来烦我们了。


find / -name "*log" > output_find &


这样就不会有信息一直输出了。


当然了,我们还可以更保险一些,将标准错误输出也重定向到同一个文件,这样就不会有任何输出了。


find / -name "*log" > output_find 2>&1 &


但现在有一个问题:虽然我们的进程是被放到后台了,在终端貌似看不到它的运行过程了。但是此进程还是与此终端相关联的,假如我们把终端关闭,那么这个进程也就会结束。


nohup命令:使进程与终端分离


&符号虽然常用,但却有一个不可忽视的缺点:后台进程与终端相关联,一旦终端关闭或者用户登出,进程就自动结束。


如果我们想让进程在以上情况下仍然继续在后台运行,那么我们须要用到nohup命令。


当用户注销(logout)或者网络断开时,终端会收到 HUP(hangup,英语《挂断》的意思)信号从而关闭其所有子进程;终端被关闭时也会关闭其子进程。


我们可以用nohup命令使命令不受HUP信号影响。


我们用man来看一下nohup命令的解释:


0?wx_fmt=jpeg


可以看到,nohup命令的简单描述如下:


run a command immune to hangups, with output to a not-tty


翻译出来大致就是:使得运行的命令不受hangup信号影响,而且输出会存放到一个非tty中。


nohup命令的用法很简单:在nohup命令之后接要运行的命令。例如:


nohup cp node-v0.10.22.tar.gz node-v0.10.22-copy.tar.gz


0?wx_fmt=jpeg


可以看到这次的输出信息是:ignoring input and appending output to nohup.out


大致意思是:忽略输入,把输出追加到nohup.out文件中。


使用nohup命令后,输出会被默认地追加写入到一个叫nohup.out的文件里。


现在,我们的进程已经不受终端关闭或者用户断开连接的影响了,会一直运行。当然了,用kill命令还是可以结束此进程的。


nohup命令相当有用。想象以下场景:

《我登录远程服务器,然后运行了一个耗时命令,或者一个需要一直运行的命令,例如一个游戏的服务器程序。这时假如我掉线了,或者我不小心用exit命令推出了登录。那么这个耗时命令也会中止运行。那就很麻烦了。而且,如果这个程序本应该一直运行很久的,我也不可能一直保持登录状态等它结束啊,我家里还有老婆孩子呢,不能不去做饭啊,我要下班。。。开个小玩笑》。


幸好,nohup命令解决了这样的难题。


Ctrl + Z,jobs,bg和fg命令:控制进程的前后台切换


我们来考虑一种情况:假如你要将进程转到后台运行,但是执行命令时忘记了在最后加上&符号。


如何再使此进程转为后台进程呢?有几种方法。我们一一来学习。


Ctrl + Z:转到后台,并暂停运行


我们用top命令来演示。运行:


top


因为top命令的作用是实时地显示各种系统信息和进程列表。这时,我们按下Ctrl + Z这个组合键:


0?wx_fmt=jpeg


可以看到终端显示了

[1]+  Stopped    top

这行信息。


stopped是英语《停止的》的意思,然后我们又看到[1]这个熟悉的信息,表示这是此终端第一个后台进程。


所以表示top命令被放到了后台,此进程还是驻留在内存中,但是被暂停运行了。这个时候命令提示符又出现了,我们可以做其他事情了。


bg命令:使进程转到后台


经过上面的Ctrl + Z操作,我们可怜的top进程已经被《打入冷宫》(转入后台,并且被暂停运行了)。


但是皇后不甘心啊:《臣妾虽然做不到,但即使在冷宫中,我也要工于心计,运筹帷幄,以期早日打败甄�帧贰D窃趺窗炷兀靠梢栽诵�bg命令。


就是很简单的输入bg,然后回车。bg是英语background的缩写,表示《后台》。


bg命令的作用是将命令转入后台运行。假如命令已经在后台,并且暂停着,那么bg命令会将其状态改为运行。


不加任何参数,bg命令会默认作用于最近的一个后台进程,也就是刚才被Ctrl + Z暂停的top进程。如果后面加 %1,%2这样的参数(不带%,直接1,2这样也可以),则是作用于指定标号的进程。因为进程转入后台之后,会显示它在当前终端下的后台进程编号。例如目前top进程转入了后台,它的进程编号是1(可以由[1]+推断)。依次类推,bg %2就是作用于编号为2的后台进程。


我们输入bg,然后回车。看到如下输出:


0?wx_fmt=jpeg


可以看到,终端首先显示了:


[1]+ top &


表示top命令被转到了后台,但是接着,它又显示了这一条信息:


[1]+  Stopped   top


咦,为什么top进程还是暂停着呢?照理说bg命令会把在后台暂停的进程重新唤醒,使之在后台重新运行啊。


我们用ps命令来查看一下进程信息:


ps -aux


0?wx_fmt=jpeg


在上图中可以看到,top这个进程的进程号是23051,状态是T


首先补充一些知识=======================


Linux中进程有5种状态:
1. 运行 (正在运行或在运行队列中等待) 
2. 中断 (休眠中, 受阻, 在等待某个条件的形成或接受到信号) 
3. 不可中断 (收到信号不唤醒和不可运行, 进程必须等待直到有中断发生) 
4. 僵死 (进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放) 
5. 停止 (进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行) 

ps命令标识进程的5种状态码:
D 不可中断 uninterruptible sleep (usually IO) 
R 运行 runnable (on run queue) 
S 中断 sleeping 
T 停止 traced or stopped 
Z 僵死 a defunct ("zombie") process

=====================================


因此,top进程的状态还是T,也就是停止(stopped)的状态。很奇怪是吗?


我们用其他的命令来测试看看。我们测试find命令。首先运行:


find / -name "*log" > find_log 2>&1


上面这个命令的作用是:在根目录 / 下查找以log结尾的文件,将标准输出和标准错误输出都重定向到find_log文件中。


因此,虽然上述命令在运行,但终端中看不到任何信息。


我们用Ctrl + Z来暂停此进程,并将其转到后台。然后再运行bg命令,使其重新在后台运行。


0?wx_fmt=jpeg


奇怪了,为什么bg作用于暂停的find命令后,并没有像刚才top命令一样仍然显示Stopped呢?


我们再用ps -aux 看一下:


0?wx_fmt=jpeg


可以看到,top命令的状态是T,也就是停止(Stopped)。而find命令的状态则是D,也即是不可中断的睡眠(但其实是在运行,等会我们就会看到)。


疑问:所以小编也不清楚为什么对普通的命令如find,bg是起作用的,会将其转成后台运行。但是对于top命令,bg为什么不能将其转成后台运行,有可能是因为top命令本身比较特殊吧。有读者能赐教么?谢谢。


小结一下:


如果你本想要使一个命令运行在后台,成为后台进程,但是忘记加&符号了。那么可以按下面的顺序使此进程转为后台运行:


  1. Ctrl + Z:使进程转为后台暂停。

  2. bg:使进程转为后台运行。


那你也许要问:为什么不直接用bg命令一步到位呢?


因为,如果不先用Ctrl + Z将此进程暂停,此进程就一直在前台运行,你没法在命令提示符后面输入啊。


jobs命令:显示后台进程状态


这个命令很强大,毕竟和乔布斯乔老爷子(乔布斯的英文就是jobs,全名是Steve Jobs。job是英语《工作》的意思)一样名字么。


job命令的作用是显示当前终端里的后台进程状态。虽然我们可以用ps命令来查看进程状态,但是ps命令输出的进程列表太长了。


聪明如你一定想到了,我们可以用jobs命令来显示刚才那两个进程的状态:top进程和find进程。


0?wx_fmt=jpeg


jobs命令的输出共分三列,我们逐列来说明:


  1. 显示后台进程标号:比如上例中top进程的标号是1,find进程的标号是2,如果还有其他后台进程,那么就会有[3],[4],等等。这个标号和PID(进程号)是不一样的。这个标号只是显示当前终端下的后台进程的一个编号。

  2. 显示后台进程状态:比如Stopped是停止的意思,Running是运行的意思。还有其他状态。

  3. 命令本身。


可以看到,我们的top进程确实是在后台暂停了,因为显示Stopped,是英语《停止的》的意思。find进程在后台运行,因为显示Running,是英语《运行中》的意思。


fg命令:使进程转到前台


fg是英语foreground的意思,表示《前台》。


与bg命令相反,fg命令的作用是:使进程转为前台运行。


用法也很简单,和bg一样,如果不加参数,那么fg命令作用于最近的一个后台进程。如果加参数,如%2,那么表示作用于本终端中第二个后台进程。


好了,讲了这么多知识点,是不是有点晕呢?没关系。


我们用下面这个状态图来做个总结,应该就很清楚了:


0?wx_fmt=jpeg


解释一下上图:


  1. 如果我们运行一个程序,默认情况下,它会成为一个前台运行的进程。我们可以按组合键Ctrl + C来销毁此进程。

  2. 我们也可以使此进程在后台运行。假如运行程序时就用&放在命令最后,那么进程就会在后台运行。

  3. 假如在进程运行起来后,按Ctrl + Z,则进程会转到后台,并且停止。此时如果运行bg命令,则进程重新运行,并继续在后台。

  4. fg命令可以使进程转到前台,并且运行。


花点时间好好理解一下这个状态图,这个图很重要,几乎概括了后台前台进程切换的所有情况。


screen命令:合并多个终端


最后一节,我们来学习一个特殊的命令:screen


screen这个程序(所有命令其实都是程序)通常没有在Linux发行版里预装,如果你的Ubuntu系统里没有screen这个程序,那么可以如此安装:


sudo apt-get install screen


安装完之后,你可以输入screen命令,回车,会显示以下内容:


0?wx_fmt=jpeg


按回车或空格跳过这个介绍页面。


screen命令用于在一个终端中打开多个终端,就好像在一个页面中开多个标签栏一样(使用过浏览器的朋友肯定有这种使用经验),很酷吧。


但是screen打开的多个终端是重叠在一起的,如果你不知道,还以为只是打开了一个终端,但是我们会学习如何在各个打开的终端间切换。


在我们运行了screen命令后,再用回车键跳过那页介绍之后,我们看到终端里好像没发生什么变化,就跟之前我们看到的终端一样诶,那screen到底做了什么呢?


其实,screen为我们开了一个虚拟终端,就是在当前实际的终端里又开了一个终端。


如果你再运行screen,那么它又会新开一个虚拟终端。那么怎么退出每个新开的虚拟终端呢?可以按Ctrl + D或者用exit命令。


每次你按Ctrl + D或运行exit命令,都会关闭当前所在的虚拟终端,直到最后一个虚拟终端被关闭,screen程序退出,回到我们的实际终端里,如下图:


0?wx_fmt=jpeg


上图显示了[screen is terminating],表示所有screen开的虚拟终端都已关闭,screen退出(terminate是英语《终结,停止》的意思。施瓦辛格的电影《终结者》就是《The Terminator》)。


现在我们已经知道如何退出screen了。我们重新回去吧,再输入screen就好了。


在screen程序中,几乎所有的操作都是以Ctrl + a开始的。以下所有的讲解中,英文字母区分大小写。也就是说:b和B是不同的,前者就是按下键盘上的b键,B则是需要用Shift + b。


如何操作呢?首先,按下Ctrl + a键,然后松开Ctrl键和a键,再按其他键来完成一定的操作。


Ctrl + a再加?号:显示帮助页面


我们先用Ctrl + a键(也就是同时按下Ctrl键和a键),然后松开这两个键,再按下?号(需要Shift + /号)。


screen的帮助页面就会显示:


0?wx_fmt=jpeg


可以看到,帮助页面显示了各种操作的实现方法。(好好学英语,很有好处吧)


帮助页总共有3页,可以通过第一页第一行Screen key bingings,page 1 of 3知道。目前是在3页中的第一页,按空格可以翻到下一页,按回车退出帮助页。


那怎么来阅读这个帮助页面呢?


比如说,你想要知道screen的版本号,那就是version,可以看到需要用到v键。但是光是按v键还不够,因为我们看到第一页第二行Command key: ^A ,就是说以下所有的操作,都需要先按下Ctrl + a键。^表示Ctrl键。


所以说,要知道screen的版本号,可以先按Ctrl + a键(也就是同时按下Ctrl键和a键),然后松开这两个键,再按下v键。就会在左下角显示screen的版本号了。


当然了,这个帮助页面还是不太容易懂,不过我们也不需要全部记住,只要会用常用的一些组合键就好了。


常用的组合按键


  1. Ctrl + a,松开,再按c:创建一个新的虚拟终端。

  2. Ctrl + a,松开,再按w:显示当前虚拟终端的列表。会显示在左下角,类似下图:

    0?wx_fmt=jpeg

    此处的 0$ bash    1-$ bash    2*$ bash   表示此时打开了3个虚拟终端,都叫作bash,编号是0,1,2。有*的那个虚拟终端就是我们目前所在的虚拟终端,也就是第3个,编号是2。

  3. Ctrl + a,松开,再按A:重命名当前虚拟终端。修改后的名字,你之后再用Ctrl + a,松开,再按w时就会看到。

  4. Ctrl + a,松开,再按n:跳转到下一个虚拟终端。

  5. Ctrl + a,松开,再按p:跳转到上一个虚拟终端。

  6. Ctrl + a,松开,再按Ctrl + a:跳转到最近刚使用的那个虚拟终端。

  7. Ctrl + a,松开,再按0~9数字键:跳转到第0~9号虚拟终端。

  8. Ctrl + a,松开,再按 "(双引号):会让你选择跳转到哪个虚拟终端。

  9. Ctrl + a,松开,再按k:关闭当前终端。


以上是一些常用的screen组合键,下面我们重点来看两个很有用的组合键,分别用于分割虚拟终端和分离screen。


Ctrl + a,松开,再按S:分割虚拟终端为多个小虚拟终端


注意是大写的S,所以是Shif + s。如果这样操作一次,则当前虚拟终端被分割为上下两部分。如下图所示:


0?wx_fmt=jpeg


如果再按这样操作,就分割成3部分,4部分...


可以看到我在上面的半部分中运行了ls命令,下面的半部分暂时还没跳转过去操作,因此下半部分连命令行提示符也没有,空空的。


那我们如何跳转到下半部分去操作呢?Ctrl + a,松开,再按Tab键。


光标就会跳转到下半部分了,但是还是没见有命令行提示符,那是因为还没为下半部分创建虚拟终端呢。


所以我们可以新建一个:Ctrl + a,松开,再按c。或者打开一个现有的虚拟终端。


0?wx_fmt=jpeg


可以看到,我们用Ctrl + a,松开,再按c之后,下半部分的左下角的--变成了3 bash,说明新建了一个虚拟终端,编号是3,也就是第4个(虚拟终端的编号从0开始)。


我们在这个3 bash的虚拟终端里运行top命令,如下:


0?wx_fmt=jpeg


那么我们如何关闭新分割出来的虚拟终端呢?只要Ctrl + a,松开,再按X(是大写的X,也就是Shift + x)。


Ctrl + a,松开,再按d:分离screen


如果我们在screen程序中,先按Ctrl + a,松开,再按d,就可以使screen程序与当前实际终端分离了,有点类似nohup命令的作用。


这样我们就可以重回我们自己的实际终端了,而screen并没有退出,还在后台运行。


0?wx_fmt=jpeg


可以看到 [detached from 6815.pts-0.oscar-laptop]


表示我们的screen与实际终端分离(detach是英语《分离,挣脱》的意思)了。


之后如果你要重回screen中,可以输入


screen -r


就又回到刚才的screen的虚拟终端里了。


我们可以使好几个screen进入分离(detached)状态。


0?wx_fmt=jpeg


可以看到,我们继刚才分离了编号6815的screen进程之后,现在又分离了一个编号13840的screen进程。


之后再运行screen -r想要回去的时候,因为有两个screen分离进程了,实际终端会询问你要回到哪一个,如下图:


0?wx_fmt=jpeg


你想要回到哪一个就用:


screen -r 编号


就可以了。例如我要回到6815那个screen,只要这样:


screen -r 6815


如果你在实际终端下,输入:


screen -ls


则会列出当前打开着的screen进程:


0?wx_fmt=jpeg


怎么样,screen是不是很有趣呢?好好练习,你就会比较熟练了。


用过Emacs或Vim编辑器的读者,也许觉得screen有点像Emcas或Vim中的一部分功能。


是有点像。不过,screen怎么能和Emacs及Vim如此强大的编辑器相比呢。


总结


  1. 我们可以使程序在后台运行,成为后台进程。这样在当前终端中我们就可以做其他事了,而不必等待此进程运行结束。

  2. 为了使一个程序在后台运行,可以在命令的最后加上&这个符号。但是,如果你关闭终端或退出登录,此后台进程还是会结束。为了将后台进程与本终端分离,可以使用nohup命令,使得进程不再受终端关闭或用户登出的影响。

  3. 如果你运行了一个前台进程,但是想要将其转为后台运行进程。你可以先用Ctrl + Z组合按键将其转为后台暂停,然后运行bg命令使其在后台重新运行。如果你要将一个后台命令(不管它是后台运行还是后台暂停)重新转为前台运行,只要用fg命令就可以了。

  4. screen是一个程序,你可以用apt-get来安装。screen命令使用户能够在一个终端中打开多个虚拟终端。


第三部分第五课预告


今天的课就到这里,一起加油吧!

下一课我们学习:延时执行,唯慢不破

【Linux探索之旅】第三部分第四课:后台运行及合并多个终端

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
有时候我们在Linux里面,运行一个服务,当服务启动后,我们这个终端,可能就被,这个服务占用了,如
有时候我们在Linux里面,运行一个服务,当服务启动后,我们这个终端,可能就被,这个服务占用了,如
有时候我们在Linux里面,运行一个服务,当服务启动后,我们这个终端,可能就被,这个服务占用了,如
有时候我们在Linux里面,运行一个服务,当服务启动后,我们这个终端,可能就被,这个服务占用了,如
有时候我们在Linux里面,运行一个服务,当服务启动后,我们这个终端,可能就被,这个服务占用了,如
有时候我们在Linux里面,运行一个服务,当服务启动后,我们这个终端,可能就被,这个服务占用了,如
1.复位——reset命令 [rory@localhost ~]$ cat /bin/arch 结果为: 满屏的乱码 使用reset命令 [rory
笔记 #运行级别脚本介绍 #准备工作 #进入目录 cd /home/wgb/shell #建立文件夹 mkdir 0421 #进入目
最近很忙,忙的连写日记的功夫都没有了。 有个项目的需求是需要把多个圆环的区域合并。得到包络线和
最近很忙,忙的连写日记的功夫都没有了。 有个项目的需求是需要把多个圆环的区域合并。得到包络线和
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号