How to Debug and Capture Error Output from Linux Init.d/Rc.d Startup Scripts


1 views

When working with Linux startup scripts in /etc/init.d or /etc/rc.d, error messages often disappear into the void during boot. Unlike regular terminal commands, these scripts run in a special system context where stdout/stderr aren't always captured by default.

For modern systems using systemd:

journalctl -b -u your-service-name.service
journalctl --boot --priority=err

For older systems using SysVinit, try these approaches:

Method 1: Direct Logging to File

Modify your init script to explicitly redirect output:

#!/bin/sh
exec > /var/log/myscript.log 2>&1
# Your actual script commands here

Method 2: Temporary Terminal Output

For immediate debugging, force output to terminal:

#!/bin/sh
exec > /dev/console 2>&1
echo "Debug: Starting my service"
# Your commands

Method 3: Using logger Utility

Send messages directly to syslog:

#!/bin/sh
logger -t myscript "Starting service"
your_command || logger -t myscript -p user.err "Command failed!"

For complex cases, consider these professional approaches:

Debugging rc.local

Modify /etc/rc.local to capture all output:

#!/bin/sh
exec 2>> /var/log/rc.local.err
exec 1>> /var/log/rc.local.log

# Your commands
exit 0

Using screen for Interactive Debugging

For really stubborn issues, you can try:

#!/bin/sh
/usr/bin/screen -dmS initscript /path/to/your/script.sh

Then attach to the screen session after boot completes.

  • Always implement proper logging in your init scripts
  • Include status checks and error handling
  • Consider moving to systemd if possible for better logging
  • Document your logging approach in script headers

When your carefully crafted init scripts fail during system boot, the frustration begins when you realize the error messages have vanished into the ether. Unlike interactive shell sessions where stderr is immediately visible, boot-time script execution operates differently.

Before implementing custom solutions, exhaust these standard logging locations:

# System messages (traditional location)
/var/log/messages

# Modern systemd systems
journalctl -b

# Specific service logs
/var/log/daemon.log
/var/log/syslog

When standard logs don't capture your script output, implement these proactive measures:

#!/bin/sh
# Redirect all output to a dedicated log file
exec > /var/log/my_script.log 2>&1

# Alternative: Separate stdout and stderr
exec 1>/var/log/my_script_out.log
exec 2>/var/log/my_script_err.log

For complex issues, force the script to run interactively after boot:

# Add this to your init script
if [ "$1" = "debug" ]; then
    set -x
    shift
fi

Then test with: sudo /etc/init.d/yourscript debug

On modern systems, consider creating a proper systemd service unit:

[Unit]
Description=My Custom Service

[Service]
ExecStart=/path/to/your/script.sh
StandardOutput=journal
StandardError=journal
Restart=on-failure

[Install]
WantedBy=multi-user.target

For production systems, implement log rotation:

# /etc/logrotate.d/my_script
/var/log/my_script.log {
    weekly
    missingok
    rotate 4
    compress
    notifempty
    create 640 root adm
}

Add these functions to your scripts for better debugging:

log() {
    echo "$(date '+%Y-%m-%d %T') - $@" >> /var/log/my_script.log
}

die() {
    log "FATAL: $@"
    exit 1
}