Linux - Devices & Filesystems

Creating Partitions

On any operating system, a disk needs to be partitioned before it can be used. A partition is a logical subset of the physical disk, and information about partitions are stored in a partition table.

Note: See Where is the bootloader for differences between MBR and GPT.

MBR Partitions

# Utility for managing MBR partitions on Linux
fdisk /dev/<device>

# Display the current disk config
fdisk -l

Note: all disk-related operations need to be executed as root.

fdisk commands:

m                               # Help
p                               # Display the partition table
F                               # Check for unallocated space

n                               # Create a new partition
d                               # Delete a partition

t                               # Change partition type
l                               # Display list of all partition types

w                               # Write changes to the disk

Note: The maximum size of a new partition will be limited to the maximum amount of contiguous unallocated space.

It’s a best practise to run partprobe after writing something to the disk.

GPT Partitions

GPT partitions can have a nearly unlimited number of partitions with size limited to the OS (RHEL has certified GPT partitions using XFS at 500TiB and a theoretical maximum of 16EiB).

# Utility for managing GPT partitions on Linux
gdisk /dev/<device>

# Display the current disk config
gdisk -l

Note: all disk-related operations need to be executed as root.

fdisk commands:

?                               # Help
p                               # Display the partition table
F                               # Check for unallocated space
s                               # Sort partitions

n                               # Create a new partition
d                               # Delete a partition
r                               # Recover a partition

t                               # Change partition type
l                               # Display list of all partition types

w                               # Write changes to the disk

It’s a best practise to run partprobe after writing something to the disk.

GNU Parted

GNU Parted is a very powerful partition editor used to create, delete, move, resize, rescue and copy partitions.

# Start using parted
parted /dev/<device>

Parted commands:

# Switch to a different disk
select /dev/<device>
# Get more information about a specific partition
print
# List of all block devices connected to your system
print devices
# Get information about all connected devices at once
print free

# Create a partition table on an empty disk
mklabel msdos
mklabel gpt
# Create a partition
mkpart <partition-type> <fs-type> <start> <end>
# Remove a partition
rm <partition-number>
# Recover a partition
rescue <start> <end>
# Resize a partition
resizepart <partition-number> <end>
resize2fs /dev/<partition>

SWAP Partitions

Swap partitions can be created with any of the methods above fdisk, gdisk, bepending on your type of partition.

# Create a swap partition with fdisk
fdisk /dev/<device>
Command: t
82
# Create a swap partition with gdisk
gdisk /dev/<device>
Command: t
8200
# Create a swap partition with parted
mkpart <partition-type> linux-swap <start> <end>

Creating Filesystems

Partitioning disks is only one step towards being able to use a disk. After that, formatting the partition with a filesystem is needed before using it to store data.

# Display the filesystem info
lsblk -f /dev/<partition>

EXT Filesystems

Extended Filesystem ext was the first filesystem for Linux, and replaced by new versions called ext2, ext3 and ext4.

# Create a ext filesystem on a specific partition
mkfs.ext<ext-version> /dev/<partition>
mke2fs -t ext<ext-version> /dev/<partition>

# mkfs/mke2fs ext parameters
-b <size>                       # Set size of data blocks in the device
-c                              # Check target device for bad blocks
-d <directory>                  # Copy contents of specific directory to root of the new filesystem
-F                              # Force creation (dangerous!)
-L <label>                      # Set volume label (max 16 characters)
-n                              # Simulate creation of the filesystem
-q                              # Quiet mode (no output to the terminal)
-U <id>                         # Set UUID of a partition
-V                              # Verbose mode (debugging)

XFS Filesystems

Tools for managing XFS filesystems are part of the xfsprogs package.

XFS filesystems are divided into at least 2 parts:

  • log section: log of all filesystem operations (Journal)
  • data section

Note: The log section may be located inside the data section (default) or on a separate disk.

# Create a xfs filesystem on a specific partition
mkfs.xfs /dev/<partition>
mke2fs -t xfs /dev/<partition>

# mkfs/mke2fs xfs parameters
-b size=<value>                 # Set size of data blocks in the device
-m crc=<boolean>                # Enables/disables CRC32c checks to verify integrity of metadata
-m uuid=<value>                 # Set UUID of a partition
-f                              # Force creation (dangerous!)
-l logdev=<device>              # Put log section on a specific device
-l size=<bytes>                 # Set size of log section (m, g, ...)
-q                              # Quiet mode (no output to the terminal)
-L <label>                      # Set volume label (max 12 characters)
-N                              # Simulate creation of the filesystem

FAT or VFAT Filesystems

# Create a fat filesystem on a specific partition
mkfs.fat /dev/<partition>
mke2fs -t fat /dev/<partition>

mkfs.vfat /dev/<partition>
mke2fs -t vfat /dev/<partition>

# mkfs/mke2fs fat/vfat parameters
-c                              # Check target device for bad blocks
-C <file-name> <block-count>    # Create specific file and create FAT filesystem inside it
-F <size>                       # Selects size of FAT (12, 16 or 32)
-n <label>                      # Set volume label (max 11 characters)
-v                              # Verbose mode (debugging)

exFAT Filesystem

# Create a exfat filesystem on a specific partition
mkfs.exfat /dev/<partition>
mke2fs -t exfat /dev/<partition>

# mkfs/mke2fs exfat parameters
-i <volume-id>                  # Set volume ID (32b hex nr)
-n <label>                      # Set volume label (max 15 characters)
-p <sector>                     # Set first sector of first partition on the disk (default 0)
-s <sectors>                    # Set number of physical sectors per cluster of allocation (power of 2)

Btrfs Filesystem

The B-Tree Filesystem is a copy-on-write filesystem (very resilient to crashes).

Note: copy-on-write - data is written to free space on disk, then the file’s original metadata is updated to refer to the new data and only then the old data is freed up, as it is no longer needed.

Tools for managing Btrfs filesystems are part of the btrfs-progs package.

# Create a btrfs filesystem on a specific partition
mkfs.btrfs /dev/<partition>
mke2fs -t btrfs /dev/<partition>

# mkfs/mke2fs btrfs parameters
-L <label>                      # Set volume label (max 256 characters)
-m <value>                      # Set how metadata will be distributed in the disk array (raid(0,1,5,6,10), single, dup)

Note: Multiple devices can be passed to mkfs.btrfs. This will span the filesystem over all the devices which is similar to a RAID or LVM setup.

Managing subvolumes:

# Create a subvolume
btrfs subvolume create /mnt/<mountpoint>
# Check subvolume status
btrfs subvolume show /mnt/<mountpoint>
# Mount the subvolume
mount -t btrfs -o subvol=<subvolume-name> /dev/<partition> /mnt/<mountpoint>

Working with snapshots:

# Create a snapshot
btrfs subvolume snapshot /mnt/<mountpoint> /mnt/<mountpoint>/snap
# Create a read-only snapshot
btrfs subvolume snapshot -r /mnt/<mountpoint> /mnt/<mountpoint>/snap

SWAP

mkswap -L <label> /dev/<device>
# Enables a swap partition or file
swapon -L <label>
# Disables a swap partition or file
swapoff -L <label>
# Check is swap space was added
free -m

Note: Linux also supports the use of swap files instead of partitions.

dd if=/dev/zero of=<file-name> bs=<bytes> count=<value>
mkswap <file-name>
swapon <file-name>

NFS

Network File Systems (NFS) is a way of mounting directories over a network. In a typical NFS setup there’s a server that exports a directory and any number of clients.

# Exporting NFS
/etc/exports

# Mount options
rw
ro
no_root_squash

# Services on the server
prcbind
nfs-server
rpc-statd
nfs-idmapd

Mounting NFS:

showmount -e <server-ip>
mount -t nfs <erver-ip>:/<server-path> /<client-path>

Note: root_squash (by default) vs no_root_squash (not recommended) - squash any root user right to nfsnobody

Samba - Server Message Block is a protocol that can be used to share access to files, printers and other resources. While the name of the protocol has changed to cifs (Common Internet File System), many packages still use SMB terminology.

Exporting SMB directories:

# Set Samba configuration in /etc/samba/smb.conf
[share]
    browsable = yes
    path = /smb
    writable = yes

Note: writeable needs to be specified because there is no default value, if not specified, the share won’t be writable.

# Create a samba user to mount the share
useradd <user>
smbpasswd - a <user>

# Install packages to help kernel understand SMB mount
yum install -y cifs-utils samba-client
mount -t cifs /<server-ip>/shared /mnt/<directory> -username=<user> -password=<password>

Filesystem Integrity

Disk Usage

# View how many 1KB block are being used
du -h
# Show an individual count for all files in the directory
du -ah
# Exclude subdirectories
du -Sh
# Distinction between current and subdirectories with total
du -Shc
# Set subdirectory depth
du -h -d<depth>
# Exclude some types of files from the count
du -ah --exclude=<pattern>

Disk Free Space

# List of all of the available filesystems on your system
df -h
# Show used/available inodes instead of blocks
df -i
# Show type of each filesystem
df -hT
# Show only specific filesystems
df -ht <filesystem-type>
# Exclude filesystems
df -hx <filesystem-type>
# Customize output
df -h --output=source,fstype,size,used,avail,pcent,target,itotal,iused,ivail,ipcent

EXT Filesystem Maintenance

The fsck command is a utility used to check ext-based filesystems:

# Invoke ext filesystem check
fsck /dev/<partition>

# fsck parameters
-A                              # Check all filesystems in /etc/fstab
-C                              # Display a progress bar
-N                              # Simulate filesystem check
-R                              # When used with -A, skip the root filesystem
-P                              # When used with -A, check the root filesystem in parallel
-V                              # Verbose mode (debugging)
-M                              # Don't check mounted filesystems
-t <filesystem>                 # Set filesystem type to check
-s                              # Serialize fsck operations
-l                              # Create exclusive lock file /run/fsck/<disk-name>.lock for whole disk device
-r                              # Report certain statistics for each fsck when it completes

Note: Never run fsck on a mounted filesystem!

Note: in /etc/fstab the SWAP partition is always set to 0. Beacause swap data is transient, there is no need to check for data consistency since nothing is stored here permanently.

The e2fsck command is a utility used to check ext-based filesystems:

# Invoke ext filesystem check
e2fsck /dev/<partition>

# e2fsck parameters
-p                              # Automatically fix any errors found
-y                              # Answer yes to all prompts
-n                              # Answer no to all prompts
-f                              # Force filesystem check

The tune2fs command is a utility used to adjust parameters on ext-based filesystems:

# Invoke ext filesystem tuning
tune2fs -l /dev/<partition>

# tune2fs parameters
-L                              # Set volume label (max 12 characters)
-l                              # Displays filesystem label
-U                              # Sets the filesystem UUID
-u                              # Displays the filesystem UUID (alternative for blkid)
-c                              # Enables/disables lazy counters
-C <number>                     # Set maximum mount count
-i <time>                       # Define a time interval between checks (d, m, y)
-e <behaviour>                  # Define kernel behaviour (continue, remoount -ro, panic)
-j                              # Add a journal to an ext2 filesystem (transform to ext3)
-J size=<bytes>                 # Journal size in megabytes
-J location=<path-to-file>      # Journal storage location
-J device=<device>              # Put journal on an external device
-f                              # Brute force option

XFS Filesystem Maintenance

The xfs_repair command is a utility used to check xfs-based filesystems:

# Invoke xfs filesystem check
xfs_repair -n /dev/<partition>

# xfs_repair parameters
-l <log-device>                 # Set external log device
-r <real-time-device>           # Set external real-time device
-m <number>                     # Limit the memory usage in megabytes
-d                              # Dangerous mode, enable repair of mounted read-only filesystems
-v                              # Verbose mode (debugging)
-L                              # Zero out a corrupt log

The xfs_admin command is a utility used to adjust parameters on xfs-based filesystems:

# Invoke xfs filesystem check
xfs_admin /dev/<partition>

# xfs_repair parameters
-L                              # Set volume label (max 12 characters)
-l                              # Displays filesystem label
-U                              # Sets the filesystem UUID
-u                              # Displays the filesystem UUID (alternative for blkid)
-c                              # Enables/disables lazy counters

Other utilities used to maintain xfs-based filesystems:

# Invoke xfs filesystem debug
xfs_db /dev/<partition>
# Invoke xfs filesystem defragmentation
xfs_fsr /dev/<partition>
# Summarize free space for the filesystem
freesp /dev/<partition>
# Get file fragmentation data
frag

Note: Without any extra arguments xfs_fsr will run for 2h and try to defragment all mounted, writable XFS filesystems listed on /etc/mtab/.

Mounting and Unmounting Filesystems

Mounting means attaching the filesystem to a specific point in your system’s directory tree, called a mountpoint.

Manual

Mounting a filesystem:

# Mount a filesystem
mount -t <filesystem-type> /dev/<partition> <mountpoint>
# List all mounted filesystems
mount
# List mounted filesystems of a specific type
mount -t <filesystem-type>

# mount parameters
-a                              # Mount all filesystems in /etc/fstab
-o                              # Pass a list of mount options
-r                              # Mount filesystem as read-only
-w                              # Mount the filesystem as writeable

Unmounting a filesystem:

# Unmount a filesystem
umount /dev/<partition>
umount <mountpoint>

# umount parameters
-a                              # Unmount all filesystems in /etc/fstab
-f                              # Force unmount
-r                              # Make filesystem read-only if unmount is not possible

Dealing with open file:

# Display a list of processes accessing device and which files are open
lsof /dev/<partition

Note: Nowadays filesystems can be mounted anywhere, but it is still a good practice to mount filesystems under /mnt.

On Boot

The file /etc/fstab contains descriptions about the filesystems that can be mounted. This is a text file, where each line describes a filesystem to be mounted.

#DEVICE IDENTIFIER                          MOUNTPOINT      FS TYPE     MOUNT OPTIONS       DUMP FREQUENCY      FS CHECK ORDER
LABEL=opt                                   /opt            ext4        defaults            1                   2
UUID=6e2c12e3-472d-4bac-a257-c49ac07f3761
device identifier mountpoint type options dump pass
Device (not recommended), label or UUID Where the filesystem will be mounted Filesystem type Mount options passed to mount Whether ext-based filesystems should be backed-up by dump Defines filesystem check order on bootup
# /etc/fstab mount options
atime   | noatime               # Whether to update access time information
auto    | noauto                # Whether to mount automatically (-a)
dev     | nodev                 # Whether to interpret char/block devices
exec    | noexec                # Whether to execute binairies
user    | nouser                # Whether to enable filesystem mouting by an ordinary user
suid    | nosuid                # Whether to enable SETUID and SETGID bits
sync    | async                 # Whether to do all I/O operations to the filesystem synchronously or asynchronously
ro      | rw                    # Mount filesystem as read-only or writable
group                           # Allows user to mount filesystem if the user's group owns the device
remount                         # Attempt to remount an already mounted filesystem
defaults                        # Pass options: rw,suiq,dev,exeec,auto,nouser,async

Mounting Disks with Systemd

Systemd creates a configuration file called a mount unit. Each volume to be mounted gets its own mount unit in /etc/systemd/system/.

vim <unit>.mount

# Basic format of a mount unit
[Unit]
# Short description of the mount unit
Description=<description>

[Mount]
# What should be mounted
What=/dev/disk/by-uuid/<volume-uuid>
# Full path to where the volume should be mounted
Where=<path-to-file>
# Filesystem type
Type=<filesystem-type>
# Mount options
Options=<options>

[Install]
# Systemd boot target
WantedBy=<target>

Mount units can be automounted whenever the mount point is accessed.

vim <unit>.automount

# Basic format of a automount unit
[Unit]
Description=<description>

[Automount]
Where=<path-to-file>

[Install]
WantedBy=<target>

Note: The mount unit must have the same name as the mountpoint (for example: if mountpoint is /mnt/external, the unit should be mnt-external.mount)

After the unit creation, the unit must be started and services should be reloaded.

# Reload the services
systemctl daemon-reload
systemctl start <unit>.mount

File Permissions and Ownership

Querying Information

# List content of any directory
ls -l
# List content of directories
ls -ld
# List content of hidden files
ls -la

The first letter in each output of ls -l describes the type of the file.

-                               # Normal file
d                               # Directory
l                               # Symbolic link
b                               # Block device
c                               # Character device (terminals and serial ports)
s                               # Sockets

Note: Be careful when altering permissions on block devices, character devices or socket.

Permissions

  • Symbolic permissions: rwx-
  • Numberic permissions: 421-
Number Read Write Execute
7 X X X
6 X X  
5 X   X
4 X    
3   X X
2   X  
1     X
0      

Default permissions for files and directories.

# Default permissions for files
-rw-r--r--
644
# Default permissions for directories
drwxr-xr-x
755

# Check current umask value
umask
# Check current umask value (symbolic)
umask -S
# Modify defaul permissions
umask u=<permissions>,g=<permissions>,o=<permissions>

Note: Subtract the umask value from the default permission to get the currently configured permission value.

Permanent Configuration:

  • /etc/bashrc = umask set for whole system
  • /home/<user>/.bashrc = umask set for individual user
Value Permission for Files Permission for Directories
0 rw- rwx
1 rw- rw-
2 r– r-x
3 r– r–
4 -w- -wx
5 -w- -w-
6 –x
7

Modifying Permissions

The command chmod is used to modify the permissions for a file.

Symbolic mode:

# Set symbolic file permissions for entity
chmod <entity>=<symbolic-permissions> <file>
# Add symbolic file permissions for entity
chmod <entity>+<symbolic-permissions> <file>
# Remove symbolic file permissions for entity
chmod <entity>-<symbolic-permissions> <file>

# Change symbolic directory permissions for entity
chmod -R <entity>(=|+|-)<symbolic-permissions> <file>

Octal mode:

# Set octal file permissions for entity
chmod <ocatl-permissions> <file>

# Change octal directory permissions for entity
chmod -R <octal-permissions> <file>

Note: If a permission value is odd, it is executable.

Modifying Ownership

# Change a file's user ownership
chown <user> <file>
# Change a file's group ownership
chown :<group> <file>
# Change a file's user and group ownership
chown <user>:<group> <file>

Note: Querying groups

# Check which groups exist
getent group
# Check to which groups a user belongs
groups <user>
# Check which users belong a specific group
groupmems -g <group> -l

Note: the group ownership of a file/directory can also be changed with chgrp.

  chgrp <group> <file>

Special Permissions

Set UID

set user id - This permission has a s in place of an x in the user column.

# Add a SUID to a file (octal)
chmod 4<octal-permissions> <file>
# Remove a SUID from a file (octal)
chmod 0<octal-permissions> <file>

# Add a SUID to a file (symbolic)
chmod u+s <file>
# Remove a SUID from a file (symbolic)
chmod u-s <file>

Note: This will not work on bash scripts anymore due to security updates. Also, many file systems can be mounted with the nosuid option.

Set GID

set group id - This permission has a s in place of an x in the group column.

# Add a SGID to a file (octal)
chmod 2<octal-permissions> <file>
# Remove a SGID from a file (octal)
chmod 0<octal-permissions> <file>

# Add a SGID to a file (symbolic)
chmod g+s <file>
# Remove a SGID from a file (symbolic)
chmod g-s <file>

Note: It’s more useful is when you apply the set GID bit a directory that is intended to be used for a whole group of users that can share content within it so that everybody has access to create files within it, and the group itself retains ownership of the contents of this directory.

Sticky Bit

restricted deletion flag - This permission has a t in place of an x in the other column.

# Add a sticky bit to a file (octal)
chmod 1<octal-permissions> <file>
# Remove a sticky bit from a file (octal)
chmod 0<octal-permissions> <file>

# Add a sticky bit to a file (symbolic)
chmod o+t <file>
# Remove a sticky bit from a file (symbolic)
chmod o-t <file>

Note: The sticky bit is very useful in the /tmp directory.

ACL

Access Control Lists allow a much more granular permission structure as opposed to the “normal” octal User/Group/Other permissions.

# Read filesystem ACLs
getfacl <file>

# Create an ACL for a user
setfacl -m u:<user>:<symbolic-permissions> <file>
# Remove an ACL for a user
setfacl -x u:<user> <file>
# Remove all ACLs for a user (including the mask)
setfacl -b u:<user>

# Create an ACL for a group
setfacl -m g:<group>:<symbolic-permissions> <file>
# Remove an ACL for a group
setfacl -x g:<group> <file>
# Remove all ACLs for a group (including the mask)
setfacl -b g:<group>

# Set default ACLs to set permissions for newly created files
setfacl -d -m u:<user>:<symbolic-permissions> <directory>
# Remove the default ACL
setfacl -k <directory>
setfacl --remove-default <directory>

# Quick set an ACL
getfacl <file> | setfacl --set-file=- <other-file>

Note: use the option -R when setting an ACL for a directory to run recursively.

A hard link is an additional entry in the filesystem pointing to the same place (inode) on the disk.

# Creating a hard link
ln <target> <link-name>
# Display hard links
ls -li
# Move/rename a hard link
mv <link-name> <destination>
# Remove a hard link
rm <link-name>
unlink <file>

Note: The target must already exist, it is a good pracitce to specify the full path.

A soft link points to the path of another file. If you delete the file the link points to (called target) the link will still exist, but it “stops working”, as it now points to “nothing”.

# Creating a soft link
ln -s <target> <link-name>
# Display soft links
ls -lh
# Move/rename a soft link
mv <link-name> <destination>
# Remove a soft link
rm <link-name>
unlink <file>

Find Files and File Location

Linux directory structure

/                               # Root directory
/bin                            # Essential binaries
/boot                           # Files needed by the boot process (initrd and kernel)
/dev                            # Physical/virtual devices connected to the system
/etc                            # Host-specific configuration files
/home                           # User home directories
/lib                            # Shared libraries to boot the operating system and to run binaries
/media                          # User-mountable removable media
/mnt                            # Mountpount for temporarily mounted filesystems
/opt                            # Application software packages
/root                           # Home directory for the superuser
/run                            # Run-time variable data
/sbin                           # System binaries
/srv                            # Data served by the system
/tmp                            # Temporary files
/usr                            # Read-only user data
/proc                           # Virtual filesystem with running process data
/var                            # Variable data written during system operations

Temporary Files and Folders

  • All content in /tmp is cleared upon system boot.
  • All content in /run is cleared upon system boot.
  • All content in /var/tmp persists through a system boot.
# Create ad hoc temporary files
mktemp <name-template>

Finding Files

The find command is a utility used to find files in a filesystem:

# Search for a specific file
find <start-point> -name <file-name>

# Searching by parameters
-maxdepth <depth>               # Set how deep find goes
-mindepth <depth>               # Set how deep find goes
-mount                          # Avoid searching inside mounted filesystems
-fstype <filesystem-type>       # Search a specific filesystem type
-user <user>                    # Match files owned by the user
-group <group>                  # Match files owned by the group
-readable                       # Match files that are readable by the current user
-executable                     # Match files that are writable by the current user
-perm <octal-permissions>       # Match files that have exactly the specified permissions
-empty                          # Match empty files and directories
-size <blocks>                  # Match files of specified size (1 block = 512B)

# Searching by time
-amin <minutes>                 # Match files accessed n minutes ago
-cmin <minutes>                 # Match files changed n minutes ago
-mmin <minutes>                 # Match files modified n minutes ago

-atime <days>                 # Match files accessed n days ago
-ctime <days>                 # Match files changed n days ago
-mtime <days>                 # Match files modified n days ago

# Example: search .jpg files in current directory which have been modified less than 24h ago
find . -name '*.jpg' -mtime -1 -size +100M

Note: Use -perm -<octal-permissions> to search for files with at least the specified permissions.

The locate command is a utility used to find files using a database maintained by updatedb:

# Search for a file based on a pattern
locate <pattern>
# Search for a file based on multiple pattern
locate <pattern> <pattern>
# Search for a file that matches all on multiple pattern
locate -A <pattern> <pattern>
# Count the number of files matching a pattern
locate -c <pattern>

The behavior of updatedb can be controlled by the file /etc/updatedb.conf.

PRUNEFS=<filesystem-type>       # Exclude specific filesystem types
PRUNENAMES=<directory>          # Exclude specific directories
PRUNEPATHS=<path-to-file>       # Exclude specific paths
PRUNE_BIND_MOUNTS=<boolean>     # Whether or not to bind mounts

Finding Binaries, Man Pages and Source Code

The which command is a utility used to find the full path to an executable:

# Search for an executable
which <executable>
# Show all pathnames that match the executable
which -a <executable>

The type command is a utility used to gather information about an executable:

# Search for an executable
type <executable>
# Show all pathnames that match the executable
type -a <executable>
# Show the file type of an executable
type -t <executable>

The whereis command is a utility used to gather information about an executable, man page or source code:

# Search for an executable
whereis <binary>
# Show information about a binary
whereis -b <binary>
# Show information about a man page
whereis -m <binary>
# Show information about a source code
whereis -s <binary>