You restarted the service and the terminal is silent
You restarted the web server and the site is down. The terminal gives you a blank stare. You type tail -f /var/log/httpd/error_log out of habit from an old tutorial, but the file is empty. Nothing happens. You suspect the service crashed, but you have no proof. Fedora isn't writing to /var/log the way you expect. The logs are hiding in the journal.
The journal captures what text files miss
Fedora uses systemd to manage services. systemd captures standard output and standard error from every service and stores it in a binary journal. This journal is a structured database, not a flat text file. It indexes every log entry by unit name, priority, timestamp, and process ID.
Old-school tools write directly to text files in /var/log. Modern Fedora services write to the journal. tail -f watches a file. journalctl -f watches the stream. If you watch the wrong place, you see nothing. The journal also handles log rotation automatically. Text files require external tools like logrotate to manage size. The journal enforces retention policies defined in the configuration.
Run journalctl first. Read the actual error before guessing.
Follow the journal stream
The primary tool for real-time debugging on Fedora is journalctl. The -f flag follows the log stream, similar to tail -f. This command streams new entries as they arrive.
Here's how to follow all logs in real-time. This is useful when you are unsure which service is causing the issue.
# Follow the entire journal stream
journalctl -f
# -f keeps the terminal open and prints new entries as they arrive
# This command works without sudo for user-level logs
System services require root privileges to view. If you see a permission error, add sudo. The journal protects system privacy by restricting access to sensitive logs.
journalctl: Failed to read from journal: Permission denied
Use sudo to unlock system logs. The journal enforces these boundaries for security.
Here's how to isolate output from a specific service. Filtering by unit name removes noise from other processes.
# Follow only the web server logs
sudo journalctl -u httpd -f
# -u restricts output to the specified systemd unit
# sudo is required to read logs from system services
Most sysadmins type journalctl -xeu <unit> muscle-memory style when debugging a failed service. The x flag adds explanatory text for known errors, and the e flag jumps to the end of the log. Use -f when you need to watch live activity, and use -xe when you need to diagnose a past failure.
When text files still matter
Some legacy applications or custom scripts write directly to text files in /var/log. tail -f remains the correct tool for these files. The -f flag follows the file by inode. If the file is rotated and replaced with a new inode, tail -f stops watching.
Here's how to watch a traditional text log file.
# Watch a traditional text log file
sudo tail -f /var/log/messages
# -f prints new lines as the file grows
# sudo is needed because /var/log is owned by root
If the log file is managed by logrotate, the file will be renamed and a new file created. tail -f will continue watching the old renamed file, which stops growing. You will see no new output.
Here's how to handle log rotation safely with tail. The capital F flag follows the file by name instead of inode.
# Use capital F to handle log rotation safely
sudo tail -F /var/log/httpd/error_log
# -F follows the file by name, not inode
# If the file is rotated and recreated, tail -F resumes watching the new file
Trust the package manager. Manual file edits drift, snapshots stay. Use tail -F for any file that might be rotated.
Persistence and rotation
The journal can be volatile or persistent. By default, Fedora configures the journal to persist logs across reboots. This requires the /var/log/journal/ directory to exist. If the directory is missing, logs are stored in /run/log/journal/ and lost when the system restarts.
Here's how to check if the journal is persistent.
# Check if the journal is persistent across reboots
ls -ld /var/log/journal
# If this directory exists, logs survive a system restart
# If it is missing, logs are stored in memory and lost on reboot
If the directory is missing, create it to enable persistence. The systemd service will take ownership automatically.
# Create the persistent journal directory
sudo mkdir -p /var/log/journal
# -p creates parent directories if needed
# The systemd-journald service will set correct permissions on next restart
Configuration for the journal lives in /etc/systemd/journald.conf. Never edit files in /usr/lib/systemd/journald.conf. That file ships with the package and will be overwritten on updates. Edit /etc/ to override defaults.
Here's how to verify the journal configuration.
# Check current journal settings
sudo systemctl show systemd-journald | grep -E "SystemMaxUse|SystemKeepFree"
# SystemMaxUse defines the maximum disk space the journal can consume
# SystemKeepFree ensures enough disk space remains for other processes
Snapshot the system before changing journal retention policies. Future-you will thank you if disk space runs out unexpectedly.
Advanced filtering
The journal supports powerful filters without needing grep. Piping to grep works, but native filters are faster and preserve structured context. You can filter by priority, time, and multiple fields simultaneously.
Here's how to filter by priority and unit.
# Filter by priority level and unit simultaneously
sudo journalctl -u httpd -p err -f
# -p err shows only error and higher severity messages
# Combining filters reduces noise without needing grep
Priority levels follow syslog conventions. err includes errors, critical, alert, and emergency messages. notice includes notices and higher. Use journalctl -p help to see all levels.
Here's how to filter by time range.
# Follow logs from the last hour only
sudo journalctl -f --since "1 hour ago"
# --since restricts output to entries after the specified time
# This is useful when debugging an issue that started recently
You can combine time filters with unit filters. This narrows the scope to a specific service during a specific window.
Verify the fix
After applying a configuration change or restarting a service, verify that the logs reflect the new state. Restart the service to generate fresh log entries. Watch the journal output to confirm the service starts cleanly.
Here's how to trigger a restart and verify the output.
# Restart the service to generate new log entries
sudo systemctl restart httpd
# systemctl restart sends a stop signal followed by a start signal
# Watch the journal output for the restart event
Look for the Started message in the journal output. If the service fails, the journal will show the error immediately.
-- Subject: A start job for unit httpd.service has begun execution
-- Defined-By: systemd
-- Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- A start job for unit httpd.service has begun execution.
--
-- The job identifier is 1234.
Run systemctl status <unit> after the restart. This command shows the current state and recent log lines in one view. Always check status before restarting.
Common pitfalls
Log rotation breaks tail -f. If you are watching a text file and the output stops, check if the file was rotated. Switch to tail -F to avoid this issue.
Buffering hides output. Some applications, especially Python or Java programs, buffer their output. The journal won't see the logs until the buffer flushes. This can make it look like the service is silent when it is actually running. Configure the application to flush output frequently, or use stdbuf to force unbuffered output.
SELinux denials require specific filtering. SELinux audit messages appear in the journal with the setroubleshoot identifier. Raw audit logs are hard to read. setroubleshoot translates them into human-readable summaries.
Here's how to watch for SELinux denials.
# Watch for SELinux denials in real-time
sudo journalctl -f -t setroubleshoot
# -t filters by syslog identifier
# setroubleshoot translates raw audit messages into human-readable summaries
Read SELinux denials before disabling SELinux. The denial message usually tells you exactly which file or port needs a policy adjustment.
Choose the right tool
Use journalctl -f when you are debugging a systemd service or kernel message.
Use journalctl -u <unit> -f when you need to isolate output from a specific service.
Use journalctl -xe when you need to read past errors with explanatory context rather than streaming live output.
Use tail -f when you are monitoring a legacy application that writes directly to a text file in /var/log.
Use tail -F when the log file might be recreated or rotated, as the capital F flag reopens the file if the inode changes.
Use journalctl -f -t setroubleshoot when you are troubleshooting permission issues that might be caused by SELinux.
Run journalctl first. Read the actual error before guessing.