|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
' I3 O3 P1 O6 {( e5 h8 t, c
这是“你应该知道的Unix和Linux命令”系列的第三篇,在这篇文章中,我会介绍lsof这个工具,如果说netcat是进行网络诊断的瑞士军刀,那么lsof就是Unix调试的瑞士军刀。
0 i% m+ e1 H2 ^5 d8 }
! {: m2 x$ }( Y1 t+ JLsof是遵从Unix哲学的典范,它只做一件事情,并且做的相当完美——它可以列出某个进程打开的所有文件信息。打开的文件可能是普通的文件,目录,NFS文件,块文件,字符文件,共享库,常规管道,明明管道,符号链接,Socket流,网络Socket,UNIX域Socket,以及其它更多。因为Unix系统中几乎所有东西都是文件,你可以想象lsof该有多有用。+ x; Q2 k9 B7 D/ d( n
* t% y4 [1 F: v, W- \. |如何使用lsof?6 F& p% Y7 T# \( U l6 T$ q
% F- I/ V3 L+ ?这篇文章中我会尽力列举我能想到的所有lsof的用法,让我们先从最简单的开始(或许你已经知道了),然后逐渐增加复杂度:
8 Q3 q4 M! d! |( P: I
3 i1 Z( E k6 n/ s$ g& U列出所有打开的文件7 r0 T+ F3 b% M1 v! V
; O3 g' o8 E. x& y4 j; k0 }# lsof, f$ f0 u6 W% Q9 N! }7 [+ X
J3 R# y! w# z" m0 ?不带任何参数运行lsof会列出所有进程打开的所有文件。
, o4 b' L' s L5 O M3 n7 L. _! q! V; R; N
找出谁在使用某个文件% f- P* V1 _2 d+ G. j% S$ p+ x
& A% @' i$ Y$ Z" L/ t: n
# lsof /path/to/file
: a" H f* W" v% e% J+ e. j) S* L+ @$ V: H! t h+ x
只需要执行文件的路径,lsof就会列出所有使用这个文件的进程,你也可以列出多个文件,lsof会列出所有使用这些文件的进程。
4 I5 m! K, e+ R5 I( Y$ }) x
) b9 J9 Y$ ^ K3 r; U3 _ K$ g+ R* }/ W你也可以一次制定多个文件:* f7 Z* ^0 K9 n& w" ]/ W- }
7 g4 }. {1 v' q. m# lsof /path/to/file1 /path/to/file2# x k. R1 U2 t0 l# f
% I0 d! K4 H2 Q# Z) z递归查找某个目录中所有打开的文件
! k; w0 F; e ~4 K- H; T8 j' i5 x! R8 X6 ?, |! a
# lsof +D /usr/lib. @0 j) ]$ \6 T/ |: U( c
& p1 x6 y5 M0 `4 f& ?加上+D参数,lsof会对指定目录进行递归查找,注意这个参数要比grep版本慢:. \ t( D: t& d% r1 Z9 k( b/ r
& z4 w/ }4 J) Z) F# w# {# lsof | grep '/usr/lib'2 \: E6 u- l# Y" z
# N7 F. w* I5 z$ Z" I: D! C" q; C之所以慢是因为+D首先查找所有的文件,然后一次性输出。
9 S/ h6 U( ]2 m
+ u5 B4 T7 I0 t. T6 S列出某个用户打开的所有文件( c/ V8 D) [- z$ l
8 [1 N' e6 a/ [' y9 x* b; P# lsof -u pkrumins
" V& w1 W5 W0 x1 G! _: h
" d' d/ T7 n7 l1 y-u选项限定只列出所有被用户pkrumins打开的文件,你可以通过逗号指定多个用户:7 f0 H) D, @# a$ I4 W
* U; d6 u# e* t; ~# lsof -u rms,root9 `$ v. B2 n- C* y/ C4 V
1 r0 b$ y. B- p" M1 X {
这条命令会列出所有rms和root用户打开的文件。3 S$ v% s( [$ h+ ]: T `! \
' {) I9 P, k& l: y& q你也可以像下面这样使用多个-u做同样的事情:1 v4 v% A- `3 F3 m
, B# }2 Y; F' @. _
# lsof -u rms -u root! I5 d! t2 U2 G" O
) T3 }6 r0 x9 h! W* P' n9 T E E查找某个程序打开的所有文件
6 {& v( S" l- B5 E* l5 e: |3 c5 A0 e) z8 F# C
# lsof -c apache# D8 M l( b, y8 Q% i0 |
/ _# C2 i G& O
-c选项限定只列出以apache开头的进程打开的文件:' ^% S' J" ^; ?, ?5 k5 T. a9 q
" Z# ~# G4 E9 N L/ k: K+ \0 \3 @
所以你可以不用像下面这样写:7 \& ]* t7 r: _$ B" t+ L- |: j8 r4 ^
. G& l7 [" h* q( `6 e" P# H# lsof | grep foo8 i' G0 x" I' u f
9 q+ N: f8 m: e) }$ a2 t n而使用下面这个更简短的版本:; C# y; X a4 K+ E( S: U: s
1 @. a6 x' B: g! _# lsof -c foo7 c2 [1 W. _, U, o- B4 [4 y% N1 p
! b8 h9 d& b- z( |3 ]
事实上,你可以只制定进程名称的开头:( u. ~" P. Z4 K
, b5 ]. O5 w) \& p. {* S# lsof -c apa
- V' B6 s. j! k2 v8 f* A) ^
4 x& z* D: {( N m& b1 g: a: S% B' R这会列出所有以apa开头的进程打开的文件% [6 b8 Q1 L* x) i- h7 I9 _
3 ^) W/ [; P: U; L8 o4 S+ A; F8 K# k你同样可以制定多个-c参数:
1 x0 ?" d( ?' N; T, s2 C$ T# k. V8 u+ t4 |6 {
# lsof -c apache -c python4 K. I; J/ y1 G( t. e" s4 v; x
2 s7 `) I6 h7 `这会列出所有由apache和python打开的文件) L1 }; b, U* u5 X2 c. X4 X* n& W; L
( [3 z* ^7 d( a! ~) S
列出所有由某个用户或某个进程打开的文件8 L; b% g' S2 W+ r5 X* D
4 j( y& J/ R8 h6 T3 }* ]. D6 w ^
# lsof -u pkrumins -c apache7 `; C. ` g+ r7 _% m
8 f! c9 o' d b+ f5 s+ K
你也可以组合使用多个选项,这些选项默认进行或关联,也就是说上面的命令会输入由pkrumins用户或是apache进程打开的文件。
5 \, e; ?# X0 ~! [, Y+ H# N) p6 q5 }3 \, R3 A# u! ]$ D* i
列出所有由一个用户与某个进程打开的文件
0 d* a) L, @. P8 A4 |7 C
9 l1 o7 E' P; d# lsof -a -u pkrumins -c bash" R: C/ a1 h: `$ W, S
* H; @: \+ r5 d+ x# ~, M, a
-a参数可以将多个选项的组合条件由或变为与,上面的命令会显示所有由pkrumins用户以及bash进程打开的文件。
; u3 Q# I& ]# H i6 b( k: R/ z2 M
# p) [1 f) g( i* k" o) S列出除root用户外的所有用户打开的文件
) z) S( D R! K% S8 }0 O( `
- `1 ^) w5 q9 f D# lsof -u ^root+ \, h; k5 _! O' k
8 s# U6 t/ U. E; g }( l注意root前面的^符号,它执行取反操作,因此lsof会列出所有root用户之外的用户打开的文件。: i$ W0 M+ S1 e! R; U
' |# l# ^, d" L$ O. u$ A& J& X9 J- F
列出所有由某个PID对应的进程打开的文件& |6 {' G% n3 ?; k
# K! r; ~) d, |( F8 O" Y# lsof -p 1- W1 v, ?3 |8 b
8 l7 I U0 b! u: ?* c5 ~- j-p选项让你可以使用进程id来过滤输出。7 C7 i u$ [+ v
% H$ Z5 Q% W z. \; N" M, o5 k, q
记住你也可以用都好来分离多个pid。
( K$ I0 [4 P- o
# j0 ~. `2 x r. b8 V1 j" ^# lsof -p 450,980,333
y3 d5 V* `" u
" w) V. E5 a3 Z1 U7 F+ g2 m' y列出所有进程打开的文件除了某个pid的
$ b/ ]! x- J5 i* {. u4 `) |+ h$ p5 k$ y0 s
# lsof -p ^1
0 B9 V1 b/ I4 L( M
* @% Q' C2 [4 t- F6 {% B同前面的用户一样,你也可以对-p选项使用^来进行取反。
" X+ w* q0 ?9 ^7 Y; p& b# e
& l1 }$ r' }! ~8 \# V- c列出所有网络连接/ F/ ?2 g: p5 t- i3 n
; T: z9 D- f2 f( V* M
# lsof -i
4 x+ r! w& i: L6 ]3 C8 h
( ~- x `: S3 J- X1 jlsof的-i选项可以列出所有打开了网络套接字(TCP和UDP)的进程。5 H/ D7 W) F% D, W4 Q
) d6 d4 O! `# O
列出所有TCP网络连接/ X+ K1 H- D% a- S
& C {) p8 m& [5 S
# lsof -i tcp
& w6 ]; {3 e- C2 P: p* Y7 c/ \' D4 F% Y( q" _
也可以为-i选项加上参数,比如tcp,tcp选项会强制lsof只列出打开TCP sockets的进程。' X- }& \. e' F: V
6 E7 M0 L' j! V8 c9 T列出所有UDP网络连接+ v( a7 d% ]4 j) n! Q& c5 H
& B, E0 L2 s. D9 }# lsof -i udp+ _& y" J" D& p0 c' ^
; g8 Y2 M8 s% s1 ?7 m
同样udp让lsof只列出使用UDP socket的进程。; V8 G7 o, [6 p' q0 k* A
' V* }5 B/ r4 H& U( q5 ]3 L' r找到使用某个端口的进程/ D: i3 k4 C' T" ?
5 A- h3 O' j; @# lsof -i :25* N- |9 j+ Y/ E3 a( [! V5 l
& W# d. D' ]6 N6 u) g: G( r; s; X:25和-i选项组合可以让lsof列出占用TCP或UDP的25端口的进程。" b, Z+ W: q+ z3 U( u
U) W5 ^) [' c1 O, m2 n
你也可以使用/etc/services中制定的端口名称来代替端口号,比如:) A4 w) {0 {1 v N6 j( I
: d3 E$ {) {' C
# lsof -i :smtp
8 ~$ {# r% H) J1 @7 M7 B% G5 Z. p! Z8 {0 @( B& n
找到使用某个udp端口号的进程: L/ l9 q+ h; W) F8 x# {( j" W4 D, r: h
+ q7 [9 \$ z' V' G' g4 ^
# lsof -i udp:531 U! k( E7 f: O% A6 y3 W
$ @/ l' a2 |/ y
同样的,也可以找到使用某个tcp端口的进程:
" ]7 h: j, R( L5 h9 v3 B$ M, s. i, s4 G' C) ]- S
# lsof -i tcp:80
2 H' t2 o8 O5 H4 T9 x% s" |" c% l' n3 I+ T( `
找到某个用户的所有网络连接
4 w$ u; s; h4 `+ d T$ l6 f# R G6 S: ^# o4 ^3 _
# lsof -a -u hacker -i
, b4 N6 @& {+ i8 p
" j; `" S% G C- p使用-a将-u和-i选项组合可以让lsof列出某个用户的所有网络行为。
5 E, J# [2 r. d; [8 H& ^! i2 |0 y6 v
列出所有NFS(网络文件系统)文件9 G' f9 E" h6 ]6 \" N4 `' ^8 E3 y& N
7 j- g# ?: r, n. n Y/ @9 h
# lsof -N
; r9 s- @2 J$ I! |6 @; g% b
, ^- u- o: L; G' v这个参数很好记,-N就对应NFS。7 y% _8 z& ]$ @ a
) a3 A1 M( C/ J; g9 }4 H$ z列出所有UNIX域Socket文件: h5 y& J) c$ K* p7 q; @* B' w
6 M+ g9 W& P. t
# lsof -U
6 z1 p: Q0 o- ~! t9 P1 r2 u/ C: O, W4 G. X5 o6 V4 U- J
这个选项也很好记,-U就对应UNIX。
$ n p+ ?+ n3 ~" X& o% J, a8 A& T1 l- b! Z
列出所有对应某个组id的进程: X; ^; d/ ~/ Q/ q O) H$ J* _( }" X
1 b0 n$ i- `( O- i5 ?/ P% W4 n$ \+ B# lsof -g 1234
6 k; |" ~) N: L- x1 Q/ r; g. z8 d& u# |- J
进程组用来来逻辑上对进程进行分组,这个例子查找所有PGID为1234的进程打开的文件。
- S/ _) C4 X) o) M4 A# N3 p" t
6 }6 p4 r9 X* U+ O* {列出所有与某个描述符关联的文件
. ?' H- k6 O. s0 D* W: h: E" J
- y( w+ E* | ?% r3 o9 p6 w3 d# R3 b) d* G# lsof -d 2' a, h" ^8 u; {- Q6 h6 z
: |- i. K5 m2 A; W/ \7 L这个命令会列出所有以描述符2打开的文件。
* }( p1 E: N; k0 ? d; \2 B9 ~: j9 y5 }- `+ B* h" U' X$ K
你也可以为描述符指定一个范围:# Q w1 f% i7 N- v8 `& x$ l; C5 E0 G
% W3 E5 ~, s) F R
# lsof -d 0-21 l# I) K _4 e0 a+ X" v w- ^
( y# P- x. n$ P4 ~! k* T* m这会列出所有描述符为0,1,2的文件。
6 i. S) |4 r G4 j) b# f5 `) ~
-d选项还支持其它很多特殊值,下面的命令列出所有内存映射文件:
7 f7 w3 ?4 G6 v ~ V! G2 v, j0 N# C8 y# S' R* m3 n: f0 A/ a3 T. C
# lsof -d mem
1 { a2 f% [. p0 C
( s G+ b. H- ftxt则列出所有加载在内存中并正在执行的进程:; l. _, u0 l3 [+ W6 f! b
, G# Q0 u; Y( I# g0 P( F) u# lsof -d txt; j: q& a' Q6 `
% `7 J) O& R% W$ R& ]输出使用某些资源的进程pid9 g# t' _, ^& f5 ]/ Q& V
' f( G$ [1 p; i& T
# lsof -t -i; z# D$ v% h! T: x
" x$ U, l6 k3 v8 D3 }1 u3 _-t选项输出进程的PID,你可以将它和-i选项组合输出使用某个端口的进程的PID,下面的命令将会杀掉所有使用网络的进程:. _( x# r% i9 U: L7 J* }( t" t
+ J6 K& @- M) P5 d; }9 \
# kill -9 `lsof -t -i`
3 ^& s2 S' I) o6 ^- S& @: |. e2 r8 ]6 F1 u, M- n* w; [
循环列出文件2 a) V8 I- ~: {* P" ]( p; ]( u
& _& F# S) t y9 z* h5 f7 p
# lsof -r 1
% Z- i6 T2 H* b; B! G- r0 p9 G) R$ b. E
-r选项让lsof可以循环列出文件直到被中断,参数1的意思是每秒钟重复打印一次,这个选项最好同某个范围比较小的查询组合使用,比如用来监测网络活动:/ w6 _$ z% _; \( P
7 r+ k, b0 y7 ?8 S
# lsof -r 1 -u john -i -a
. m( [6 |7 T6 S# {( b. S# ?3 E
8 A$ q3 w B; b5 d) `如何安装lsof?
s6 K% H+ }" C4 x& f$ f3 w* f$ C# p' j- b0 ^
许多Unix系统都内置了lsof,如果你的系统没有安装,你可以从这里直接下载源代码。
, d* k. y3 W' _. U( x9 C2 a( w: D8 u# {+ M
BSD系统有一个类似的工具可以做同样的事情,叫做fstat。
! W4 _ V2 l" s' W, `/ U
( l+ B% x' y; n9 ]' ~9 Q你可以通过man lsof来了解关于lsof的完整文档,或者通过lsof -h查看。3 L1 n! y+ z1 {3 d' N) R
$ o5 J4 H1 x" _开始体验lsof的乐趣吧! |
|