Linux systems 28 entries 22 run in the sandbox

Linux disk and storage cheat sheet

Free space, inodes, mounts, block devices and archives. Each entry has a worked example and the flags worth knowing, and where one is easy to get wrong, the gotcha.

Free space

df -h

Show size, used and available space for every mounted filesystem.

Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p1   30G   29G  1.0G  97% /
tmpfs           3.9G     0  3.9G   0% /dev/shm
-h
Human-readable sizes.
-T
Show the filesystem type.
-x tmpfs
Exclude a filesystem type from the list.
PATH
Only the filesystem that contains PATH, as in df -h /var/lib/docker.

Gotcha ext4 reserves about 5% for root, so a disk can show Avail 0 while Use% reads 95%.

df -i

Show inode usage. A filesystem can run out of inodes while plenty of bytes are free.

df -i /var
Filesystem      Inodes  IUsed IFree IUse% Mounted on
/dev/nvme0n1p1  1966080 1966080     0  100% /
-i
Inodes instead of blocks.

Gotcha 'No space left on device' with free space in df -h means inodes: millions of tiny files, often sessions, cache or mail spools.

du -xh --max-depth=1 <dir> | sort -h

Rank the subdirectories of a path by size to find where the space went.

sudo du -xh --max-depth=1 /var | sort -h
56K	/var/tmp
1.2G	/var/cache
22G	/var/log
24G	/var
-x
Stay on one filesystem.
-h
Human-readable sizes; pair with sort -h.
-s
One total per argument.
--max-depth=N
Report N levels deep (-d N on BSD).

lsof +L1

When df says the disk is full but du cannot find the files, a process is holding deleted files open.

sudo lsof +L1 | sort -k7 -n | tail
COMMAND  PID  USER  FD  TYPE DEVICE     SIZE/OFF NLINK NODE NAME
server  1432 webapp  4w  REG  259,1 21474836480     0 5212 /var/log/webapp/debug.log (deleted)
+L1
Files whose link count is below 1: deleted but still open.
SIZE/OFF
Space that is freed only when the file is closed.

Gotcha Free the space without a restart by truncating through procfs: : > /proc/1432/fd/4.

ncdu -x <dir>

Interactive disk usage browser. Faster to explore than repeated du runs.

sudo ncdu -x /
-x
Do not cross filesystem boundaries.
d (key)
Delete the selected item after confirmation.

Devices & mounts

lsblk -f

Show block devices, partitions, filesystems, labels, UUIDs and where they are mounted.

NAME        FSTYPE LABEL UUID                                 MOUNTPOINTS
nvme0n1
└─nvme0n1p1 ext4   root  3f1c6a0e-8f6e-4a0f-9a2f-2f7c1d9e0b11 /
nvme1n1     xfs    data  9b2d4c31-1f0e-4d6a-8b7a-6e1f0a2c3d44 /data
-f
Include filesystem type, label and UUID.
-o COLS
Choose columns, for example -o NAME,SIZE,MOUNTPOINT.

findmnt

Show mounts as a tree, or answer which filesystem a path lives on and with which options.

findmnt -T /var/lib/docker
-T PATH
The mount that contains PATH.
-o TARGET,SOURCE,OPTIONS
Choose columns.
--verify
Check /etc/fstab for errors before you reboot.

mount

List mounts, or mount a device on a directory.

mount | grep " / "
-t TYPE
Filesystem type such as ext4, xfs or nfs.
-o OPTS
Mount options such as ro, noatime or nofail.
-a
Mount everything in /etc/fstab: the safe way to test an fstab edit.

mount -o remount,rw <mountpoint>

Switch a filesystem that the kernel dropped to read-only back to read-write after checking why it happened.

sudo mount -o remount,rw /
remount
Change options without unmounting.
ro / rw
Read-only or read-write.

Gotcha The kernel remounts read-only after I/O errors. Read dmesg first; forcing rw on a failing disk can make corruption worse.

umount <mountpoint>

Detach a filesystem. It must not be in use by any process.

sudo umount /mnt/backup
-l
Lazy: detach now, clean up when no longer busy.
fuser -vm DIR
Show which processes keep it busy.

Gotcha 'target is busy' often means your own shell is sitting inside the mount point. cd out first.

/etc/fstab entry

Mount a data volume at boot by UUID, without hanging the boot if the volume is missing.

UUID=9b2d4c31-1f0e-4d6a-8b7a-6e1f0a2c3d44  /data  xfs  defaults,noatime,nofail  0  2
UUID=
Stable identifier; device names like /dev/sdb can change between boots.
nofail
Keep booting if the device is absent.
noatime
Skip access-time writes.
0 2
dump flag, then fsck order (1 for root, 2 for others).

Gotcha Test with sudo mount -a and findmnt --verify before rebooting. A bad fstab line can drop a cloud VM into emergency mode.

growpart <disk> <n> && resize2fs <part>

After enlarging a cloud volume, grow the partition and then the filesystem online.

sudo growpart /dev/nvme0n1 1 && sudo resize2fs /dev/nvme0n1p1
growpart DISK N
Extend partition N to fill the disk.
resize2fs
Grow ext2/3/4 to the partition size.
xfs_growfs MOUNT
Grow XFS; takes the mount point, not the device.

lvextend -r -L +<size> <lv>

Grow an LVM logical volume and its filesystem in one step.

sudo lvextend -r -L +10G /dev/vg0/data
-L +10G
Add 10 GiB; -l +100%FREE uses all free extents.
-r
Resize the filesystem too.
vgs / lvs
Show volume groups and logical volumes.

pvcreate <dev> && vgcreate <vg> <dev> && lvcreate -n <lv> -L <size> <vg>

Build LVM from a blank disk: a physical volume, a volume group on it, then a logical volume you can format and mount.

sudo pvcreate /dev/sdd
pvcreate DEV
Mark a disk or partition as LVM space.
vgcreate VG DEV...
Pool physical volumes; vgextend adds more later.
lvcreate -n NAME -L 5G VG
Carve a volume; -l 100%FREE takes all that is left.
/dev/VG/LV
The new device for mkfs, mount and fstab (also /dev/mapper/VG-LV).

Gotcha pvcreate on a disk that holds a filesystem offers to wipe it. Check lsblk -f first.

mkfs.<type> [-L label] <dev>

Put a new, empty filesystem on a partition, disk or logical volume. Everything on it before is gone.

sudo mkfs.ext4 -L scratch /dev/sdd
mkfs.ext4 / mkfs.xfs
The two usual Linux filesystems; XFS can grow but never shrink.
-L LABEL
A name to mount by: LABEL=scratch in fstab.
-F (ext) / -f (xfs)
Overwrite an existing filesystem without asking.
blkid DEV
Read back the type, label and UUID afterwards.

Gotcha The tools refuse a mounted device, but not an unmounted one that still holds data you need. Read the device name twice.

parted -s <disk> mklabel gpt mkpart <name> <fs> <start> <end>

Create a partition table and partitions from the command line, as scripts and cloud-init do.

sudo parted -s /dev/sdd mklabel gpt mkpart data ext4 1MiB 100% print
mklabel gpt
A new, empty GPT partition table (msdos for old MBR).
mkpart NAME FS START END
START and END like 1MiB, 10GiB or 100%.
set N lvm on
Flag a partition for LVM.
print / -l
Show one disk, or every disk.

Gotcha The FS type in mkpart only labels the partition; run mkfs on the new partition afterwards.

fallocate -l <size> /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile

Add swap without a partition: a file with real blocks, private to root, given a swap signature and turned on.

sudo fallocate -l 1G /swapfile && sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfile && swapon --show
fallocate -l 1G
Reserve real blocks; a sparse truncate file cannot be swap.
chmod 600
Swap holds memory pages; nobody else may read it.
/swapfile none swap sw 0 0
The fstab line that keeps it after a reboot; test with swapon -a.
swapoff FILE
Turn it off again before deleting the file.

dd if=<source> of=<target> bs=<size> count=<blocks>

Copy data block by block: a file of an exact size filled with zeros or random data, or a copy of a file or a disk. It asks nothing and overwrites the target at once.

dd if=/dev/zero of=/tmp/test.img bs=1M count=100 && ls -lh /tmp/test.img
if= / of=
Input and output; standard input and standard output when left out.
bs=1M count=100
100 blocks of 1 MiB. K, M and G are powers of 1024; kB, MB and GB powers of 1000.
status=progress
Show how far the copy is; status=none prints nothing.
conv=notrunc
Keep the rest of an existing output file.

Gotcha of=/dev/sdX writes straight over that disk, with no question asked. Check the name with lsblk first.

fsck [-f] [-y] <device>

Check a filesystem and repair what a crash left behind. A mount that fails with "Structure needs cleaning" is asking for it.

sudo umount /data && sudo fsck -f /dev/vg0/data && sudo mount /data
-f
Check even when the filesystem looks clean.
-y / -n
Answer yes to every repair, or change nothing and only report.
xfs_repair DEVICE
The tool for XFS; fsck does nothing there.
exit status
0 no errors, 1 errors corrected, 4 errors left, 8 could not run.

Gotcha Unmount first. Checking a mounted filesystem corrupts it, which is why fsck refuses.

blkid <device>

Print a block device's filesystem type, label and UUID, the values fstab should reference.

sudo blkid /dev/nvme1n1
/dev/nvme1n1: LABEL="data" UUID="9b2d4c31-1f0e-4d6a-8b7a-6e1f0a2c3d44" TYPE="xfs"
-s UUID -o value
Print only the UUID, for scripts.

fuser -vm <mountpoint>

Show which processes are using a filesystem, the usual answer to 'target is busy'.

sudo fuser -vm /mnt/backup
-v
Verbose: user, PID, access type and command.
-m
Treat the argument as a mounted filesystem.
-k
Kill those processes; be sure first.

swapon --show

List active swap devices and files with their size and usage.

NAME      TYPE SIZE USED PRIO
/swapfile file   2G 1.4G   -2
--show
Table of active swap areas.
vm.swappiness
sysctl that controls how eagerly the kernel swaps (default 60).

Gotcha Heavy swap use on a server means memory pressure. Latency collapses long before the OOM killer steps in.

iostat -xz 1

Per-device I/O utilization and latency, refreshed every second.

iostat -xz 1 3
-x
Extended stats: r/s, w/s, await, %util.
-z
Hide idle devices.
await
Average ms per I/O including queueing; rising await means saturation.

Gotcha %util near 100 is meaningful for single disks. SSDs and cloud volumes serve requests in parallel, so watch await too.

Archives & copies

tar -czf <archive> <paths>

Create a gzip-compressed archive.

tar -czf nginx-backup.tgz /etc/nginx
-c
Create a new archive.
-z / -J
Compress with gzip or xz.
-f FILE
Archive file name; must come right before the name.
-C DIR
Change to DIR first, which avoids absolute paths inside the archive.
--exclude=PAT
Skip matching paths.

Gotcha A backup you have never restored is a hope, not a backup. List (-t) or test-extract it.

tar -xzf <archive> -C <dir>

Extract an archive into a chosen directory, or list its contents without extracting.

tar -tzf nginx-backup.tgz
-x
Extract.
-t
List contents only.
-C DIR
Extract into DIR.
-v
Print each file.

Gotcha Extract into a scratch directory and diff before overwriting live files.

zip -r <archive.zip> <paths>

Pack files into a .zip archive, the format Windows and macOS open without extra tools. The originals stay where they are.

zip -r site.zip site -x '*.log'
-r
Take directories with everything in them.
-x PATTERN
Leave out matching names; quote the pattern.
-u
Only add files that are new or changed.
-d NAME
Delete an entry from the archive.

Gotcha Without -r a directory goes in empty. zip keeps modes but not owners, so system backups belong in tar.

unzip <archive.zip> -d <dir>

Extract a .zip archive, or list and test it without extracting anything.

unzip -l release.zip
-l
List the entries with sizes and dates.
-t
Test every entry against its checksum.
-d DIR
Extract into DIR, created when it is missing.
-o / -n
Overwrite existing files without asking, or never.
-p
Write one file to standard output.

Gotcha An archive may hold hundreds of loose files and unzip puts them in the current directory: list it first, or always extract with -d into a fresh one.

rsync -avh <src>/ <dest>/

Copy or mirror directories efficiently, locally or over SSH, transferring only differences.

rsync -avh --dry-run --delete ./site/ web-01:/var/www/site/
-a
Archive: recursive, keeps permissions, times, symlinks.
-v -h
Verbose with human-readable numbers.
--delete
Remove files at the destination that are gone from the source.
--dry-run / -n
Show what would happen.

Gotcha A trailing slash on the source copies its contents; without it you get dest/site/. With --delete, that mistake can wipe the target.

Your pager is ready.

Free, instant, and it works on your phone. No signup: start as a guest and save your progress later.