RED HAT ENTERPRISE LINUX

System Logging

Locating and Interpreting Logs for Troubleshooting

CIS238RH | RHEL System Administration 2
Mesa Community College

Learning Objectives

1
Use journalctl to query the systemd journal

Filter logs by time, unit, priority, and other criteria

2
Navigate traditional log files in /var/log

Locate and read rsyslog-managed log files

3
Understand log priorities and facilities

Interpret severity levels from debug to emergency

4
Configure time synchronization with chronyd

Ensure accurate timestamps across all log entries

Logging Architecture

RHEL uses two complementary logging systems: the systemd journal for structured logging and rsyslog for traditional text-based log files.

systemd Journal

Binary format, indexed, structured data. Query with journalctl. Captures all systemd service output.

rsyslog

Traditional text log files in /var/log. Human-readable. Configured in /etc/rsyslog.conf.

Facilities & Priorities

Classification system. Facility = source type. Priority = severity level (0-7).

chronyd

NTP client/server for time sync. Ensures accurate timestamps. Replaces ntpd.

Dual System: Messages often go to both journal AND rsyslog. Use whichever is most convenient for your task.

The systemd Journal

The journal is a system service (systemd-journald) that collects and stores logging data in a structured, indexed binary format.

# View all journal entries (most recent last)
[root@server ~]# journalctl

# View entries in reverse order (newest first)
[root@server ~]# journalctl -r

# Follow new entries in real-time (like tail -f)
[root@server ~]# journalctl -f

# Show only the last 20 entries
[root@server ~]# journalctl -n 20

# Show entries since last boot
[root@server ~]# journalctl -b

# Check journal disk usage
[root@server ~]# journalctl --disk-usage
Archived and active journals take up 48.0M in the file system.

Filtering by Unit

# Show logs for a specific service
[root@server ~]# journalctl -u sshd.service
Jan 20 10:15:23 server sshd[1234]: Server listening on 0.0.0.0 port 22.
Jan 20 10:15:23 server sshd[1234]: Server listening on :: port 22.
Jan 20 14:32:01 server sshd[5678]: Accepted publickey for student from 192.168.1.100
Jan 20 14:32:01 server sshd[5678]: pam_unix(sshd:session): session opened for user student

# Follow logs for a service in real-time
[root@server ~]# journalctl -u httpd.service -f

# Multiple units
[root@server ~]# journalctl -u sshd.service -u crond.service

# Show logs for a unit since last boot
[root@server ~]# journalctl -u NetworkManager.service -b

# Units can be shortened (without .service)
[root@server ~]# journalctl -u sshd
Tip: The -u filter is your most common tool. When troubleshooting a service, always start with journalctl -u servicename.

Filtering by Time

# Logs since a specific time
[root@server ~]# journalctl --since "2024-01-20 09:00:00"

# Logs until a specific time
[root@server ~]# journalctl --until "2024-01-20 17:00:00"

# Time range
[root@server ~]# journalctl --since "2024-01-20 09:00" --until "2024-01-20 12:00"

# Relative time expressions
[root@server ~]# journalctl --since "1 hour ago"
[root@server ~]# journalctl --since "yesterday"
[root@server ~]# journalctl --since "2 days ago" --until "1 day ago"

# Today's logs
[root@server ~]# journalctl --since today

# Combine with unit filter
[root@server ~]# journalctl -u sshd --since "1 hour ago"
Time Formats: Use "YYYY-MM-DD HH:MM:SS" or relative expressions like "yesterday", "1 hour ago", "today".

Log Priorities

0
emerg
System unusable
1
alert
Immediate action
2
crit
Critical condition
3
err
Error condition
4
warning
Warning condition
5
notice
Normal but significant
6
info
Informational
7
debug
Debug messages
# Show only error and higher priority (0-3)
[root@server ~]# journalctl -p err

# Show warnings and higher (0-4)
[root@server ~]# journalctl -p warning

# Priority range (warning through error)
[root@server ~]# journalctl -p warning..err

# Combine with other filters
[root@server ~]# journalctl -p err -u httpd --since today

Additional Filters

# Filter by executable path
[root@server ~]# journalctl /usr/sbin/sshd

# Filter by PID
[root@server ~]# journalctl _PID=1234

# Filter by UID (user ID)
[root@server ~]# journalctl _UID=1000

# Filter by hostname (useful for aggregated logs)
[root@server ~]# journalctl _HOSTNAME=webserver

# Kernel messages only
[root@server ~]# journalctl -k
[root@server ~]# journalctl --dmesg

# Show available field values
[root@server ~]# journalctl -F _SYSTEMD_UNIT
sshd.service
crond.service
NetworkManager.service
...

# Output in different formats
[root@server ~]# journalctl -o verbose    # All fields
[root@server ~]# journalctl -o json        # JSON format

Persistent Journal Storage

Default Behavior: On RHEL, the journal is stored in memory (/run/log/journal) and lost on reboot unless configured for persistence.
# Check current journal location
[root@server ~]# ls -la /var/log/journal/
ls: cannot access '/var/log/journal/': No such file or directory  # Not persistent

# Enable persistent storage
[root@server ~]# mkdir -p /var/log/journal
[root@server ~]# systemd-tmpfiles --create --prefix /var/log/journal
[root@server ~]# systemctl restart systemd-journald

# Or set in configuration
[root@server ~]# vim /etc/systemd/journald.conf
[Journal]
Storage=persistent

# List available boots (only with persistent storage)
[root@server ~]# journalctl --list-boots
-2 abc123 Fri 2024-01-18 09:00:00 EST—Fri 2024-01-18 18:00:00 EST
-1 def456 Sat 2024-01-19 08:00:00 EST—Sat 2024-01-19 23:00:00 EST
 0 ghi789 Sun 2024-01-20 07:00:00 EST—Sun 2024-01-20 15:30:00 EST

# View logs from previous boot
[root@server ~]# journalctl -b -1

Traditional Log Files

/var/log/
├── messages ← General system messages
├── secure ← Authentication, sudo, sshd
├── maillog ← Mail server logs
├── cron ← Cron job execution
├── boot.log ← Boot process messages
├── dmesg ← Kernel ring buffer
├── audit/ ← SELinux audit logs
│ └── audit.log
├── httpd/ ← Apache logs (if installed)
│ ├── access_log
│ └── error_log
└── nginx/ ← Nginx logs (if installed)
# View recent entries in messages
[root@server ~]# tail -f /var/log/messages

# Search for errors in secure log
[root@server ~]# grep -i "failed" /var/log/secure

rsyslog Configuration

[root@server ~]# cat /etc/rsyslog.conf
...
#### RULES ####

# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none;cron.none     /var/log/messages

# The authpriv file has restricted access.
authpriv.*                                    /var/log/secure

# Log all the mail messages in one place.
mail.*                                        /var/log/maillog

# Log cron stuff
cron.*                                        /var/log/cron

# Everybody gets emergency messages
*.emerg                                       :omusrmsg:*

# Save boot messages to boot.log
local7.*                                      /var/log/boot.log

Rule Format: facility.priority action
Example: authpriv.* = all priorities from authpriv facility → write to /var/log/secure

Syslog Facilities

FacilityDescriptionDefault Log
kernKernel messages/var/log/messages
userUser-level messages/var/log/messages
mailMail system/var/log/maillog
daemonSystem daemons/var/log/messages
authSecurity/authorization/var/log/secure
authprivPrivate auth messages/var/log/secure
cronCron daemon/var/log/cron
local0-7Custom/local useConfigurable
# Send test message to a facility
[root@server ~]# logger -p local0.info "Test message to local0"
[root@server ~]# logger -p authpriv.warning "Security test warning"

# Check where it went
[root@server ~]# tail /var/log/messages

Reading Log Entries

Jan 20 14:32:01 server sshd[5678]: Accepted publickey for student from 192.168.1.100 port 52341 ssh2

Timestamp: Jan 20 14:32:01
When the event occurred

Hostname: server
Which system generated the log

Service[PID]: sshd[5678]
Process name and ID

Message: Accepted publickey...
The actual log content

# Common log patterns to search for
[root@server ~]# grep -i "failed\|error\|denied" /var/log/secure
Jan 20 14:15:33 server sshd[4521]: Failed password for student from 192.168.1.50
Jan 20 14:15:35 server sshd[4521]: Failed password for student from 192.168.1.50
Jan 20 14:15:38 server sudo[4599]: student : command not allowed

Log Analysis Techniques

# Count occurrences of patterns
[root@server ~]# grep -c "Failed password" /var/log/secure
47

# Find unique IP addresses attempting SSH
[root@server ~]# grep "Failed password" /var/log/secure | \
    awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head
     23 192.168.1.50
     12 10.0.0.100
      8 172.16.0.25

# Timeline of errors from journal
[root@server ~]# journalctl -p err --since today --no-pager | head -20

# Watch for specific patterns in real-time
[root@server ~]# tail -f /var/log/secure | grep --line-buffered "Failed"

# Correlate across multiple logs
[root@server ~]# grep "14:32" /var/log/messages /var/log/secure

# Journal output suitable for scripting
[root@server ~]# journalctl -u sshd -o json --since "1 hour ago" | \
    jq '.MESSAGE' | head

Time Synchronization

Accurate timestamps are critical for log analysis. During incidents, you correlate events across multiple systems - impossible if clocks disagree.

chronyd

RHEL's default NTP client. Fast sync, handles intermittent connectivity, low resource usage.

NTP Protocol

Network Time Protocol. Synchronizes clocks over the network to reference time servers.

# Check current time settings
[root@server ~]# timedatectl
               Local time: Sun 2024-01-20 15:45:30 EST
           Universal time: Sun 2024-01-20 20:45:30 UTC
                 RTC time: Sun 2024-01-20 20:45:30
                Time zone: America/New_York (EST, -0500)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
Scenario: Server A logs an error at 14:30:00, Server B shows related event at 14:29:55. Did B cause A, or vice versa? Without sync, you can't know.

chronyd Configuration

# Check chronyd service status
[root@server ~]# systemctl status chronyd
● chronyd.service - NTP client/server
     Loaded: loaded (/usr/lib/systemd/system/chronyd.service; enabled)
     Active: active (running)

# View current time sources
[root@server ~]# chronyc sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* time.cloudflare.com           3   6   377    34   -234us[ -312us] +/-   15ms
^+ ntp.ubuntu.com                2   6   377    35  +1234us[+1156us] +/-   28ms
^+ time.google.com               1   6   377    36   +892us[ +814us] +/-   12ms

# Check synchronization status
[root@server ~]# chronyc tracking
Reference ID    : CF8A9A87 (time.cloudflare.com)
Stratum         : 4
Ref time (UTC)  : Sun Jan 20 20:45:30 2024
System time     : 0.000000234 seconds fast of NTP time
Last offset     : -0.000078234 seconds
RMS offset      : 0.000125432 seconds
...

Configuring Time Servers

# Edit chronyd configuration
[root@server ~]# vim /etc/chrony.conf
# Use public servers from the pool.ntp.org project.
pool 2.rhel.pool.ntp.org iburst

# Use specific servers (enterprise environment)
server time.company.internal iburst prefer
server ntp1.company.internal iburst
server ntp2.company.internal iburst

# Allow stepping clock at startup if offset > 1 second
makestep 1.0 3

# Record the rate at which the system clock gains/loses time.
driftfile /var/lib/chrony/drift

# After editing, restart chronyd
[root@server ~]# systemctl restart chronyd

# Force immediate sync
[root@server ~]# chronyc makestep
200 OK

# Verify new sources
[root@server ~]# chronyc sources -v

Setting Timezone

# View current timezone
[root@server ~]# timedatectl show --property=Timezone
Timezone=America/New_York

# List available timezones
[root@server ~]# timedatectl list-timezones | grep America
America/Chicago
America/Denver
America/Los_Angeles
America/New_York
...

# Set timezone
[root@server ~]# timedatectl set-timezone America/Los_Angeles

# Verify change
[root@server ~]# timedatectl
               Local time: Sun 2024-01-20 12:45:30 PST
           Universal time: Sun 2024-01-20 20:45:30 UTC
                Time zone: America/Los_Angeles (PST, -0800)

# Alternative: use symlink directly
[root@server ~]# ls -l /etc/localtime
lrwxrwxrwx. 1 root root 38 Jan 20 12:45 /etc/localtime -> ../usr/share/zoneinfo/America/Los_Angeles

Troubleshooting Workflow

1
Identify the timeframe

When did the problem occur? Use --since and --until to narrow scope.

2
Check service-specific logs

journalctl -u servicename -p err --since "1 hour ago"

3
Check system-wide logs

journalctl -p err --since "1 hour ago" or check /var/log/messages

4
Look for related events

Check /var/log/secure for auth, /var/log/audit/audit.log for SELinux

5
Correlate across systems

Check logs on related servers at the same timestamp

# Quick troubleshooting sequence
[root@server ~]# journalctl -u httpd -p err --since "30 min ago"  # Service errors
[root@server ~]# journalctl -p err --since "30 min ago"          # All errors
[root@server ~]# tail -100 /var/log/messages | grep -i error     # Text files
[root@server ~]# ausearch -m AVC -ts recent                      # SELinux denials

Best Practices

✓ Do

  • Enable persistent journal storage on servers
  • Configure NTP and verify synchronization
  • Use UTC timezone on servers
  • Filter logs by time first, then by unit/priority
  • Check multiple log sources when troubleshooting
  • Monitor logs proactively, not just reactively
  • Set up log rotation to manage disk space
  • Document what normal looks like

✗ Don't

  • Ignore time synchronization
  • Delete logs without archiving
  • Assume one log file has all the answers
  • Read entire log files without filtering
  • Forget to check SELinux audit logs
  • Overlook rotated log files (.1, .gz)
  • Rely only on memory-based journal
  • Panic - be systematic
Proactive Monitoring: Set up tools like logwatch, or forward logs to a central system for alerting on errors before users report problems.

Key Takeaways

1

journalctl: Query journal with -u unit, -p priority, --since/--until time, -f follow, -b boot

2

/var/log: messages (general), secure (auth), cron, boot.log, application-specific directories

3

Priorities: 0=emerg through 7=debug. Use -p err for errors and above. Filter for what matters.

4

Time sync: chronyd for NTP, timedatectl for status/timezone. Accurate timestamps are essential.

Graded Lab

  • Update the time zone on an existing server.
  • Configure system journals to persist to storage and to rotate more often.
  • Configure a new log file to store all messages for authentication failures.

Next: Managing Security with SELinux