|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
7 W D) P$ K5 k% H q) ~这是“你应该知道的Unix和Linux命令”系列的第三篇,在这篇文章中,我会介绍lsof这个工具,如果说netcat是进行网络诊断的瑞士军刀,那么lsof就是Unix调试的瑞士军刀。
4 v+ M4 Z* _- r9 ]4 u r" P" }
; z5 o5 [- v& R! K e$ sLsof是遵从Unix哲学的典范,它只做一件事情,并且做的相当完美——它可以列出某个进程打开的所有文件信息。打开的文件可能是普通的文件,目录,NFS文件,块文件,字符文件,共享库,常规管道,明明管道,符号链接,Socket流,网络Socket,UNIX域Socket,以及其它更多。因为Unix系统中几乎所有东西都是文件,你可以想象lsof该有多有用。+ D U4 w H B# B
( o1 L5 W+ r- x- k7 I. r
如何使用lsof?
X" T6 X/ j! o4 `& K# r* |$ h
- t: \) p1 z/ C& n这篇文章中我会尽力列举我能想到的所有lsof的用法,让我们先从最简单的开始(或许你已经知道了),然后逐渐增加复杂度:
" ~: q9 J& n [( z' c' b: \$ y1 v/ d% u9 H
列出所有打开的文件
. {+ K5 {2 C$ `9 h# O
, i9 x( x2 @) d3 W8 R# lsof
, h9 B" `* Z$ |% v) }& ^2 ^% e( U: q
不带任何参数运行lsof会列出所有进程打开的所有文件。
3 {) |6 [4 ~ `( W& P
" _" M2 ~% V0 R; v3 L( p找出谁在使用某个文件6 a# R# B! Z# ?1 m
& l9 x8 t* N0 ?7 W4 P
# lsof /path/to/file+ G1 `4 O- c x3 R
) }4 Z/ p) \, u: i只需要执行文件的路径,lsof就会列出所有使用这个文件的进程,你也可以列出多个文件,lsof会列出所有使用这些文件的进程。
( ^$ s# G5 D3 A6 g7 |4 q* b4 E2 n. H" B, j
你也可以一次制定多个文件:; s2 s. g9 H5 t, j: Z9 m& F) ]
* ^5 j* n: m0 T# lsof /path/to/file1 /path/to/file2
2 i' E2 ^0 f; g# V3 A
7 x+ B! ^% H8 b3 q( z/ C& I递归查找某个目录中所有打开的文件1 E1 y, ^* g/ n/ a8 J
' ~0 c" X( B$ ~2 a0 e# D# lsof +D /usr/lib. f6 m( C/ k6 {% u; l4 `
3 t( w$ ^2 K$ |% D
加上+D参数,lsof会对指定目录进行递归查找,注意这个参数要比grep版本慢:/ k5 V: o+ K3 @* h% w2 V
; E* S# p9 `" k0 U' ~# lsof | grep '/usr/lib'
# Q5 c" j! z1 Q& h' m2 ?& x* I3 X( a) x4 k7 t: {
之所以慢是因为+D首先查找所有的文件,然后一次性输出。
6 |9 D. J. b! D1 H% w: E" q/ w
3 @" d3 r/ g& f& g- q列出某个用户打开的所有文件
5 K0 v5 V) Y5 i6 A7 N
/ p0 \2 U/ W6 @& v# lsof -u pkrumins
3 |. t3 R- T3 e7 ?- t2 F9 M4 Y
: M& K) I' A2 V( l% o1 G. z-u选项限定只列出所有被用户pkrumins打开的文件,你可以通过逗号指定多个用户:, R8 E; @& E8 O& o3 n/ I/ Q4 W
" `; K6 R1 E: i# @2 b, C a# lsof -u rms,root5 i) V6 b/ ~: F0 a6 N
- T/ y* H. [' r5 E0 O这条命令会列出所有rms和root用户打开的文件。
4 T& a' X4 S& k% |/ Z& p6 k
- n" n2 X' v! |3 k0 c. J6 `9 o( X你也可以像下面这样使用多个-u做同样的事情:+ l$ a8 U0 d* Q
]! D+ z+ A U a0 U, R1 S1 T* f9 T
# lsof -u rms -u root+ u5 V2 B9 ]3 t% V
! n; [" ~* Q- k查找某个程序打开的所有文件
9 h2 U2 N" I+ [" w; M0 u
; k1 |2 X9 G! b0 e4 J# \# lsof -c apache- Q4 x) g' d" x3 I0 `
" j: A) E( C5 C1 X8 n2 A; L) S
-c选项限定只列出以apache开头的进程打开的文件:# y: X y M# A5 x+ i
; E; b* a; R6 D+ `% u' M4 x7 H0 V所以你可以不用像下面这样写:
, |/ ~+ V- i# ?) Q* `( @0 b3 W
9 b# o4 B# n1 n( [! y' V8 Z! h# p# lsof | grep foo
1 M5 T& X- R4 }) U8 u+ f+ P. E' o. @9 Y' U; W" U2 ^
而使用下面这个更简短的版本:3 `% Q9 Z% Y" ^
( s) k+ G2 r: k( Z
# lsof -c foo6 g. U5 R/ J9 T2 V7 v% T1 z: g
! J, r8 j: D# k/ ~5 \& `
事实上,你可以只制定进程名称的开头:
4 `% b1 h$ v6 U3 D4 v
/ P' {! [+ Z4 L# C/ ?* X# lsof -c apa& A/ U* _+ l6 b: i4 D; ?# \! x
5 I% P: [1 I% m这会列出所有以apa开头的进程打开的文件& j, h. h+ Y0 \5 W& R( D
7 h# N; t+ D! [0 o, d+ }0 y( t你同样可以制定多个-c参数:. X! U' o8 v* z* M
4 i- j- |3 f+ \' D# lsof -c apache -c python! B8 C% m7 S1 I- c
0 Z- R2 d( `1 O0 I- O9 g+ J
这会列出所有由apache和python打开的文件- x1 n3 ~1 ^( j- r8 F
/ z+ p3 M. ?3 p2 o! M O3 o列出所有由某个用户或某个进程打开的文件
% m( g2 W' H7 N" f2 o/ J, X; A+ Y- v! @; s/ F0 e
# lsof -u pkrumins -c apache2 d: u% g) C. i
1 u5 W" X" z, N0 _! E5 i你也可以组合使用多个选项,这些选项默认进行或关联,也就是说上面的命令会输入由pkrumins用户或是apache进程打开的文件。
0 _9 \* O4 S" J( S. b" o
* u( C O' `8 E列出所有由一个用户与某个进程打开的文件4 r/ v% ?# {: @/ `2 [6 N
3 w6 d5 f7 m# L, ~& ^
# lsof -a -u pkrumins -c bash
" @4 M: Z$ V: k% r
7 A& M o8 X1 ]% ?# p1 ]/ B) D-a参数可以将多个选项的组合条件由或变为与,上面的命令会显示所有由pkrumins用户以及bash进程打开的文件。
% v; H+ l, e% R, x. d, `: v& m2 g; z/ L- _/ \! {; [, l. i# ^- H
列出除root用户外的所有用户打开的文件
* F8 W4 F5 C i/ b; y/ X
5 O$ [- s: w8 x# lsof -u ^root8 T4 {0 n- w) B) R0 Q
) q+ A) \4 M9 [, _注意root前面的^符号,它执行取反操作,因此lsof会列出所有root用户之外的用户打开的文件。
) f6 e& K5 G+ P3 M: r& ?; j' Q0 m
. K8 d0 c: } }/ }: M$ x列出所有由某个PID对应的进程打开的文件
# P" ^7 b+ P3 [* P) Y, L6 y& s1 K& M
# lsof -p 1& N5 d5 O( P8 U( p9 K9 m
3 ]& \6 |4 w# `$ F
-p选项让你可以使用进程id来过滤输出。
4 e: v8 o& U+ J- @3 \" T* { h2 q/ @, n' T
记住你也可以用都好来分离多个pid。
! Y$ o. t7 H/ a2 B- p
" q$ U: J+ a3 T+ K3 R( t/ E# lsof -p 450,980,3334 Z1 G. e j3 H% Z! i
6 K: J/ c8 v$ }+ X) v8 M列出所有进程打开的文件除了某个pid的
5 `! }4 b( k! R3 Z
& @- g- |8 A+ G% g0 Z/ O# lsof -p ^16 Z& j: {- q) V) \! m n; u
# ~& y( ?7 g, Q6 n. k0 X: I同前面的用户一样,你也可以对-p选项使用^来进行取反。
8 {& s5 A( D* Q6 m7 e0 `9 C
" }* q7 O5 R3 q列出所有网络连接, T3 x+ W# F, I( _
; u$ a/ O) G9 f8 }8 A0 A) I# lsof -i
; v% ?5 w5 s+ t. e3 V6 Q% b" l: t- h, R' z! J6 a
lsof的-i选项可以列出所有打开了网络套接字(TCP和UDP)的进程。! I) k6 H3 D" ^: \
- n$ }7 Q+ D2 L3 M9 m2 G9 M/ B
列出所有TCP网络连接
; I' x% `! h5 G: y& }0 Y3 T! w" y8 K5 }8 A( ]0 j% H5 [* u' n/ @
# lsof -i tcp
% T0 z# L: F& ~4 \6 @8 T4 x
2 R9 @: b3 x( n3 c也可以为-i选项加上参数,比如tcp,tcp选项会强制lsof只列出打开TCP sockets的进程。
6 c( s5 V$ t" `8 y1 N- [1 ?( y+ |
0 q# O, {' e/ t7 c1 r- B* `列出所有UDP网络连接" x) ]4 s; v" Q
) w+ B6 ? L6 e! f4 W ~2 ?2 E6 U
# lsof -i udp: R$ J" u1 i" N4 y" q
& O: u. l- c7 `6 g
同样udp让lsof只列出使用UDP socket的进程。
" E+ P, b+ U# b
1 Q) M! R' Q9 G" H4 }找到使用某个端口的进程
/ f7 u( Y6 d8 V5 G+ `4 d6 N
' b- K6 _. G/ t4 i# lsof -i :257 a# K5 F; D5 W! U$ h
8 p3 e2 J7 C5 a$ h8 C
:25和-i选项组合可以让lsof列出占用TCP或UDP的25端口的进程。
. s, ^, i9 G4 P" ?4 H: A( V5 x6 J- P9 i* Z. X
你也可以使用/etc/services中制定的端口名称来代替端口号,比如:
7 P, A5 Q+ ~+ c; t! ^) X+ A% X X; N0 V) B, ~2 l
# lsof -i :smtp0 i2 P/ f3 X4 B) s, G3 Q
6 [0 K, C5 [2 _# k找到使用某个udp端口号的进程, s' P+ q- {7 t7 X4 c
8 T2 ~* ^: R4 M! y# lsof -i udp:53
L5 d+ \2 o) {. a9 l( l0 E- m% A v# [8 k
同样的,也可以找到使用某个tcp端口的进程:
4 _- x/ B. ?0 y' i& B: ]5 ]' P2 F* V7 Z( A% h, k% Q0 D" E4 \
# lsof -i tcp:80 _2 r4 u$ ^# A- o0 ~
, F8 w$ s, M) O6 {5 w" H
找到某个用户的所有网络连接
! o1 E! n1 D$ c+ \8 Q
' @ W+ L1 v4 G5 g H9 h# lsof -a -u hacker -i
, c' V# e3 E' i% ]% p
1 @! h+ c) Q) Y r9 F. I& q使用-a将-u和-i选项组合可以让lsof列出某个用户的所有网络行为。
/ K1 ^ r# k+ x: i; O
3 |9 F5 N( ^' A! H6 z6 @8 ]列出所有NFS(网络文件系统)文件
3 `( z6 W. c- [! \: Q. s/ z! ~! ^5 i3 L2 \( g3 y+ K9 R
# lsof -N
9 [$ i) r) ^7 }, l
, }, E6 X( E7 m7 L. Z1 O这个参数很好记,-N就对应NFS。
) `+ U- F3 u& p: O) N+ F
X* M* }& ]3 u' W a9 R: g( S列出所有UNIX域Socket文件. Z) p3 b H! i# J8 h; m
/ n3 n% j/ i. D' [0 _9 F# lsof -U- H1 n9 g8 t' \: {0 X
: B: {/ ]9 C: S4 f7 j, j
这个选项也很好记,-U就对应UNIX。
# B) t5 {" g/ v9 F# _: S. }2 K6 A- Y9 U3 \8 R4 C f; ^
列出所有对应某个组id的进程/ {# v* S/ d$ X2 b: j: I
: d2 t5 \2 [" e) `% f# lsof -g 1234
0 \2 s6 y. G% G, g% s6 @ ^
8 s$ r' w( R* v. T; p进程组用来来逻辑上对进程进行分组,这个例子查找所有PGID为1234的进程打开的文件。9 x) s8 B( H& F+ u9 i. u
% w) `. G6 h% N ~
列出所有与某个描述符关联的文件
" e- ^( \; q: F7 {! W3 H& c, W
# lsof -d 2
5 j2 B" n- `# U8 Z; v i" c
4 `" m2 [: U' Z' n这个命令会列出所有以描述符2打开的文件。
8 J4 I4 @! D, n3 }& s
; C7 e) L7 R Q9 x" O: N/ G你也可以为描述符指定一个范围:
, Y3 A' m! G5 y+ I+ e2 i$ k) T9 R. r! I
# lsof -d 0-24 ]: R; A7 {4 W
3 k$ D/ J$ k0 J这会列出所有描述符为0,1,2的文件。0 _- l# @/ k# Y6 N! Y4 G% `3 y
. D+ f+ }' {2 C& X9 ]-d选项还支持其它很多特殊值,下面的命令列出所有内存映射文件:
7 s/ q3 K; ~5 o9 i
- ~# q4 T6 o' G1 B+ G& w# lsof -d mem
' r# c/ h1 _2 S; ~, a% r8 ?& H% A% {+ `) X+ O; {; S7 {9 f
txt则列出所有加载在内存中并正在执行的进程:
4 H/ D4 ^7 @0 @1 L. Y7 U7 m" \! I$ |/ v; p9 F
# lsof -d txt* B3 J: S" ^; S; s- h
8 X" x! T4 Q% T5 C3 H输出使用某些资源的进程pid
% q, d$ n/ L, Q9 o! {2 p& |. y8 _
1 l6 |; J1 @" H4 T- o* ?' Y# lsof -t -i3 A' [' A' T1 s M
! S% N: E9 N# J/ ?-t选项输出进程的PID,你可以将它和-i选项组合输出使用某个端口的进程的PID,下面的命令将会杀掉所有使用网络的进程:
; ~1 f4 `: o$ K6 I$ `+ a. J# b t: ~9 i6 y
# kill -9 `lsof -t -i`
' a% b" G Z1 e7 N8 E3 b
* X1 p; ^' Y7 D- l循环列出文件2 U/ A3 f) c% f3 [4 X+ M% }
* k1 U- x0 i9 a% g# j9 p; p
# lsof -r 1' _$ N3 O8 Y/ N9 x) g9 b+ m' o
9 v/ s: A5 N' N& ~3 A1 q. _% N-r选项让lsof可以循环列出文件直到被中断,参数1的意思是每秒钟重复打印一次,这个选项最好同某个范围比较小的查询组合使用,比如用来监测网络活动:
, V; {) d/ r* G
: q8 x3 x# c) K& I! b# lsof -r 1 -u john -i -a
5 X" k9 R4 \+ J* y7 e2 L5 b. t8 o1 d. U$ _; h
如何安装lsof?7 }/ w" \8 Z& a: N0 B
# c: h9 d# [, u8 ?7 F许多Unix系统都内置了lsof,如果你的系统没有安装,你可以从这里直接下载源代码。7 c8 P; F6 U5 W' |
; Z! M# _0 c# Z4 ~& E R s! OBSD系统有一个类似的工具可以做同样的事情,叫做fstat。
E) o& E; u/ V
1 |! z: ~/ W" v你可以通过man lsof来了解关于lsof的完整文档,或者通过lsof -h查看。
S9 `4 M: e4 m8 H/ R( Z( u6 ]$ l# n
开始体验lsof的乐趣吧! |
|