说实话,使用 pgrep 来查找进程 ID 比 ps aux | grep 那套组合操作要方便得多——至少不用再担心 grep 自身进程混入结果,还得额外加上 grep -v grep 来清理干扰。更关键的是,pgrep 直接读取 procfs 文件系统,不启动新进程,因此完全不会有干扰项。默认输出就是纯数字 PID,每行一个,拿到手后可以直接传给 kill 或 ps 等命令。

直接使用 pgrep 就能干净地获取 PID,无需再写 ps aux | grep 并额外过滤,也避免了 grep 自身进程混入结果的问题。
为什么 pgrep nginx 比 ps aux | grep nginx 更可靠
后者的老毛病在于会把 grep nginx 这一行也当作匹配项输出,必须额外加上 grep -v grep 才能剔除;而 pgrep 直接从 procfs 读取进程信息,不创建新进程,天然没有干扰。此外,还有几个细节值得留意:
- 默认只输出纯数字 PID,每行一个,可直接通过管道传递给
kill、ps等命令 - 内核限制进程名最大显示前 15 个字符,
ps aux显示不全,但pgrep的-f选项可以绕过这个限制 - 不存在“意外匹配”:比如查询
bash,pgrep bash不会匹配到bashful或rbash(除非加上-i或使用正则)
pgrep -f 匹配完整命令行才是日常刚需
许多服务启动时进程名仍然是 python 或 java,真正区分它们要靠参数。此时只查询进程名根本无法找到目标。而 pgrep -f 能够匹配完整的命令行,在这种场景下才是真正的利器:
pgrep -f "python manage.py runserver"→ 找到 Django 开发服务器pgrep -f "java.*-jar.*app.jar"→ 匹配带 jar 参数的 Java 进程pgrep -f "nginx: worker process"→ 区分 master 进程和 worker 进程(注意空格和冒号要写全)- 不使用
-f时,pgrep python可能返回几十个无关的 Python 进程
按用户、精确名称、数量统计等操作,别硬记参数
实际运维中高频组合就那么几个,记住应用场景比死背选项更有效:
- 查询某个用户的全部相关进程:
pgrep -u www-data nginx - 确认是否只有一个实例在运行:
pgrep -c nginx返回1才放心 - 只想杀掉最旧的那个(比如重启后遗留的旧进程):
pgrep -o nginx | xargs kill - 确保完全匹配进程名,避免误伤:
pgrep -x sshd不会匹配到sshd_config或ssh-agent - 多个关键词一起查询:
pgrep -f "redis|mysql"(注意 shell 会解释管道符,需要加引号)
容易被忽略的细节:分隔符、空格、权限
pgrep 输出默认以换行分隔,但在脚本里拼接命令时可能需要逗号或空格——这时候 -d 就不能省略:
pgrep -d, -f "node server.js"→ 输出1234,5678,方便嵌入到kill命令中- 命令行里有空格或特殊字符(如
./my script.sh),必须用双引号包裹整个模式,单引号不行(shell 不会展开变量) - 普通用户只能查看自己的进程,
pgrep -u root必须用 root 权限执行,否则静默返回空 pgrep -P $PID查询子进程时,如果父进程已退出,结果为空——不是命令错误,而是进程树已经改变
