目前为止,你知道输入的命令都对应着磁盘上的文件,当命令被 Shell 解释执行后,操作系统就会创建对应的进程,进程干完活后会退出,也有很多进程一直不退出,长期驻留在系统内。要查看当前有哪些进程,输入 ps 命令,该命令常用的额参数组合是 ps -ef 和 ps aux,在一个进程里还可以创建进程,成为子进程,就产生了进程树的概念,输入 pstree 你将看到一棵树,这些命令中 PID 表示进场的号码,如要强行终止某个进程,可以使用 kill PID 来执行,类似的命令还有 killall xxx 和 pkill xxx 杀死所有名称都是 xxx 的进程,你可能会看到 kill -9 PID 这样的命令,-9 表示一个信号,输入 kill -l 可查看所有的信号,你会发现第 9) 号是 SIGKILL,表示强制结束信号,信号是进程异步通讯的一种机制,有些信号具有强制性,有些信号进程可以忽略不处理。
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
不管你使用 ps 还是 ps -ef、ps aux、pstree,你都会发现列表里有一项就是这个命令本身,因为你运行命令的时候,这个进程还未结束,所以列表里包含了它对应的进程。
docker@manager:~/test$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 4164 1016 ? Ss 03:33 0:09 /sbin/init
root 2 0.0 0.0 0 0 ? S 03:33 0:00 [kthreadd]
root 4 0.0 0.0 0 0 ? I< 03:33 0:00 [kworker/0:0H]
root 6 0.0 0.0 0 0 ? I< 03:33 0:00 [mm_percpu_wq]
......
docker 7798 0.0 0.1 7276 1880 pts/0 R+ 06:47 0:00 ps aux
docker@manager:~/test$ pstree
init-+-VBoxService
|-acpid
|-crond
|-dockerd---containerd
|-forgiving-getty---bash
|-forgiving-getty---sleep
|-ntpd
|-sshd---sshd---sshd---bash---pstree // 当前进程
|-udevd---2*[udevd]
`-2*[udhcpc]
操作系统会为每个进程分配资源,这些资源包括单不仅限于cpu时间片、内存、文件句柄、数据缓存区等等,前面说到 uptime 可以查看系统负荷,如果系统负荷非常大,要找出是哪个进场占用了系统的资源,怎么办呢? 最简单的办法是输入 top 命令看看,这个命令会打印和不断刷新进程的信息,通常我们最关心的是 PID、%CPU、%MEM、COMMAND 这4列, 按 M 可以按照进程占用内存大小排序,按 P 可以按照进程占 CPU 排序,c 可以切换进程的全路径,h 查看帮助,w 可以把当前设置保存到文件里面,按 enter 可以立马刷新进程信息,你可以一直按一直按或按住不放,不同的发行版本 top 显示的数据不太相同,但是大同小异,这个命令还有一个增强版 htop,但是需要单独安装软件包,由于还没有讲到软件包管理这章,所以暂且知道就行了。
top - 15:06:38 up 284 days, 14:28, 1 user, load average: 0.01, 0.07, 0.07
Tasks: 313 total, 1 running, 311 sleeping, 0 stopped, 1 zombie
Cpu(s): 1.3%us, 0.7%sy, 0.0%ni, 98.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 4048224k total, 3646004k used, 402220k free, 80040k buffers
Swap: 0k total, 0k used, 0k free, 1029896k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1374 mongodb 20 0 6024m 365m 291m S 0 9.2 4116:39 /usr/bin/mongod --config /etc/mongod.conf
......
在 top 界面按下 ctrl + z 后,top 命令就被切换到了后台,可以使用 ps 和 jobs 命令确认。
ubuntu@ebs-33107:~/test$ ps
PID TTY TIME CMD
5111 pts/0 00:00:00 bash
6379 pts/0 00:00:03 top
6622 pts/0 00:00:00 ps
ubuntu@ebs-33107:~/test$ jobs
[1]+ Stopped top
可以使用 fg 命令把恢复到前台显示,输入 fg 1,其中 1 是任务的序号,只有一个任务的时候可以只输入 fg,bg 可以将任务在后台继续运行。当我们执行一个命令需要运行很长时间的时候,就可以把进程切换到后台,同时输入其他的命令。需要注意的是,当用户退出 shell 的时候任务会停止执行,当我们远程登录到服务器上执行任务的时候,如果希望退出了后任务依然运行,可以借助 nohup 这个命令,它的英文愿意是 no hang up,默认情况下它会把命令的输出放在当前目录的 nohup.out 文件中,默认的 & 表示把命令放到后台执行。
ubuntu@ebs-33107:~$ nohup find / -name xxx &
[1] 8427
ubuntu@ebs-33107:~$ nohup: ignoring input and appending output to ‘nohup.out’
ubuntu@ebs-33107:~$ jobs
[1]+ Running nohup find / -name xxx &
我们退出终端后重新进入,执行 jobs 啥也没有? 不是说好了要一直运行吗,骗子! 这里有一个坑注意一下,jobs 命令本身只能回显当前终端下的任务列表,需要使用 ps aux 或者 ps -ef 命令来确认,什么还是没有,骗子! 可能因为 find 已经完成使命结束了,试试 cat nohup.out 看看执行结果。
来一个更极端的例子,我们使用 ping localhost 查看本机的 ip 地址,退出后再执行 jobs 查看发现啥也没有,好家伙 jobs 居然不讲武德,使用 tail 和 ps 可以确认任务仍然在运行。
ubuntu@ebs-33107:~$ nohup ping localhost &
[1] 11897
ubuntu@ebs-33107:~$ nohup: ignoring input and appending output to ‘nohup.out’
ubuntu@ebs-33107:~$ jobs
[1]+ Running nohup ping localhost &
// 使用 tail -f nohup.out 命令查看 ping 任务可以看到不断有输出,
64 bytes from localhost (127.0.0.1): icmp_seq=93 ttl=64 time=0.097 ms
64 bytes from localhost (127.0.0.1): icmp_seq=491 ttl=64 time=0.094 ms
64 bytes from localhost (127.0.0.1): icmp_seq=748 ttl=64 time=0.088 ms
64 bytes from localhost (127.0.0.1): icmp_seq=707 ttl=64 time=0.018 ms
64 bytes from localhost (127.0.0.1): icmp_seq=94 ttl=64 time=0.080 ms
// ctrl + c 退出 tail 命令
exit // 退出终端
// 重新登录终端后输入 jobs 啥也没有
ubuntu@ebs-33107:~$ jobs
ubuntu@ebs-33107:~$ tail -f nohup.out
64 bytes from localhost (127.0.0.1): icmp_seq=42 ttl=64 time=0.096 ms
64 bytes from localhost (127.0.0.1): icmp_seq=43 ttl=64 time=0.125 ms
64 bytes from localhost (127.0.0.1): icmp_seq=44 ttl=64 time=0.089 ms
......
// 一直在输出,说明 ping localhost 还在干活儿
// 用 ps 确认一下
ubuntu@ebs-33107:~$ ps aux | grep ping // 表示过滤出有 ping 字符串的进程,后面管道章节详细介绍
ubuntu 12757 0.0 0.0 8604 860 ? S 16:04 0:00 ping localhost
ubuntu 13276 0.0 0.0 17776 924 pts/0 S+ 16:05 0:00 grep --color=auto ping
输入 kill 12757 让它见马克思去,rm nohup.out 清理输出文件。
你可能会看到很多很多使用 nohup 命令的时候带有 >/dev/null 和 2>&1 的命令参数,这是关于输入输出重定向的知识,后面的内容会详细介绍。
到目前为止,你已经学习了大量的 linux 基础知识,虽然有的知识点只是走马观花或者只有一个概念性的东西,学习是不断积累的工程,学习方法比知识本身更重要,一个软件80%的功能我们是用不到的,所以即便你觉得某个知识点很模糊,很肤浅,也不要觉得心理不安,用到时候你再去搜索,再去看看他的帮助,重要的是建立 linux 这一系列的知识体系,哦,原来 linux 是这个样子工作的,随着不断的积累和试错,在脑子里不断修正对它最初的样子,你会发现原来一切都是那么经典。