When we run out of space in a Linux server, usually bad things happen (like full logs, inability to launch new processes, problems creating and opening files, and many more similar beauties), therefore it’s a good idea to have a quick reference to free up space quick in case of need.
This procedure is divided into 2 areas: the Quick Reference useful when you have an incident and need to free up space quick, and the Comprehensive Guide on how to free up space, so we can proceed to free up some more space once the server is not into a critical state.
Quick Reference
1.- First of all and before you do any emergency cleanup, take a SNAPSHOT, so we can revert to a previously working state in case we delete something valuable, or that we can retrieve later some of the content deleted to be able to do a postmortem analysis.
2.- Cleanup yum and man caches for a quick win (they can always be re-created later)
sudo yum clean all sudo rm -rf /var/cache/yum sudo rm -rf /var/tmp/yum-* sudo rm -rf /var/cache/man/ |
3.- Remove old kernels
package-cleanup --oldkernels --count=1 |
e.g.,
[root@localhost /]# package-cleanup --oldkernels --count=1 Loaded plugins: fastestmirror --> Running transaction check ---> Package kernel.x86_64 0:3.10.0-1127.el7 will be erased ---> Package kernel-devel.x86_64 0:3.10.0-1127.el7 will be erased --> Finished Dependency Resolution Dependencies Resolved ============================================================================================================================================================ Package Arch Version Repository Size ============================================================================================================================================================ Removing: kernel x86_64 3.10.0-1127.el7 @anaconda 64 M kernel-devel x86_64 3.10.0-1127.el7 @C7.8.2003-base 38 M Transaction Summary ============================================================================================================================================================ Remove 2 Packages Installed size: 102 M Is this ok [y/N]: y Downloading packages: Running transaction check Running transaction test Transaction test succeeded Running transaction Erasing : kernel-3.10.0-1127.el7.x86_64 1/2 Erasing : kernel-devel-3.10.0-1127.el7.x86_64 2/2 Verifying : kernel-devel-3.10.0-1127.el7.x86_64 1/2 Verifying : kernel-3.10.0-1127.el7.x86_64 2/2 Removed: kernel.x86_64 0:3.10.0-1127.el7 kernel-devel.x86_64 0:3.10.0-1127.el7 Complete! |
Note: in order to remove kernels and other packages, yum-utils need to be installed, if it’s not installed, you can install it as it is a really small package and well worth it:
yum install yum-utils |
4.- Remove orphan packages
First review orphan packages in our system:
package-cleanup --quiet --leaves --exclude-bin |
e.g.,
[root@localhost /]# package-cleanup --quiet --leaves --exclude-bin libdnet-1.12-13.1.el7.x86_64 libicu-50.2-4.el7_7.x86_64 libsysfs-2.1.0-16.el7.x86_64 samba-libs-4.10.16-18.el7_9.x86_64 |
And then you can safely delete them:
package-cleanup --quiet --leaves --exclude-bin | xargs yum remove -y |
The above commands can be launched more than one time, as the packages deleted with the first batch could create additional orphan packages again, so you can repeat these steps until no orphan packages appear anymore after the first package-cleanup command.
e.g.,
[root@localhost /]# package-cleanup --quiet --leaves --exclude-bin | xargs yum remove -y Loaded plugins: fastestmirror Resolving Dependencies --> Running transaction check ---> Package libdnet.x86_64 0:1.12-13.1.el7 will be erased ---> Package libicu.x86_64 0:50.2-4.el7_7 will be erased ---> Package libsysfs.x86_64 0:2.1.0-16.el7 will be erased ---> Package samba-libs.x86_64 0:4.10.16-18.el7_9 will be erased --> Finished Dependency Resolution Dependencies Resolved ============================================================================================================================================================= Package Arch Version Repository Size ============================================================================================================================================================= Removing: libdnet x86_64 1.12-13.1.el7 @anaconda 69 k libicu x86_64 50.2-4.el7_7 @koji-override-1 24 M libsysfs x86_64 2.1.0-16.el7 @anaconda 146 k samba-libs x86_64 4.10.16-18.el7_9 @updates 679 k Transaction Summary ============================================================================================================================================================= Remove 4 Packages Installed size: 25 M Downloading packages: Running transaction check Running transaction test Transaction test succeeded Running transaction Erasing : libicu-50.2-4.el7_7.x86_64 1/4 Erasing : libsysfs-2.1.0-16.el7.x86_64 2/4 Erasing : samba-libs-4.10.16-18.el7_9.x86_64 3/4 Erasing : libdnet-1.12-13.1.el7.x86_64 4/4 Verifying : libdnet-1.12-13.1.el7.x86_64 1/4 Verifying : samba-libs-4.10.16-18.el7_9.x86_64 2/4 Verifying : libsysfs-2.1.0-16.el7.x86_64 3/4 Verifying : libicu-50.2-4.el7_7.x86_64 4/4 Removed: libdnet.x86_64 0:1.12-13.1.el7 libicu.x86_64 0:50.2-4.el7_7 libsysfs.x86_64 0:2.1.0-16.el7 samba-libs.x86_64 0:4.10.16-18.el7_9 Complete! |
5.- Delete the updatedb (as we can run “updatedb” to recreate it later -it doesn’t come installed by default- ):
First locate the path of the db, and then delete:
locate --statistics Database /var/lib/mlocate/mlocate.db: 12,841 directories 88,414 files 5,456,472 bytes in file names 2,197,019 bytes used to store database sudo rm /var/lib/mlocate/mlocate.db -f |
6.- We can compress old logs that we need to keep, using bzip2 on max setting (note that some minimum space is needed in order to be able to compress a file, we cannot compress a file if it is kept in a FS that is 100% full):
|
Note: if we haven’t got space to compress a file on the FS where we are, then we can move them (to /tmp for example), compress them, and move back to their original place.
bzip2 is the compressor that compresses the most, but any others can be used, like compress.
To locate big log files quickly:
find . -xdev -name "*.log" -ls | sort -nk7 # <-- check all log files in the current FS, sort by size find . -xdev -name "*.log" -ls | sort -nrk7 # <-- same cmd as before, but sorted in reverse-order (bigger files first, some people prefer this output) find / -xdev -name nohup.out -ls | sort -nk7 # <-- check all nohup logs in root FS |
e.g.,
[root@localhost log]# find . -xdev -name "*.log" -ls | sort -nk7 67149905 0 -rw------- 1 root root 0 Apr 11 07:22 ./anaconda/anaconda.log 67149907 0 -rw------- 1 root root 0 Apr 11 07:22 ./anaconda/program.log 67149908 0 -rw------- 1 root root 0 Apr 11 07:22 ./anaconda/packaging.log 67149909 0 -rw------- 1 root root 0 Apr 11 07:22 ./anaconda/storage.log 67509355 0 -rw------- 1 root root 0 Apr 11 07:22 ./anaconda/ifcfg.log 67509356 0 -rw------- 1 root root 0 Apr 11 07:22 ./anaconda/ks-script-AO4ae1.log 67509357 0 -rw------- 1 root root 0 Apr 11 07:22 ./anaconda/ks-script-Iozn9c.log 67509358 0 -rw------- 1 root root 0 Apr 11 07:22 ./anaconda/ks-script-YLP_La.log 67509359 0 -rw------- 1 root root 0 Apr 11 07:22 ./anaconda/journal.log 33799324 4 -rw-r--r-- 1 root root 61 Apr 1 16:30 ./vboxadd-setup.log 34335571 4 -rw-r--r-- 1 root root 470 Mar 15 17:25 ./vboxadd-install.log 67151044 12 -rw-r--r-- 1 root root 10099 Apr 1 16:30 ./tuned/tuned.log 33554521 16 -rw------- 1 root root 12314 Apr 11 07:10 ./yum.log 465479 1180 -rw------- 1 root root 1207418 Apr 11 07:20 ./audit/audit.log |
7.- If we cannot free up enough space, we can expand the disk or add a new disk on the VM and expand the FS mounted over the disks. This option is fairly straightforward in a VM, but can be more cumbersome in a physical server.
This option is also the best option to gain free space without any other side-effects.
To do this procedure, refer to the appropriate official documentation for each case, for example here is the documentation from AWS and VMware:
VM in AWS: Extend a Linux file system after resizing a volume
VM in VMware: Extending a logical volume in a virtual machine running Red Hat or Cent OS
Comprehensive Guide
1.- Look at the FS space from root:
cd /; df -h |
And then find out the biggest directories, so we can find out where most space is being consumed:
du -hs * --exclude=proc | sort -hr |
e.g.,
[root@localhost /]# cd /; df -h Filesystem Size Used Avail Use% Mounted on devtmpfs 237M 0 237M 0% /dev tmpfs 244M 0 244M 0% /dev/shm tmpfs 244M 4.5M 240M 2% /run tmpfs 244M 0 244M 0% /sys/fs/cgroup /dev/sda1 40G 4.4G 36G 12% / tmpfs 49M 0 49M 0% /run/user/1000 [root@localhost log]# du -hs * --exclude=proc | sort -hr | head 1.2M audit 268K messages-20220329 216K anaconda 84K messages-20220405 60K messages-20220410 28K secure-20220329 28K dmesg.old 28K dmesg 20K messages 20K cron-20220410 |
2.- Once we have identified the biggest space hogs, now we can drill-down and investigate this directories to see if we can clear unneeded stuff.
To take into consideration:
some file extensions that can be deleted “somewhat” safely:
*.rpm ← linux software packages (they can be deleted and downloaded later via yum, or moved to /tmp)
*.dmp ← program or linux core dumps
*.trc ← traces & debug info from programs
*.iso ← program ISOs (usually they can be downloaded again, but check just in case)
To check unknown files we can use the command:
file file -to-check |
If the “file” command does not satisfy us (like when it reports a binary or executable file), we might be able to find out some more info about our file using strings:
strings file -to-check |
This command will show all ASCII strings kept on the file, where we can check for copyright msgs, product & version strings or other constants that we might use to find out more information about our file.
e.g.,
[root@localhost /]# file swapfile swapfile: Linux/i386 swap file (new style), version 1 (4K pages), size 524287 pages, no label, UUID=d72cb0f6-7d72-4f03-b0c2-c652bf245c9a [root@localhost /]# file bin bin: symbolic link to `usr/bin' [root@localhost /]# file /var/log/lastlog /var/log/lastlog: data [root@localhost /]# file /var/log/vboxadd-install.log /var/log/vboxadd-install.log: ASCII text [root@localhost bin]# file yes yes: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=62e4da10c23933e52f6c398b1546fa8e6f286206, stripped [root@localhost bin]# strings yes | less ... Try '%s --help' for more information. Usage: %s [STRING]... or: %s OPTION Repeatedly output a line with all specified STRING(s), or 'y'. --help display this help and exit --version output version information and exit http://www.gnu.org/software/coreutils/ Report %s translation bugs to <http://translationproject.org/team/> For complete documentation, run: info coreutils '%s invocation' %s online help: <%s> GNU coreutils /usr/share/locale David MacKenzie standard output 8.22 ... |
3.- Check quickly for any big files in root specifically:
|
4.- Check wrong devices in /dev (check for “rmto”,”rmt0.1″,”null 2>&1″, etc, specially look for BIG files, as they shouldn’t be any in /dev )
find /dev -xdev -size +1M - ls |
This files can get created by wrongly formed redirection operators to /dev/null, tape devices, etc. In our days is not very common to see this condition, but worth checking when we need to recover space.
5.- Check for core dumps, actually they are disabled by default in Linux, since they can be quite big depending on the amount of RAM present on the system and we might find a few, depending on the frequency of the issue that causes the dump on the first place:
coredumpctl |
If there are any, this command will show a list of them, so we can decide to take them off this server for support or delete them directly.
e.g.,
|
6.- Truncate logs in /var/log bigger than 150 Mb & older than a week or older than one month (this step destroys data and it’s just an example, adapt it to your needs):
find /var/log -name "*.log" \( \( -size +150M -mtime +7 \) -o -mtime +30 \) -exec ls {}\; #<-- first list the files that will be truncated find /var/log -name "*.log" \( \( -size +150M -mtime +7 \) -o -mtime +30 \) -exec truncate {} --size 5M \; #<-- then truncate them to a specific size, in this case 5Mb |
7.- Check for zero files, they do not really use space, but they do consume inodes & can also cause issues (and frankly, they do visually molest when there are many of them).
ls -l | awk '{ if ($5 == 0) print $0 }' # <-- first review the empty files, just in case... ls -l | awk '{ if ($5 == 0) print $9 }' | xargs rm # <-- ...then zap'em! |