Troubleshooting Linux
A method that works on every distribution, how Linux starts and where it breaks, the commands I would use first, the usual symptoms, worked examples from a full disk to a broken boot loader, and when it is cheaper to reinstall.
Open in the interactive Digital Garden
| What You Need |
|---|
| A second device, a phone or another computer, to read and search on while the broken one is broken. If the machine has a network connection and SSH is still running, it can also be used to log in to it from there |
| A USB stick with a live system on it: the installer of your own distribution or a rescue image such as SystemRescue. It is both a repair tool and a way to reach your files when the installed system will not start |
Root access or sudo, and the name and the version of the distribution (the command cat /etc/os-release shows both). Advice for Debian and for the Red Hat family is often different, and half of the failed repairs begin with a command written for the other one |
| Somewhere to copy your files to: an external disk, another computer, a server |
| A text file for notes, and an hour or two in peace |
Jump to the Examples
Disclaimer: Should you decide to act upon any information on this website, you do so at your own risk! A single wrong character in a command that runs as root, such as rm, dd, chmod -R, mkfs or fsck on the wrong device, can erase a disk or make a system unbootable, and Linux will not ask you whether you are sure. Back up first, check the device name twice, read what a command does before you press Enter, and never paste a line that you cannot explain, especially one that pipes a download straight into a shell.
Linux does not break less than other systems, it breaks differently. The good news is that it usually tells you what is wrong, in plain text, in a log, with a time stamp. The bad news is that it will not open a window about it, so you have to know where to read. This note is about that: a method that works on every distribution, a map of the boot process, the commands I would use first, and a few typical failures worked through step by step. The examples were written for Debian and its relatives (Ubuntu, Mint) and for the Red Hat family (Fedora, Rocky, Alma), and where the two differ, both versions are shown.
Other notes continue where this one stops. Choosing and installing a distribution, also on an old computer, is in Reviving an Old Computer. The terminal is in Communication with the Machines, the network in Computer Networks, a Debian server with SSH, updates and containers in Constructing a Cloud, and the dangers and the backups in Security Considerations. If you are coming from the other side, the same approach for the other big system is in Troubleshooting Windows.
A Method Before the Commands
On Linux it is especially tempting to skip straight to a command from a forum, because there is always one. Slow down for a few minutes first.
- Read the message. Really read it, all of it, including the last line. An error such as No such file or directory, Permission denied or Connection refused already says which family of problems you are in. Copy the exact text into your notes, or photograph the screen if you cannot copy it.
- Ask what changed. An update, a new package, an edited file in
/etc, a new disk, a different kernel, a full disk. The package manager keeps a history (/var/log/apt/history.logon Debian,dnf historyon Fedora), and it is often the shortest route to the cause. - Look at the logs before you guess.
journalctlis the first place for almost everything (see the next sections). - Save your data first. You can reinstall Linux in twenty minutes, but you cannot reinstall your photographs. A live USB stick can reach the files even when the system is unusable.
- Change one thing at a time, and write it down. Make a copy of a configuration file before you edit it (
cp file file.bak), so that going back is one command. - Test the cheapest explanation first. A full disk, a stopped service, a typo in a configuration file, a wrong permission. These are the causes of most of what happens, and they take a minute to rule out.
- Distrust copy and paste of anything with
sudoin it, from a post that is five years old, for a distribution you do not use. If you cannot say what the command does, look it up first, withmanor tldr. - Know when to stop. See the section on reinstalling. On Linux it costs less than it does elsewhere.
How Linux Starts, and Where It Breaks
The boot is a chain, and the symptom tells you which link is broken. It helps to know the names, because the error messages and the guides use them.
Power on
|
[ Firmware (UEFI / BIOS) ] hardware test, finds the boot device
|
[ Boot loader (GRUB, systemd-boot) ] shows the menu, loads the kernel
|
[ Kernel + initramfs ] drivers for the disk, finds and mounts the root file system
|
[ systemd (PID 1) ] mounts /etc/fstab, starts the services, reaches a "target"
|
[ Login manager (GDM, SDDM, LightDM) ] the graphical login, or a text login
|
[ Desktop session ]
Where it stops, and where I would look first (my own rules of thumb, not a complete list):
| Stops at | What you see | Usual suspects | First move |
|---|---|---|---|
| Firmware | No logo, "No bootable device", or the firmware menu again and again | A disk that is not seen, a reset boot order. After a Windows update on a dual-boot computer, the Windows entry is often first again | Check the boot order in the firmware setup. From a live system, efibootmgr shows and changes the UEFI entries |
| Boot loader | A grub> or grub rescue> prompt, "no such partition", "file not found" | Partitions were resized, moved or cloned, the disk order changed, or another operating system overwrote the boot loader | Boot the live USB stick and reinstall GRUB from a chroot (Example 5) |
| Kernel and initramfs | "Kernel panic: VFS: Unable to mount root fs", or a (initramfs) prompt with "ALERT! UUID=... does not exist" | A wrong root device or UUID, a missing disk driver in the initramfs, an update that was interrupted, a failing disk | Pick an older kernel under Advanced options in the GRUB menu. Then regenerate the initramfs |
| systemd | "You are in emergency mode", or "A start job is running for..." for a minute and a half | A line in /etc/fstab that cannot be mounted (a disk that is gone, a wrong UUID, a network share that is not available yet), or a service that fails | journalctl -xb, then fix /etc/fstab. Add nofail to the lines of the non-essential disks |
| Login and desktop | A black screen after an update, a login that returns to the login screen, a frozen desktop | The graphics driver (especially a proprietary one after a kernel update), a full disk or home directory, wrong ownership in the home directory (for example after a graphical program was started with sudo) | Switch to a text console with Ctrl + Alt + F3 and check df -h and the ownership of the home directory. Test with the kernel parameter nomodeset |
The Tools Already on the Machine
As on every system, you do not need to install anything to begin. These are present on practically every distribution, with the exception of a few that are in separate packages, and those are named in the table. The basics of the terminal are in Communication with the Machines.
What there is and what it tells you:
| Command | What it is good for | Package, if separate |
|---|---|---|
journalctl -b, -b -1, -p err, -u name, -f | The system log of the current boot, of the previous boot, only errors, one service, or live as it is written. The most useful command on the list | systemd |
systemctl status name, systemctl --failed | The state of one service with its last log lines, and the list of everything that failed to start | systemd |
dmesg --level=err,warn | Messages of the kernel: hardware, drivers, disks, memory. It may need sudo | util-linux |
top, htop, free -h, uptime | Who uses the processor and memory, whether swap is in use, and the load average over 1, 5 and 15 minutes | htop is separate |
df -h, df -i, du -xh --max-depth=1 / | Free space, free inodes (the number of files a file system can hold), and which directory is big | coreutils |
lsblk -f, blkid, findmnt | Disks, partitions, file systems, UUIDs, and what is mounted where | util-linux |
smartctl -a /dev/sda | The SMART data of a disk: reallocated sectors, errors, temperature, power-on hours | smartmontools |
ip a, ip route, ss -tulpn, resolvectl status, dig | Addresses, routes, who is listening on which port, which DNS server is in use, a DNS query | dig is in dnsutils or bind-utils |
lspci -k, lsusb, lsmod | The hardware that the system sees, and which kernel driver is attached to it | pciutils, usbutils |
lsof, strace | Which files a program has open, and every system call that it makes. The last resorts when a program fails without saying why | separate |
systemd-analyze blame | Which units made the boot slow | systemd |
sensors | Temperatures and fan speeds | lm-sensors |
man, --help, tldr | The manual, the short help, and the community's short examples | tldr is separate |
| A live USB system | Starts without touching the disk. For mounting, copying, a chroot and repairing | - |
One detail about the logs. On some distributions the journal is kept only in memory and is lost at the restart, which is exactly when you want it. If journalctl -b -1 says that there are no entries for the previous boot, make it permanent with sudo mkdir -p /var/log/journal and restart the machine (or set Storage=persistent in /etc/systemd/journald.conf). Do it today, before the problem.
Common Symptoms and the First Things to Check
The table is only a starting point. Each row says what I would look at first, and what comes next if the first look shows nothing. The numbered examples after it go through the steps in detail.
Symptoms, first checks and the next step:
| Symptom | First checks | If that does not help |
|---|---|---|
| Slow, or a high load | top or htop: is it the processor, the memory, or a process waiting for the disk? Is swap in use? How much free space is there? | SMART of the disk, temperatures, systemd-analyze blame for a slow boot (Example 1) |
| "No space left on device" | df -h for the space and also df -i for the inodes. A disk can be full of millions of tiny files while the space still looks free | Find the big directories, the logs, the package cache. Deleted files that a program still holds open (Example 2) |
| A service will not start | systemctl status name and journalctl -u name -b. The reason is nearly always in the last few lines | Test the configuration, check the port, the permissions and SELinux (Example 3) |
| "Permission denied", although the permissions look right | ls -l, id, and namei -l /path/to/file, which shows the permissions of every directory on the way | SELinux or AppArmor (see the note below) |
| No network, or the Wi-Fi is gone | Is it only this machine? Does the cable or the Wi-Fi light work? rfkill list shows a blocked radio | The ladder of Example 4, the firmware of the Wi-Fi card in dmesg, and Computer Networks |
| The package manager complains | "dpkg was interrupted", "Unable to locate package", "held broken packages", or dnf conflicts. Is the disk full, are the repositories right for this version? | Example 6 |
| No sound | On a current desktop wpctl status shows PipeWire's outputs, and the volume control shows the selected device | systemctl --user status pipewire wireplumber, and the kernel messages about the sound card |
| The clock is wrong, or the certificates "expired" | timedatectl. On a dual-boot computer Windows and Linux disagree about whether the hardware clock keeps the local time or UTC | Let Windows use UTC, or tell Linux with timedatectl set-local-rtc 1. The first is the cleaner one |
| A program crashes | Start it from a terminal and read what it prints. coredumpctl list shows the crashes that were saved | Update or reinstall it, try it with a new user account to exclude the settings, strace as the last resort |
| A USB stick or a disk is not seen | sudo dmesg -w while you plug it in, then lsblk and lsusb | Another port or cable, a power problem, or a file system that the kernel cannot mount without a package (exFAT and NTFS tools) |
| Strange logins, a process that you do not know | last, journalctl -u ssh (or sshd), ss -tulpn, ps aux --sort=-%cpu | Disconnect from the network, keep the evidence, change the passwords and keys from another device. More in Security Considerations and Constructing a Cloud |
A Note on SELinux and AppArmor
Besides the usual file permissions, many distributions add a second layer that decides what a program may do, whoever starts it. The Red Hat family (Fedora, RHEL, Rocky, Alma) uses SELinux, switched on by default. Ubuntu and Debian use AppArmor. When a service gets "Permission denied" while the ordinary permissions are perfect, and it started working when you moved a file somewhere else, this layer is the usual explanation.
getenforce # Enforcing, Permissive or Disabled sudo ausearch -m avc -ts recent # the recent SELinux denials sudo restorecon -Rv /path/to/directory # put the default labels back on files sudo aa-status # AppArmor: the profiles and their modes
The most common cause on SELinux is a file that was moved (not copied) from a home directory into the directory of a service, so that it keeps the old label. restorecon usually fixes that. sudo setenforce 0 switches SELinux to permissive until the next restart, which is a good test: if the problem goes away, you know that it is SELinux. Then switch it back on with setenforce 1 and fix the label or the rule. "Disable SELinux" in the first answer of a forum thread is not a fix, it is giving up the protection of the machine.
Examples: Step by Step
Each example is the order in which I would try things, not the only possible one. Stop as soon as the problem is solved, and write down what worked. Lines that begin with # in the boxes are comments.
Example 1: The Machine Has Become Slow
uptime # load average: compare it with the number of processor cores (nproc) free -h # is "available" memory small, is swap in use? top # press M to sort by memory, P by processor journalctl -k | grep -i "out of memory" # did the kernel have to kill something? systemd-analyze blame | head -15 # if the problem is a slow start
- Read the load against the cores. A load of 4 is nothing on a machine with 8 cores, and a disaster on one with 2. A high load with a low processor use usually means that processes are waiting for the disk or the network.
- Memory. The column that matters in
free -his available, not free: Linux uses the unused memory for caching, and gives it back at once. When available is small and swap is busy, the machine is out of memory, and a browser with many tabs is the usual guilty party. If the kernel killed a process, the log says "Out of memory: Killed process". - Disk. A disk that is full, or dying, makes everything slow. Check
df -hand the SMART data:sudo smartctl -a /dev/sda(for an NVMe disk the device is/dev/nvme0). Reallocated or pending sectors, or a status other than PASSED, mean that the first job is a backup, and the second is a new disk. - Heat.
sensorsshows the temperatures. A laptop at 95 degrees under a light load has a blocked cooler, and the processor slows itself down to survive. - The start-up. If it is only the boot that is slow,
systemd-analyze blameshows the unit that takes the longest. A network share, or a disk that is no longer there, that waits for a time-out is typical. - If the system is on a mechanical hard disk, the fastest improvement is an SSD, with any software.
Example 2: The Disk Is Full
df -h # which file system is full? df -i # or is it out of inodes? sudo du -xh --max-depth=1 /var | sort -h # where is the space? (repeat in the biggest directory) journalctl --disk-usage # the size of the logs sudo journalctl --vacuum-size=200M # keep only 200 MB of them sudo lsof +L1 # deleted files that a program still keeps open
The -x option of du keeps it on one file system, so that it does not wander into other disks. If df -h shows space but programs still say "No space left on device", the inodes are the problem: a directory with millions of tiny files (a mail queue, session files, a cache) is the reason, and df -i proves it. If a big file was deleted and the space did not come back, a running program still has it open. lsof +L1 lists those, and a restart of that program releases the space.
The usual safe savings are the package cache and the packages that nobody needs any more:
sudo apt clean # Debian family: the downloaded packages sudo apt autoremove # packages that were installed as dependencies and are not needed now sudo dnf clean all # Red Hat family sudo dnf autoremove
Old kernels also take up space, and so do the container images (docker system df shows them). Do not delete anything under /usr, /lib or /etc by hand to make room, and keep in mind that a completely full root file system can also mean that you cannot log in at all, because the login wants to write a small file. In that case the live USB stick is the way in.
Example 3: A Service Will Not Start
systemctl status nginx # replace nginx with your service journalctl -u nginx -b --no-pager | tail -30 sudo nginx -t # most servers can check their own configuration sudo ss -tulpn | grep :80 # is something else already on the port?
- The status and the log. The last lines nearly always contain the sentence that explains it: a syntax error in line 14, an address that is already in use, a file that cannot be opened.
- Test the configuration with the program's own check, if it has one:
nginx -t,apachectl configtest,sshd -t,named-checkconf,postfix check. Never restartsshdover an SSH session beforesshd -thas said that it is fine, and keep a second session open while you test. - The port. If another process holds it,
ss -tulpnshows which one. - Permissions and labels. Does the service's user have access to the files and the directories on the way (
namei -l)? On the Red Hat family, look at SELinux (above). - The unit file. If you edited a unit, run
sudo systemctl daemon-reloadfirst. The right way to change the unit of a package issudo systemctl edit name, which creates a small override that survives updates, not the edit of the original file. - After the fix:
sudo systemctl restart name, andsystemctl status nameonce more. A service that is in the state failed repeatedly can be reset withsudo systemctl reset-failed name.
Example 4: The Network Does Not Work
The method is a ladder: go up one step at a time, and the first step that fails shows where the problem is. The background of addresses, gateways and DNS is in Computer Networks.
ip a # does the interface have an address? is it "UP"? ip route # is there a "default via" line, the gateway? ping -c 3 192.168.1.1 # the router (use the address from the line above) ping -c 3 1.1.1.1 # the Internet by address, DNS is not needed ping -c 3 example.org # the Internet by name, DNS is needed resolvectl status # which DNS servers are in use (systemd-resolved)
- No address, or the interface is down: the cable or the Wi-Fi first.
rfkill listshows whether the radio is blocked by software or by a key. For the Wi-Fi card that is not seen at all,lspci -kandsudo dmesg | grep -i firmwaretell whether the driver wants a firmware file that is missing (the package is often calledfirmware-iwlwifi,linux-firmwareor similar). - An address, but nothing from the router: the wrong network, the wrong password, or the router is the problem. Try another device.
- The router answers, the address does not: the connection of the router itself to the Internet.
- The address answers, the name does not: DNS. Try
resolvectl query example.org, thendig @1.1.1.1 example.orgto see whether another DNS server answers. If it does, the one in use is the problem. - Everything fine locally, and the one service is unreachable from outside:
ss -tulpn(is it listening on the right address?), the firewall (sudo nft list ruleset, orsudo firewall-cmd --list-allon the Red Hat family,sudo ufw statuson Ubuntu), and then the router's port forwarding.
On most desktop distributions the network is managed by NetworkManager, so nmcli shows the connections, and sudo systemctl restart NetworkManager is a mild first aid. Do not mix several network managers: a file edited in /etc/network/interfaces together with NetworkManager, or a netplan file together with an old configuration, is a reliable source of mysterious problems.
Example 5: Linux Will Not Start
Start with the cheap things: is the disk visible in the firmware setup, and does the GRUB menu appear? In the menu, Advanced options lists the older kernels, and starting one of them is the quickest test of whether the latest update is the problem. After that, it depends on where it stops (the table in the section on starting).
(a) Emergency mode, or a long wait at the start. The system started, but a mount failed. Log in with the root password in the emergency shell (or press Ctrl + D to try to continue), and read:
journalctl -xb | tail -50 # what failed? sudo blkid # the real UUIDs of the disks sudo nano /etc/fstab # compare the UUIDs, add nofail to disks that are not essential sudo mount -a # test: no error means that fstab is good
(b) A black screen, or a broken graphical start after an update. At the GRUB menu press e over the entry, add nomodeset at the end of the line that starts with linux, and continue with Ctrl + X. This is only for this boot and it makes the system use a basic graphics mode, so if it works, the graphics driver is the problem, and it is a matter of reinstalling or rolling back the proprietary driver. With a text console (Ctrl + Alt + F3) the same repairs are possible.
(c) GRUB or the initramfs is broken. Boot the live USB stick and repair from a chroot. First find out which partition is which, and double-check the names. They are different on every computer:
lsblk -f # find the root partition and the EFI partition (small, vfat) sudo mount /dev/nvme0n1p2 /mnt # the root partition (an example name!) sudo mount /dev/nvme0n1p1 /mnt/boot/efi # the EFI partition (UEFI computers only) for d in dev proc sys run; do sudo mount --rbind /$d /mnt/$d; done sudo chroot /mnt
Now you are working inside the installed system, and the repair is the one of that family:
# Debian family, UEFI: grub-install --target=x86_64-efi --efi-directory=/boot/efi update-grub update-initramfs -u -k all # Red Hat family: dnf reinstall grub2-efi-x64 shim-x64 # UEFI: puts the boot files back grub2-mkconfig -o /boot/grub2/grub.cfg dracut --force --regenerate-all # regenerate the initramfs
The commands for an old computer with a BIOS and not UEFI differ: grub-install /dev/sda (the disk, not the partition). Exit with exit, unmount, restart. If the system is encrypted with LUKS, open it first with cryptsetup open, and have the passphrase ready. The details of every distribution are on its own wiki, and the ArchWiki is good even for those that are not Arch.
(d) A damaged file system. Run fsck only on a file system that is not mounted, so from the live system or from the rescue shell: sudo fsck -f /dev/sdXN. Doing it on a mounted file system can wreck it. First look at the SMART data: if the disk is failing, copy the data off before the long repairs, and do not run them on it twice.
Example 6: The Package Manager Is Broken
The usual reasons are an interrupted update (the power, a closed terminal, a full disk), a repository that does not match your version, or a package from outside (a PPA, a downloaded .deb or .rpm) that conflicts with the system. Check the free space first, then:
# Debian family sudo dpkg --configure -a # finish what was interrupted sudo apt --fix-broken install sudo apt update sudo apt full-upgrade apt-mark showhold # packages that are held back on purpose, and so block others # Red Hat family sudo dnf clean all sudo dnf history # what was done last, and the numbers of the transactions sudo dnf history undo 42 # undo the transaction number 42, if it was the cause
If the cause is a third-party repository, switch it off (remove the file under /etc/apt/sources.list.d/ or /etc/yum.repos.d/), and then try again. Mixing the repositories of different releases ("just for this one program") is how the system becomes a puzzle that nobody can solve, so avoid it. A package that is damaged on the disk can be reinstalled with sudo apt install --reinstall name or sudo dnf reinstall name. And never fix a conflict with --force or by deleting files from the package database, unless you are prepared to reinstall afterwards.
When to Stop Repairing
Here Linux has a real advantage. The settings are text files, the system and your data can live in separate places, and a reinstall that keeps your files takes about as long as one long troubleshooting session. There is no shame in it. Do it when you repeat yourself, when the fix of last month is needed again, when you cannot explain what is going on, or when the number of manual changes has made the machine something that nobody would be able to repeat.
The options, from the gentlest to the most thorough:
| Option | What it keeps | When I would use it |
|---|---|---|
| A new user account (test only) | Everything | To see whether the problem lives in the settings of one user (a configuration in the home directory) or in the system. If the new account works, move the old settings aside (mv ~/.config ~/.config.old) instead of reinstalling |
| Reinstall the packages | Everything | A damaged program or a group of programs. apt install --reinstall or dnf reinstall, and for the whole desktop its metapackage |
| Roll back a snapshot | The files as they were at the snapshot | If you had set up Timeshift or Snapper (Btrfs) before the update that broke it. This is the best reason to set it up |
| Reinstall the system, keep /home | Your files and settings in the home directory | A damaged system with a healthy disk. In the installer choose manual partitioning, give the root partition a format, and the /home partition a mount point without a format. A separate /home partition is the arrangement that makes this possible |
| A clean install | Nothing | A replaced disk, a system that has been upgraded through many releases, a suspected intrusion, or when you want to start with a tidy list of what is installed |
Before you wipe anything, back up the home directory, the /etc directory (the settings of every service), the databases (with their own dump tool, not by copying the files of a running server – see Constructing a Database), and the list of installed packages (apt-mark showmanual, or dnf repoquery --userinstalled). Then a reinstall is also a documentation exercise. A system that was damaged by an intrusion is not reinstalled over the old one with the same passwords: see Security Considerations.
Making It Less Likely Next Time
- Back up, and try the restore once. rsync, BorgBackup and restic are the usual tools. A backup that has never been restored is a hope. The 3-2-1 rule is in Security Considerations.
- Take a snapshot before a big update. Timeshift (for the system files, on ext4 with rsync or on Btrfs) or Snapper on Btrfs and openSUSE. Updates that go wrong then cost a restart, not an evening.
- Put
/etcunder version control with etckeeper. It commits the changes of the settings before and after each package operation, so that "what changed" has a precise answer. - Keep a separate
/homeon a separate partition or disk if you can, and a fallback kernel in the boot menu (the package managers keep the last two or three, which is a good default). - Stay with the repositories of the distribution. Every extra repository and every
curl | sudo bashis a debt that is paid later, at the update of the next release. - Use the release that fits your patience. A long-term release for the machine that has to work, and a rolling or a fast one for the machine that you like to play with. Read the release notes before the big upgrade, and do not do it the evening before you need the computer.
- Watch the disks and the space.
smartd(from smartmontools) can send an e-mail when the disk begins to fail, and the same goes for a cron job that warns at 85 percent of full. The logs should not be able to fill the root file system. - Keep the system updated, with automatic security updates on servers (see Constructing a Cloud), and a restart when a kernel or a library that is in use has been updated.
- Write down what you did, in a text file in the home directory or in a notes system. In six months this will be the best documentation of the machine that exists.
Some resources:
- ArchWiki – General troubleshooting (useful for every distribution)
- journalctl manual and systemctl manual
- Debian Reference
- Fedora Quick Docs and Red Hat documentation
- GNU GRUB manual
- SystemRescue, smartmontools
- The Linux man pages online
A Few More Thoughts
Linux repays the habit of reading. Almost everything is a text file and almost every failure leaves a line somewhere, so the skill is less a matter of knowing commands than of knowing where to look, and of staying calm enough to read the whole message. When you finally ask somebody else for help, a question that contains the distribution and its version, the exact error, the relevant lines from the journal, and what you have already tried gets an answer in an hour. A question that says "it does not work" gets a request for exactly that information, a day later.
I find it worth remembering that most of what is called "breaking" in Linux is something that we did ourselves, usually at the end of a long evening, with a command from a page that we did not fully read. That is also the good news: it means that the habits of this note, the copies, the notes, the snapshot and the one change at a time, remove most of the risk. If this machine is one of several that you run, and one of them is the mail server of Constructing E-mail or the cloud of Constructing a Cloud, these habits are no longer optional.