我们在运行Python、WRF时,经常要判断程序是否还在运行?怎么让程序转入后台,SSH断开后,任务会不会停止?这篇文章来记录一下如何认识和查看进程,控制前后台任务以及使用tmux保持远程会话。
进程
程序时磁盘上的文件,而进程时程序的一次运行实例,同一个程序可以同时启动多次,每次运行都是不同的进程,拥有独立PID,即Process ID,即进程编号。
我们可以使用echo $$来查看当前shell的PID,然后执行:
1 | ps -p $$ -o pid,ppid,user,state,command |
我们得到的是:
1 | PID PPID USER STAT COMMAND |
这其中,PID代表当前进程编号,PPID代表父进程编号,父进程就是启动另一个进程的进程,USER代表运行进程的用户,STATE代表进程状态,COMMAND代表运行的程序。
如何查看系统进程?
执行:ps aux | head可以查看系统进程的前十行,如果我们只运行ps aux,会出现很多行,因为这条命令是显示系统中属于各个用户、包括没有关联终端的进程,并使用详细格式。这里aux的意思是将BSD风格的几个选项写在一起:
1 | a 显示其他用户的进程,而不只当前用户 |
因此我们使用ps aux得到的范围会很大。它输出的常见字段是:USER PID %CPU %MEM VSZ RSS STAT STARTED TIME COMMAND,这其中,USER代表谁启动的,PID是进程编号,%CPU是进程编号,%MEM是内存占比,STAT代表状态,COMMAND是具体命令。
如何查找指定进程?
当我们需要查找zsh进程时,可以使用pgrep -fl zsh,其中pgrep是按照名称查找进程,-f是代表匹配完整命令,-l代表显示PID和名称。
我们也可以使用ps aux | grep zsh,其中pgrep的在用途上相当于把查看进程和按名称筛选结合起来,但pgrep并不是在内部简单执行ps | grep,它是专门查询进程信息的工具。
查找其他进程,直接将zsh替换为其他名称,查找Python:pgrep -fl python,查找SSH,pgrep -fl ssh。
-f和-x的区别是什么
要注意刚刚提到的-f,意思是在查找时,检查完整命令行,而不是短进程名,例如我们有一个名为analysis.python的文件在运行,如果我们只想查找anapysis.py,而不是其他python文件,我们使用pgrep -fl 'analysis.py',输出可能类似48231 python3 analysis.py,这就是-f的作用,它可以检查包括脚本文件在内的完整命令。
当我们进行普通匹配时,可能范围会较宽,例如pgrep zsh,会查找名称中匹配zsh的进程,如果要求进程名必须恰好时zsh,可以使用pgrep -xl zsh,其中-x要求整个进程名完全匹配。
我们再总结一下,当我们有一个进程是这样启动的:python3 analysis.python,它有两部分信息,进程名称:python3,完整命令:python3 analysis.py。当我们使用pgrep analysis.py时,通常找不到,因为analysis.py不是进程名称,知识传给Python的参数,加上-f,就会检查完整命令行。
而-x要求完整匹配,如果执行pgrep -x python,就要求整个进程名称必须刚好等于:python
前台进程
前台进程就是当前任务占用这个终端,并接受终端的输入。例如交互式环境。当我们需要终端前台任务时,按下control + C,进程结束
后台进程
当我们在终端运行sleep 120 &,可能得到[1] 12345,其中[1]代表Shell的任务编号,12345代表系统的进程PID。我们可以查看当前Shell管理的任务:jobs -l,可能会得到:[1] 12345 Running sleep 120。需要注意的是Job ID,[1] 只有在当前Shell会话中才有意义,而PID,是操作系统中使用的进程编号。
最后一个进程
我们使用echo $!可以来查看最后一个进程,$!表示最近一次放入后台的进程PID,想要停止后台进程时,可以使用kill $!
前台、暂停与后台切换
暂停前台任务
如果我们想要暂停前台任务sleep 300,可以执行Ctrl+z,这样我们终端会看到[1] + suspended sleep 300,这表示任务依然存在,但暂时停止运行。此时查看:jobs -l,状态会是suspended,而不是running。
Ctrl+z通常发送SIGTSIP信号,这个信号是Unix/macOS/Linux中的一种进程信号,名字可以拆成:
1 | SIG signal,信号 |
在后台继续执行
还是刚刚被暂停的进程,终端执行bg,我们会看到[1] + continued sleep 300,再执行jobs -l,任务状态变为:running,这样暂停的任务就转为在后台继续运行。
拿回前台、控制指定任务
执行fg,这样sleep 300回重新占用终端。
如果同时有多个后台任务:
1 | sleep 300 & |
终端显示为:
1 | [1] PID1 running sleep 300 |
我们可以使用任务编号来控制:
1 | fg %1 |
也可以使用PID来控制:
1 | kill 62373 # 按操作系统的PID,进程编号 |
tmux使用方法
我们可以使用tmux new -s day03来创建会话,并命名为day03,如果要脱离会话,需要按下Ctrl+b,松开按键,再按d。我们可以使用tmux ls来查看现有会话,并使用tmux attch -t day03来恢复对话。如果想要结束任务,可以按Ctrl+c,然后执行exit就可以退出tmux会话。具体操作可以用多了就记住了
tmux像是运行在终端里面的终端会话管理器。假如我们通过SSH登陆服务器,并运行python3 analysis.python,如果网络断开,或者SSH连接断开,电脑休眠,那么前台程序可能随会话结束而被终端。
而假如我们先在服务器上启动tmux,然后在tmux中运行python3 analysis.py,此时可以把tmux会话分离,执行Ctrl+b, d,退出当前洁面后,tmux会话和程序仍然在服务器上运行,以后重新连接服务器,再执行tmux attch就可以回到之前的界面。这对于我们需要使用服务器的小伙伴来说,简直太友好了。tmux对于我们来说,特别适合运行耗时较长的预处理程序,监控WRF日志,网络断开后重新连接等。
而且tmux还可以创建多个窗口,分离后再连接,窗口、面板和其中运行的 Shell 通常还在,不需要重新布置。