11

PLEASE NOTE: I have read all the similar questions re. cron, paths, env variables and so on, but have found none that offer solutions to my particular problem.


I have a script that makes some MySQL dumps and then deletes old ones like this:

/usr/bin/find "/home/bkp/dbdump" -name "*.gz" -mtime +5 -delete

(above command has been modified from my original command by suggestions from comments)

However, the files are never deleted when cron runs this script. The cron user is root.

Debugging notes

  • If I manually run the script in which the command appears, it deletes them as expected.

  • If I run the above find command on its own from the command line as root, it deletes them as expected (and with -print it returns a list of files older than 5 days as expected)

  • I have also added an explicit path statement to root's crontab, but
    that doesn't change anything.

  • Cron sends no error, and if I pipe the find operation to a log file,
    that comes up empty or is not created at all.

  • I'm using Ubuntu server 14.04.03 LTS.

7
  • I would avoid wildcard expansion (e.g.*.gz) in path. cron might interpret as *.gz, not expanding all gz files.
    – Archemar
    Dec 13, 2015 at 10:11
  • What output do you get if you run the job without an action /usr/bin/find /home/bkp/dbdump/*.gz -mtime +5
    – user9517
    Dec 13, 2015 at 10:54
  • @Archemar Why wouldn't the wildcard get expanded? cron commands are run through the shell, and the shell expands wildcards.
    – Barmar
    Dec 16, 2015 at 7:02
  • cron should send email with output and error messages. Do you get any such email from this job?
    – Barmar
    Dec 16, 2015 at 7:04
  • @Iain it works as expected. Dec 18, 2015 at 5:44

4 Answers 4

6

The problem is that crontab doesn't have $PATH set when it runs. You can actually provide it with a path by adding this to the top of the file opened via crontab -e:

PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

(or whatever PATH you'd prefer to use). This means you can avoid specifying the full paths to commands, directly from cron.

There are multiple problems with your original command. You're basically asking the shell to do the wildcard expansion, rather than find. Secondly, you're not providing a full path for rm; use /bin/rm or /usr/bin/rm, wherever it's located on your system (see which rm).

The first argument for find is the "location to search", and then you specify the "search query" with the various -<option>s. So, the proper format of the command you want to run is:

find "/home/bkp/dbdump" -name "*.gz" -mtime +5 -exec rm -f {} \;

or

find "/home/bkp/dbdump" -name "*.gz" -mtime +5 delete

If you don't specify the PATH definition like above, use:

/usr/bin/find "/home/bkp/dbdump" -name "*.gz" -mtime +5 -exec /bin/rm -f {} \;

or

/usr/bin/find "/home/bkp/dbdump" -name "*.gz" -mtime +5 delete
2
  • 1
    It should have $PATH set, but it will be the system's default. This will include /usr/bin and /bin, so it should be able to find the rm command.
    – Barmar
    Dec 16, 2015 at 7:01
  • So I tried putting $PATH in the crontab (although as mentioned elsewhere it would probably default to the system path if not stated), and made sure everything had full paths. I also used -name "*.gz" instead of a wildcard on the find path. But nothing happens. The command just doesn't seem to run and there are no errors thrown. Dec 19, 2015 at 10:32
3

Try this instead

find /home/bkp/dbdump -type f -name '*.gz' -mtime +5 -delete
3
  • Why would you redirect stderr to a file? By default it will be send by email if there was any output.
    – kasperd
    Dec 13, 2015 at 10:04
  • Yes it is true that by default is sending any email to the spooler MAIL of the user and can be read using mail.
    – shad0VV
    Dec 13, 2015 at 10:13
  • 1
    To get the same effect as the original command you would need to add -maxdepth 1. Dec 14, 2015 at 7:40
0

If I invoke the find command directly from root's crontab and not as part of the script, then it works.

The script in question uses csh. I believe that root's cron environment on Ubuntu will be using /bin/bash (or /bin/dash?). Perhaps this conflicts in some way with how the find command was running.

Either way, the main issue it solved, albeit somewhat inelegantly.

-2

Dear Crontab uses sh shell instead of bash by default. you can use /dev/null to empty files. check below script. it will help.

#!/bin/bash
tar=$(ls -lt /backup/manual | grep ^d | tail -n1 | awk '{print $NF}')
for i in $(find /backup/manual/"$tar" -type f ) 
 do cat /dev/null > "$i" 
done > /dev/null 2>&1 && mv /backup/manual/"$tar" /tmp/

explanation: kindly use for loop to reach all files from targeted folders and make them null and move to /tmp directory at last

You must log in to answer this question.

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