Fixing “top: failed tty get” and Terminal Issues in Cron Jobs for CPU Monitoring


10 views

When trying to execute top commands in cron jobs for server monitoring, many system administrators encounter two common errors:

  • top: failed tty get when running without batch mode
  • 'dumb': unknown terminal type when using batch mode (-b flag)

Cron jobs run in a non-interactive environment without a proper terminal emulation. Unlike your SSH session which has full terminal capabilities, cron:

  • Lacks proper TERM environment variable
  • Has no attached TTY device
  • Runs with minimal environment variables

Here's a robust approach to implement CPU monitoring via cron:

#!/bin/bash
# Set proper terminal environment
export TERM=dumb

# Capture CPU usage for specific user
top -b -n 1 -u www-data > /tmp/cpu_usage.log

# Alternative using /proc (no terminal dependencies)
grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage "%"}' > /tmp/cpu_total.log

For systems missing the dumb terminal definition:

# Create symlink for terminal definition
sudo mkdir -p /usr/share/terminfo/d
sudo ln -s /lib/terminfo/d/dumb /usr/share/terminfo/d/dumb

# Alternative locations to check
# /usr/lib/terminfo/d/dumb
# /etc/terminfo/d/dumb
# /lib64/terminfo/d/dumb
  1. Always use -b (batch mode) with top in cron
  2. Explicitly set TERM=dumb in your script
  3. Consider using /proc statistics for simpler metrics
  4. For advanced monitoring, use dedicated tools like sysstat
#!/bin/bash
# CPU monitoring wrapper for cron

# Environment setup
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
export TERM=dumb

# Threshold in percentage
THRESHOLD=90

# Get CPU usage
CPU_USAGE=$(top -bn 2 -d 0.5 | grep '^%Cpu' | tail -n 1 | awk '{print $2}' | cut -d. -f1)

# Alert if threshold exceeded
if [ "$CPU_USAGE" -ge "$THRESHOLD" ]; then
    echo "High CPU usage detected: ${CPU_USAGE}%" | mail -s "CPU Alert" admin@example.com
fi
  • Test your script with env -i /path/to/script to simulate cron's environment
  • Capture stderr by adding 2>&1 to your cron command
  • Check /var/log/syslog for cron job errors

When running system monitoring scripts via cron, you might encounter terminal-related errors that don't appear when executing the same commands interactively. A common scenario is when trying to monitor CPU usage with top:

top -c -n 1 -u www-data > /tmp/kill-cpu

This works fine in your shell but fails in cron with:

top: failed tty get

Cron jobs run in a non-interactive environment without a proper terminal (tty) attached. When you try to run top in this context, it fails because:

  • It expects a terminal for display control
  • Default terminal settings may be missing

The immediate fix is to use top's batch mode with -b flag:

top -b -n 1 -u www-data > /tmp/kill-cpu

But you might then encounter:

'dumb': unknown terminal type

This occurs because cron doesn't set the TERM environment variable. You have several solutions:

Option 1: Set TERM in your cron job

TERM=linux top -b -n 1 -u www-data > /tmp/kill-cpu

Option 2: Create missing terminfo links

If your system is missing terminfo definitions:

mkdir -p /usr/share/terminfo/d
ln -s /lib/terminfo/d/dumb /usr/share/terminfo/d/dumb

For more reliable cron monitoring, consider these alternatives:

Using mpstat

mpstat -P ALL 1 1

Using sar

sar -u 1 1

Using /proc/stat

For a lightweight solution:

grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage "%"}'
  • Always specify full paths to binaries
  • Set required environment variables explicitly
  • Consider using wrapper scripts with proper environment setup
  • Log errors for debugging

Example wrapper script:

#!/bin/bash
export TERM=linux
/path/to/top -b -n 1 -u www-data > /tmp/kill-cpu 2>/tmp/cron-error.log