Linux管理进程
#Linux进程管理的底层原理 常规的进程管理分为进程查看,进程正常关闭,进程的重启。我们在之前的章节已经学习完了进程查看部分,接下来就要学习进程正常关闭,强制关闭,进程重启。 除了上述说的常规进程管理之外,还有一些额外的进程管理比如中断进程,暂停进程,恢复暂停进程等内容。 实际上软件在开发的时候就定义了特定的进程管理接口,这些接口会通过什么样的方式能管理本软件运行的进程,在Linux系统中标准的进程管理接口就是通过接收不同的信号来定义不同的进程行为。 所以在Linux系统中所谓的进程管理(除了进程查看外),其实就是向进程发送特定的信号,下面我们就会介绍一些能给进程发送信号的命令。
1、kill
kill 是 Linux/Unix 系统中用于向进程发送信号的命令,常用于终止进程、重启进程或触发特定操作。 #信号机制 在 Linux 中,进程间通过信号(Signal) 进行通信。信号是一种异步通知机制,用于通知进程发生了某个事件。每个信号都有一个编号和名称,例如: SIGTERM(15):默认的终止信号,请求进程正常退出(允许清理资源)。 SIGKILL(9):强制终止信号,立即终止进程(无法被阻塞或忽略)。 SIGHUP(1):挂起(hang up)信号,常用于重启服务。 SIGINT(2):中断信号,相当于按下 Ctrl+C。通常用于交互式中断,通知进程需要正常终止。继承自 Unix 早期,用于终端控制。 SIGSTOP(19):暂停信号,暂停进程运行(但不终止)。 SIGCONT(18):继续执行已暂停的进程。 对于运维人员来说,上述提到的信号(SIGTERM、SIGKILL、SIGHUP、SIGINT、SIGSTOP、SIGCONT)在日常的进程管理和服务维护中较为常用,掌握这些信号的含义和基本用法,通常能够满足他们处理大多数常见的进程相关问题,如正常关闭进程、强制终止异常进程、重启服务以及暂停和恢复进程等操作。而开发人员在开发软件时,需要更深入地考虑各种可能的情况,包括进程在不同场景下的行为、与其他进程的交互等,所以往往需要了解更多种类的进程信号,以便更好地控制和管理进程,处理各种复杂的业务逻辑和异常情况。 但在一些复杂的运维场景中,运维人员可能也需要了解更多的进程信号。例如,在处理一些特定的系统故障或性能问题时,可能需要用到其他信号来获取更详细的进程信息或进行特殊的调试操作。 但在一些复杂的运维场景中,运维人员可能也需要了解更多的进程信号。例如,在处理一些特定的系统故障或性能问题时,可能需要用到其他信号来获取更详细的进程信息或进行特殊的调试操作。 #kill 基本语法 kill[选项][信号] PID... PID:进程 ID,可以是单个 PID 或多个 PID(用空格分隔)。 信号:可以是信号名称(如 SIGTERM)、信号编号(如 15)或简写(如 -15)。 #发送不同信号示例 1. 正常终止进程 kill 1234# 默认发送 SIGTERM(15) kill-15 1234# 显式发送 SIGTERM kill-SIGTERM 1234 2. 强制终止进程 kill-9 1234# 发送 SIGKILL kill-SIGKILL 1234 3. 重启服务 kill-1$(pgrep nginx)# 重启 nginx(等价于 nginx -s reload) 4. 暂停和恢复进程 kill-STOP 1234# 暂停 PID 为 1234 的进程 kill-CONT 1234# 恢复运行 #批量操作进程 1. 终止多个进程 kill 1234 5678 9012# 同时终止多个进程 2. 终止所有同名进程 pgrep firefox |xargs kill# 终止所有 firefox 进程 #kill参数选项详解 -l列出所有可用的信号名称和编号。 -s指定要发送的信号名称(如 -s SIGTERM)。 -n指定要发送的信号编号(如 -n 9)。 #常见场景 1.优雅地终止无响应的进程 # 先尝试正常终止 kill 1234 # 等待几秒后,若进程仍在运行,使用强制终止 sleep 5 &&kill-9 1234 #注意事项 慎用 SIGKILL:强制终止可能导致数据丢失或资源泄漏(如文件锁未释放)。 信号优先级:某些进程(如 init 进程)可能忽略 SIGKILL。 PID 复用:进程终止后,其 PID 可能被新进程复用,因此操作前需确认 PID 的正确性。 root 权限:普通用户只能向自己的进程发送信号,root 可向所有进程发送信号。
2、killall
killall 是 Linux/Unix 系统中用于终止指定名称进程的命令,它通过进程名而非 PID 来批量终止进程,使用起来比 kill 更简洁。 #常用选项 -s 信号指定要发送的信号(如 -s SIGKILL 或 -s 9)。 -9 或 -KILL强制终止进程(等价于 -s SIGKILL)。 -15 或 -TERM正常终止进程(等价于 -s SIGTERM,默认行为)。 -i交互式模式,终止前询问确认。 -e精确匹配进程名(必须完全一致)。 -u 用户只终止指定用户的进程。 -w等待所有进程终止后再返回。 -v显示详细的终止过程。 #终止进程示例 1. 终止所有同名进程(部分匹配) killall firefox# 终止所有 firefox 进程(包括 firefox-bin 等变体) 2. 强制终止进程 killall-9 apache2# 强制终止所有apache2进程 3. 交互式终止(确认后执行) killall-i chrome# 终止chrome前询问确认 4. 精确匹配进程名 killall-e python3# 只终止名为"python3"的进程,不匹配"python3.8" 5. 终止特定用户的进程 killall-u root cron# 终止root用户的cron进程 killall是快速终止同名进程的便捷工具,尤其适合批量操作。但使用时需谨慎,避免因部分匹配导致误杀。对于复杂场景,建议结合pkill和pgrep使用,以获得更精确的控制。
3、pkill
pkill 是 Linux/Unix 系统中用于根据进程名、用户、终端等条件查找并终止进程的命令。它结合了 pgrep(查找进程)和 kill(发送信号)的功能,提供更灵活的进程筛选和控制。 #基本语法和常用选项 pkill[选项][信号] 进程名模式 进程名:指定要终止的进程名称(支持部分匹配)。 信号:可选参数,指定要发送的信号(默认为 SIGTERM,即 15)。 -u 用户按用户 ID 或用户名终止进程pkill -u tom(终止用户 tom 的所有进程) -t 终端按终端(TTY)终止进程(如pts/0)pkill -t pts/1(终止第二个终端的进程) -s SID按会话 ID(Session ID)终止进程pkill -s 12345 -g 进程组按进程组 ID(PGID)终止进程pkill -g 23456 -P PID按父进程 ID 终止子进程pkill -P 123(终止 PID 为 123 的所有子进程) -f按完整命令行(而非进程名)匹配(支持部分正则)pkill -f"python /script.py"-i忽略大小写pkill -i Firefox -x精确匹配进程名(而非包含)pkill -x python3(仅匹配名为 "python3" 的进程) -v反向匹配(终止不满足条件的进程)pkill -v-u root(终止非 root 用户的进程) #注意事项 权限限制:普通用户只能终止自己的进程,root 可终止所有进程。 正则表达式风险:使用-f 时需谨慎,避免匹配到无关进程。例如: pkill-f python# 可能误杀包含"python"的其他命令(如"python3.8"、"pyenv") 信号选择:优先使用 SIGTERM(默认)让进程优雅退出,仅在必要时使用 SIGKILL。 进程名 vs 命令行:进程名通常是命令的前部分(如 bash),而命令行包含完整参数(如 bash /script.sh)。
4、taskset
taskset 是 Linux 系统中用于设置或查看进程 / 线程 CPU 亲和性(CPU Affinity)的工具。通过 taskset,你可以将进程或线程绑定到特定的 CPU 核心上运行,从而优化性能或隔离资源。 #线程通俗解释 为了细化进程的工作,可以为进程定义不同线程来代替进程完成不同的工作。可以理解为进程有进程的工作,进程下面的线程有线程的工作。通过这种方式来细化进程的工作,提高程序的执行效率和响应能力,使进程能够同时处理多个任务。可以使用`ps-efL` 查看线程信息。如果是线程,会在输出中显示线程的 ID(LWP)以及所属的进程 ID(PID)等信息;如果是子进程,则会有独立的 PID 和不同的进程状态等信息。不是所有的进程都是多线程的,很多简单的程序可能只包含一个单线程的进程,不过大多服务器进程和图形应用程序都是多线程的,这样更有利于高效处理复杂的业务逻辑、提高资源利用率和响应速度等优点。 #核心概念:CPU 亲和性 CPU 亲和性是指操作系统将进程或线程限制在特定 CPU 核心上运行的机制。绑定 CPU 的主要用途如下: 1. 提高缓存命中率 进程持续在同一 CPU 上运行,可利用 CPU 缓存,减少缓存失效。 2. 避免跨核调度开销 减少进程在不同 CPU 核心间切换的开销。 3. 资源隔离 将关键进程绑定到特定 CPU,避免被其他进程干扰(如数据库、实时任务这种重要业务十分重要)。 #基本语法和常用选项 taskset[选项] [掩码|CPU列表] [命令 [参数...]]# 运行新命令并绑定 CPU taskset[选项] [掩码|CPU列表]-p PID# 修改已运行进程的 CPU 亲和性 -p操作已运行的进程(通过 PID),而非启动新进程。 -c使用 CPU 编号(如 0,1,2)而非掩码(如 0x7)指定 CPU。 -a操作进程的所有线程(而非仅主进程)。 --all-tasks 同 -a,操作所有线程。 #绑定CPU示例 1. 查看 CPU 亲和性 # 查看 PID 为 1234 的进程的 CPU 亲和性 taskset-p 1234 2. 启动新进程并绑定 CPU # 将 nginx 绑定到 CPU 0 taskset-c 0 nginx # 将 MySQL 绑定到 CPU 2 和 3 taskset-c 2,3 mysqld 4.绑定多线程进程的所有线程 # 将 PID 为 1234 的进程的所有线程绑定到 CPU 0-3 taskset-pac 0-3 1234 pid 1234's current affinity mask: f# 掩码表示法(0xf 对应二进制 1111,即 CPU 0-3) pid 1234's current affinity list: 0-3# 列表表示法 #掩码 vs 列表 掩码(Mask):用十六进制表示 CPU 集合,每一位对应一个 CPU。 例如: 0x1 → CPU 0(二进制 0001) 0x3 → CPU 0 和 1(二进制 0011) 0xF → CPU 0-3(二进制 1111) 列表(List):用逗号分隔的 CPU 编号或范围。 例如: 0 → CPU 0 0,2 → CPU 0 和 2 0-3 → CPU 0-3 #实战场景 1. 优化性能 将 CPU 密集型任务绑定到特定核心,避免被其他进程干扰: # 将视频编码任务绑定到 CPU 4-7 taskset-c 4-7 ffmpeg -i input.mp4 output.mp4 2. 隔离关键进程 为数据库服务器预留 CPU 资源: # 将 MySQL 绑定到 CPU 2-5 taskset-c 2-5 mysqld 3. 负载均衡 将多线程应用的线程分布到不同 CPU 上: # 将 Java 应用的所有线程分布到 CPU 0-3 taskset-ca 0-3 java -jar app.jar #注意事项 1. 超线程(HT)处理器 若 CPU 支持超线程(如每个物理核心对应两个逻辑核心),绑定到同一物理核心的不同逻辑核心(如 0,1)可能无法完全隔离资源。 2. 系统负载 过度绑定可能导致资源利用不均,需根据实际负载调整。 3. 权限 普通用户只能修改自己的进程,root 用户可修改所有进程。 4. 与 nice 命令配合 nice 调整进程优先级,taskset 控制 CPU 绑定,两者可结合使用优化资源分配。 通过 taskset,你可以精细化控制进程的 CPU 分配,提升关键应用的性能或实现资源隔离。 #taskset进阶内容 1.taskset 的本质 taskset 设置的是进程的 CPU 亲和性(CPU Affinity),即进程可以运行在哪些 CPU 上,但操作系统仍会调度其他进程到这些 CPU 上。被绑定的进程只会在指定 CPU 上运行,但其他未绑定的进程仍可能被调度到这些 CPU。taskset 本身不支持完全独占 CPU,需要配合其他机制(如 cgroups 或内核参数)实现。 2.为什么 CPU 仍会被其他进程使用? Linux 默认采用 SMP(对称多处理) 架构,所有 CPU 核心共享同一个任务队列。当你使用 taskset 绑定时,若指定 CPU 空闲,其他进程可能被调度到这些 CPU 上。若被绑定的进程处于阻塞状态(如等待 I/O),操作系统会将这些 CPU 分配给其他进程。 3.如何实现 CPU 独占? 若需要完全独占 CPU 核心,避免其他进程干扰,可使用以下步骤 (1)使用grubby更新内核参数隔离 CPU #通用方式 grubby--update-kernel=ALL --args="isolcpus=1-3"#RHEL9.0~9.2 修改/etc/default/grub,添加isolcpus参数 GRUB_CMDLINE_LINUX_DEFAULT="isolcpus=2-3"grub2-mkconfig-o /boot/grub2/grub.cfg #RHEL9.3之后 grub2-mkconfig-o /boot/grub2/grub.cfg --update-bls-cmdline (2)重启和检查 reboot cat /proc/cmdline (3)使用taskset将进程绑定到隔离的CPU (4)移除cpu隔离 grubby--update-kernel=ALL --remove-args="isolcpus=1-3"#适用场景 高性能计算:如数据库、实时系统,需确保关键进程独占CPU。 性能测试:排除其他进程干扰,精确测量性能。 资源隔离:在多租户环境中为特定应用预留CPU。
5、numactl
numactl主要用于处理非统一内存访问(NUMA)架构系统中的内存和 CPU 亲和性。它不仅可以将进程绑定到特定的 CPU 核心,还能指定进程使用的内存节点,以优化内存访问性能,减少跨节点内存访问的延迟。提供了更高级的功能,如自动将进程分配到最合适的 CPU 和内存节点,以及支持内存绑定的策略等。 taskset专注于将进程绑定到特定的 CPU 核心上,通过设置进程的 CPU 亲和性掩码来指定允许进程运行的 CPU 集合。功能相对较为简单直接,主要用于明确指定进程在哪些 CPU 核心上运行,以避免进程在多个 CPU 之间频繁迁移,减少上下文切换开销。 numactl在 NUMA 架构系统中对内存和 CPU 亲和性的管理更为全面和复杂,适用于对内存性能要求较高的场景;而taskset则更侧重于简单直接地控制进程的 CPU 绑定,适用于对 CPU 核心分配有明确需求的情况。在实际使用中,需要根据具体的系统架构、应用需求和性能目标来选择合适的工具和配置方法。 # 绑定到NUMA节点0的所有CPU numactl--cpubind=0 --membind=0 cat /dev/zero # 绑定到CPU 0-3和8-11 numactl--physcpubind=0-1,3-4 cat /dev/zero # 绑定到CPU 0-7,内存交错分配到节点0和1 numactl--physcpubind=0-7 --interleave=0,1 cat /dev/zero # 使用ps显示进程CPU亲和性 ps-o pid,args,psr -p 19478