欢迎来到罐子的实验室
本次目标
理解「进程」是什么,学会查看、终止、挂起、前后台切换正在运行的程序,读懂退出码。
学完你能做什么:
- 用
Ctrl-C / Ctrl-Z / fg / bg 控制前台后台
1. 进程是什么
每当你运行一个命令,Linux 内核就给它分配一个进程(process)——一个正在运行的程序实例,带一个唯一的编号 PID(进程 ID)。
你的 Shell 是个进程,你跑的 ls、vim、浏览器都是进程。开机时 Linux 启动第一个进程(PID 1),它再启动一堆别的进程,层层派生。
管理这些进程——看它们、停它们、让它们后台跑——就是本模块的内容。
2. ps:列出进程
ps(process status)列出进程。最常用的两种写法:
user@host:~$ ps -ef# 标准语法,-e 全部,-f 完整格式UID PID PPID C STIME TTY TIME CMDroot 1 0 0 09:00 ? 00:00:02 /sbin/inituser 500 1 0 09:01 ? 00:00:00 /usr/lib/code-serveruser 800 500 0 09:02 pts/0 00:00:00 bashuser 900 800 0 09:03 pts/0 00:00:00 ps -ef
或:
user@host:~$ ps aux# BSD 语法,a 所有用户,u 详细,x 无终端的也显示USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND...
两种都行,记一种就够。关键列:
| |
|---|
PID | |
PPID | |
USER | |
%CPU | |
STAT | |
COMMAND | |
💡 输出可能被终端宽度截断,看不全命令。用 ps -efww 或 ps auxww(两个 w)禁用截断。
动手练习 1:找到自己的进程
任务:列出所有你启动的进程。
思路引导:ps -u $USER 或 ps -ef | grep $USER。
参考答案:
user@host:~$ ps -u $USER PID TTY TIME CMD 800 pts/0 00:00:00 bash 900 pts/0 00:00:00 ps
常见错误:ps 不带任何参数只列当前终端的进程,看不到系统全局的——要 -e 或 aux。
3. kill:终止进程
kill 给进程发信号,默认发的是 TERM(终止),让进程「体面地」结束:
user@host:~$ sleep 1000 &# 启动个后台 sleep[1] 12345# 它的 PID 是 12345user@host:~$ kill 12345# 用 PID 杀它user@host:~$
kill 的参数是 PID,不是进程名。先 ps 找到 PID,再 kill。
信号类型
kill -9 PID 是「核选项」——进程卡死、不理 TERM 时才用。kill -9 会让程序来不及保存数据就死。
user@host:~$ kill 12345# 先礼后兵:发 TERMuser@host:~$ kill -9 12345# 还不死?发 KILL
💡 按 PID 杀要先用 ps 查;pkill 名字 和 killall 名字 可以按名字杀,但要小心匹配范围。
动手练习 2:杀掉一个 sleep
任务:
- 启动
sleep 300 &(后台运行 5 分钟)。 kill
参考答案:
user@host:~$ sleep 300 &[1] 12345user@host:~$ ps | grep sleep12345 pts/0 00:00:00 sleepuser@host:~$ kill 12345user@host:~$ ps | grep sleep# 没输出,说明已终止
常见错误:
- ❌
kill sleep(传了名字)→ kill: kill sleep: no such process,kill 要 PID。 - ⚠️ 杀了别人的进程会
Operation not permitted——你只能杀自己的(root 除外,→ 详见《模块 10》)。
4. Ctrl-C:中断前台进程
如果一个程序占着你的终端(前台运行),按 Ctrl-C 给它发中断信号,通常能让它退出:
user@host:~$ sleep 1000^C# 按 Ctrl-Cuser@host:~$
Ctrl-C 是「我想停掉这个」最常用的快捷键。
动手练习 3:中断一个长任务
任务:运行 sleep 1000(前台),然后用 Ctrl-C 中断它,确认回到提示符。
参考答案:
user@host:~$ sleep 1000^Cuser@host:~$
常见错误:Ctrl-C 只能中断前台进程,后台进程要用 kill。
5. Ctrl-Z:挂起(不终止)
Ctrl-Z 把前台进程挂起(suspend,暂停)并放回后台,不终止它——你可以稍后恢复:
user@host:~$ sleep 1000^Z[1]+ Stopped sleep 1000user@host:~$
[1] 是作业号(job 1),Stopped 表示它被暂停了。现在你能继续在终端敲别的命令,那个 sleep 还「活着」但不动。
动手练习 4:挂起一个任务
任务:运行 sleep 1000,挂起它,然后 ps 看它还在不在(只是 Stopped 状态)。
参考答案:
user@host:~$ sleep 1000^Z[1]+ Stopped sleep 1000user@host:~$ ps PID ... STAT CMD 12345 ... T sleep 1000# STAT 是 T,表示 stopped
💡 STAT 列含义见第 7 节,T = stopped。
6. fg / bg / &:前后台切换
挂起之后怎么办?
fg(foreground)把挂起的进程恢复到前台继续运行。bg命令 &
user@host:~$ sleep 1000^Z[1]+ Stopped sleep 1000user@host:~$ bg# 放后台继续跑[1]+ sleep 1000 &user@host:~$ fg# 又拉回前台sleep 1000^C# 不想要了,Ctrl-C 终止user@host:~$
直接后台启动:
user@host:~$ sleep 1000 &[1] 12345user@host:~$# 立刻回到提示符,sleep 在后台跑
有多个后台作业时用作业号指定:fg %1、bg %2。jobs 命令列出当前所有作业。
动手练习 5:前后台切换
任务:
Ctrl-Zjobs
参考答案:
user@host:~$ sleep 1000 &[1] 12345user@host:~$ fgsleep 1000^Z[1]+ Stopped sleep 1000user@host:~$ bg[1]+ sleep 1000 &user@host:~$ jobs[1]+ Running sleep 1000 &
常见错误:fg / bg 不带参数只对最近一个作业操作,多个作业会混淆——养成用 %N 指定的习惯。
7. STAT 列:看进程状态
ps 的 STAT 列用字母表示进程当前状态:
| |
|---|
R | running / runnable(运行中或等待 CPU) |
S | interruptible sleep(可中断睡眠,大多数进程常态) |
D | uninterruptible sleep(深度睡眠,通常在等 IO) |
T | |
Z | |
附加符号:
例:
动手练习 6:解读状态
任务:挂起一个 sleep,用 ps -o pid,stat,cmd 看它的 STAT。
参考答案:
user@host:~$ sleep 1000^Z[1]+ Stopped sleep 1000user@host:~$ ps -o pid,stat,cmd PID STAT CMD 800 Ss bash 12345 T sleep 1000 ← T 表示 stopped 12346 R+ ps -o pid,stat,cmd ← R+ 表示前台运行
8. 退出码 $?
每个命令结束都返回一个退出码(exit code):0 表示成功,非 0 表示失败(具体数字代表不同错误)。
用 $? 读取上一条命令的退出码(→ 变量详见《模块 08》):
user@host:~$ ls /etc > /dev/nulluser@host:~$ echo $?0# 成功user@host:~$ ls /不存在ls: cannot access '/不存在': No such file or directoryuser@host:~$ echo $?2# 失败,码 2
退出码是命令间协作的基础——&&、||、if 都靠它判断(→ 详见《模块 11》)。
动手练习 7:判断成功
任务:写一条命令——「如果 /etc/passwd 存在就打印 OK」。用 test -f /etc/passwd && echo OK。
参考答案:
user@host:~$ test -f /etc/passwd && echo OKOKuser@host:~$ test -f /nope && echo OK# 不打印,因为 test 失败
(test -f 文件 在文件存在时返回 0。)
9. 实战场景:排查卡死的进程
真实工作中常遇到:某个程序卡死、占 CPU 100%、或者端口被占用。排查套路:
ps aux | grep 程序名kill PID- 端口占用用
ss -tlnp | grep 端口号(需要 root 看进程名)。
动手练习 8:模拟排查
任务:
ps aux | grep sleepkill
参考答案:
user@host:~$ sleep 999 &[1] 12345user@host:~$ ps aux | grep '[s]leep'# [s]leep 技巧避免 grep 匹配到自己user 12345 ... sleep 999user@host:~$ kill 12345
💡 ps aux | grep sleep 会把 grep sleep 自己也列出来(因为它含 sleep 字样)。写 grep '[s]leep' 是个老技巧:正则 [s]leep 匹配 sleep,但不匹配字面的 [s]leep,于是排除了 grep 自己。
本模块速查表
| |
|---|
ps -ef | |
ps -u $USER | |
kill PID | |
kill -9 PID | |
Ctrl-C | |
Ctrl-Z | |
fg | |
命令 & | |
jobs | |
$? | |
STAT 字母速记
R=运行 S=睡眠 D=深度睡眠 T=暂停 Z=僵尸+=前台 s=会话首领 l=多线程
kill 信号
TERM(15)=请求终止(默认)KILL(9)=强制杀死(核选项)INT(2)=中断(同 Ctrl-C)
下一步
你启动的进程都以「你自己」的身份运行。但 Linux 是多用户系统——谁能做什么,由用户和权限决定。这是 Linux 安全的地基。