如何找到具有最大文件描述符的进程?

如何找到具有最大文件描述符的进程?

这个循环有什么问题for?我试图找到哪个进程拥有最大数量的文件描述符。for循环中的第一个命令ps aux | awk '{print $2}'仅打印出进程 ID。我知道第一个错误lsof: illegal process ID: PID存在,因为输出的第一行是PID,但是循环不应该对其余行正常工作吗?

[root@serv5 ~]# for i in `ps aux | awk '{print $2}'` ; do `lsof -p $i | wc -l` ; done
lsof: illegal process ID: PID
lsof 4.82
 latest revision: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/
 latest FAQ: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ
 latest man page: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/lsof_man
 usage: [-?abhlnNoOPRtUvVX] [+|-c c] [+|-d s] [+D D] [+|-f[gG]] [+|-e s]
 [-F [f]] [-g [s]] [-i [i]] [+|-L [l]] [+m [m]] [+|-M] [-o [o]] [-p s]
[+|-r [t]] [-s [p:s]] [-S [t]] [-T [t]] [-u s] [+|-w] [-x [fl]] [--] [names]
Use the ``-h'' option to get more help information.
-bash: 0: command not found
-bash: 22: command not found
-bash: 4: command not found
-bash: 4: command not found
-bash: 4: command not found
-bash: 4: command not found
^C
[root@serv5 ~]#

为什么它执行输出wc -l而不是返回循环?

或者还有其他方法可以找到具有最大文件描述符的进程吗?

答案1

问题是您所在do ... done部分中的反引号。

编写 shell 脚本时,不需要将块( 、 等)封装if; then ... fiwhile; do ... done反引号中。这样做会导致 shell 评估反引号的内容,然后执行该内容。因此,反引号返回一个数字(打开文件的数量),然后尝试运行该数字,从而产生command not found.

因此你想要:

for i in `ps aux | awk '{print $2}'` ; do lsof -p $i | wc -l ; done

答案2

这是很多年前的问题,但是OP所问的问题应该可以通过使用

lsof | awk '{print $2}'| uniq -c| sort -n

这将打印每个 pid 打开的文件数。

答案3

(正如 val0x00ff 和 Patrick 所指出的,您的循环不需要``通过命令替换来导致问题。这是关于寻找另一种方法来解决问题的第二部分。)

您可以直接使用以下命令显示每个进程的文件描述符数量lsof

lsof -Fpcn | nawk '
 /^p/ { pid=substr($0,2) }
 /^c/ { cmd=substr($0,2) }
 /^n/ { fd[cmd"["pid"]"]++ }
 END  { for (cc in fd) printf("%-20s %i\n",cc,fd[cc]) } ' | sort -n -k 2

这应该适用于大多数带有lsof.

-Fpcn选项输出一个“机器可读”格式,标记每一行:

  • 带有前导“p”的 PID
  • 带有前导“c”的命令(名称)输出
  • 带有前导“n”的文件描述符输出

awk 脚本使用关联数组(由“command[pid]”索引)跟踪文件描述符计数,并在END{}输入处转储该数组。

这些 FD 计数通常与其他方法不同,值得注意的ps是,/proc/PID/fd因为lsof计数不仅仅是实际文件描述符,特别是内存映射文件,可能会导致某些进程的数字丢失。

如果您想要实际 FD 的准确计数,您需要添加“-d0-999999”以将输出限制lsof为仅数字文件描述符。从技术上讲,高数字应该至少是每个进程的最大 FD 数量,可以使用 或 来确定这一点,ulimit -ngetconf OPEN_MAXroot 可以更改这一点。在 Linux 上,您可以在 中检查每个进程的限制/proc/PID/limits,并且可以将其用作/proc/sys/fs/file-nr上限。

在 Linux 系统上计算文件描述符的其他廉价而令人愉快的方法是/proc

(cd /proc; ls -d [0-9]* ) | while read pid; do set -- /proc/$pid/fd/*; echo $pid $#; done
ps axo "pid" | while [...]

答案4

zshLinux 上,你可以这样做:

(){ pid=$1:t; } /proc/<->(nOe['(){ REPLY=$#; } $REPLY/fd/*(N)'])

进入$pid具有最多打开文件描述符的进程的 pid。

更详细的版本可能是:

by_number_of_fds() {
  local process_dir=${1-$REPLY}
  local -a fds=( $process_dir/fd/*(N) )
  REPLY=$#fds
}
process_dirs_sorted_by_number_of_fds=(
  /proc/<->(O+by_number_of_fds)
)
pid_with_most_fds=$process_dirs_sorted_by_number_of_fds[1]:t

相关内容