출처 : http://security.kaist.ac.kr/docs/lsof.html, 글 권용철
저자의 동의하에 커피닉스에 올렸습니다. (2003.9.4)
다른 곳으로 옮기시기 위해서는 원문에서 밝힌대로 저자와 협의하시기 바랍니다.
아래부터 글의 시작이며 일체의 수정없이 그대로입니다.

LSOF 설치 & 활용 가이드

written by godslord@sparcs.kaist.ac.kr


-. 이 문서의 저작권은 저자에게 있습니다. 본문의 무단 인용, 복사는 저자와의 협의 없이 절대 불가능합니다.


Table of Contents

  • lsof란?
  • lsof 패키지 구하기
  • lsof 설치
  • lsof Source의 간략한 설명
  • lsof의 Command Line Option들
  • lsof 사용하기


    * lsof란?

    LiSt Open Files의 약자로서, 이름이 말하는 것들을 그대로 수행하는 프로그 램이다. 좀 더 구체적으로, 현재 System에서 돌아가는 모든 Process에 의해서 Open된 파일들에 대한 정보를 보여준다.


    * lsof 패키지 구하기

    lsof의 최신 버젼은 ftp://vic.cc.purdue.edu/pub/tools/unix/lsof에서 쉽게 구할 수 있다.


    * lsof 설치

    lsof의 설치는 비교적 간단하다. 패키지를 풀면, lsof_???(release number)의 디렉토리가 생성되며, 이 디렉토리 내의 Configure라는 Script로 환경 설정을 해 준 다음 컴파일 해 주면 된다. Configure에서는 인자로 설치 대상 OS를 적 어주면 된다. 지원되는 OS목록은 -h 옵션으로 확인할 수 있다.

    다음 예제는 Linux일 때 이다.

    	$ ./Configure -h
    	$ ./Configure linux
    	$ make
    
    Configure에서는 Inventory Mode를 실행할 것인가와, Customization을 할 것 인 가를 각각 물어온다. 전자는 현재 lsof 패키지가 제대로 되어 있는가를 검 사하는 것으로서, 뛰어 넘으려면 -n 옵션을 주면 된다. 후자는 lsof를 사용자 가 원하는 기능을 포함시켜 컴파일 할 수 있도록 도와주는 것이다. Customization은 machine.h를 직접 수정하거나, Customize Script를 실행해도 똑같은 효과를 볼 수 있다.

    Customization Script에서 물어오는 옵션들을 알아보도록 하자.

    Options
    항목기본 설정 값설명
    HASSECURITY disabled 이 옵션은 root만이 전체 시스템의 openfile 들에 대하여 실행할 수 있게 한다.
    WARNINGSTATE enabled 이 옵션은 lsof가 필요할 때 마다 Warnning 메시지를 출력하게 한다. disable되어 있으면 출력하지 않는다. +/-w 옵션으로 켜고 끌 수 있다.
    WARNDEVACCESS enabled 이 옵션은 /dev(/devices) 아래의 파일들에 대해 Access할 수 없을 때, 메시지를 출력하느냐를 설정한다. 위 WARNINGSTATE옵션이 enable되어 있거나 +w옵션으로 실행했을 때 해당한다.
    HASDCACHE enabled 이 옵션은 lsof가 /dev(/devices) 아래의 파일들에 대한 여러가지 정보를 가지고 있는 Cache 파일을 생성할 것인지를 결정한다. HASENVDC, HASPERSDC, HASPERSDCPATH, HASSYSDC는, 이 Cache파일들의 Path를 지정하는 옵션이다.
    HASENVDC, HASPERSDC, HASPERSDCPATH   HASDCACHE 옵션 참조
    HASKERNIDCK enabled 이 옵션은 커널의 버전등을 체크하여, lsof가 컴파일 됐을 당시의 커널에서만 돌아가도록 하는 옵션이다. AIX등에서는 이 옵션을 켤 경우, 실행시 마다 꽤 시간이 많이 걸릴 수도 있다.

    Makefile에서는 install rule이 빠져있다. 따라서 이 부분은 각자가 알아서 적당하게 써 넣어 줘야 한다. 물론 대부분의 경우에는 @echo 블럭 내의 부분을 지시하는 대로 조금만 고쳐 주면 된다.

    고쳐야 할 부분은 Makefile 첫 헤더 부분의 BIN(실행파일이 설치 될 디렉토리), DOC(Manual Page가 설치 될 디렉토리), GRP(/dev(/devices)/kmem의 group)이다. 이 것들을 알맞게 수정해 준 다음에, install rule을 다음과 같이 만든다.

    	--- Makefile in /lsof_x.xx
    	install: all FRC
    		install -m 2755 -g ${GRP} ${PROG} ${BIN}/${PROG}
    		install -m 444 ${MAN} ${DOC}/${MAN}
    
    	$ su
    	# make install
    
    이제 인스톨까지 모두 마친 것이다.


    * lsof Source의 간략한 설명

    arg.c : 공통적으로 사용되는 아규먼트 처리 함수들
    lsof.h : 공통적으로 사용되는 헤더로서, Platform에 따른 헤더들을 포 함하고 있다.
    main.c : lsof의 주요 실행 부분
    misc.c : 범용의 여러가지 잡다한 함수들
    node.c : 범용 node 읽기 함수들 - inode, vnode읽기
    print.c : 범용 print 지원(화면 출력) 함수들
    proc.c : 범용 proc file system을 지원하는 함수들
    proto.h : lsof에서 사용하는 모든 함수들의 prototype들
    store.c : lsof에서 직접 다루는 file structure를 지원하는 함수들
    usage.c : lsof의 사용법을 표시해 주은 함수들
    version.h : lsof의 버젼 정보를 포함하고 있다.


    * lsof의 Command Line Option들

    1) Select Options
    lsof로 검사할 대상 파일들을 지정할 때 사용하는 옵션들이다.

    -a : 각각의 파일 선택 옵션들을 AND 연산하여 대상 파일들을 선택 -a 옵션이 없다면 모두 OR 연산 되게 된다.
    -c : -c 옵션으로 지정된 프로그램의 프로세스가 사용하고 있는 파일 들을 대상으로 한다.
    -d : 지정한 descriptor들이 나타내는 파일들을 열거한다. 여러개의 descriptor는 ","로 구분하며, "3-10" 범위를 지정할 수도 있다.
    -g : 지정한 프로세스 그룹 아이디를 가진 모든 프로세스들이 사용하고 있는 파일들을 선택(comma separate)
    -i : 인터넷 Socket들에 대해서 수행한다. 프로토콜 이름, 호스트와 서비스 이름을 지정해서도 수행할 수 있다.
    -N : NFS로 연결되어 있는 파일들에 대해서 수행한다.
    -U : 해당 UNIX domain 내에 있는 모든 Socket들에 대해서 수행한다.

    2) Output Options
    lsof의 수행 결과를 여러가지 포맷으로 나타내어 주는 옵션들이다.

    -F : 인자로 주어진 Charactor로, 각 필드를 분리해서 출력한다. 다른 Awk, Perl등에서 직접 입력으로 받아 사용할 수 있다.
    -g : 프로세스 그룹 아이디들을 출력한다.
    -l : 로긴 네임 대신에 UID를 출력한다.
    -n : 호스트 이름 대신에 IP address를 출력한다.
    -o : 파일들의 offset을 항상 출력한다.
    -P : 포트 Service 이름 대신에 포트 넘버를 그대로 출력한다.
    -s : 파일의 크기를 항상 출력한다.

    3) Precautionary Options
    lsof는 System Dependent한 여러가지 기능을 사용하고, 이것들 때문에 수행에 오랜 시간이 걸리거나, 다른 작업을 Block하는 경우도 있다. 이를 막기위한 옵션들이다.

    -b : Kernel 내부에서 Block될 수 있는 System Call들의 사용을 피한다.
    -D : 기존에 존재하는 device 캐쉬 파일을 무시하고 새로운 캐쉬 파일 을 생성한다.
    -O : lsof가 kernel에서 Block 될 수 있는 가능성을 가진 일을 수행할 때, fork(2)를 사용하는 것을 피한다.
    -S : lstat/readlink/stat System Call시, Time Out을 설정한다.
    -w : 컴파일 시에 지정한 Warning Message 처리 방법을 토글하여 수행 한다(enable -> disable, disable -> enable).

    4) Miscellaneous Lsof Options
    기타 여러가지 잡다한 옵션들이다.

    -?,h : 도움말 출력
    -k : 커널 심볼 파일을 지정한다.
    -r : 인자로 주어진 초의 기간을 주기로 반복해서 실행한다. 기본 값 은 15초이다.
    -v : lsof에 대한 여러가지 정보(컴파일 상황 등등)들을 표시한다.


    * lsof 사용하기

    Tip 1) 어떤 특정한 파일을 사용하고 있는 프로세스들에 대한 정보를 알고 싶을 때,

    $ lsof <expected file name with path>

    을 실행하면 된다.

    $ lsof /etc/passwd

    를 실행하면, /etc/passwd를 억세스하고 있는 프로세스들을 점검할 수 있으며, 이 파일을 가지고 장난치는 프로세스들도 발견할 수 있다.

    Tip 2) 어떤 파일 시스템 내에, 그렇게 큰 크기의 파일들을 찾을 수 없는데도 불구하고, Available Space가 0을 향해서 치닫고 있을 수도 있다. 아마도, unlink된 파일에 대고 계속해서 써 대고 있을 가능성이 크다. lsof는

    $ lsof <expected directory - root of mounted partition>

    의 형식으로 해당 디렉토리 내, 혹은 partition 내에 있는 모든 파일들에 대해 억세스하고 있는 프로세스들을 열거해 줄 수 있다. 역시 장난 치는 프로세스를 발견할 수 있을 것이다.

    Tip 3) 긴급히 어떤 파일 시스템을 unmount해야 할 때, 여러분은 해당 파일 시스템에 있는 파일들을 사용하는 프로세스들 덕분에 unmount를 하지 못하고 마냥 기다리기만 했던 일을 겪어 봤을 것이다. lsof는 파일 시스템 내에 있는 파일들에 대해서 억세스하고 있는 프로세스들을 다 찾아줄 수 있다.

    $ lsof <expected file system name>

    이것을 이용해서 즉시 unmount를 하는 스크립트도 간단히 만들 수 있을 것이다.

    Tip 4) lsof는 모든 네트워크 Socket들을 찾아낼 수 있다.

    $ lsof -i

    를 실행하면, 현재 사용되고 있는 모든 Socket들을 볼 수 있을 것이다.

    Tip 5) Tip 4)를 잘 이용하면, 어떤 네트워크 Connection에 대해서 그 목적지 나 어디서 부터 맺어진 연결인지를 쉽게 알아낼 수 있다. 만약, 여러분의 서버 에서 돌아가고 있는 프로세스들 중에서, security.kaist.ac.kr로 연결을 하고 있는 프로세스를 잡아낼 수 있으며, 구체적으로 어떤 서비스(혹은 포트)에 연 결하고 있는가도 지정하여 알아낼 수 있다.

    $ lsof -i@security.kaist.ac.kr $ lsof -iTCP(|UDP)@security.kaist.ac.kr:smtp

    물론 여러개의 -i옵션을 이용해서 다양한 호스트로의 연결을 잡아낼 수 있다.

    Tip 6) Tip 5)를 응용해서 netstat과 물려서 이용하는 예도 있다.

    	$ netstat -t
    	Active Internet connections (w/o servers)
    	Proto Recv-Q Send-Q Local Address           Foreign Address         State 
    	tcp        0      0 security.kaist.ac:1019 fool.bbaga.co.kr:login ESTABLISHED
    
    자, 누군가가 fool.bbaga.co.kr의 login 서비스로 커넥트하고 있는 것이 발견 됐다. 이 프로세스를 Tip 5)를 이용해서 찾아보도록 하자.

    	$ lsof -iTCP@fool.bbaga.co.kr:login
    	COMMAND     PID     USER   FD   TYPE     DEVICE   SIZE/OFF  INODE NAME
    	rlogin    25023 godslord    3u  inet 0x10144168      0t184    TCP security.kaist.ac.kr:1019->fool.bbaga.co.kr:login
    	...
    
    Tip 7) lsof로, 어떤 특정한 프로그램의 프로세스들이 억세스하고 있는 모든 파일들을 볼 수 있다. -c 옵션으로 이것을 간단하게 해결할 수 있다.

    $ lsof -c httpd

    httpd 데몬을 통해서 억세스 되고 있는 모든 파일들을 열람할 수 있다.

    Tip 8) lsof를 이용하여, rcp나 ftp를 이용한 파일 전송 과정을 모니터링 할 수도 있다. 먼저 대상이 되는 프로세스를 ps 등을 이용해서 찾아낸다. 그런 다음,

    $ lsof -p <PID>

    를 하면 당연히 해당 프로세스가 열고 있는 파일들을 열람할 수 있게 된다. 조금 더 자세히하고 싶다면, ftp는 일반적으로 9,10이나 10,11번을 각각 Socket과 Local Data File에 할당하고, rcp는 3,4번을 할당한다. 이를 이용 하면,

    $ lsof -p <PID> -ad9,10 -r

    이런 식으로 되며, 어떤 뜻인지는 위의 옵션 설명을 보고 해석해 보기 바란다.

    Tip 9) lsof로는 어떤 유저가 열고 있는 모든 파일들을 열거해 볼 수도 있다.

    $ lsof -u<loginname> 혹은 $ lsof -u<UID>

    -u 옵션에는 인자를 ","로 구분하여 여러 인자를 한 꺼번에 넘길 수 있다.

    $ lsof -ugodslord,sakai,astroby

    즉, godslord, sakai, astroby의 유저들이 열고 있는 모든 파일들을 열거한다. -u 옵션을 사용하면서, 특정한 유저에 대한 정보는 보고 싶지 않을 때는, Login Name이나 UID의 앞에 "^"를 붙여 주면 된다.

    $ lsof -u ^root 혹은 $ lsof -u ^0

    이렇게 되면, root에 대해서는 체크를 하지 않는다.

    Tip 10) lsof를 이용해서, 로그인 추적도 가능하다. 다음의 예제는 Solaris 2.x 에서의 경우이다.

    	$ lsof -i@security.kaist.ac.kr
    	COMMAND    PID USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
    	in.rlogin 8112 root    0u  inet 0x60d7c7e8      0t2  TCP fool.bbaga.co.kr:login->security.kaist.ac.kr:1018 (ESTABLISHED)
    	in.rlogin 8112 root    1u  inet 0x60d7c7e8      0t2  TCP fool.bbaga.co.kr:login->security.kaist.ac.kr:1018 (ESTABLISHED)
    	in.rlogin 8112 root    2u  inet 0x60d7c7e8      0t2  TCP fool.bbaga.co.kr:login->security.kaist.ac.kr:1018 (ESTABLISHED)
    
    security.kaist.ac.kr에서부터 fool.bbaga.co.kr로 로긴한 프로세스가 있다. 이 프로세스의 ID는 8112번이다.

    	$ lsof -p 8112
    	COMMAND    PID USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
    	....
    	in.rlogin 8112 root    4u  VCHR       23,0      0t0 136785 /devices/pseudo/clone@0:ptmx->logindmux->ptm
    	in.rlogin 8112 root    5u  VCHR        4,0      0t0 136939 /devices/pseudo/clone@0:logindmux->logindmux
    	in.rlogin 8112 root    6u  VCHR        4,1      0t0 136939 /devices/pseudo/clone@0:logindmux->logindmux
    	...
    
    물론 다른 내용도 많겠지만 위의 내용, 특히 맨 첫 라인에 주목해 보자. 이 프로세스는 DEVICE 항목에서 보듯이, 23, 0의 Device를 사용하고 있으며, 이는 곧, /dev/pts/0을 의미한다.

    	$ lsof /dev/pts/0
    	COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
    	tcsh    8114  godslord   15u  VCHR   24,0  0t35381 136786 /dev/pts/../../devices/pseudo/pts@0:0
    	...
    
    즉, 이 유저는 /dev/ptr/0에서 tcsh 프로세스를 가지고 로긴한 사실을 알 수 있다.

    Platform마다 다르지만 비슷한 방법으로 로긴을 추적해 낼 수 있다.