We help IT Professionals succeed at work.

Need help writing and scheduleing a bash script on Unix

electricd7
electricd7 used Ask the Experts™
on
Hello,

I need to write a bash script that will do a find on files, delete each file it finds, wait a bit, then do the next.  All this while logging to a file.  I have the following script which I thought would work, but when I run it, I get:

#:/pool1/comp1-backupexec$ ./DeleteExpired.sh
/volumes/pool1/comp1-backupexec/DeleteExpired.sh: line 2: syntax error near unexp'cted token `do
'volumes/pool1/comp1-backupexec/DeleteExpired.sh: line 2: `do

Now I know the "find" syntax works, but some sort of problem with the "do" I guess.  I am just not very good at bash :)  Once i have this all up and working, I would like to schedule it to run weekly.  Thanks!
for i in `find /pool1/comp1-backupexec -mtime +21 -name "B2D*"`
	do

		rm $i

		sleep 100

		echo "$i" >> /pool1/comp1-backupexec/deletionlog.log

done

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Most Valuable Expert 2013
Top Expert 2013

Commented:
Did you perhaps write the script under Windows to then copy-and-paste it to Unix?

Or did you transfer it via FTP in ASCII instead of BINARY mode?

It seems quite as if there was some sort of invalid character in front of "do" or at the end of line 1.

If I'm guessing right write the script directly under Unix using "vi" or the like.

wmp

Author

Commented:
I did write it in windows first, then copy it via SMB to the unix machine.  I have since used vi on the nix box and re-written it from scratch, but get the same error?
Most Valuable Expert 2013
Top Expert 2013

Commented:
Seems there is a carriage-return immediately following "do"!

Check with "cat -v  ./DeleteExpired.sh"

Do you see "^M" after "do"?

Author

Commented:
Here is the output from that:

for i in 'find /pool1/uhhg-backupexec -mtime +21 -name "B2D*"'^M
do^M
                rm $1^M
                sleep 100^M
                echo "$1" >> /pool1/uhhg-backupexec/deletionlog.log^M
done^M
Most Valuable Expert 2013
Top Expert 2013

Commented:
So you did something wron when rewriting!

Open the file in vi under Unix, position the cursor under the "M" of each of the "^M" characters and press "x"

Author

Commented:
OK, but I don't see the "^M" while in vi?  i just backed all the spaces and tabs out of the script in vi, and then reran with same results.  All I am doing in vi is typing the first line, hitting return, typeing the next line hitting return, etc.  Should all of this exist on a single line?
Most Valuable Expert 2013
Top Expert 2013

Commented:
Must be some strange setting in your terminal emulator. Which one do you use?

Anyway, this should help (from command line):

tr -d "\r" < scriptname > scriptname.new

Author

Commented:
OK, ran this command

tr -d "r" DeleteExpired.sh DeleteExpired.sh.new

Just went back to prompt and did not create a new file...maybe its this version of unix or something??
Most Valuable Expert 2013
Top Expert 2013

Commented:
Didn't you see the "<" and ">" characters in my comment? And it's "\r" (backslash r) not "r" alone!

Author

Commented:
sorry I did have the \r but didn't realize the < > were needed...i thought you were using those to show a variable :)

I have now run this command:

 tr -d "\r" < DeleteExpired.sh > deleteexpired.sh

when it went back to prompt, i can do and ls -l and see the new deleteexpired.sh file but it is 0 bytes and "vi deleteexpired.sh" does in fact show that the file is empty.
Most Valuable Expert 2013
Top Expert 2013

Commented:
Strange!

Do you get any output on the screen with this:

 tr -d "\r" < DeleteExpired.sh

Author

Commented:
Nevermind...i just started a new session of vi and created the file again and now it executes withought the error "./ deleteexpired.sh" though it doesn't appear to actually be doing anything...
Most Valuable Expert 2013
Top Expert 2013

Commented:
The script will not write anything to the terminal,
and there will be a delay of 100 seconds between each of the "rm" actions.

Check /pool1/comp1-backupexec/deletionlog.log

Author

Commented:
Yea sorry, thats what I meant...the file deletionlog.log didn't exist after 5 or so minutes, so I created it, and it still sits at 0bytes.  ps ax shows nothing related to the script.
Most Valuable Expert 2013
Top Expert 2013

Commented:
Did you start the right script (not the empty one from tr above)?
Most Valuable Expert 2013
Top Expert 2013

Commented:
Or maybe the find command doesn't give any results?

Author

Commented:
Ok after some tweaking, I have the following code which now returns a different error so we are getting somewhere:

rm: invalid option -- m
Try `rm --help' for more information.

Its like the value for "i" isn't coming back as what it expects.  I can verify that the find line ran alone returns a long list of files.


#!/bin/bash
for i in 'find /volumes/pool1/uhhg-backupexec -mtime +21 -name "B2D*"'
do
rm $i
sleep 100
echo "$i" >> /volumes/pool1/uhhg-backupexec/deletionlog.log
done

Open in new window

Author

Commented:
Yea i just put the echo line above the rm line and found that the value of i is:

find /volumes/pool1/uhhg-backupexec -mtime +21 -name "B2D*"

not sure how i get the value of i to be = the result from the find?
Most Valuable Expert 2013
Top Expert 2013
Commented:
You used the wrong "ticks"!

To execute a command and store the result you must either use backticks  `  `  
or (very much better!!) the $(  )  notation:

for i in $(find /volumes/pool1/uhhg-backupexec -mtime +21 -name "B2D*")

Old, (often mistakable) notation:

for i in `find /volumes/pool1/uhhg-backupexec -mtime +21 -name "B2D*"`

Author

Commented:
bingo! that is now working.  Now how do I schedule that to run?  That is the last step...i guess if its still running at time of next schedule i don't want it to re-run either
Most Valuable Expert 2013
Top Expert 2013

Commented:
Congrats!

Now log in to your Unix box as the user who shall run the script (root?) and issue

crontab -e

An editor (probably vi) will open the user's crontab (or an empty table if there is none).

To run the script every Sunday on 2:00 AM add the line:

0 2 * * 0 /volumes/pool1/comp1-backupexec/DeleteExpired.sh >/dev/null 2>&1

Save the file and you're done. The "crontab" utility will restart the scheduler daemon "cron" automatically, so the new setting can take effect.

wmp

Author

Commented:
K that is easy enough...will the job restart if its running the next time it is scheduled?  the only reason that is a problem is because the script writes output to a log file, and when the job runs again it overwrites the log instead of appending to it...just dont want to lose the log

Author

Commented:
Yea just verified that if the cron job is still running at the next scheduled interval, it starts a second identical job of the script.  This will not work.  How do I kill it before running it again??!
Most Valuable Expert 2013
Top Expert 2013

Commented:
Yes, the job will restart regardless of whether it's still running or not.

The logfile will not be overwritten, because you use ">>" and not ">", but will get messed up nonetheless.

To avoid this you could add a datestamp like YYYYMMDD to it:

Add to the script immediately above the "for" line (i. e. before the loop starts):

LOGFILE=/pool1/comp1-backupexec/deletionlog.$(date "+%Y%m%d").log

(Please note that "Y" is uppercase, "m" and "d" are lowercase.)

and change line 6 to:

echo "$i" >> $LOGFILE

This will create on next Sunday:

/pool1/comp1-backupexec/deletionlog.20110807.log
and
/pool1/comp1-backupexec/deletionlog.20110814.log
one week later etc.




Author

Commented:
thanks...heres your points!