I'm using Ubuntu 16.04 and I created a sh file.

cd /home/malus
echo "______________________________________________________________________" >> /home/malus/top.txt 
date >> /home/malus/top.txt 
sudo top n 1 o %MEM u mysql | grep mysql >> /home/malus/top.txt

I want to save the information of MySQL into a file (top.txt) + date + seperator

When I run the sh file all is correct and the output file contains 3 lines.

But, when I let crontab to run the script the output file does not contain the top output and instead I have an empty line (I have seperator + date but not top output).

For crontab I used this command:

sudo crontab -e

And the contents are:

00 * * * * /home/malus/top.sh
15 * * * * /home/malus/top.sh
30 * * * * /home/malus/top.sh
45 * * * * /home/malus/top.sh

Edited Part:

The output when I run the script file directly (./top.sh), as you see there are some bizarre characters (in Notpad++ they are as ESC)

Wed Apr 10 11:24:33 EDT 2019
(B[m  636 mysql     20   0 3681720 1.233g   4236 S   0.0 63.3 113:35.71 mysqld                                                                           (B[m[39;49m[K

The output of crontab, as you see there is no output for top command:

Wed Apr 10 11:30:01 EDT 2019


I did these changing according to steeldriver and terdon (Thanks to you both)

The script file:

echo "______________________________________________________________________" >> /home/malus/top.txt 
date >> /home/malus/top.txt 
sudo top n 2 -b o %MEM u mysql | grep mysql >> /home/malus/top.txt

For running the crontab as root:

sudo crontab -e

The crontab contents:

00 * * * * /home/malus/top.sh 2>>/home/malus/top.err
15 * * * * /home/malus/top.sh 2>>/home/malus/top.err
30 * * * * /home/malus/top.sh 2>>/home/malus/top.err
45 * * * * /home/malus/top.sh 2>>/home/malus/top.err
  • Try using the full path to the top command /usr/bin/top instead of top – Parto Apr 10 '19 at 15:03
  • @Parto Thanks for your answer, but not working – Malus Jan Apr 10 '19 at 15:15
  • Please edit your question and show us the output of top n 1 o %MEM u mysql | grep mysql. – terdon Apr 10 '19 at 15:19
  • 1
    The (B[m sequences are formatting characters - if you want to avoid them, run top in batch mode (top -b) – steeldriver Apr 10 '19 at 15:46
  • 1
    @steeldriver that's actually the problem, almost certainly. You need the -b. Malus, does it work if you use top b n 1 o %MEM u mysql | grep mysql? Also, you probably want n 2 and not n 1. top -n 1 doesn't show the right output (it's the value since boot, not the current one). – terdon Apr 10 '19 at 15:52

You have added this to root's crontab (you ran sudo crontab -e), so why are you running top with sudo? Everything in that crontab will be run as root. More importantly, you should never run a command with sudo unless that command needs to be run as root. The top command never needs root access, every user sees the same output, so the sudo there is pointless. The cd is also pointless, there's no need to move into the /home/malus directory. So change your script to:

echo "______________________________________________________________________" >> /home/malus/top.txt 
date >> /home/malus/top.txt 
top n 1 o %MEM u mysql | grep mysql >> /home/malus/top.txt

That said, I don't see any other problem in your file. The top command is in /usr/bin and /usr/bin is in cron's PATH, so you don't need a full path for it. What is happening is probably that the command has no output.

For example, if I run your top on a system where the mysql user is running something, I get:

$ top n 1 o %MEM u mysql | grep mysql
 2379 mysql     20   0 28.915g 5.612g  13516 S   0.0  4.3   2038:41 mysqld         

However, if the mysql user isn't running anything, there is no output since the grep mysql won't match:

$ top n 1 o %MEM u mysql | grep mysql 

So, if the date is being correctly added to /home/malus/top.txt, then the lack of output from top just means the mysql user wasn't running anything when the crontab was run.

The only other explanation is that you have your top and/or grep commands in a non-standard location. If so, run type top and type grep to see where they are:

$ which top grep

And then use those paths:

echo "______________________________________________________________________" >> /home/malus/top.txt 
date >> /home/malus/top.txt 
/usr/bin/top n 1 o %MEM u mysql | /bin/grep mysql >> /home/malus/top.txt

But that's really unlikely unless you have moved these and they aren't in /usr/bin or /bin.

Finally, to debug it further, change the crontab so that it also keeps the error output:

00 * * * * /home/malus/top.sh 2>>/home/malus/top.err
15 * * * * /home/malus/top.sh 2>>/home/malus/top.err
30 * * * * /home/malus/top.sh 2>>/home/malus/top.err
45 * * * * /home/malus/top.sh 2>>/home/malus/top.err

Then see if anything is written to /home/malus/top.err.

The error you had, TERM environment variable not set. is because the environment variable $TERM isn't set in the cron's shell session, and top need that to know what kind of output to produce:

$ unset TERM
$ top
TERM environment variable not set.

A simple workaround, therefore, is to set it in your script:

echo "______________________________________________________________________" >> /home/malus/top.txt 
date >> /home/malus/top.txt 
TERM=xterm top n 1 o %MEM u mysql | grep mysql >> /home/malus/top.txt
  • Thanks @terdon for explaining in detail. I did all the modifications that you asked me, unfortunately did not work. I can explain more here: 1- If I run the top.sh with or without sudo it works. but when crontab run it does not work. which is why I add also sudo for crontab and I had tested before without sudo top (just top) 2- As you said -b removed the characters, thanks 3-I found an error message as output: TERM environment variable not set. 4-I'm pretty sure that mysql is running, I want to run the crontab for checking the memory that mysql take. – Malus Jan Apr 10 '19 at 16:26
  • @MalusJan please add all of these details to your question so everyone can see them. Also, make sure to use n 2, otherwise the memory results will be wrong. But do you still have the same issue with the top output not in the file even when using b? – terdon Apr 10 '19 at 16:48
  • I'll modify the question. In the error file (top.err) there is an error message: TERM environment variable not set – Malus Jan Apr 10 '19 at 16:52
  • @MalusJan Ah! Yes, that is from top and it means it cannot run! Of course, there's no TERM variable set in the cron environment! Does it work if you add TERM=xterm to your script? Alternatively, just don't use top (it isn't the right tool for this anyway), use ps -o %mem | grep [m]ysql – terdon Apr 10 '19 at 17:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.