출처 : http://www.morenice.kr/72

linux 시스템에서 프로세스를 통하여 파일을 열 수 있다. 

여기서 파일이란 데이터를 담을 수 있는 파일 뿐만 아니라, 통신을 위한 socket, event_poll 등 file descriptor, 라이브러리 파일, char device까지 포함한다. 개발된 프로그램이 소켓을 사용하여 통신하는 경우 실제로 소켓이 열려 있는지 디버깅을 위한 용도, 그리고 프로세스가 열 수 있는 파일의 갯수가 한정되어지기 때문에 시스템 모니터링을 위해서 열려진 파일이 얼마만큼인지 확인하는 용도등으로 파일을 확인하는 방법은 필요하다.


결론부터 말하자면, lsof(list open file)라는 명령어를 통하여 모든 프로세스에 대하여 열고 있는 파일에 대하여 확인할 수 있다.

root@ubuntu:~# lsof
COMMAND    PID     USER   FD      TYPE     DEVICE SIZE/OFF       NODE NAME
init         1     root  cwd       DIR      252,0     4096          2 /
init         1     root  rtd       DIR      252,0     4096          2 /
init         1     root  txt       REG      252,0   124704    2490376 /sbin/init
init         1     root  mem       REG      252,0    79672    1441818 /lib/i386-linux-gnu/libnsl-2.13.so
init         1     root  mem       REG      252,0    30684    1441811 /lib/i386-linux-gnu/librt-2.13.so
init         1     root  mem       REG      252,0  1434180    1441809 /lib/i386-linux-gnu/libc-2.13.so
init         1     root  mem       REG      252,0    38500    1441821 /lib/i386-linux-gnu/libnss_nis-2.13.so
init         1     root  mem       REG      252,0   117960    1441832 /lib/i386-linux-gnu/ld-2.13.so
init         1     root  mem       REG      252,0    42580    1441834 /lib/i386-linux-gnu/libnss_files-2.13.so
init         1     root  mem       REG      252,0    29984    1441858 /lib/libnih-dbus.so.1.0.0
init         1     root  mem       REG      252,0    26400    1441822 /lib/i386-linux-gnu/libnss_compat-2.13.so
init         1     root  mem       REG      252,0    75040    1441860 /lib/libnih.so.1.0.0
init         1     root  mem       REG      252,0   121644    1441827 /lib/i386-linux-gnu/libpthread-2.13.so
init         1     root  mem       REG      252,0   243400    1441799 /lib/i386-linux-gnu/libdbus-1.so.3.5.4
init         1     root    0u      CHR        1,3      0t0       5396 /dev/null
init         1     root    1u      CHR        1,3      0t0       5396 /dev/null
init         1     root    2u      CHR        1,3      0t0       5396 /dev/null
init         1     root    3r     FIFO        0,8      0t0        928 pipe
init         1     root    4w     FIFO        0,8      0t0        928 pipe
...
...



COMMAND와 PID 필드가 있기 때문에 본인이 필요한 내용을 grep을 통해서 보는 방향이 편리하다.

root@ubuntu:~# lsof | grep sshd
sshd      2169     root  cwd       DIR      252,0     4096          2 /
sshd      2169     root  rtd       DIR      252,0     4096          2 /
sshd      2169     root  txt       REG      252,0   470240    1713853 /usr/sbin/sshd
sshd      2169     root  mem       REG      252,0   117960    1441832 /lib/i386-linux-gnu/ld-2.13.so
sshd      2169     root  mem       REG      252,0    79476    1442028 /lib/i386-linux-gnu/libz.so.1.2.3.4
sshd      2169     root  mem       REG      252,0    79672    1441818 /lib/i386-linux-gnu/libnsl-2.13.so
sshd      2169     root  mem       REG      252,0   140788    1705602 /usr/lib/i386-linux-gnu/libk5crypto.so.3.1
sshd      2169     root  mem       REG      252,0    26112    1705609 /usr/lib/i386-linux-gnu/libkrb5support.so.0.1
sshd      2169     root  mem       REG      252,0    46644    1446070 /lib/i386-
...
...



추가적으로 /proc을 조금만 뒤져보면 프로세스가 열고 있는 fd 정보를 확인할 수 있다. 프로그램이 실행되어 프로세스화 되면 /proc/PID로 디렉토리가 생성되고 그 안에 여러가지 정보를 담고 있고, 그 안에 fd라는 디렉토리를 열면 사용중인 fd(file descriptor)를 확인 가능하다. 

아래는 실행중인 아파치 프로세스의 PID(2285)를 기반으로 fd 디렉토리에서 ls한 결과이다. 0~2번까지는 시스템에서 자동으로 잡히는 fd영역이고, 3번부터 사용자(코드에서 열고 있는)에 의한 열린 fd 리스트들이다. socket과 pipe 그리고 로그를 적기 위한 데이터파일과 eventpoll을 열고 있다.

 

root@ubuntu:/proc/2285/fd# ls -al
합계 0
dr-x------ 2 root     root      0 2012-01-04 23:42 .
dr-xr-xr-x 7 www-data www-data  0 2012-01-04 23:41 ..
lr-x------ 1 root     root     64 2012-01-04 23:42 0 -> /dev/null
l-wx------ 1 root     root     64 2012-01-04 23:42 1 -> /dev/null
l-wx------ 1 root     root     64 2012-01-04 23:42 2 -> /var/log/apache2/error.log
lrwx------ 1 root     root     64 2012-01-04 23:42 3 -> socket:[13645]
lr-x------ 1 root     root     64 2012-01-04 23:42 4 -> pipe:[11969]
l-wx------ 1 root     root     64 2012-01-04 23:42 5 -> pipe:[11969]
l-wx------ 1 root     root     64 2012-01-04 23:42 6 -> /var/log/apache2/other_vhosts_access.log
l-wx------ 1 root     root     64 2012-01-04 23:42 7 -> /var/log/apache2/access.log
lrwx------ 1 root     root     64 2012-01-04 23:42 8 -> anon_inode:[eventpoll]







여기서 잠깐!!! 

lsof는 내부적으로 어떤 동작을 하는지 궁금해서 strace 해보았다. 실제로 lsof에서도 /proc/ 디렉토리 아래의 PID(process id)의 디렉토리 각각 들어가 필요한 정보를 읽어들인다.

  • stat File
  • cwd File
  • root File
  • exe File
  • maps File
  • fd Directory
  • fd_info Directory



strace 결과 내용중에서 apache(pid:2285)에 대해서 처리하는 내용을 일부 첨부한다.

4904 stat64("/proc/2285/", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
4905 open("/proc/2285/stat", O_RDONLY|O_LARGEFILE) = 4
4906 read(4, "2285 (apache2) S 2274 2274 2274 "..., 4096) = 199
4907 close(4)                                = 0
4908 readlink("/proc/2285/cwd", "/"..., 4096) = 1
4909 stat64("/proc/2285/cwd", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
4910 readlink("/proc/2285/root", "/", 4096)  = 1
4911 stat64("/proc/2285/root", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
4912 readlink("/proc/2285/exe", "/usr/lib/apache2/mpm-prefork/apache2"..., 4096) = 36
4913 stat64("/proc/2285/exe", {st_mode=S_IFREG|0755, st_size=1296895, ...}) = 0
4914 open("/proc/2285/maps", O_RDONLY|O_LARGEFILE) = 4
4915 read(4, "00110000-0012d000 r-xp 00000000 "..., 4096) = 4057
4916 stat64("/usr/lib/libaprutil-1.so.0.3.9", {st_mode=S_IFREG|0644, st_size=120884, ...}) = 0
4917 stat64("/lib/i386-linux-gnu/libdl-2.13.so", {st_mode=S_IFREG|0644, st_size=9736, ...}) = 0
4918 stat64("/usr/lib/apache2/modules/mod_authz_user.so", {
...
...
4969 open("/proc/2285/fd", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 4
4970 getdents64(4, /* 11 entries */, 32768)  = 264
4971 readlink("/proc/2285/fd/0", "/dev/null"..., 4096) = 9
4972 lstat64("/proc/2285/fd/0", {st_mode=S_IFLNK|0500, st_size=64, ...}) = 0
4973 stat64("/proc/2285/fd/0", {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
4974 open("/proc/2285/fdinfo/0", O_RDONLY|O_LARGEFILE) = 7
4975 fstat64(7, {st_mode=S_IFREG|0400, st_size=0, ...}) = 0
4976 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb78c1000
4977 read(7, "pos:\t0\nflags:\t00\n", 1024)  = 17
4978 close(7)                                = 0
4979 munmap(0xb78c1000, 4096)                = 0
4980 readlink("/proc/2285/fd/1", "/dev/null", 4096) = 9
4981 lstat64("/proc/2285/fd/1", {st_mode=S_IFLNK|0300, st_size=64, ...}) = 0
4982 stat64("/proc/2285/fd/1", {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
4983 open("/proc/2285/fdinfo/1", O_RDONLY|O_LARGEFILE) = 7
4984 fstat64(7, {st_mode=S_IFREG|0400, st_size=0, ...}) = 0
...


'Programming > Server' 카테고리의 다른 글

[FCM] 서버측 UnknownHostException  (0) 2018.10.01
[CentOS 7] systemd 기본 설정  (0) 2018.09.30
크롤링 robots.txt 주의점  (0) 2018.09.19
리눅스 터미널 명령어 종류  (0) 2018.09.17
[Linux] 포트 확인  (0) 2018.09.17

+ Recent posts