LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   How do I make a cron job run "every two weeks"? (https://www.linuxquestions.org/questions/linux-newbie-8/how-do-i-make-a-cron-job-run-every-two-weeks-402888/)

Seventh 01-13-2006 08:57 AM

How do I make a cron job run "every two weeks"?
 
Greetings all.

I'm looking to make a cron job that will purge the contents of a handful of folders the first and fifteenth of each month -

Basically my folder setup is:

/etc/stuff/1
/etc/stuff/2
/etc/stuff/3
/etc/stuff/4
/etc/stuff/5

I want to keep the 1/2/3/4/5 folders, but any files/subfolders under them I want to delete automatically every other Tuesday. I think the basic bash would just be something like

cd /etc/stuff/1
rm -rf *
cd /etc/stuff 2
rm -rf *

(etc)

But I'm not sure if *.* is the proper syntax, and very much unsure how to set it to run on those days.

Thanks very much in advance. :)

haertig 01-13-2006 09:12 AM

To see how to setup your cron, run "man -S5 crontab" to see the syntax options.

For your remove commands:
Code:

cd /etc/stuff/1
rm -rf *.*

...this can be dangerous. What if your cd command failed? Like if the directory had inadvertantly been removed prior to cron running this command? You would recursively remove stuff that you didn't intend to depending on what your old working directory was. Could be disasterous. Better to fully specify the target removal to the command, like this::
Code:

rm -rf /directory/subdirectory

homey 01-13-2006 09:47 AM

Be careful with the rm -rf , you may want to test it by using ls first.
Code:


#!/bin/bash

for i in $(seq 1 4) ; do

find /etc/stuff/$i/* -exec rm -rf {} \; 2> /dev/null

done


minute hour day month dayofweek /full/path/to/script

an asterisk (*) can be used to specify all valid values.

dayofweek — any integer from 0 to 7, where 0 or 7 represents Sunday

For example: run a script the first day of every month at 4:10AM
10 4 1 * * /root/scripts/backup.sh

Code:

This one should work for you...

For example: run a script every other tuesday at 4:10AM
10 4 1 * 2/2 /path/to/someplace/myscript.sh


haertig 01-13-2006 10:06 AM

Code:

rm -rf /directory/subdirectory
One other tip related to what I said above. If you expect something to be a directory, not a file, it's even better to explicitly say so on the command line. Add a trailing slash to the target remove path to force it to be interpreted as a directory. Like this:
Code:

rm -rf /directory/subdirectory/

Seventh 01-13-2006 10:08 AM

Great advice so quick - thank you very much guys, I really appreciate it. :)

My folders aren't actually named 1/2/3/4/5, they're user initials (I probably should have been clearer).


Would the following work, where aa, bb, cc = the user's initials?

Code:

#!/bin/bash

find /etc/stuff/aa/* -exec rm -rf {} \; 2> /dev/null
find /etc/stuff/bb/* -exec rm -rf {} \; 2> /dev/null
find /etc/stuff/cc/* -exec rm -rf {} \; 2> /dev/null
find /etc/stuff/dd/* -exec rm -rf {} \; 2> /dev/null

Or is there another part of that loop I'd need to add?

Also, if I just wanted to do it monthly, simply dropping this script into cron.monthly as something like cleanup.sh would do the trick, correct?

Trying to take baby steps so I don't inadvertantly delete anything. Thanks again1

Seventh 01-13-2006 10:11 AM

Quote:

Originally Posted by haertig
Code:

rm -rf /directory/subdirectory
One other tip related to what I said above. If you expect something to be a directory, not a file, it's even better to explicitly say so on the command line. Add a trailing slash to the target remove path to force it to be interpreted as a directory. Like this:
Code:

rm -rf /directory/subdirectory/

In this case my exact path is /etc/stuff/cq. I need to maintain the /cq/ folder itself, just delete all files and folders in it. Would I be better off doing:

rm -rf /etc/stuff/cq/*

Or am I way off base and that isn't even close? :D

(I've always said that it's fine to ask silly questions as long as you only ask 'em once, I hope you guys don't mind me being such a novice here). :)

timmeke 01-13-2006 10:13 AM

Or simply use:
rm -rf /etc/stuff/[12345]/*
or something like that.

homey, you're close, but I think you can't use the "/2" syntax when you're not specifying a range (multiple
values).
And "2" is just 1 value, not a range. Think of "a-b/2" as "from a to b in steps of 2".
So, using "2/2" as day of the week would probably run every Tuesday or not at all.

Using a combination of day of month and day of week doesn't work either, since there is the job runs when either of the two entries is matched ("or" relationship, not "and"). At least, that's so for my Vixie cron.
Other implementations of cron (ATT cron, BSD cron) may work differently.
Look carefully at the man pages, is my advice...

One alternative, would be to run the script every Tuesday, but to make it check (via a toggle) if it should
be run or not.
So: first Tuesday => script runs and sets the toggle (ie via a file) so that it knows that it shouldn't run
on next Tuesday.
2nd Tuesday => script runs again, but sees the toggle, clears it, and stops immediately after, without
performing the "rm -rf" task.
3rd Tuesday, no toggle, so same as first Tuesday...
Running a script every Tuesday is easy:
0 2 * * 2 path/to/your_script

I believe the easiest way of implementing a toggle like that is to store a file, ie in /var/run.
You'll need to have write permission on the directory where the toggle file is stored.
The script can then simply check (in Bash):
if [[ -f /var/run/toggle_file ]]; then
#toggle exists
rm -f /var/run/toggle_file
exit;
else
touch /var/run/toggle_file #stores the empty toggle file
#now do the clean up commands
exit;

homey 01-13-2006 10:38 AM

If you have a lot of names, it may be good to put them in /home/names.txt ...
Code:

#!/bin/bash

names=/home/names.txt
for i in $(cat $names); do

find /home/etc/stuff/$i/* -exec rm -rf {} \; 2> /dev/null

done

If you have a few names, this may work...
Code:

#!/bin/bash

name="aa bb cc dd"
for i in $name ; do

find /home/etc/stuff/$i/* -exec rm -rf {} \; 2> /dev/null

done


Seventh 01-13-2006 10:42 AM

You guys are awesome, thank you. :D


Code:

#!/bin/bash

name="aa bb cc dd"
for i in $name ; do

find /home/etc/stuff/$i/* -exec rm -rf {} \; 2> /dev/null

done

So that, saved as cleanup.sh cron.monthly, should monthly purge everything, right?

homey 01-13-2006 10:51 AM

Don't forget to chmod +x myscript.sh

I put a line in /etc/crontab but you can put the script into the /etc/cron.monthly if you prefer.

For example: run a script every other tuesday at 4:10AM
10 4 * * 2/2 /path/to/someplace/myscript.sh

haertig 01-13-2006 10:54 AM

Quote:

Originally Posted by Seventh
rm -rf /etc/stuff/cq/*

This will work. If you also have hidden files in these directories (hidden files begin with a dot), you should add a command to get those explicitly, e.g.:
Code:

rm -rf /etc/stuff/cq/*
rm -rf /etc/stuff/cg/.*

An standalone * wildcard will not match a filename that begins with a dot.

Seventh 01-13-2006 10:59 AM

Thank you very much everyone. :)

merchtemeagle 01-13-2006 11:55 AM

Quote:

Originally Posted by haertig
To see how to setup your cron, run "man -S5 crontab" to see the syntax options.

For your remove commands:
Code:

cd /etc/stuff/1
rm -rf *.*

...this can be dangerous. What if your cd command failed? Like if the directory had inadvertantly been removed prior to cron running this command? You would recursively remove stuff that you didn't intend to depending on what your old working directory was. Could be disasterous. Better to fully specify the target removal to the command, like this::
Code:

rm -rf /directory/subdirectory

Or:

Code:

cd /etc/stuff/1 && rm -rf *


All times are GMT -5. The time now is 09:36 AM.