tmpfs와 /tmp
— 이강우 2024/10/17 07:36
tmpfs
란 간단히 말해 메모리 기반 파일시스템이다. 메모리의 여유영역을 램드라이브
처럼 활용하는 기능이라고 보면 된다.
관련링크 : https://www.kernel.org/doc/html/v6.6/filesystems/tmpfs.html
당연하게도 메모리 영역이므로 데이터가 영구적으로 보관되지 않으며 실제로는 파일시스템으로 마운트 하여 사용하는동안에만 데이터가 유지되고 마운트를 해제하는 즉시 내용이 소실되는 형태로 동작한다.
그래서 /tmp
같은 임시 영역을 tmpfs
로 구성하여 사용하는 방식이 나왔다.
RHEL
/usr/lib/systemd/system/tmp.mount
파일의 내용을 보면 아래와 같다.
# SPDX-License-Identifier: LGPL-2.1-or-later # # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] Description=Temporary Directory /tmp Documentation=https://systemd.io/TEMPORARY_DIRECTORIES Documentation=man:file-hierarchy(7) Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems ConditionPathIsSymbolicLink=!/tmp DefaultDependencies=no Conflicts=umount.target Before=local-fs.target umount.target After=swap.target [Mount] What=tmpfs Where=/tmp Type=tmpfs Options=mode=1777,strictatime,nosuid,nodev,size=50%%,nr_inodes=1m # Make 'systemctl enable tmp.mount' work: [Install] WantedBy=local-fs.target
위와 같이 해당 systemd 설정에 /tmp
를 tmpfs
타입으로 마운트 하여 쓰게 설정되어있다.
사용하려면
$ systemctl enable tmp.mount
하게 되면 바로 /tmp
경로가 tmpfs
타입으로 변경된다.
하지만 이것은 권장되는 방식이 아니며 시스템에 이미 자동으로 사용할 수 있도록 구성되어있다.
/usr/lib/systemd/system/basic.target
내용을 보게되면 아래와 같다.
# SPDX-License-Identifier: LGPL-2.1-or-later # # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] Description=Basic System Documentation=man:systemd.special(7) Requires=sysinit.target Wants=sockets.target timers.target paths.target slices.target After=sysinit.target sockets.target paths.target slices.target tmp.mount # We support /var, /tmp, /var/tmp, being on NFS, but we don't pull in # remote-fs.target by default, hence pull them in explicitly here. Note that we # require /var and /var/tmp, but only add a Wants= type dependency on /tmp, as # we support that unit being masked, and this should not be considered an error. RequiresMountsFor=/var /var/tmp # RHEL-only: Disable /tmp on tmpfs. #Wants=tmp.mount
맨 아래쪽을 보면
# RHEL-only: Disable /tmp on tmpfs. #Wants=tmp.mount
와 같이 설정되어있다. RHEL
은 기본적으로 /tmp
를 tmpfs
타입을 사용하지 않도록 되어있다.
Wants=tmp.mount
부분의 주석만 해제하면 자동으로 /tmp
를 tmpfs
타입으로 사용할 수 있다.
이런경우 관리자가 수동으로 umount /tmp
를 하거나 systemctl stop tmp.mount
를 한다 하여도 일정 시간 뒤에 systemd가 자동으로 감지하여 다시 tmp.mount
를 수행하게 되므로 주의하기 바란다.
또한 /tmp
경로의 용량이 부족하거나 크게 필요한 경우에는 메모리가 허용하는 한 실시간으로 확장해서 사용이 가능하다.
[root@localhost ~]# df -hP Filesystem Size Used Avail Use% Mounted on devtmpfs 4.0M 0 4.0M 0% /dev tmpfs 636M 0 636M 0% /dev/shm tmpfs 255M 3.8M 251M 2% /run /dev/mapper/rl-root 17G 1.3G 16G 8% / /dev/vda1 960M 225M 736M 24% /boot tmpfs 128M 0 128M 0% /run/user/0 tmpfs 636M 0 636M 0% /tmp [root@localhost ~]# mount -o remount,size=10G /tmp [root@localhost ~]# df -hP Filesystem Size Used Avail Use% Mounted on devtmpfs 4.0M 0 4.0M 0% /dev tmpfs 636M 0 636M 0% /dev/shm tmpfs 255M 3.8M 251M 2% /run /dev/mapper/rl-root 17G 1.3G 16G 8% / /dev/vda1 960M 225M 736M 24% /boot tmpfs 128M 0 128M 0% /run/user/0 tmpfs 10G 0 10G 0% /tmp [root@localhost ~]# free -m total used free shared buff/cache available Mem: 1271 306 865 7 249 964 Swap: 2047 0 2047
위의 예제에서는 /tmp
용량을 10G로 늘렸는데, 이 시스템의 메모리는 1271M밖에 되지 않는다.
용량을 늘리는 것 자체는 성공했지만 실수로라도 /tmp
영역의 데이터가 물리 메모리 용량을 넘게 쌓이면 시스템이 멈춘다. 매우 위험하다!!
[root@localhost ~]# cd /tmp/ [root@localhost tmp]# ll total 0 [root@localhost tmp]# dd if=/dev/zero of=data bs=1M count=10 10+0 records in 10+0 records out 10485760 bytes (10 MB, 10 MiB) copied, 0.00415868 s, 2.5 GB/s [root@localhost tmp]# dd if=/dev/zero of=data bs=1M count=100 100+0 records in 100+0 records out 104857600 bytes (105 MB, 100 MiB) copied, 0.0360715 s, 2.9 GB/s [root@localhost tmp]# ll -h total 100M -rw-r--r--. 1 root root 100M Oct 17 17:05 data [root@localhost tmp]# dd if=/dev/zero of=data bs=1M count=1000 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB, 1000 MiB) copied, 0.375854 s, 2.8 GB/s [root@localhost tmp]# ll -h total 1000M -rw-r--r--. 1 root root 1000M Oct 17 17:05 data [root@localhost tmp]# free -m total used free shared buff/cache available Mem: 1271 1192 75 916 1064 79 Swap: 2047 91 1956 [root@localhost tmp]# dd if=/dev/zero of=data bs=1M count=3000 3000+0 records in 3000+0 records out 3145728000 bytes (3.1 GB, 2.9 GiB) copied, 2.35655 s, 1.3 GB/s [root@localhost tmp]# ll -h total 3.0G -rw-r--r--. 1 root root 3.0G Oct 17 17:05 data [root@localhost tmp]# free -m total used free shared buff/cache available Mem: 1271 1228 64 969 1068 42 Swap: 2047 2047 0
실제 물리 메모리 용량 이상으로 3000M
파일을 생성해도 멀쩡한 이유는 스왑영역
까지 끌어다 쓰기 때문이다.
위에 보는 바와 같이 free
메모리는 64메가밖에 남지 않았고 스왑영역은 모두 사용하는것을 볼 수 있다.
여기서 용량을 더 사용하면 어떻게 될까?
[root@localhost tmp]# dd if=/dev/zero of=data bs=1M count=4000 Connection closing...Socket close. Connection closed by foreign host. Disconnected from remote host(192.168.0.203:22) at 17:05:39. Type `help' to learn how to use Xshell prompt. [C:\~]$
이와 같이 해당 시스템은 먹통이 되며 강제 리부팅하지 않는 이상 복구 되지 않는다.
Amazon AWS EC2
EC2 인스턴스의 경우는 이 /tmp
가 기본적으로 tmpfs
타입으로 구성되어있다.
[root@ip-172-31-17-98 system]# df -hP Filesystem Size Used Avail Use% Mounted on devtmpfs 4.0M 0 4.0M 0% /dev tmpfs 475M 0 475M 0% /dev/shm tmpfs 190M 448K 190M 1% /run /dev/xvda1 8.0G 1.6G 6.4G 20% / /dev/xvda128 10M 1.3M 8.7M 13% /boot/efi tmpfs 95M 0 95M 0% /run/user/1000 tmpfs 475M 0 475M 0% /tmp
이것을 비활성화 하고 싶다면 /usr/lib/systemd/system/basic.target
에서 Wants=tmp.mount
를 주석처리 하면 된다.
[root@ip-172-31-17-98 system]# cat basic.target # SPDX-License-Identifier: LGPL-2.1-or-later # # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] Description=Basic System Documentation=man:systemd.special(7) Requires=sysinit.target Wants=sockets.target timers.target paths.target slices.target After=sysinit.target sockets.target paths.target slices.target tmp.mount # We support /var, /tmp, /var/tmp, being on NFS, but we don't pull in # remote-fs.target by default, hence pull them in explicitly here. Note that we # require /var and /var/tmp, but only add a Wants= type dependency on /tmp, as # we support that unit being masked, and this should not be considered an error. RequiresMountsFor=/var /var/tmp #Wants=tmp.mount # <<< 주석처리
그리고 tmp.mount
를 종료하면 된다.
[root@ip-172-31-17-98 ~]# systemctl disable --now tmp.mount
혹시라도 /tmp
영역을 사용중이 프로그램이 있는경우 실패 할 수 있다.
이런경우 해당 서비스나 프로그램을 먼저 종료한 후 수행하거나
아니면 systemctl disable tmp.mount
명령어만 실행하고 리부팅 진행하도록 한다.