进程是 Linux 上运行程序的实例。控制进程就相当于让系统按照你的意图执行任务、暂停、恢复或终止它们。本节介绍最常用的进程控制操作,从查看进程到发送信号,再到管理前后台任务,所有这些命令都可以立即在终端中使用。
1. 查看进程
最经典的两个命令是 ps 和 top。
ps:查看当前时刻的进程快照。
ps aux # 显示所有用户的所有进程,包含 CPU、内存占用
ps -ef # 另一种常见格式,显示父进程 ID 等
top或htop:实时刷新进程列表,按照 CPU 或内存排序。
top # 进入交互界面,按 q 退出
htop # 更友好的界面,彩色、可鼠标点击(需单独安装)
示例:如果你怀疑某个程序 CPU 占用过高,可以用 top 迅速定位,然后按 k(在 top 中)输入进程 ID 和信号 15 来终止它。
2. 前台与后台任务
当你在终端运行一个命令时,它会占用当前终端,直到执行完毕,这称为前台进程。如果想让命令在后台运行,可以在命令末尾加 &:
long_running_command &
此时终端会返回一个作业号(job number)和进程 ID(PID),然后你可以继续输入其他命令。
管理这些前后台作业的常用命令:
jobs:列出当前终端下的所有后台作业。fg %1:把作业号 1 的后台程序拉到前台。bg %1:让被暂停(Ctrl+Z)的作业在后台继续运行。Ctrl+Z:暂停当前前台进程,并放入后台暂停状态。
例如,你正在编辑配置文件,临时想查看一个日志,可以按 Ctrl+Z 暂停编辑器,用 cat 查看完毕后,再 fg 回到编辑器。
3. 脱离终端:nohup 和 disown
默认情况下,启动后台任务的那个终端如果关闭,系统会向该终端上的所有进程发送 SIGHUP 信号,常常导致进程退出。为了避免这种情况:
nohup:运行命令的同时忽略挂断信号,并将输出重定向到nohup.out。
nohup long_task &
disown:如果已经用&将任务放入后台,可以:
long_task &
disown %1 # 将作业1从终端的作业列表中移除,关闭终端时不会收到 SIGHUP
对于需要长久运行的服务,更规范的做法是使用 systemd 或 supervisor 等服务管理器,但临时任务用 nohup 和 disown 非常快捷。
4. 终止进程与信号
kill 命令其实不是专门用来“杀死”进程的,而是用来发送信号。默认发送的是 SIGTERM(信号 15),它礼貌地请求进程自行退出。如果进程卡死不响应,可以使用 SIGKILL(信号 9)强制终止。
kill 1234 # 发送 SIGTERM 给 PID 1234
kill -9 1234 # 发送 SIGKILL 强制终止(最后手段)
kill -STOP 1234 # 暂停进程(相当于 Ctrl+Z 但可针对任意进程)
kill -CONT 1234 # 恢复被暂停的进程
也可以使用 pkill 按进程名匹配:
pkill -f my_server.py # 终止所有命令行里包含 my_server.py 的进程
killall 按进程名精确匹配,但需注意不同发行版行为可能略有差异,通常 pkill 更灵活。
5. 进程优先级与资源限制
nice和renice:调整进程的 CPU 调度优先级。优先级值范围从 -20(最高优先级)到 19(最低优先级)。普通用户只能提升优先级值(降低优先级),root 可以任意设置。
nice -n 10 tar czf big.tar.gz . # 以较低优先级运行压缩
renice 5 -p 1234 # 将进程 1234 的优先级设为 5
ulimit:限制当前 shell 及其子进程能使用的资源,比如最大打开文件数、最大内存等。对于防止某个程序耗尽系统资源很有效。
ulimit -a # 查看所有限制
ulimit -n 4096 # 设置最大打开文件数为 4096
cgroups(控制组):现代 Linux 使用 cgroups 更精细地限制进程的 CPU、内存、I/O,通常由容器运行时或 systemd 来配置,但也可以手动操作(详见相关高级章节)。
6. 守护进程
守护进程(daemon)是在后台长期运行的服务进程,不依赖任何终端。传统的编程方式会通过两次 fork() 来创建守护进程,但现在更推荐使用 systemd 的服务文件或现代的进程管理器。作为用户,你只需关注如何管理已有服务:
systemctl status sshd
systemctl restart nginx
如果需要把自己的程序临时当作守护进程运行,可以考虑 setsid 命令,它会将进程移到一个新的会话里,摆脱终端:
setsid my_server &
进程控制是系统管理的核心技能。掌握这些命令和概念,你就能灵活地调度计算资源,优雅地停止或重启服务,以及在长期运行脚本时避免因终端关闭而被打断。