proc,lsof,ulimit
http://www.eygle.com/archives/2011/12/oracle_lsof_recovery_database.html
对于Oracle数据库来说,如果有文件被删除,只要文件句柄未关闭,则就可以在lsof的输出中看到标记为deleted的状态标记.
通过 proc 下的文件目录,可以找到文件句柄信息,这个就是Oracle的数据文件:
root@db2 # ls -l /proc/762/fd/329
-rw-r----- 1 oracle dba 1048584192 Dec 20 10:16 /proc/762/fd/329
可以通过复制拷贝恢复这个文件。
-The End-
http://xiaoz5919.iteye.com/blog/609957
Brock 老兄写了一篇文章《你从未用过的 10 条 Linux 命令(10 Linux commands you've never used)》,虽然标题有点过于绝对和主观,不过文章还是不错的。其实,无论你是否听说过或者使用过这些命令,都值得我们再来重温一遍。不是吗?
这 10 条 Linux 命令依次是:
- pgrep:比如,你可以使用
pgrep -u root
来代替ps -ef | egrep '^root ' | awk '{print $2}'
,以便抓取属于 root 的 PID。 - pstree:我觉得这个命令很酷,它可以直接列出进程树,或者换句话说是按照树状结构来列出进程。
- bc:这个命令在我的系统中没有找到,可能需要安装。这是用来执行计算的一个命令,如使用它来开平方根。
- split:这是一个很有用的命令,它可以将一个大文件分割成几个小的部分。比如:
split -b 2m largefile LF_
会将 largefile 分割成带有 LF 文件名前缀且大小为 2 MB 的小文件。 - nl:能够显示行号的命令。在阅读脚本或代码时,这个命令应该非常有用。如:
nl wireless.h | head
。 - mkfifo:作者说这是他最喜欢的命令。该命令使得其他命令能够通过一个命名的管道进行通信。嗯,听起来有点空洞。举例说明,先创建一个管道并写入内容:
mkfifo ive-been-piped ls -al split/* | head > ive-been-piped
然后就可以读取了:
head ive-been-piped
。 - ldd:其作用是输出指定文件依赖的动态链接库。比如,通过
ldd /usr/java/jre1.5.0_11/bin/java
可以了解哪些线程库链接到了java 依赖(动态链接)了哪些库。(感谢 NetSnail 的指正。) - col:可以将 man 手册页保存为无格式的文本文件。如:
PAGER=cat man less | col -b > less.txt
- xmlwf:能够检测 XML 文档是否良好。比如:
curl -s 'http://bashcurescancer.com' > bcc.html xmlwf bcc.html perl -i -pe 's@<br/>@<br>@g' bcc.html xmlwf bcc.html bcc.html:104:2: mismatched tag
- lsof:列出打开的文件。如:通过
lsof | grep TCP
可以找到打开的端口。
这 10 条 Linux 命令,有些的确比较鲜为人知。我个人也只用过其中很少的几个命令,像 col、split、lsof 等等。当然,有些大牛们可能全部都用过。通过引荐本文,希望我们能够更加重视 Linux 命令的使用。
http://www.linuxfly.org/post/73/
在使用linux做为关键应用的过程中,特别是大压力负载的时候,经常会遇到一些诸如“too many open files”,“系统默认最大线程数是多少?如何调整?”等问题。此时,我们就必须使用ulimit或proc去调整系统的某些参数。
一、区别
ulimit和对proc目录都可以作出某些限制,但它们之间是有区别的:
1、ulimit命令:
1)直接使用ulimit命令,只对当前tty(终端有效),若要每次都生效的话,可以把ulimit参数放到对应用户的.bash_profile里面;
2)针对所有用户的设置,在/etc/security/limits.conf文件,其是可以对系统用户、组进行cpu、文件数等限制的,通过它可以针对某个用户或全部进行限制。但不能超越系统的限制;
(*表示所有用户、soft表示可以超出,但只是警告;hard表示绝对不能超出,unlimited用于表示不限制)
3)另一方法是,如果想对所有用户设置,也可以放在/etc/profile文件里面,下面是该文件里面的默认参数:
2、/proc目录:
1)/proc目录里面包括很多系统当前状态的参数,例如:
/proc/sys/fs/inode-max
是对整个系统的限制,并不是针对用户的;
2)proc目录中的值可以进行动态的设置,若希望永久生效,可以修改/etc/sysctl.conf文件,并使用下面的命令确认:
例如增加:
fs.inode-max=xxx
二、ulimit命令简介
(以下引用网上的部分资料)
1、说明:
ulimit用于shell启动进程所占用的资源.
2、类别:
shell内建命令
3、语法格式:
ulimit [-acdfHlmnpsStvw] [size]
4、参数介绍:
-S 设置软件资源限制.
-a 显示当前所有的资源限制.
-c size:设置core文件的最大值.单位:blocks
-d size:设置数据段的最大值.单位:kbytes
-f size:设置创建文件的最大值.单位:blocks
-l size:设置在内存中锁定进程的最大值.单位:kbytes
-m size:设置可以使用的常驻内存的最大值.单位:kbytes
-n size:设置内核可以同时打开的文件描述符的最大值.单位:n
-p size:设置管道缓冲区的最大值.单位:kbytes
-s size:设置堆栈的最大值.单位:kbytes
-t size:设置CPU使用时间的最大上限.单位:seconds
-v size:设置虚拟内存的最大值.单位:kbytes
unlimited 是一个特殊值,用于表示不限制
5、简单实例:
如果我们想要对由shell创建的文件大小作些限制,如:
引用:
-rw-r--r-- 1 javalee javalee 150062 7月 22 02:39 h
[/home/javalee]ulimit -f 100 #设置创建文件的最大块(一块=512字节)
[/home/javalee]cat h>newh
File size limit exceeded
[/home/javalee]
[/home/javalee]ll newh
-rw-r--r-- 1 javalee javalee 51200 11月 8 11:47 newh
文件h的大小是150062字节,而我们设定的创建文件的大小是512字节x100块=51200字节,当然系统就会根据你的设置生成了51200字节的newh文件。
若要每次都生效,把你要设置的ulimit放在/etc/profile这个环境文件中即可。
※ 注意,不同的核心版本,ulimit 可设定的值可能会有不同,详细可参考系统中的/etc/security.limit.conf 文件或man 2 setrlimit 中的说明。另外,ulimit -u 可限制普通用户可打开的最大进程(线程)值,但对root 用户无效。
三、实例说明
对于一般的应用来说(象Apache、系统进程)1024完全足够使用。但是如何象squid、mysql、java等单进程处理大量请求的应用来说就有点捉襟见肘了。如果单个进程打开的文件句柄数量超过了系统定义的值,就会提到“too many files open”的错误提示。如何知道当前进程打开了多少个文件句柄呢?下面一段小脚本可以帮你查看:
在系统访问高峰时间以root用户执行上面的脚本,可能出现的结果如下:
131 24204
57 24244
57 24231
56 24264
其中第一行是打开的文件句柄数量,第二行是进程号。得到进程号后,我们可以通过ps命令得到进程的详细内容。
mysql 24204 24162 99 16:15 ? 00:24:25 /usr/sbin/mysqld
哦,原来是mysql进程打开最多文件句柄数量。但是他目前只打开了131个文件句柄数量,远远底于系统默认值1024。
但是如果系统并发特别大,尤其是squid服务器,很有可能会超过1024。这时候就必须要调整系统参数,以适应应用变化。以root用户运行以下命令:
以上命令中,H指定了硬性大小,S指定了软性大小,n表示设定单个进程最大的打开文件句柄数量。个人觉得最好不要超过4096,毕竟打开的文件句柄数越多响应时间肯定会越慢。设定句柄数量后,系统重启后,又会恢复默认值。如果想永久保存下来,可以修改.bash_profile文件,可以修改 /etc/profile 把上面命令加到最后。
四、/proc目录配置
由于/proc目录涉及的配置非常多,包括网络、文件系统等,后续以一篇独立的文章进行吧。
※实际应用中,需要分析清楚问题出现的原因,根据实际情况灵活配置!
http://www.l99.com/EditText_view.action?textId=465578&client=
lsof(list open files)是一个列出当前系统打开文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。
常用的参数列表:
lsof filename 显示打开指定文件的所有进程
lsof -a 表示两个参数都必须满足时才显示结果
lsof -c string 显示COMMAND列中包含指定字符的进程所有打开的文件
lsof -u username 显示所属user进程打开的文件
lsof -g gid 显示归属gid的进程情况
lsof +d /DIR/ 显示目录下被进程打开的文件
lsof +D /DIR/ 同上,但是会搜索目录下的所有目录,时间相对较长
lsof -d FD 显示指定文件描述符的进程
lsof -n 不将IP转换为hostname,缺省是不加上-n参数
lsof -i 用以显示符合条件的进程情况
查看22端口现在运行的情况 lsof -i :22
查看所属root用户进程所打开的文件类型为txt的文件 lsof -a -u root -d txt
ulimit用于shell启动进程所占用的资源.
,参数介绍:
-H 设置硬件资源限制.
-S 设置软件资源限制.
-a 显示当前所有的资源限制.
-c size:设置core文件的最大值.单位:blocks
-d size:设置数据段的最大值.单位:kbytes
-f size:设置创建文件的最大值.单位:blocks
-l size:设置在内存中锁定进程的最大值.单位:kbytes
-m size:设置可以使用的常驻内存的最大值.单位:kbytes
-n size:设置内核可以同时打开的文件描述符的最大值.单位:n
-p size:设置管道缓冲区的最大值.单位:kbytes
-s size:设置堆栈的最大值.单位:kbytes
-t size:设置CPU使用时间的最大上限.单位:seconds
-v size:设置虚拟内存的最大值.单位:kbytes
http://www.ibm.com/developerworks/cn/aix/library/au-lsof.html
在 UNIX® 环境中,文件无处不在,这便产生了一句格言:“任何事物都是文件”。通过文件不仅仅可以访问常规数据,通常还可以访问网络连接和硬件。在有些情况下,当您使用 ls
请求目录清单时,将出现相应的条目。在其他情况下,如传输控制协议 (TCP) 和用户数据报协议 (UDP) 套接字,不存在相应的目录清单。但是在后台为该应用程序分配了一个文件描述符,无论这个文件的本质如何,该文件描述符为应用程序与基础操作系统之间的交互提供了通用接口。
因为应用程序打开文件的描述符列表提供了大量关于这个应用程序本身的信息,所以能够查看这个列表将是很有帮助的。完成这项任务的实用程序称为 lsof
,它对应于“list open files”(列出打开的文件)。几乎在每个 UNIX 版本中都有这个实用程序,但奇怪的是,大多数供应商并没有将其包含在操作系统的初始安装中。要获取更多关于 lsof
的信息,请参见参考资料部分。
只需输入 lsof
就可以生成大量的信息,如清单 1 所示。因为 lsof
需要访问核心内存和各种文件,所以必须以 root 用户的身份运行它才能够充分地发挥其功能。
bash-3.00# lsof COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sched 0 root cwd VDIR 136,8 1024 2 / init 1 root cwd VDIR 136,8 1024 2 / init 1 root txt VREG 136,8 49016 1655 /sbin/init init 1 root txt VREG 136,8 51084 3185 /lib/libuutil.so.1 vi 2013 root 3u VREG 136,8 0 8501 /var/tmp/ExXDaO7d ... |
每行显示一个打开的文件,除非另外指定,否则将显示所有进程打开的所有文件。Command
、PID
和 User
列分别表示进程的名称、进程标识符 (PID) 和所有者名称。Device
、SIZE/OFF
、Node
和 Name
列涉及到文件本身的信息,分别表示指定磁盘的名称、文件的大小、索引节点(文件在磁盘上的标识)和该文件的确切名称。根据 UNIX 版本的不同,可能将文件的大小报告为应用程序在文件中进行读取的当前位置(偏移量)。清单 1 来自一台可以报告该信息的 Sun Solaris 10 计算机,而 Linux® 没有这个功能。
FD
和 Type
列的含义最为模糊,它们提供了关于文件如何使用的更多信息。FD
列表示文件描述符,应用程序通过文件描述符识别该文件。Type
列提供了关于文件格式的更多描述。我们来具体研究一下文件描述符列,清单 1 中出现了三种不同的值。cwd
值表示应用程序的当前工作目录,这是该应用程序启动的目录,除非它本身对这个目录进行更改。txt
类型的文件是程序代码,如应用程序二进制文件本身或共享库,再比如本示例的列表中显示的 init
程序。最后,数值表示应用程序的文件描述符,这是打开该文件时返回的一个整数。在清单 1 输出的最后一行中,您可以看到用户正在使用 vi
编辑 /var/tmp/ExXDaO7d,其文件描述符为 3。u
表示该文件被打开并处于读取/写入模式,而不是只读 (r
) 或只写 (w
) 模式。有一点不是很重要但却很有帮助,初始打开每个应用程序时,都具有三个文件描述符,从 0 到 2,分别表示标准输入、输出和错误流。正因为如此,大多数应用程序所打开的文件的 FD 都是从 3 开始。
与 FD
列相比,Type
列则比较直观。根据具体操作系统的不同,您会发现将文件和目录称为 REG
和 DIR
(在 Solaris 中,称为 VREG
和VDIR
)。其他可能的取值为 CHR
和 BLK
,分别表示字符和块设备;或者 UNIX
、FIFO
和 IPv4
,分别表示 UNIX 域套接字、先进先出 (FIFO) 队列和网际协议 (IP) 套接字。
尽管与使用 lsof
没有什么直接的关系,但对 /proc 目录进行简要的介绍是有必要的。/proc 是一个目录,其中包含了反映内核和进程树的各种文件。这些文件和目录并不存在于磁盘中,因此当您对这些文件进行读取和写入时,实际上是在从操作系统本身获取相关信息。大多数与 lsof
相关的信息都存储于以进程的 PID 命名的目录中,所以 /proc/1234 中包含的是 PID 为 1234 的进程的信息。
在 /proc 目录的每个进程目录中存在着各种文件,它们可以使得应用程序简单地了解进程的内存空间、文件描述符列表、指向磁盘上的文件的符号链接和其他系统信息。lsof
实用程序使用该信息和其他关于内核内部状态的信息来产生其输出。稍后我将把 lsof
的输出与 /proc 目录中的信息联系起来。
前面,我向您介绍了如何简单地运行不带任何参数的 lsof
,以便显示关于每个进程所打开的文件的信息。本文余下的部分将重点关注如何使用 lsof
来显示所需的信息以及如何正确地对其进行解释。
lsof
常见的用法是查找应用程序打开的文件的名称和数目。您可能想尝试找出某个特定应用程序将日志数据记录到何处,或者正在跟踪某个问题。例如,UNIX 限制了进程能够打开文件的数目。通常这个数值很大,所以不会产生问题,并且在需要时,应用程序可以请求更大的值(直到某个上限)。如果您怀疑应用程序耗尽了文件描述符,那么可以使用 lsof
统计打开的文件数目,以进行验证。
要指定单个进程,可以使用 -p
参数,后面加上该进程的 PID。因为这样做不仅会返回该应用程序所打开的文件,还会返回共享库和代码,所以通常需要对输出进行筛选。要完成此任务,可以使用 -d
标志根据 FD
列进行筛选,使用 -a
标志表示两个参数都必须满足 (AND)。如果没有 -a
标志,缺省的情况是显示匹配任何一个参数 (OR) 的文件。清单 2 显示了 sendmail
进程打开的文件,并使用 txt 对这些文件进行筛选。
清单 2. 带有 PID 筛选器并进行 txt 文件描述符筛选的 lsof 输出
sh-3.00# lsof -a -p 605 -d ^txt COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sendmail 605 root cwd VDIR 136,8 1024 23554 /var/spool/mqueue sendmail 605 root 0r VCHR 13,2 6815752 /devices/pseudo/mm@0:null sendmail 605 root 1w VCHR 13,2 6815752 /devices/pseudo/mm@0:null sendmail 605 root 2w VCHR 13,2 6815752 /devices/pseudo/mm@0:null sendmail 605 root 3r DOOR 0t0 58 /var/run/name_service_door(door to nscd[81]) (FA:->0x30002b156c0) sendmail 605 root 4w VCHR 21,0 11010052 /devices/pseudo/log@0:conslog->LOG sendmail 605 root 5u IPv4 0x300010ea640 0t0 TCP *:smtp (LISTEN) sendmail 605 root 6u IPv6 0x3000431c180 0t0 TCP *:smtp (LISTEN) sendmail 605 root 7u IPv4 0x300046d39c0 0t0 TCP *:submission (LISTEN) sendmail 605 root 8wW VREG 281,3 32 8778600 /var/run/sendmail.pid |
清单 2 为 lsof
指定了三个参数。第一个是 -a
,它表示当所有的参数都为真时,才显示这个文件。第二个参数是 -p 605
,它限制仅输出 PID 为 605 的进程,可以通过 ps
命令获取这个信息。最后一个参数 -d ^txt
,它表示筛选出其中 txt 类型的记录(脱字符号 [^] 表示排除)。
清单 2 的输出提供了关于进程行为的信息。如 cwd
行所示,该应用程序的工作目录为 /var/spool/mqueue。文件描述符 0、1 和 2 分配给了 /dev/null(Solaris 大量使用符号链接,所以这里显示了相应的伪设备)。FD 3 是一个 Solaris 门(高速远程过程调用 (RPC) 接口),以只读模式打开。FD 4 中的内容比较有趣,因为它是一个字符设备的只读句柄,实质上是 /dev/log。从这个文件中,您可以收集该应用程序向 UNIX syslog 守护进程进行的记录,所以 /etc/syslog.conf 规定了日志文件的位置。
作为一个网络应用程序,sendmail
对网络端口进行监听。文件描述符 5、6 和 7 可以告诉您,该应用程序正以 IPv4 和 IPv6 模式监听简单邮件传输协议 (SMTP) 端口,并以 IPv4 模式监听提交端口。最后一个文件描述符是只写的,并且指向 /var/run/sendmail.pid。FD
列中的大写 W
表示该应用程序具有对整个文件的写锁。该文件用于确保每次只能打开一个应用程序实例。
在其他情况下,您有一个文件或目录,并且需要知道哪个应用程序控制了该文件(打开了该文件)。清单 2 显示了由 sendmail
进程打开了 /var/run/sendmail.pid。如果您不知道这个信息,那么在给定文件名的情况下,lsof
可以提供该信息。清单 3 显示了相应的输出。
bash-3.00# lsof /var/run/sendmail.pid COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sendmail 605 root 8wW VREG 281,3 32 8778600 /var/run/sendmail.pid |
正如输出所示,进程 sendmail
(PID 为 605)控制了文件 /var/run/sendmail.pid,并且通过排它锁打开该文件以便进行写入。如果出于某种原因,您需要删除这个文件,那么正确的做法是中止该进程,而不是直接删除这个文件。否则,这个守护进程下次可能无法正常启动,或者可能稍后会启动另一个实例,从而导致争用。
有时您只知道在文件系统的某处打开了文件。在卸载文件系统时,如果该文件系统中有任何打开的文件,那么操作将会失败。通过指定装入点的名称,您可以使用 lsof
显示一个文件系统中所有打开的文件。清单 4 显示了如何尝试卸载 /export/home,然后使用 lsof
找出谁在使用该文件系统。
bash-3.00# umount /export/home umount: /export/home busy bash-3.00# lsof /export/home COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME bash 1943 root cwd VDIR 136,7 1024 4 /export/home/sean bash 2970 sean cwd VDIR 136,7 1024 4 /export/home/sean ct 3030 sean cwd VDIR 136,7 1024 4 /export/home/sean ct 3030 sean 1w VREG 136,7 0 25 /export/home/sean/output |
在这个示例中,用户 sean 正在其 home 目录中进行一些操作。有两个 bash
(一种 Shell)实例正在运行,并且当前目录设置为 sean 的 home 目录。还有一个名为 ct
的应用程序正运行于相同的目录,并且其标准输出(文件描述符 1)重定向到一个名为 output 的文件。要成功地卸载 /export/home,应该在通知用户以确保情况正常之后,中止这些进程。
这个示例说明了应用程序的当前工作目录非常重要,因为它仍保持着文件资源,并且可以防止文件系统被卸载。这就是为什么大部分守护进程(后台进程)将它们的目录更改为根目录、或服务特定的目录(如 sendmail
示例中的 /var/spool/mqueue)的原因,以避免该守护进程阻止卸载不相关的文件系统。如果 sendmail
从 /export/home/sean 目录启动,并且没有将其目录更改为 /var/spool/mqueue,那么在卸载 /export/home 前必须中止它。
如果您对非装入点目录中打开的文件感兴趣,那么必须通过 +d
或 +D
指定该目录的名称,具体使用其中的哪一个标志取决于您需要递归到子目录(+D
)或者不需要递归到子目录(+d
)。例如,要查看 /export/home/sean 中所有打开的文件,可以使用 lsof +D /export/home/sean
。在前面的示例中,相关的目录是一个装入点,而这里与前面的示例存在细微的差别,并且限制了 lsof
和内核之间的交互。这还会引起潜在的问题,即 lsof /export/home
与 lsof /export/home/
(请注意尾部的斜杠)有所区别。第一种方式可以正常工作,因为它指向了装入点。第二种方式不会生成任何输出,因为它指向了目录。如果您在 Shell 中使用 Tab 键自动完成命令,那么可能碰到这个问题,其中会帮助您添加结尾的斜杠。在这种情况下,您可以删除这个斜杠或者使用 +D
指定目录。前者是首选的方法,因为与指定任意的目录相比,其执行速度更快。
在前面的部分中,我们研究了 lsof
的基本用法,即显示打开的文件和控制它们的进程之间的关系。当您想对系统进行一些烦琐的操作,而又不希望破坏别人重要的文档时,这种方法很有帮助。您还可以使用相同的方法执行一些高难度的 UNIX 操作。
当 UNIX 计算机受到入侵时,常见的情况是日志文件被删除,以掩盖攻击者的踪迹。管理错误也可能导致意外删除重要的文件,比如在清理旧日志时,意外地删除了数据库的活动事务日志。有时可以恢复这些文件,并且 lsof
可以为您提供帮助。
当进程打开了某个文件时,只要该进程保持打开该文件,即使将其删除,它依然存在于磁盘中。这意味着,进程并不知道文件已经被删除,它仍然可以向打开该文件时提供给它的文件描述符进行读取和写入。除了该进程之外,这个文件是不可见的,因为已经删除了其相应的目录条目。
前面曾在转到 /proc 目录部分中说过,通过在适当的目录中进行查找,您可以访问进程的文件描述符。在随后的内容中,您看到了lsof
可以显示进程的文件描述符和相关的文件名。您能明白我的意思吗?
但愿它真的这么简单!当您向 lsof
传递文件名时,比如在 lsof /file/I/deleted
中,它首先使用 stat()
系统调用获得有关该文件的信息,不幸的是,这个文件已经被删除。在不同的操作系统中,lsof
可能可以从核心内存中捕获该文件的名称。清单 5 显示了一个 Linux 系统,其中意外地删除了 Apache 日志,我正使用 grep
工具查找是否有人打开了该文件。
清单 5. 在 Linux 中使用 lsof 查找删除的文件
# lsof | grep error_log httpd 2452 root 2w REG 33,2 499 3090660 /var/log/httpd/error_log (deleted) httpd 2452 root 7w REG 33,2 499 3090660 /var/log/httpd/error_log (deleted) ... more httpd processes ... |
在这个示例中,您可以看到 PID 2452 打开文件的文件描述符为 2(标准错误)和 7。因此,可以在 /proc/2452/fd/7 中查看相应的信息,如清单 6 所示。
# cat /proc/2452/fd/7 [Sun Apr 30 04:02:48 2006] [notice] Digest: generating secret for digest authentication [Sun Apr 30 04:02:48 2006] [notice] Digest: done [Sun Apr 30 04:02:48 2006] [notice] LDAP: Built with OpenLDAP LDAP SDK |
Linux 的优点在于,它保存了文件的名称,甚至可以告诉我们它已经被删除。在遭到破坏的系统中查找相关内容时,这是非常有用的内容,因为攻击者通常会删除日志以隐藏他们的踪迹。Solaris 并不提供这些信息。然而,我们知道 httpd
守护进程使用了 error_log 文件,所以可以使用 ps
命令找到这个 PID,然后可以查看这个守护进程打开的所有文件。
# lsof -a -p 8663 -d ^txt COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME httpd 8663 nobody cwd VDIR 136,8 1024 2 / httpd 8663 nobody 0r VCHR 13,2 6815752 /devices/pseudo/mm@0:null httpd 8663 nobody 1w VCHR 13,2 6815752 /devices/pseudo/mm@0:null httpd 8663 nobody 2w VREG 136,8 185 145465 / (/dev/dsk/c0t0d0s0) httpd 8663 nobody 4r DOOR 0t0 58 /var/run/name_service_door (door to nscd[81]) (FA:->0x30002b156c0) httpd 8663 nobody 15w VREG 136,8 185 145465 / (/dev/dsk/c0t0d0s0) httpd 8663 nobody 16u IPv4 0x300046d27c0 0t0 TCP *:80 (LISTEN) httpd 8663 nobody 17w VREG 136,8 0 145466 /var/apache/logs/access_log httpd 8663 nobody 18w VREG 281,3 0 9518013 /var/run (swap) |
我使用 -a
和 -d
参数对输出进行筛选,以排除代码程序段,因为我知道需要查找的是哪些文件。Name
列显示出,其中的两个文件(FD 2 和 15)使用磁盘名代替了文件名,并且它们的类型为 VREG
(常规文件)。在 Solaris 中,删除的文件将显示文件所在的磁盘的名称。通过这个线索,就可以知道该 FD 指向一个删除的文件。实际上,查看 /proc/8663/fd/15
就可以得到所要查找的数据。
如果可以通过文件描述符查看相应的数据,那么您就可以使用 I/O 重定向将其复制到文件中,如 cat /proc/8663/fd/15 > /tmp/error_log
。此时,您可以中止该守护进程(这将删除 FD,从而删除相应的文件),将这个临时文件复制到所需的位置,然后重新启动该守护进程。
对于许多应用程序,尤其是日志文件和数据库,这种恢复删除文件的方法非常有用。正如您所看到的,有些操作系统(以及不同版本的 lsof
)比其他的系统更容易查找相应的数据。
网络连接也是文件,这意味着可以使用 lsof
获得关于它们的信息。您曾在清单 2 中看到过这样的示例。该示例假设您已经知道 PID,但是有时候并非如此。如果您只知道相应的端口,那么可以使用 -i
参数利用套接字信息进行搜索。清单 8 显示了对 TCP 端口 25 的搜索。
# lsof -i :25 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sendmail 605 root 5u IPv4 0x300010ea640 0t0 TCP *:smtp (LISTEN) sendmail 605 root 6u IPv6 0x3000431c180 0t0 TCP *:smtp (LISTEN) |
需要以 protocol:@ip:port
的形式向 lsof
实用程序传递相关信息,其中的 protocol 为 TCP 或 UDP(可以使用 4 或 6 作为前缀,表示 IP 的版本),IP 为可解析的名称或 IP 地址,而 port 为数字或表示该服务的名称(来自 /etc/services)。需要一个或多个元素(端口、IP、协议)。在清单 8 中,:25
表示端口 25。输出显示,进程 605 正在使用 IPv6 和 IPv4 监听端口 25。如果您对 IPv4 不感兴趣,那么可以将筛选器改为 6:25
,以表示监听端口 25 的 IPv6 套接字,或者直接使用 6
表示所有的 IPv6 连接。
除了显示出这些守护进程正在监听的对象,lsof
还可以发现发生的连接,同样是使用 -i
参数。清单 9 显示了搜索与 192.168.1.10 之间的所有连接。
# lsof -i @192.168.1.10 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sshd 1934 root 6u IPv6 0x300046d21c0 0t1303608 TCP sun:ssh->linux:40379 (ESTABLISHED) sshd 1937 root 4u IPv6 0x300046d21c0 0t1303608 TCP sun:ssh->linux:40379 (ESTABLISHED) |
在这个示例中,sun
和 linux
之间有两个 IPv6 连接。对其进行更仔细的研究可以看出,这些连接来自于两个不同的进程,但它们却是相同的,这是因为两台主机是相同的,并且端口也是相同的(ssh 和 40379)。这是由于进入主进程的连接分叉出一个处理程序,并将该套接字传递给它。您还可以看到,名为 sun
的计算机正在使用端口 22 (ssh),而 linux
具有端口 40379。这表示,sun
是该连接的接收者,因为它关联于该服务的已知端口。40379 是源或临时端口,并且仅对这个连接有意义。
因为,至少在 UNIX 中,套接字是另一类文件,所以 lsof
可以获得关于这些连接的详细信息,并找出谁对它们负责。
UNIX 大量使用了文件。作为系统管理员,lsof
允许您对核心内存进行查看,以找出系统当前如何使用这些文件。lsof
最简单的用法可以告诉您哪些进程打开了哪些文件,以及哪些文件由哪些进程打开。在收集关于应用程序工作情况的信息时,或在进行某些可能损坏数据的操作前确保文件未被使用时,这一点特别重要lsof
更高级的用法可以帮助您查找删除的文件,并获得关于网络连接的信息。这是一个功能强大的工具,它几乎可以用于任何地方。
http://www.2cto.com/os/201110/109114.html
1)查看对某个文件的使用情况
-------------------------------------------------------
root@troy:/# lsof -w /etc/passwd
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 2340 troy 10r REG 8,1 1804 2886346 /etc/passwd
-------------------------------------------------------
注:-w参数表示不打印警告信息.
lsof程序会打开/proc/PID/fd/目录找到对映的文件句柄,再通过stat系统调用得到文件的详细信息.
同时还会利用fdinfo目录下的文件句柄得到打开文件时的状态.
例如:
1.1)创建程序test.c,本程序在/tmp/目录下以O_WRONLY(只写)和O_SYNC(同步)方式打开temp文件.
-------------------------------------------------------
root@troy:/tmp# more test.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main ()
{
int fd;
fd = open("/tmp/temp", O_WRONLY|O_SYNC);
lseek(fd, 80L, SEEK_SET);
sleep(100);
close(fd);
return 0;
}
root@troy:/tmp# gcc test.c -o testfd
root@troy:/tmp# ./testfd &
-------------------------------------------------------
1.2)观察testfd程序打开的文件/tmp/temp
-------------------------------------------------------
cat /proc/$(lsof -w /tmp/temp|awk '/testfd/{print $2}')/fdinfo/3
pos: 80
flags: 0110001
-------------------------------------------------------
我们看到程序输出pos和flags两组数据,pos字段表示被打开文件的当前读写位置,flags表示以文件方式打开该文件.
pos为80表示从文件起始位置移动80个字节的位置.
flags为0110001中的xxxxxx1表示以只写方式打开文件,如果是只读则为xxxxxx0,如果可读可写则为xxxxxx2,
其中的xx1xxxx表示以同步方式(O_SYNC)打开文件,如果改用以O_ASYNC方式打开文件,则为xx2xxxx,
如果同时指定了O_SYNC和O_ASYNC两种方式打开文件,结果则为xx3xxxx.
如果我们增加了O_APPEND方式打开文件,结果则为xxx2xxx.
如果我们增加了O_NONBLOCK方式打开文件,结果则为xxx4xxx.
如果同时指定了O_APPEND和NONBLOCK两种方式,结果则为xxx6xxx.
最后指明一下O_ASYNC用于打开终端和socket文件,默认产生SIGIO信号.
而O_NONBLOCK表示不阻塞打开的文件,只用于FIFO的管道文件中.
2)查看对某个目录的使用情况
我们先执行上个试验的程序.
-------------------------------------------------------
root@troy:~# /tmp/testfd &
[1] 17021
root@troy:~# lsof +d /tmp/
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
gedit 2531 troy 7u unix 0xffff880029a49b00 0t0 17106 /tmp/gedit.troy.917415843
testfd 17021 root txt REG 8,1 8617 262475 /tmp/testfd
testfd 17021 root 3w REG 8,1 0 262412 /tmp/temp
bash 3926 troy cwd DIR 8,1 4096 262149 /tmp
bash 4001 troy cwd DIR 8,1 4096 262149 /tmp
-------------------------------------------------------
如果不加参数+d呢?这里我们只看到了用户的当前使用目录,如下:
-------------------------------------------------------
root@troy:~# lsof -w /tmp
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 3926 troy cwd DIR 8,1 4096 262149 /tmp
bash 4001 troy cwd DIR 8,1 4096 262149 /tmp
-------------------------------------------------------
有什么区别吗?
加+d参数的情况下,lsof会遍列所有的进程,以及进程下所有的fd,fdinfo,cwd,root,exec,maps,以查找被程序占用中的目录.
而不加参数+d的情况下,lsof只会遍列所有进程的cwd,cwd是用户当前目录的软链接.如下:
-------------------------------------------------------
root@troy:~# ls -l /proc/3926/cwd
lrwxrwxrwx 1 troy troy 0 2011-02-09 19:23 /proc/3926/cwd -> /tmp
-------------------------------------------------------
3)查看某个进程的使用情况
-------------------------------------------------------
troy@troy:/proc/23294$ lsof -p 23294
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
ssh 23294 troy cwd DIR 8,1 4096 262149 /tmp
ssh 23294 troy rtd DIR 8,1 4096 2 /
ssh 23294 troy txt REG 8,1 339712 1058082 /usr/bin/ssh
ssh 23294 troy mem REG 8,1 51712 787472 /lib/libnss_files-2.11.1.so
ssh 23294 troy mem REG 8,1 43552 787456 /lib/libnss_nis-2.11.1.so
ssh 23294 troy mem REG 8,1 97256 787430 /lib/libnsl-2.11.1.so
ssh 23294 troy mem REG 8,1 35712 787454 /lib/libnss_compat-2.11.1.so
ssh 23294 troy mem REG 8,1 135745 787466 /lib/libpthread-2.11.1.so
ssh 23294 troy mem REG 8,1 10224 787804 /lib/libkeyutils-1.2.so
ssh 23294 troy mem REG 8,1 31168 1050775 /usr/lib/libkrb5support.so.0.1
ssh 23294 troy mem REG 8,1 14584 798518 /lib/libcom_err.so.2.1
ssh 23294 troy mem REG 8,1 154048 1050756 /usr/lib/libk5crypto.so.3.1
ssh 23294 troy mem REG 8,1 803192 1050769 /usr/lib/libkrb5.so.3.3
ssh 23294 troy mem REG 8,1 14696 795838 /lib/libdl-2.11.1.so
ssh 23294 troy mem REG 8,1 1572232 787469 /lib/libc-2.11.1.so
ssh 23294 troy mem REG 8,1 213784 1050761 /usr/lib/libgssapi_krb5.so.2.2
ssh 23294 troy mem REG 8,1 93000 787444 /lib/libresolv-2.11.1.so
ssh 23294 troy mem REG 8,1 92752 786985 /lib/libz.so.1.2.3.3
ssh 23294 troy mem REG 8,1 1622304 796093 /lib/libcrypto.so.0.9.8
ssh 23294 troy mem REG 8,1 136936 787431 /lib/ld-2.11.1.so
ssh 23294 troy 0u CHR 136,20 0t0 23 /dev/pts/20
ssh 23294 troy 1u CHR 136,20 0t0 23 /dev/pts/20
ssh 23294 troy 2u CHR 136,20 0t0 23 /dev/pts/20
ssh 23294 troy 3u IPv4 1603924 0t0 TCP troy.local:41879->10.1.1.7:ssh (ESTABLISHED)
ssh 23294 troy 4w FIFO 0,8 0t0 1603904 pipe
ssh 23294 troy 5u CHR 136,19 0t0 22 /dev/pts/19
ssh 23294 troy 6r CHR 5,0 0t0 1129 /dev/tty
ssh 23294 troy 7u CHR 136,21 0t0 24 /dev/pts/21
ssh 23294 troy 8u CHR 136,20 0t0 23 /dev/pts/20
ssh 23294 troy 9u CHR 136,20 0t0 23 /dev/pts/20
ssh 23294 troy 10u CHR 136,20 0t0 23 /dev/pts/20
-------------------------------------------------------
lsof程序会跟据用户指定的PID,遍列/proc/目录找到该PID,在/proc/PID目录下依次打开stat,maps,fd,fdinfo.
stat文件包含了当前进程的信息.
当前进程的stat如下:
23294 (ssh) S 23291 23294 23294 34837 23294 4202496 836 0 0 0 8 10 0 0 20 0 1 0 29282141 39632896 658 18446744073709551615 140114439372800 140114439700540 140733214155456 140733214149016 140114423930835 0 0 4096 136331271 18446744071580239593 0 0 17 1 0 0 0 0 0
maps文件包含映像的文件:
当前进程的maps如下:
7f6eecf42000-7f6eecf4e000 r-xp 00000000 08:01 787472 /lib/libnss_files-2.11.1.so
7f6eecf4e000-7f6eed14d000 ---p 0000c000 08:01 787472 /lib/libnss_files-2.11.1.so
7f6eed14d000-7f6eed14e000 r--p 0000b000 08:01 787472 /lib/libnss_files-2.11.1.so
7f6eed14e000-7f6eed14f000 rw-p 0000c000 08:01 787472 /lib/libnss_files-2.11.1.so
7f6eed14f000-7f6eed159000 r-xp 00000000 08:01 787456 /lib/libnss_nis-2.11.1.so
7f6eed159000-7f6eed358000 ---p 0000a000 08:01 787456 /lib/libnss_nis-2.11.1.so
7f6eed358000-7f6eed359000 r--p 00009000 08:01 787456 /lib/libnss_nis-2.11.1.so
7f6eed359000-7f6eed35a000 rw-p 0000a000 08:01 787456 /lib/libnss_nis-2.11.1.so
7f6eed35a000-7f6eed371000 r-xp 00000000 08:01 787430 /lib/libnsl-2.11.1.so
7f6eed371000-7f6eed570000 ---p 00017000 08:01 787430 /lib/libnsl-2.11.1.so
7f6eed570000-7f6eed571000 r--p 00016000 08:01 787430 /lib/libnsl-2.11.1.so
7f6eed571000-7f6eed572000 rw-p 00017000 08:01 787430 /lib/libnsl-2.11.1.so
后省略.
这里用pmap 23294也可以找到加载的文件与虚拟地址的对映.
fd,fdinfo我们已经分析过了,当lsof找到/proc/23294/3时,发现是个socket文件,如下:
----------------------------------------------------
troy@troy:/proc/23294/fd$ ls -l
total 0
lrwx------ 1 troy troy 64 2011-02-11 02:47 0 -> /dev/pts/20
lrwx------ 1 troy troy 64 2011-02-11 02:47 1 -> /dev/pts/20
lrwx------ 1 troy troy 64 2011-02-11 02:47 10 -> /dev/pts/20
lrwx------ 1 troy troy 64 2011-02-11 01:07 2 -> /dev/pts/20
lrwx------ 1 troy troy 64 2011-02-11 02:47 3 -> socket:[1603924]
l-wx------ 1 troy troy 64 2011-02-11 02:47 4 -> pipe:[1603904]
lrwx------ 1 troy troy 64 2011-02-11 02:47 5 -> /dev/pts/19
lr-x------ 1 troy troy 64 2011-02-11 02:47 6 -> /dev/tty
lrwx------ 1 troy troy 64 2011-02-11 02:47 7 -> /dev/pts/21
lrwx------ 1 troy troy 64 2011-02-11 02:47 8 -> /dev/pts/20
lrwx------ 1 troy troy 64 2011-02-11 02:47 9 -> /dev/pts/20
----------------------------------------------------
此时会依次打开以下的文件,对网络套字接进行分析,各文件作用如下:
/proc/net/raw ---->原始套接字
/proc/net/unix ---->UNIX套接字
/proc/net/sockstat ---->当前套接字的使用情况
/proc/net/tcp ---->TCP套接字
/proc/net/udp ---->UDP套接字
/proc/net/udplite --->UDP无线通讯套接字
在/proc/net/tcp会找到对映的inode,socket:[1603924]的inode为1603924,而tcp中sl为12的一行正是这个socket服务.如下:
----------------------------------------------------
more /proc/net/tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000:0087 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 8984 1 ffff8800677d1380 300 0 0 2 -1
1: 00000000:0369 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 8575 1 ffff8800677d0d00 300 0 0 2 -1
2: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 8673 1 ffff880068c51a00 300 0 0 2 -1
3: 00000000:1770 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 5350 1 ffff880068c50680 300 0 0 2 -1
4: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 4315 1 ffff880068c50000 300 0 0 2 -1
5: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 25571 1 ffff88001a06c780 300 0 0 2 -1
6: 00000000:0BB8 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 7881 1 ffff8800677d0680 300 0 0 2 -1
7: 00000000:BD59 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 8986 1 ffff880068c52080 300 0 0 2 -1
8: 0100007F:0019 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 6304 1 ffff880068c50d00 300 0 0 2 -1
9: 4506010A:D6E9 0701010A:0016 01 00000000:00000000 02:00028405 00000000 1502 0 1603452 2 ffff880057896180 22 4 8 5 -1
10: 4506010A:89A5 0701010A:0016 01 00000000:00000000 02:00091EFF 00000000 1502 0 1672803 2 ffff88001a068680 25 4 18 4 -1
11: 4506010A:872E 0701010A:0016 01 00000000:00000000 02:0004B77C 00000000 1502 0 1177942 2 ffff880057893a80 125 4 0 3 2
12: 4506010A:A397 0701010A:0016 01 00000000:00000000 02:0004D6A6 00000000 1502 0 1603924 2 ffff880057894e00 23 4 0 5 -1
13: 4506010A:BD31 0701010A:0016 01 00000000:00000000 02:000139A5 00000000 1502 0 1345002 2 ffff880057897500 22 4 0 5 -1
14: 4506010A:8F21 0701010A:0016 01 00000000:00000000 02:000192BE 00000000 1502 0 1351794 2 ffff880057896800 25 4 12 4 -1
15: 4506010A:8AD1 0701010A:0016 01 00000000:00000000 02:00094915 00000000 1502 0 1447912 2 ffff880068c55b00 21 4 14 4 -1
----------------------------------------------------
其中local_address代表本地的IP和端口
4506010A(本地地址)的45转化为十进制是69,06转化为十制制是6,01转化为十进制是1,0A转化为十进制是10,倒过来也就是10.1.1.69,是本地地址.
A397(本地端口)转化为十进制是41879,也就是本地端口
rem_address代表远程IP和端口
0701010A(远程地址):10.1.1.7
0016(远程端口)22
其它参数都是内核调试时使用
uid就是用户的UID
4)显示所属user进程打开的文件
----------------------------------------------------
root@troy:/proc/2554# lsof -u test -w
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
su 2554 test cwd DIR 8,1 4096 2 /
su 2554 test rtd DIR 8,1 4096 2 /
su 2554 test txt REG 8,1 36864 262185 /bin/su
su 2554 test mem REG 8,1 27024 797476 /lib/libnss_lsass.so.2.0.0
su 2554 test mem REG 8,1 10272 1102794 /usr/lib/gconv/IBM850.so
su 2554 test mem REG 8,1 14392 1102782 /usr/lib/gconv/UTF-16.so
su 2554 test mem REG 8,1 43528 795516 /lib/security/pam_gnome_keyring.so
su 2554 test mem REG 8,1 256768 787477 /lib/libdbus-1.so.3.4.0
su 2554 test mem REG 8,1 14536 1052877 /usr/lib/libck-connector.so.0.0.0
su 2554 test mem REG 8,1 10360 795488 /lib/security/pam_ck_connector.so
su 2554 test mem REG 8,1 14344 787928 /lib/libgpg-error.so.0.4.0
su 2554 test mem REG 8,1 491000 787918 /lib/libgcrypt.so.11.5.2
su 2554 test mem REG 8,1 92752 786985 /lib/libz.so.1.2.3.3
su 2554 test mem REG 8,1 67896 1055840 /usr/lib/libtasn1.so.3.1.7
su 2554 test mem REG 8,1 10224 787804 /lib/libkeyutils-1.2.so
su 2554 test mem REG 8,1 31168 1050775 /usr/lib/libkrb5support.so.0.1
su 2554 test mem REG 8,1 14584 798518 /lib/libcom_err.so.2.1
以下略
----------------------------------------------------
通过strace,我们知道lsof通过stat系统调用得到这个进程的目录owner,正是我们要找的用户进程.
如下:
stat("/proc/2554/", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
open("/proc/2554/stat", O_RDONLY) = 4
read(4, "2554 (su) S 2533 2554 2533 34817"..., 4096) = 241
最后lsof通过调用cwd,root,fd,fdinfo,maps以及网络套接字显示输出用户进程所使用的文件.
5)显示网络服务
----------------------------------------------------
root@troy:~# lsof -i
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
smbd 767 root 22u IPv6 4410 0t0 TCP *:microsoft-ds (LISTEN)
smbd 767 root 23u IPv6 4412 0t0 TCP *:netbios-ssn (LISTEN)
sshd 787 root 3u IPv4 4227 0t0 TCP *:ssh (LISTEN)
sshd 787 root 4u IPv6 4229 0t0 TCP *:ssh (LISTEN)
avahi-dae 809 avahi 13u IPv4 4568 0t0 UDP *:mdns
avahi-dae 809 avahi 14u IPv4 4569 0t0 UDP *:50511
dhclient 883 root 5u IPv4 4530 0t0 UDP *:bootpc
Xorg 912 root 1u IPv6 4705 0t0 TCP *:x11 (LISTEN)
Xorg 912 root 3u IPv4 4706 0t0 TCP *:x11 (LISTEN)
dcerpcd 1132 root 15u IPv4 8845 0t0 TCP *:loc-srv (LISTEN)
dcerpcd 1132 root 16u IPv4 8846 0t0 UDP *:loc-srv
eventlogd 1261 root 14u IPv4 8850 0t0 TCP *:55846 (LISTEN)
exim4 1563 Debian-exim 3u IPv4 6359 0t0 TCP localhost:smtp (LISTEN)
以下略
----------------------------------------------------
lsof通过遍列所有进程的所有文件句柄,找到网络套接字,再通过/proc/net/下面的网络信息得到具体的套接字信息.
http://blog.csdn.net/tiantiantianshilan/article/details/7190167
在Linux下面部署应用的时候,有时候会遇上Socket/File: Can’t open so many files的问题,当文件打开数到900多时速能就非常快的下降,有可能打不开网页.
其实Linux是有文件句柄限制的,而且Linux默认不是很高,一般都是1024,生产服务器用其实很容易就达到这个数量.
查看方法
我们可以用ulimit -a来查看所有限制值
[root@centos5 ~]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
max nice (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 4096
max locked memory (kbytes, -l) 32
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
max rt priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 4096
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited||<
其中 "open files (-n) 1024 "是Linux操作系统对一个进程打开的文件句柄数量的限制(也包含打开的SOCKET数量,可影响MySQL的并发连接数目).这个值可用ulimit 命令来修改,但ulimit命令修改的数值只对当前登录用户的目前使用环境有效,系统重启或者用户退出后就会失效.
系统总限制是在这里,/proc/sys/fs/file-max.可以通过cat查看目前的值,修改/etc/sysctl.conf 中也可以控制.
另外还有一个,/proc/sys/fs/file-nr,可以看到整个系统目前使用的文件句柄数量
查找文件句柄问题的时候,还有一个很实用的程序lsof.可以很方便看到某个进程开了那些句柄.也可以看到某个文件/目录被什么进程占用了.
修改方法
若要令修改ulimits的数值永久生效,则必须修改配置文档,可以给ulimit修改命令放入/etc/profile里面,这个方法实在是不方便,还 有一个方法是修改/etc/sysctl.conf .我修改了,测试过,但对用户的ulimits -a 是不会改变的。只是/proc/sys/fs/file-max的值变了.(我给命令放到rc.local中失败)
我认为正确的做法,应该是修改/etc/security/limits.conf
里面有很详细的注释,比如:
* soft nofile 32768
* hard nofile 65536
也可以直接运行下面这个shell。直接copy到你的终端中运行就好了.
echo -ne "
* soft nofile 65536
* hard nofile 65536
" >>/etc/security/limits.conf
就可以将文件句柄限制统一改成软32768,硬65536.配置文件最前面的是指domain,设置为星号代表全局,另外你也可以针对不同的用户做出不同的限制
注意.这个当中的硬限制是实际的限制,而软限制,是warnning限制,只会做出warning.其实ulimit命令本身就有分软硬设置,加-H就是硬,加-S就是软
默认显示的是软限制,如果运行ulimit命令修改的时候没有加上的话,就是两个参数一起改变.
生效
修改完重新登录就可以见到.(我的系统是Centos5.1.修改了,重新登录后就立刻生效.可以用ulimit -a 查看确认.)
limits.conf的工作原理:
limits.conf的后端是这样工作的:limits.conf是pam_limits.so的配置文件,然后/etc/pam.d/下的应用程 序调用pam_***.so模块。譬如说,当用户访问服务器,服务程序将请求发送到PAM模块,PAM模块根据服务名称在/etc/pam.d目录下选择 一个对应的服务文件,然后根据服务文件的内容选择具体的PAM模块进行处理。
例:限制admin用户登录到sshd的服务不能超过2个
在/etc/pam.d/sshd 中添加 session required pam_limits.so
在/etc/security/limits.conf中添加 admin - maxlogins 2
查看应用程序能否被PAM支持,用ldd
limits.conf文件的参数
Limits.conf文件的参数可以设置成以下两种形式之一:
暂时地,适用于通过 ulimit 命令登录 shell 会话期间。
永久地,通过将一个相应的 ulimit 语句添加到由登录 shell 读取的文件之一(例如 ~/.profile),即特定于 shell 的用户资源文件;或者通过编辑 /etc/security/limits.conf。
1.core - 限制内核文件的大小
何谓core文件,当一个程序崩溃时,在进程当前工作目录的core文件中复制了该进程的存储图像。core文件仅仅是一个内存映象(同时加上调试信息),主要是用来调试的。 core文件是个二进制文件,需要用相应的工具来分析程序崩溃时的内存映像。
系统默认core文件的大小为0,所以没有创建。可以用ulimit命令查看和修改core文件的大小。
$ulimit -c
0
$ ulimit -c 1000
$ ulimit -c
1000
-c 指定修改core文件的大小,1000指定了core文件大小。也可以对core文件的大小不做限制,如:
# ulimit -c unlimited
#ulimit -c
unlimited
如果想让修改永久生效,则需要修改配置文件,如 .bash_profile、/etc/profile或/etc/security/limits.conf。
2.nofile - 打开文件的最大数目
对于需要做许多套接字连接并使它们处于打开状态的应用程序而言,最好通过使用 ulimit –n,或者通过设置nofile 参数,为用户把文件描述符的数量设置得比默认值高一些。
/proc 文件系统是一个伪文件系统,它以文件系统的方式为用户访问系统内核数据提供接口。用户和应用程序可以通过 /proc 文件系统得到系统的信息,并可以通过 /proc 文件系统改变内核的某些信息。与普通文件不同的是,/proc 的内容都是动态创建的,它只存在于内存当中。
最初开发 /proc 文件系统是为了提供有关系统中进程的信息。但是由于这个文件系统非常有用,因此内核中的很多元素也开始使用它来报告信息,或启用动态运行时配置。
/proc 文件系统分为三大类:系统信息、进程相关、子系统。
在 /etc/fstab 文件中加入如下一行使系统在启动时自动加载 /proc 文件系统(绝多数Linux发行版默认如此):
proc /proc proc defaults 0 0
当然你也可以手动加载:mount -t proc proc /proc
利用Linux proc 文件系统来读取系统信息
很多读取系统信息的程序都依赖于 /proc 文件系统,如果 /proc 文件系统不存在,它们将不可用或残缺,例如:lscpu、lsusb、lspci……ps。
有些命令的输出的信息,可以通过直接读取 /proc 文件系统来获取。例如:Linux 查看硬件信息
在 /proc 根目录下,这里的文件是只读的。
文 件 |
描 述 |
cmdline |
内核启动参数 |
cpuinfo |
cpu信息 |
iomem |
io设备的内存使用信息 |
interrupts |
显示被占用的中断信息和占用者的信息 |
ioports |
I/O端口的使用 |
kcore |
系统物理内存映像,不可读取 |
loadavg |
系统平均负载 |
meminfo |
物理内存和交换分区使用信息 |
modules |
加载模块列表 |
mounts |
挂载的文件系统 |
partitions |
系统识别的分区表 |
swaps |
交换空间的利用情况 |
version |
内核版本信息 |
uptime |
系统运行时间 |
在 /proc 目录下以数字为名的子目录都是存储和进程相关的信息,这些数字就是相关进程的进程ID,这里的文件也是只读的。
还有一个特殊的 /proc/self 目录, 它是指向当前执行进程的符号连接。例如你执行:cat /proc/self/cmdline,将返回命令本身,但会忽略空格。
文 件 |
描 述 |
cmdline |
进程启动参数 |
environ |
环境变量 |
limits |
进程限制信息 |
status |
进程状态 |
maps |
进程使用的动态链接库文件 |
内核子系统的参数
如调整内核文件限制,开启IP数据包转发……这些文件都在 /proc/sys/ 目录下,有的可以改变,有的是只读。
文件系统参数 |
||
fs/file-max |
可以分配的文件句柄的最大数目 |
|
fs/file-nr |
已分配文件句柄的数目、已使用文件句柄的数目、文件句柄的最大数目。只读 |
|
fs/inode-* |
与索引节点相关的 |
|
内核相关 |
||
kernel/ctrl-alt-del |
控制系统在接收到 ctrl+alt+delete 按键组合时如何反应。 |
|
kernel/domainname |
您配置网络域名 |
|
kernel/hostname |
您配置网络主机名 |
|
kernel/msgmax |
该文件指定了从一个进程发送到另一个进程的消息的最大长度。 |
|
kernel/msgmnb |
该文件指定在一个消息队列中最大的字节数。 |
|
kernel/msgmni |
该文件指定消息队列标识的最大数目。 |
|
kernel/threads-max |
该文件指定内核所能使用的线程的最大数目。 |
|
网络子系统 |
||
net/core/message_burst |
写新的警告消息所需的时间,以 1/10 秒为单位,在这个时间内所接收到的警告消息会被丢弃。 |
|
net/core/netdev_max_backlog |
该文件指定了,在接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。 |
|
net/core/optmem_max |
该文件指定了每个套接字所允许的最大缓冲区的大小。 |
|
net/core/rmem_default |
该文件指定了接收套接字缓冲区大小的缺省值(以字节为单位)。 |
|
net/core/rmem_max |
该文件指定了接收套接字缓冲区大小的最大值(以字节为单位)。 |
|
net/core/wmem_default |
该文件指定了发送套接字缓冲区大小的缺省值(以字节为单位)。 |
|
net/core/wmem_max |
该文件指定了发送套接字缓冲区大小的最大值(以字节为单位)。 |
|
net/ipv4/* |
IPv4相关,参阅文件 /usr/src/linux/Documentation/networking/ip-sysctl.txt |
|
net/ipv6/* |
IPv6相关 |
|
net/ipv4/ip_forward |
转发IPv4数据包 |
|
net/ipv4/ip_default_ttl |
修改IPv4默认的TTL值 |
|
net/ipv4/ip_no_pmtu_disc |
关闭IPv4路径MTU探测,默认值为FALSE |
|
net/ipv4/tcp_syn_retries |
对于一个新建连接,IPv4子系统要发送多少个SYN连接请求才决定放弃。 |
|
net/ipv4/tcp_synack_retries |
对于远端的连接请求SYN,IPv4子系统会发送SYN+ACK数据报,以确认收到上一个SYN连接请求包。这里决定内核在放弃连接之前所送出的 SYN+ACK 数目。 |
|
sys/net/ipv4/tcp_syncookies |
设置IPv4子系统是否打开SYN Cookie功能,该功能可以防止部分SYN攻击。 |
|
sys/net/ipv4/ipfrag_high_thresh |
设置IPv4分片汇聚的最大内存用量。 |
|
sys/net/ipv4/ipfrag_time |
设置IPv4分片在内存保存时间。 |
|
sys/net/ipv4/icmp_echo_ignore_all |
设置为0则IPv4子系统将忽略所有发送给自己的ICMP echo请求。 |
sysctl 命令是用来读取和修改内核子系统的。
语法:sysctl dir1.dir2.file,表示操作 /proc/sys/dir1/dir2/file 文件。
实例:
#sysctl -a 读取所有设置
#sysctl net.ipv4 读取 /proc/sys/net/ipv4/ 目录下的设置
#sysctl net.ipv4.ip_forward 读取 ip_forward 设置
#sysctl net.ipv4.ip_forward=1 修改 ip_forward 设置为1
sysctl 命令的设置只能临时修改,要永久生效还要把这些设置加入 /etc/sysctl.conf 文件。
实例:
#vim sysctl.conf
net.ipv4.ip_forward=1
这样才永久生效。
#sysctl -p 让/etc/sysctl.conf文件的设置立即生效。