2

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

ANSWER

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
6
  • Try using the full path to the top command /usr/bin/top instead of top
    – Parto
    Apr 10, 2019 at 15:03
  • @Parto Thanks for your answer, but not working
    – Malus Jan
    Apr 10, 2019 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, 2019 at 15:19
  • 1
    The (B[m sequences are formatting characters - if you want to avoid them, run top in batch mode (top -b) Apr 10, 2019 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, 2019 at 15:52

1 Answer 1

3

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
/usr/bin/top
/bin/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
4
  • 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, 2019 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, 2019 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, 2019 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, 2019 at 17:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .