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
- Always use
-b
(batch mode) with top in cron - Explicitly set TERM=dumb in your script
- Consider using /proc statistics for simpler metrics
- 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