找回密码
 注册
关于网站域名变更的通知
查看: 298|回复: 1
打印 上一主题 下一主题

Unix调试的瑞士军刀:lsof

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-3-18 13:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x

3 x9 g: B( V! D8 e这是“你应该知道的Unix和Linux命令”系列的第三篇,在这篇文章中,我会介绍lsof这个工具,如果说netcat是进行网络诊断的瑞士军刀,那么lsof就是Unix调试的瑞士军刀。+ g2 \' s- {0 B! x3 J: ~) ?* T! V+ k

. S% K. F/ _- W: iLsof是遵从Unix哲学的典范,它只做一件事情,并且做的相当完美——它可以列出某个进程打开的所有文件信息。打开的文件可能是普通的文件,目录,NFS文件,块文件,字符文件,共享库,常规管道,明明管道,符号链接,Socket流,网络Socket,UNIX域Socket,以及其它更多。因为Unix系统中几乎所有东西都是文件,你可以想象lsof该有多有用。) A+ v) e+ o. [+ n: ^9 M$ V. U
- j+ }  B- M. p; T) h
如何使用lsof?
3 m/ y: s/ T% r3 F1 i; F8 f0 P" H# `, Y* u  H3 ~7 m- R
这篇文章中我会尽力列举我能想到的所有lsof的用法,让我们先从最简单的开始(或许你已经知道了),然后逐渐增加复杂度:3 E; m! P. d0 B
& l" F. D/ u% ]1 N8 `( Q6 F( R
列出所有打开的文件
! v! a& Q% J3 q
, O+ c$ J; O, `& V& \9 u- @+ \# lsof& n  o3 I$ N. Y9 k
- _5 s8 P- ~% Z
不带任何参数运行lsof会列出所有进程打开的所有文件。
  s5 m  X2 B4 H' m$ ?* r& {( W1 O$ d3 ^$ i: r& F
找出谁在使用某个文件
3 l' f) H3 J0 k) E$ E( o) o& P0 n/ I( h1 k3 Z8 `4 ?5 Q& A( \! P
# lsof /path/to/file, \; y/ f- M* Z

; {& Z: m8 ?" g1 ^+ U6 l4 k& `; j只需要执行文件的路径,lsof就会列出所有使用这个文件的进程,你也可以列出多个文件,lsof会列出所有使用这些文件的进程。
1 R. N* c, i; Q# W
  ^# f+ |0 R) S你也可以一次制定多个文件:4 x& k/ _4 e- s6 D
+ a* h: I* ^, B
# lsof /path/to/file1 /path/to/file2
  J9 m! P7 H7 P, x6 g" y$ a: H8 C( A7 P, i" E$ C! z
递归查找某个目录中所有打开的文件% |9 h( E3 N6 {. Q
& i6 o2 E' o, t0 ~* e, [
# lsof +D /usr/lib9 v' I2 y: u  _2 ]3 Q

0 j7 k8 x& r/ q2 w, A/ J/ F2 H) r加上+D参数,lsof会对指定目录进行递归查找,注意这个参数要比grep版本慢:
! s7 N# x) a/ E& A3 p& F1 R/ X. Z+ ?- f/ U" ^  ~$ c
# lsof | grep '/usr/lib'
8 ^; D3 w7 Z( A# Q, z# ~. o: w. T% s  b# I( k# ]
之所以慢是因为+D首先查找所有的文件,然后一次性输出。, F2 F" P3 U5 `& s% N& @9 B

+ V5 L6 D' {: `6 B: d' X  |. B( f列出某个用户打开的所有文件
% @9 O! B5 p3 X) Z1 }" l; u- n- {7 h
9 s/ h) I& _! u( ^" D9 k# lsof -u pkrumins
5 a, ?) a7 a. n% Z( O* t! q$ ~
9 U, H5 o: n3 V, M' p- j3 x7 O; X  ~-u选项限定只列出所有被用户pkrumins打开的文件,你可以通过逗号指定多个用户:4 R; |$ V8 N! T; j6 t6 L) J3 Y

1 [& Z, m6 G. G+ h2 t# lsof -u rms,root5 z& R6 T4 G, u" q6 S2 X. @- f' e

3 K; e! p# @3 i+ A这条命令会列出所有rms和root用户打开的文件。. w3 B1 y  r4 \. q" A
( `% S. g. V4 N
你也可以像下面这样使用多个-u做同样的事情:
" \1 e0 R! y; M/ E  S# P3 O6 D8 z) z; Z7 d2 P" u
# lsof -u rms -u root/ T7 [" r0 d* s$ q+ F. b
7 V$ `) F) Z5 F! G# o3 |: M
查找某个程序打开的所有文件% _8 Q; [/ i! H
7 U& E  Z' K# S! Q* c" p8 U
# lsof -c apache
$ {; V- a+ E/ M* Q1 r1 I# r& `& a/ U/ T7 o$ H" p
-c选项限定只列出以apache开头的进程打开的文件:+ {/ E/ ~  l2 t6 n8 D
. X7 A5 q6 T+ t( c8 V' g4 f
所以你可以不用像下面这样写:
' i. v  V" N3 Y. h  T
' D1 u) y$ D( ]$ G! |+ V* I# lsof | grep foo
5 ^/ R1 [# o8 d' J% T. y8 N1 O/ y; @9 M+ L- i
而使用下面这个更简短的版本:
+ f3 q7 _! H# U' }
: @- }% ?+ r# z# lsof -c foo- p% V* l4 d+ P# K: c

5 d# [# ]+ n/ j, g事实上,你可以只制定进程名称的开头:
# `- [7 ^+ p: d% Q! D; o3 ~0 V4 j: e. k0 C
# lsof -c apa$ O( F) x8 U; |& k" J- B

7 z) L# O9 x. p. K0 c" b这会列出所有以apa开头的进程打开的文件
( f% y7 K% `+ Q
5 g- _3 ]' v0 _" f$ b7 H你同样可以制定多个-c参数:
6 \! O: G$ V6 E  h! H
4 i4 r+ X8 L) ]# lsof -c apache -c python
, f# }; ~6 z1 G# D* A& q  j, X  t' [  u6 q0 v. u- P2 \
这会列出所有由apache和python打开的文件
1 C- J+ u; N& l
1 K9 \0 R% F' H列出所有由某个用户或某个进程打开的文件' V0 p; r- b3 i
" ?! e: d! v$ j: }" i
# lsof -u pkrumins -c apache
: ~1 r4 R. j; A8 q9 T' t) D9 V! T0 c% o) Y; x' d2 A' U
你也可以组合使用多个选项,这些选项默认进行或关联,也就是说上面的命令会输入由pkrumins用户或是apache进程打开的文件。4 r% Z- i% Q: z" x: F3 g

% t, Z7 g$ R6 F7 y4 A( l, h1 i列出所有由一个用户与某个进程打开的文件
$ o) m, `( ?9 a' w4 |
  x; f7 g' u# ?% K# lsof -a -u pkrumins -c bash; m& d0 W8 ^  ]* e6 D
  a2 X' R. A5 t/ T# @" R
-a参数可以将多个选项的组合条件由或变为与,上面的命令会显示所有由pkrumins用户以及bash进程打开的文件。
* ?% r: Z. @+ H/ Y7 ~* g* [4 D' d9 w- B/ h- P, |
列出除root用户外的所有用户打开的文件
* X5 Q! n( z+ l# G
2 r" ^% z( _# W5 i( K0 g4 p# lsof -u ^root
7 F6 k# c$ l8 L( z; S" \6 n2 U7 e  y
注意root前面的^符号,它执行取反操作,因此lsof会列出所有root用户之外的用户打开的文件。+ k; i/ u! i+ t
( p9 n/ m3 }' |
列出所有由某个PID对应的进程打开的文件' X) L% ^; S( T
1 Z1 z% N' O2 i, q
# lsof -p 1" X3 V  h+ T! p+ u

' ^; [* i, V7 B6 D-p选项让你可以使用进程id来过滤输出。
' ]% {: x9 f6 Q/ T" A# \
8 A6 _% x9 e  T; f: _记住你也可以用都好来分离多个pid。& W: n# J4 b7 B" G5 M

/ K1 L& \, ]* L# lsof -p 450,980,333; Y' Y. S% o- j, A$ N* h4 E& R

6 ~: P: o) \+ F" c) v' K列出所有进程打开的文件除了某个pid的3 o9 y# b% N) Q" s! H1 m( \
3 ?0 c8 P: _+ T+ ^. w( u
# lsof -p ^1
6 v8 G& ~9 ?6 _5 W/ ~. q: T3 `! v3 P. G' b' b) c2 j
同前面的用户一样,你也可以对-p选项使用^来进行取反。; i. B& s6 A! D; ~' X

& j8 U! s. X% g8 t' _; ]9 N# {/ T) T7 d列出所有网络连接
9 L# q/ l- O8 v$ v0 t" H1 I1 Y; j
0 U3 u1 N% }! \- z$ p% X# lsof -i- p- v+ t6 j* q) ~% X

/ }8 z7 F1 @; ~0 @3 [  ilsof的-i选项可以列出所有打开了网络套接字(TCP和UDP)的进程。& i8 `" i7 f  ?1 `* f& B
; m: @/ m* N6 M
列出所有TCP网络连接
' x  |6 l" [" T$ ~5 J" N2 Q5 z- ?
# lsof -i tcp
& I1 ]  L7 P- K! E& T/ v0 E3 S8 \: G2 `! f6 ?$ P, U  ]
也可以为-i选项加上参数,比如tcp,tcp选项会强制lsof只列出打开TCP sockets的进程。4 }6 A/ `  f/ y- V  Z/ X+ w
3 w3 ^( l* @& T8 v& O2 E, e
列出所有UDP网络连接1 x' V/ e8 h) D. v8 \; v6 S

, n+ U4 k* M. O( @2 F1 v3 E# lsof -i udp
% u1 T- o; Q# i& l
7 S3 B& p6 O+ [& p0 Q同样udp让lsof只列出使用UDP socket的进程。# {1 P8 ]' v4 A3 f# W
# r) P3 t( ?; R0 `) {; T* F
找到使用某个端口的进程8 M% V* l2 L! r: y1 Y- ?

9 g- U* ]1 C1 a; _# lsof -i :25
% S& ~0 m3 W7 a5 \3 A& f" b
9 r# h4 J- u' e:25和-i选项组合可以让lsof列出占用TCP或UDP的25端口的进程。
/ x/ S; V7 m% S0 r/ M4 N8 x4 W. Q2 k- G+ W) A
你也可以使用/etc/services中制定的端口名称来代替端口号,比如:
2 ^' q/ G9 U" t8 l) D# D" S! ~9 v2 G2 W9 R* [% P: v3 U$ U
# lsof -i :smtp, h: k, y2 Q9 Y4 I! d4 T
0 G3 y; w; v  T$ ?* A; X
找到使用某个udp端口号的进程( D* g8 d6 @5 {

+ v+ k4 b: Y( T( b# lsof -i udp:535 k# E3 X7 y' M: _

# e& H" @( M1 J6 C同样的,也可以找到使用某个tcp端口的进程:- s. p. j) S# c

2 z+ Z* S6 J8 F& D# lsof -i tcp:80
% [9 Z1 F4 ?$ I/ p% s0 ]- t" W2 V. ~, ^1 s
找到某个用户的所有网络连接
6 r3 Y& {5 ^8 {/ e4 j8 }' w- V* @0 Y6 ~# }. t
# lsof -a -u hacker -i
4 A# o( {% ]" \& L* G, Q2 F* t! @5 N2 [) S5 n  a8 r3 o
使用-a将-u和-i选项组合可以让lsof列出某个用户的所有网络行为。; c4 l5 K2 I  n

5 n: u( B8 A  m9 r" S7 X列出所有NFS(网络文件系统)文件
* _; g2 l* X6 i6 }: e/ ^0 L. h! m* U  }1 C& \  v$ M
# lsof -N
2 A/ f3 q' T! L! @; y( q2 v+ t2 F0 Z9 o( L8 [" q, f7 E1 T& R
这个参数很好记,-N就对应NFS。" n/ ~4 j- ~; w

% R; a0 T9 X9 J) U; H列出所有UNIX域Socket文件
  ]9 T; S0 ~( Y$ I0 t/ u0 E! E& |8 w  _+ a0 `
# lsof -U. [. ?2 n- u: m3 F" ?, ?. ]* Y' S
- A1 @3 W7 x) B
这个选项也很好记,-U就对应UNIX。
6 x* T0 ?$ e! E8 Z4 [+ [! E, u! f& s
列出所有对应某个组id的进程! T8 ?8 |" z" h( K

3 |. W  [( Y  e6 r# lsof -g 1234
( L* H- x9 d, [  H  j- }( b% t. d# k) ]' K9 N
进程组用来来逻辑上对进程进行分组,这个例子查找所有PGID为1234的进程打开的文件。7 ~/ ]1 ^$ K# q8 t9 V: t
! o4 [% ~% Q" M& @
列出所有与某个描述符关联的文件& A! y2 G. @* Q( j9 l
/ G0 v1 x/ L" ~6 u+ X3 j. B5 c/ s
# lsof -d 2; Z& K. E; g$ i) C1 |
. k% y0 w5 J! r' j
这个命令会列出所有以描述符2打开的文件。+ G0 Q0 @) S! g; |2 |+ W. K
( V" w! x7 q9 ]" ?& M+ b- Q
你也可以为描述符指定一个范围:
( P7 ^- E- V7 r& w9 L3 Y) z3 p; `; ?3 Z: d! w  ~" O
# lsof -d 0-2
3 \; r8 ^' H- }  _" t( L; F, [3 I* ~# B$ ?* E
这会列出所有描述符为0,1,2的文件。$ T/ _+ t: U, Z. Z. O  w0 X3 A

, P' L/ L8 P0 ^6 G* f/ _% Z# f" V-d选项还支持其它很多特殊值,下面的命令列出所有内存映射文件:
+ D0 T9 ?3 K$ S0 Y
3 t  g6 Q# _- G, ~% P0 \0 s* Z# lsof -d mem0 M- U. J/ C" s- }; _6 V, D' q

! ?( G6 C6 w- Ytxt则列出所有加载在内存中并正在执行的进程:
/ {5 X: ]1 @" T( ~* N3 a: O+ v0 v1 d: x
# lsof -d txt
+ r8 D; p. i" F
' V& K1 L" p# r+ {7 ^输出使用某些资源的进程pid
+ r8 ]6 x1 }( Y! u) O
' U6 k3 u8 X" b8 M7 |  W  @) h# lsof -t -i
3 ]  }4 J& S2 e( r2 |) g
+ a4 a1 Z' H5 D. P2 N-t选项输出进程的PID,你可以将它和-i选项组合输出使用某个端口的进程的PID,下面的命令将会杀掉所有使用网络的进程:% }! Z9 a5 e" Y( M

) {' ]' H. @, Y4 X* a6 [# kill -9 `lsof -t -i`
5 Q8 M: E# W. z% I) N: i% Q- T, K5 _8 H8 n. n1 g
循环列出文件
9 m8 q2 M+ i& g& ~* k) o& r; M! g9 I" P( v6 O
# lsof -r 1$ U- y7 [" e+ M
$ h3 a8 @9 U% a- r5 Q; I
-r选项让lsof可以循环列出文件直到被中断,参数1的意思是每秒钟重复打印一次,这个选项最好同某个范围比较小的查询组合使用,比如用来监测网络活动:, R- e, ]* p9 y( q7 N& l# L

- P* W4 [, h/ Q6 r- `* E" U# lsof -r 1 -u john -i -a; W1 A# j0 ^4 X) r

" w8 C! n  h2 N如何安装lsof?
& G3 B+ l/ x: A% A6 A2 e' q: \  W
& Q2 Y$ b  d' K: d许多Unix系统都内置了lsof,如果你的系统没有安装,你可以从这里直接下载源代码。
, o! P0 I& T. v$ O3 a6 @- W
7 l2 c8 u0 D! n1 F& i- W2 I+ iBSD系统有一个类似的工具可以做同样的事情,叫做fstat。  ~; ]) U6 w3 `8 v8 v1 @( j( h

- U+ I1 ^3 s* `& E你可以通过man lsof来了解关于lsof的完整文档,或者通过lsof -h查看。
1 \6 w! Z* ]/ K# D5 ?, t3 ?0 o; v" Y* N
开始体验lsof的乐趣吧!

该用户从未签到

2#
发表于 2020-3-18 18:00 | 只看该作者
Unix调试的瑞士军刀:lsof
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-11-25 22:18 , Processed in 0.140625 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表