Linux进程查找:为什么pgrep无法匹配带端口的SSH进程?


阅读 9 次

现象复现

在终端执行以下命令时:

$ ps aux | grep -i ssh
USER      4364  0.0  0.0   9004  1032 ?        Ss   12:20   0:00 ssh -v -fND localhost:4000 USERNAME@SERVER-IP-ADDRESS

$ pgrep localhost:4000

发现pgrep无法匹配到包含localhost:4000参数的SSH进程。

pgrep工作原理

pgrep默认只匹配进程名而非完整命令行参数。查看man手册可知:

-f, --full
    The pattern is normally only matched against the process name.  
    When -f is set, the full command line is used.

正确匹配方式

需要添加-f参数进行全匹配:

# 基础用法(仅匹配进程名)
pgrep ssh

# 完整命令行匹配
pgrep -f "localhost:4000"

# 精确匹配SSH进程(推荐)
pgrep -f "ssh.*localhost:4000"

进阶技巧

结合pkill使用时同样需要注意:

# 危险!可能误杀其他ssh进程
pkill -f "localhost:4000"

# 安全做法(限制信号类型)
pkill -SIGTERM -f "ssh -v.*localhost:4000"

实际案例

编写脚本管理SSH隧道时:

#!/bin/bash
PORT=4000
if ! pgrep -f "ssh.*localhost:$PORT" > /dev/null; then
    echo "启动SSH隧道..."
    ssh -v -fND localhost:$PORT user@example.com
else
    echo "隧道已在运行(PID: $(pgrep -f "ssh.*localhost:$PORT"))"
fi

性能对比

不同查找方式的效率差异:

# 测试100次取平均值
time (for i in {1..100}; do pgrep ssh >/dev/null; done)
# real 0m0.8s

time (for i in {1..100}; do pgrep -f "localhost" >/dev/null; done)  
# real 0m2.3s

全模式匹配会有约3倍性能损耗,在脚本中应合理使用。