查找服务器上存在线程泄露的进程
以下是一个改进的命令,可以列出所有线程数大于200的进程及其PID和线程数:
find /proc -maxdepth 1 -type d -regex '/proc/[0-9]+' -exec sh -c 'for pid_dir dopid=$(basename "$pid_dir")if [ -f "$pid_dir/status" ]; thenthreads=$(awk "/Threads/ {print \$2}" "$pid_dir/status" 2>/dev/null)if [ -n "$threads" ] && [ "$threads" -gt 200 ]; thenecho "PID: $pid, Threads: $threads"fifidone
' sh {} +
命令详解:
-
查找所有PID目录:
find /proc -maxdepth 1 -type d -regex '/proc/[0-9]+'
-maxdepth 1
:只搜索/proc顶层目录-type d
:只匹配目录-regex
:正则匹配纯数字PID目录
-
高效处理目录:
-exec sh -c '...' sh {} +
- 使用
find -exec +
批量处理目录,比逐个处理更高效 - 避免
for i in $(ls)
可能导致的空格问题
- 使用
-
提取线程数:
threads=$(awk "/Threads/ {print \$2}" "$pid_dir/status" 2>/dev/null)
- 使用
awk
精确提取Threads行的第二个字段 2>/dev/null
忽略权限错误或已终止进程
- 使用
-
条件过滤:
if [ -n "$threads" ] && [ "$threads" -gt 200 ]; then
-n "$threads"
:确保成功获取线程数-gt 200
:筛选线程数大于200的进程
输出示例:
PID: 1234, Threads: 250
PID: 5678, Threads: 312
PID: 9012, Threads: 280
优化版本(单行命令):
find /proc -maxdepth 1 -name '[0-9]*' -type d -exec awk -F: '/^Pid|^Threads/ {pid=$2; getline; if($2>200) printf "PID: %d, Threads: %d\n", pid, $2}' {}/status \; 2>/dev/null
关键改进:
- 避免解析
ls
输出:直接使用find
匹配目录,更安全可靠 - 高效批量处理:使用
find -exec +
减少子进程创建 - 错误处理:忽略无法访问的进程目录
- 精确匹配:确保只处理有效进程状态文件
- 完整输出:同时显示PID和线程数
注意:某些系统进程可能无法访问(权限问题),这些会被自动忽略。
写在最后:
springboot内嵌两种Web服务器,Undertow和Tomcat,业务正常情况下线程数都不会大于200太多,如果大太多,那么有可能程序存在线程泄露的问题,更进一步可能会导致业务不可用