How to Execute Shell Commands Dynamically in /etc/motd (Linux Login Banner)


40 views

html

The Message of the Day (/etc/motd) file in Linux systems displays static content upon user login. By default, it doesn't support dynamic shell command execution like:

$(uptime)
or
uptime

These attempts fail because /etc/motd is processed as a plain text file by the login system, not as a shell script.

Method 1: Using update-motd (Debian/Ubuntu)

Modern Debian-based systems provide a better solution:

# Create executable script in /etc/update-motd.d/
sudo nano /etc/update-motd.d/10-system-stats

#!/bin/sh
echo "System uptime: $(uptime)"
echo "Load average: $(cat /proc/loadavg)"

# Make executable
sudo chmod +x /etc/update-motd.d/10-system-stats

Method 2: PAM motd Module

Configure PAM to execute scripts:

# Edit /etc/pam.d/sshd
session    optional     pam_motd.so motd=/run/motd.dynamic

# Create dynamic generation script
sudo nano /usr/local/bin/generate-dynamic-motd

#!/bin/bash
echo "=== System Information ==="
echo "Hostname: $(hostname)"
echo "Uptime: $(uptime -p)"
echo "Disk Usage: $(df -h / | awk 'NR==2{print $5}')" > /run/motd.dynamic

Method 3: Cron Job with Static File

# Create script
sudo nano /etc/cron.hourly/update-motd

#!/bin/bash
{
  echo "Last updated: $(date)"
  echo "Users logged in: $(who | wc -l)"
  echo "Memory usage: $(free -h | awk '/Mem/{print $3"/"$2}')"
} > /etc/motd

When implementing dynamic MOTD:

  • Restrict script permissions (root ownership, 755)
  • Validate all command outputs
  • Use absolute paths in cron jobs
  • Consider resource usage for frequent updates

Verify changes without logout:

# For SSH:
ssh localhost

# For console:
cat /run/motd.dynamic

Many sysadmins wonder whether they can embed shell commands directly in /etc/motd to create dynamic login banners. The short answer is no - the Message of the Day file is a static text file that doesn't interpret shell commands or variables.

When you try commands like:

$(uptime)

or

uptime

These appear literally in the motd because:

  • The file is read directly by login processes
  • No shell interpretation occurs during display
  • Security restrictions prevent command execution

Here are three working approaches to achieve dynamic motd content:

1. Update motd via Cron

Create a script to regenerate motd periodically:

#!/bin/bash
echo "System Uptime: $(uptime)" > /etc/motd
echo "Last Login: $(last -n 1)" >> /etc/motd

Then add to crontab:

*/5 * * * * root /usr/local/bin/update_motd.sh

2. Use pam_exec with update-motd

On Debian/Ubuntu systems:

# Create dynamic files in /etc/update-motd.d/
cat << EOF > /etc/update-motd.d/10-system-stats
#!/bin/sh
echo "Uptime: $(uptime)"
EOF
chmod +x /etc/update-motd.d/10-system-stats

3. Custom SSH Banner

For SSH-specific messages:

# In /etc/ssh/sshd_config
Banner /etc/ssh/dynamic_banner.sh

Then create an executable script:

#!/bin/bash
echo "=== SSH Server ==="
echo "Current time: $(date)"
echo "Connected from: $SSH_CLIENT"

When implementing dynamic content:

  • Ensure scripts are owned by root
  • Set proper permissions (755 for dirs, 644 for files)
  • Validate all command outputs
  • Consider using static information where possible

For most systems, the update-motd method provides:

  • Better performance than cron-based solutions
  • More maintainable script organization
  • Built-in framework on Debian/Ubuntu