这个循环有什么问题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 ... fi
在while; 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 -n
但getconf OPEN_MAX
root 可以更改这一点。在 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
在zsh
Linux 上,你可以这样做:
(){ 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