[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 400
  • Last Modified:

Please help with Linux script to remove log files

I have created the below Linux script to cycle through and remove log files. But need some assistance in getting it to work. I keep getting the following error, please help.

./log_tidy.sh: line 33: 1: ambiguous redirect
./log_tidy.sh: line 38: syntax error near unexpected token `done'
./log_tidy.sh: line 38: `done'


#Created by WL 05-10-2011

#/usr/bin/ksh

#Set log dir's for log file removal (retain 7 days)
logDir[1]="/someDir/"
logDir[2]=""
logDir[3]=""
logDir[4]=""
logDir[5]=""
logDir[6]=""
logDir[7]=""
logDir[8]=""
logDir[9]=""
logDir[10]=""
logDir[11]=""
logDir[12]=""
logDir[13]=""
logDir[14]=""
logDir[15]=""
logDir[16]=""
logDir[17]=""
logDir[18]=""

#Create loop to cycle through log directories and remove unnecessary files
for i in 1 #  2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
do

cd ${logDir[$i]}

        echo "Currently removing files in: "${logDir[$i]}
        #Find file with .log extension, of type file, and modified prior last 7 days. Check if file is open and if it is clear contents.
        find ./ -name "*.log" -type f | >$file; done

        #Find file with .log extension, of type file, and modified prior last 7 days. Check if file is open and if it isn't remove it.
        find ./ -name "*.log.*" -type f -exec rm {} \;

done

Open in new window

0
Lico_w
Asked:
Lico_w
1 Solution
 
tel2Commented:
Haven't got time to look at the logic, Lico, but here are my comments on the error messages, etc:

./log_tidy.sh: line 33: 1: ambiguous redirect
Remove the "|" from line 33.

./log_tidy.sh: line 38: syntax error near unexpected token `done'
./log_tidy.sh: line 38: `done'

Remove the "; done" from line 33 (not from line 38).

#Created by WL 05-10-2011
#/usr/bin/ksh

Swap these lines around, and put a "!" before the "/usr..." like this:
#!/usr/bin/ksh
#Created by WL 05-10-2011
0
 
Sikhumbuzo NtsadaCommented:
0
 
Lico_wAuthor Commented:
Thanks for that, I'm now getting this error though:

./log_tidy.sh: line 33: $file: ambiguous redirect

Line 33 now looks like this:

find ./ -name "*.log" -type f >$file;
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
savoneCommented:
Your not telling the script what $file is.

That variable is empty.

For example:


[root@fenrir TEMP]# find ./ -name "*.log" -type f >$file;
-bash: $file: ambiguous redirect

ambiguous redirect means it does not know where to redirect output.

If I tell the machine what the variable $file means then it does not complain. :)

[root@fenrir TEMP]# file=/var/tmp/test1; find ./ -name "*.log" -type f >$file;
[root@fenrir TEMP]#
0
 
savoneCommented:
Nowhere in your script is $file defined.

Either creates a line defining the variable like this:

file=/var/tmp/my_output_file

or just use a filename in the redirect line like so:

find ./ -name "*.log" -type f > /var/tmp/my_output_file

0
 
Lico_wAuthor Commented:
ok well what I am trying to do is clear the contents of the file it finds. I'm a bit of a newby to be honest (clearly!).

So when it goes through the for loop I need it to finds fles of the specified type and then clear the contents. Can someone give me some pointers on what I need to change?
0
 
savoneCommented:
Well I really stink with bash, and I am sure there is probably a cleaner way of doing it, but this will work:

REPLACE THIS:
find ./ -name "*.log" -type f | >$file; done

WITH THIS:
cat /dev/null > `find . -name "*.txt" -type f`

0
 
Lico_wAuthor Commented:
Ok tried that (except I used *.log instead of *.txt and received the following error:

./log_tidy.sh: line 34: `find . -name "*.log" -type f`: ambiguous redirect
0
 
savoneCommented:
Ok so I found multiple problems in your script.

First of all your using a shebang that is for korn shell, I dont know if you meant to do this or not, but I would prefer bash.  Also the shebang MUST be the first line of the script.

You have:
#Created by WL 05-10-2011

#/usr/bin/ksh

It should be:
#!/bin/bash

# Created by WL 05-10-2011



Also reading the comments in your script I dont think it is going to do what you expect.

For example your comment reads:
#Find file with .log extension, of type file, and modified prior last 7 days. Check if file is open and if it is clear contents.

Then the following line does not do all of those things:
find ./ -name "*.log" -type f | >$file; done

You would need to use mtime (modified time) to check if it is 7 days or older.
find . -mtime +7 -name "*.log" -type f

And to check if it is open or not can not be done within find (that I know of), you might have to use an if statement for that.


So the code snippet attached solves your redirect issue, but be careful because it will CLEAR ALL YOUR LOGS!!!!
**** PLEASE READ ABOVE LINE ****



#!/bin/bash

#Set log dir's for log file removal (retain 7 days)
logDir[1]="/var/tmp/test"
logDir[2]=""
logDir[3]=""
logDir[4]=""
logDir[5]=""
logDir[6]=""
logDir[7]=""
logDir[8]=""
logDir[9]=""
logDir[10]=""
logDir[11]=""
logDir[12]=""
logDir[13]=""
logDir[14]=""
logDir[15]=""
logDir[16]=""
logDir[17]=""
logDir[18]=""

#Create loop to cycle through log directories and remove unnecessary files
for i in 1 #  2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
do

cd ${logDir[$i]}

        echo "Currently removing files in: "${logDir[$i]}
        #Find file with .log extension, of type file, and modified prior last 7 days. Check if file is open and if it is clear contents.
        # find ./  -name "*.log" -type f | >$file; done
	for x in `find . -mtime +7 -name "*.log" -type f`
	do cat /dev/null > $x
	done

        #Find file with .log extension, of type file, and modified prior last 7 days. Check if file is open and if it isn't remove it.
        find ./ -name "*.log.*" -type f -exec rm {} \;

done

Open in new window

0
 
savoneCommented:
I am sorry I meant to say the above code will clear all your logs older than 7 days old.

I would recommend testing all your code in a non production environment. :)

Hope this helps!
0
 
Lico_wAuthor Commented:
Works perfectly cheers! Although I removed the -mtime option (and updated my comments!) as this was no longer required.

Can you just do me one last favour and explain how this part works:

for x in `find . -name "*.log" -type f`
      do cat /dev/null > $x

By encapsulating it in apostrophes does the result of the whole command become $x?
0
 
savoneCommented:
They are backticks not apostrophes, backticks are on the same key as the tilde.

So by using backticks are you putting the ouput of the command in backticks into the variable.

for example:
for x in `find . -name "*.log" -type f`

Here are making the output of `find . -name "*.log" -type f` equal the variable $x.

backticks = run command and use output
single quotes = take string literally, do not interpret special characters or variables (so $x would mean $x and it would not be seen as a variable)

More info here:
http://www.howtogeek.com/howto/29980/whats-the-difference-between-single-and-double-quotes-in-the-bash-shell/

0
 
savoneCommented:
Sorry, I am not sure if you need me to explain the whole thing, here goes...

for x in `find . -name "*.log" -type f`
      do cat /dev/null > $x

Basically what these two lines say are, loop through the out of `find . -name "*.log" -type f` and redirect /dev/null into each iteration of the loop.

More about /dev/null here:
http://en.wikipedia.org/wiki//dev/null


0
 
TintinCommented:
No need for an ugly array.  Shell scripts very, very rarely require arrays.

Much better written as
#!/bin/ksh
logDir=$(cat <<EOF
/somedir1
/somedir2
/somedir3
EOF
)

for dir in $logDir
do
  cd $dir
  echo "Currently clearing files in: $dir"

  for file in $(find . -name "*.log" -type f)
  do
    >$file
  done

done

Open in new window

0

Featured Post

Nothing ever in the clear!

This technical paper will help you implement VMware’s VM encryption as well as implement Veeam encryption which together will achieve the nothing ever in the clear goal. If a bad guy steals VMs, backups or traffic they get nothing.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now