现象复现
在终端执行以下命令时:
$ 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倍性能损耗,在脚本中应合理使用。