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


2 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