이 글은 lsof 의 사용방법에 대해 설명합니다. lsof 는 프로세스의 파일핸들을 조사해 볼 수 있는 유용한 툴입니다.
lsof ("LiSt Open Files") 는 서버에 열린 파일 핸들의 리스트를 보여주는 툴입니다. 여러가지 옵션들과 스위치들을 통해서 이러한 핸들들을 필터링할 수 있게 해줌으로써 솔라리스 관리자가 문제에 대한 분석을 가능하도록 도와 줍니다.
이 가이드는 lsof 의 몇가지 커맨드라인 옵션에 대해 설명합니다. 그리고 실전에서 어떻게 lsof 를 사용할 수 있는지에 대한 몇가지 예제를 보여 드립니다. (참고: 이 글의 모든 예제는 솔라리스 8 버전 이상에서 모두 적용 가능합니다; 이전 버전에서도 사용이 가능할 것으로 생각되지만 직접 확인해 보진 않았습니다.)
"lsof" 얻기
lsof 는 기본 솔라리스 설치의 표준으로 따라서 설치되지 않습니다. 그러나 SPARC 및 x86 버전의 솔라리스 패키지로 컴파일 가능하고 http://sunfreeware.com 에서 다운로드 받으실 수 있습니다.
열린 네트워크 포트 확인하기
구문:
lsof -i [<protocol>][@<interface name>][:<port>]
위의 3가지 파라미터를 일부분만 혹은 전부 지정하실 수 있습니다. 생략된 부분은 와일드카드로 간주 합니다. <port> 는 단일 포트 혹은 범위로 지정될 수 있습니다. lsof 를 이러한 방식으로 사용하는 것은 netstat -a 와 비슷한 결과를 돌려주지만 거기에 덧붙여서 프로세스와 소유자의 정보 또한 제공 합니다.
주어진 프로세스가 연 파일 핸들들의 리스트
구문:
lsof -p <process id>[,<process id>[,<process id>[...]]]
lsof 에 하나 혹은 복수개의 프로세스 ID 를 (콤마로 구분됨) 입력함으로써 모든 연관된 파일 핸들들의 리스트를 출력할 수 있습니다. 이것은 특정 실행 프로세스가 어떠한 라이브러리를 사용하는지 확인할때 아주 유용합니다. 이 커맨드를 통해서 프로세스가 어떻게 로그 파일, 설정 파일들과 상호동작하는지 확인하실 수 있습니다.
특정 유저가 연 파일 핸들들의 리스트
구문:
lsof -u <username>[,<username>[,<username>[...]]]
이 커맨드는 주어진 유저에게 속한 모든 열린 핸들들을 보여 줍니다.
주어진 파일 시스템에서 열린 모든 파일 핸들들 보기
구문:
lsof <file system or device>
이 옵션은 umount 커맨드가 수행되는 것을 막는 프로세스들을 찾을때 유용합니다. 혹은 적절한 디렉토리 항목에 없는 열린 파일을 추적할때에 유용합니다.
다른 유용한 플래그들
- -b – 커널을 블록할 수 있는 시스템 호출의 사용 회피하기
- -w – 주의 메세지 생략하기
- -P – 포트 번호를 /etc/services 에 있는 서비스 이름들과 매핑하지 말기
- -a – 이 플래그를 다른 두 플래그 사이에 삽입함으로써 두가지 플래그 모두에 매치되는 결과만 보기. 기본적으로 lsof 는 지정된 플래그들 중에 하나라도 만족하는 모든 핸들들을 보여줌.
예제
inetd 가 리스닝하고 있는 모든 포트들 보기:
현재 inetd 가 어떠한 포트들을 열고 있는지 확인해 봅시다.
gouda# ps -ef | grep inetd root 2849 1 0 May 25 ? 6:43 /usr/sbin/inetd -s gouda# lsof -i -a -p 2849 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME inetd 2849 root 11u IPv6 0x30006ec96d0 0t0 TCP *:ftp(LISTEN) inetd 2849 root 13u IPv4 0x30006ec9550 0t0 UDP *:name(Idle) inetd 2849 root 16u IPv4 0x30008f26ad8 0t0 TCP *:52783(LISTEN) inetd 2849 root 17u IPv4 0x30006ec9b50 0t0 UDP *:57504(Idle) inetd 2849 root 23u IPv6 0x30008f264d8 0t0 UDP *:servicetag(Idle) inetd 2849 root 24u IPv4 0x30008f26358 0t0 TCP *:servicetag(LISTEN)
일단 inetd 의 프로세스 ID 를 확인하고, 그 다음 lsof 가 모든 IP 핸들들과 (-i) 또한 (-a) 와 같이 포트에 의해 열린 것들을 (-p <process id>) 확인합니다.
특정 유저의 현재 열린 모든 네트워크 접속의 리스트:
가능한 보안 구멍을 추적하거나 어플리케이션이 올바른 데이타베이스에 접속하고 있는지 확인하기 위해서, lsof 는 주어진 유저의 현재 네트워크 접속들을 보여 줍니다.
gouda# lsof -i -a -u fred COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME sshd 9696 fred 5u IPv4 0x3001 0t527 TCP gouda:22->edam:46528(ESTABLISHED) sshd 9696 fred 10u IPv4 0x300e 0t0 TCP localhost:6011(LISTEN) sshd 14710 fred 5u IPv4 0x3008 0t404 TCP gouda:22->edam:46590(ESTABLISHED) sshd 14710 fred 10u IPv4 0x307d 0t0 TCP localhost:6012(LISTEN) sshd 17013 fred 5u IPv4 0x300f 0t146 TCP gouda:22->edam:50019(ESTABLISHED) sshd 17013 fred 10u IPv4 0x30e0 0t0 TCP localhost:6010(LISTEN) ssh 25259 fred 4u IPv4 0x3000 0t157 TCP gouda:54435->colby:22(ESTABLISHED) sshd 25383 fred 5u IPv4 0x3000 0t126 TCP gouda:22->brie:34480(ESTABLISHED) ssh 25438 fred 4u IPv4 0x3000 0t91 TCP gouda:54448->smokey:22(ESTABLISHED)
이 것은 fred 란 유저가 3개의 수신(incoming) ssh 접속을 가지고 있고 두개의 송신 ssh 접속을 가지고 있음을 알려 줍니다. lsof 를 다른 서버중에 하나에서 실행하고, 본래 포트를 찾아 봄으로써 (예를 들어 edam 의 포트 46528) 거기서 계속적으로 추적을 수행할 수 있습니다.
어떤 프로세스가 특정 파일 시스템의 언마운트를 막는지 찾아보기:
특정 프로세스가 umount 커맨드의 수행을 방해할 수 있습니다. -f 플래그를 통해서 잠재적으로 오류를 유발하는 대신에 lsof 는 어떠한 프로세스들이 먼저 정지 되어야 하는지를 보여 줍니다.
gouda# lsof /mnt/scratchdisk COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME bash 7268 fred cwd VDIR 85,204 512 2 /mnt/scratchdisk/edam dcm 15375 george txt VREG 85,204 292352 202 /mnt/scratchdisk/bin/dcm dcm 15375 george cwd VDIR 85,204 512 5 /mnt/scratchdisk/bin/dcm
결과는 fred 가 배시 쉘을 가지고 있고 우리의 마운트 포인트 위에서 작업하고 있음을 보여 줍니다. 그리고 george 가 동일한 파일 시스템상의 다른 디렉토리에서 dcm 의 복사를 시작하였습니다.
특정 포트에 어떠한 프로세스가 리스닝하고 있고 누가 이 포트를 사용하고 있는지 보기:
포트가 이미 사용되고 있습니다(port already in use) 오류 때문에 데몬이 시작되지 않을때 관리자는 종종 좌절하게 됩니다. lsof 는 어떤 프로세스가 우리가 사용하고자 하는 포트를 사용하고 있는지 추적하기 위해 사용될 수 있습니다.
gouda# lsof -i :7507 COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME inetd 668 root 34u IPv4 0x303f0 0t0 TCP *: 7507 (LISTEN) answer 19757 nobody 0u IPv4 0x58028 0t132 TCP gouda:7507->edam:46111 (ESTABLISHED) answer 19757 nobody 1u IPv4 0x58028 0t132 TCP gouda:7507->edam:46111 (ESTABLISHED) answer 19757 nobody 2u IPv4 0x58028 0t132 TCP gouda:7507->edam:46111 (ESTABLISHED)
위의 결과로 볼때 inetd 가 answer 라는 서비스를 그 포트에서 실행하고 있고 edam 에서 실행되는 어떤 것이 접근하고 있음을 알 수 있습니다.edam 에서 lsof -i :46111 를 수행하여 어떠한 프로세스 인지를 확인해 봅니다.
해당되는 디렉토리 항목이 없는 열린 파일을 참조하는 프로세스 찾아내기:
만약 어떤 유저가 실행중인 프로세스가 참조하는 파일을 지웠다면, 파일 시스템은 실제로 마지막 링크가 닫힐때 까지 이 파일을 삭제하지 않습니다. 이러한 경우 실행중인 프로세스만이 남게 됩니다. 만약 이 프로세스를 찾을 수 있다면 우리는 해당 프로세스를 닫거나(파일이 삭제되길 원할때) 혹은 파일을 다시 살려야 할때 /proc 파일 시스템(솔라리스 8 이상) 을 통해서 파일의 내용을 저장할 수 있습니다.
gouda # df -k /opt/myapp/data Filesystem kbytes used avail capacity Mounted on /dev/md/dsk/d100 4129290 1458133 2629865 36% /opt/myapp gouda # lsof /opt/myapp | grep '/dev/md/dsk/d100' less 15043 fred 4r VREG 102,0 144 2050050 /opt/myapp (/dev/md/dsk/d100)
위의 결과는 파일이 less (프로세스 ID 15043) 에 의해 열려져 있음을 알려 줍니다. 만약 파일을 삭제하는 것이 목표라면 less 프로세스를 종료 시킴으로써 원하는 작업을 수행할 수 있습니다. 만약 파일의 내용을 다시 살리는게 목표라면, 복사를 통해서 가능합니다. 4번째 컬럼은 파일 디스크립터 4번에 읽기 전용 핸들을 보여 줍니다. 이것은 /proc/15043/fd/4 를 읽음으로써 파일의 내용을 다시 살릴 수 있음을 의미 합니다.
이 글의 영문 원본은
wikis.sun.com Using "lsof" in the Real World
에서 보실 수 있습니다.


당신의 의견을 작성해 주세요.