Help with a rotate log script

Hi all,

Am trying to write my own log rotate script. Curremtly, what I have is as below:

 
#!/bin/ksh
file_to_rotate=${1}
x=${2}
while [[ ${x} -ge 1 ]]
do
   let curr=${x}
   let prev=${x}-1
   if [[ $x -eq 1 ]] ; then
      #echo "cp -p ${file_to_rotate} ${file_to_rotate}.${curr}"
      cp -p ${file_to_rotate} ${file_to_rotate}.${curr}
      let x=${x}-1
   else
      if [[ ! -f ${file_to_rotate}.${prev} ]] ; then
         let x=${x}-1
      else
         #echo "cp -p ${file_to_rotate}.${prev} ${file_to_rotate}.${curr}"
         cp -p ${file_to_rotate}.${prev} ${file_to_rotate}.${curr}
         let x=${x}-1
      fi
   fi
done

I run the script as ./x.ksh x.log 10 and it works like how I want it to. Unfortunately, sometimes, I have some files missing like and my number of rotated log files turns out as below:

[tmp]$ ls -ltr
total 36
-rw-r--r-- 1 oracle oinstall 198 Sep  7 00:38 x.log.9
-rw-r--r-- 1 oracle oinstall 198 Sep  7 00:38 x.log.8
-rw-r--r-- 1 oracle oinstall 198 Sep  7 00:38 x.log.7
-rw-r--r-- 1 oracle oinstall 198 Sep  7 00:38 x.log.6
-rw-r--r-- 1 oracle oinstall 198 Sep  7 00:38 x.log.2
-rw-r--r-- 1 oracle oinstall 198 Sep  7 00:38 x.log.10
-rw-r--r-- 1 oracle oinstall 198 Sep  7 00:38 x.log.1
-rw-r--r-- 1 oracle oinstall 198 Sep  7 00:38 x.log
-rwxr--r-- 1 oracle oinstall 549 Sep  7 01:38 x.ksh

Note that I have x.log.5, x.log.4, x.log.3 missing. Can anyone suggest how I can include some sort of re-ordering/renaming loop so that after I run the rotate script, I will end up with the rotated logs renamed as below:

 
-rw-r--r-- 1 oracle oinstall 198 Sep  7 00:38 x.log.9
-rw-r--r-- 1 oracle oinstall 198 Sep  7 00:38 x.log.8
-rw-r--r-- 1 oracle oinstall 198 Sep  7 00:38 x.log.7
-rw-r--r-- 1 oracle oinstall 198 Sep  7 00:38 x.log.6
-rw-r--r-- 1 oracle oinstall 198 Sep  7 00:38 x.log.2
-rw-r--r-- 1 oracle oinstall 198 Sep  7 00:38 x.log.10
-rw-r--r-- 1 oracle oinstall 198 Sep  7 00:38 x.log.1

x.log.10 should be x.log.7
x.log.9 should be x.log.6
x.log.8 should be x.log.5
x.log.7 should be x.log.4
x.log.6 should be x.log.3
x.log.2 should be x.log.2
x.log.1 should be x.log.1

Help much appreciated. Thanks in advance.

If it is ok for you, I suggest to use the unix weekday like date +%w in the file name when wrapping/copying the current log file at the end of a day (0-6).
So you won't have to track the numbers in the file names and after 1 week they are overwritten. If 7 days is not enough you could use the month's day this way for example (1-31).

what about using - if available on your system - the backup control option of cp:

cp --backup=numbered file file.bck

Unfortunately, don't have the --backup option. Never heard of that option actually. Will check on that in any case.

---------- Post updated at 05:53 PM ---------- Previous update was at 05:45 PM ----------

Hhhhmmmm ... that's a good thought actually but run the script weekly but very good suggestion.

BTW, just noted, I actually need to do the re-order/re-numbering before doing the rotate, not after ....

Don't know if you mean that you want help with this, bur here is a suggestion, I kept your syntax (with small adjustments) because I have never used ksh.

#!/bin/ksh
file_to_rotate=${1}
max=${2}
let curr=1
while [[ ${curr} -lt ${max} ]]; do
  if [[ ! -f ${file_to_rotate}.${curr} ]]; then
    let next=${curr}+1
    while [[ ${next} -le ${max} ]]; do
      if [[ -f ${file_to_rotate}.${next} ]]; then
        mv ${file_to_rotate}.${next} ${file_to_rotate}.${curr}
        let next=${max}+1 # don't know about ksh, if you can use break here instead
      else
        let next=${next}+1
      fi
    done
  fi
  let curr=${curr}+1
done

In your script in your first post I would have preferred mv x y instead of cp -p x y , on both places where you do the copy. For the first occurrence the "file_to_rotate" is not "rotated", it is copied to "file_to_rotate.1" but "file_to_rotate" still remains.
For second occurrence it will be the same result at the end, but if the script for some reason crashes in the middle you will have a confusing copy.

Hi,

I tried your script and I didn't seem to have done anything. I copy and paste your script and run it as

./x.ksh x.log 10

and nothing happens.

I do need some help with re-generating/re-naming the files with however x.log.[n] file there is before I run the log rotation.

What am trying to do is kinda like checking a set of consecutive numbers and if there is a number sequence re-do the number sequence.

For example, if am suppose to have a series of number from 1 to 10 like 1.2.3.4.5.6.7.8.9.10 and suddenly I have it a number missing that it now becomes 1.2.5.7.9.10, then I need to re-generate the number to 1.2.3.4.5.6.

It's kinda like working on a set of array where some array numbers has been pop'ed hence you need to push up some of the members. Not sure if am explaining it correctly.

Like this (using ksh93)?:

#!/usr/bin/ksh93

file_to_rotate=$1
max=$2

[[ ! -f $file_to_rotate ]] && { echo "$file_to_rotate is not valid"; exit;}
((max==1)) && { cp -p "$file_to_rotate" "$file_to_rotate".1; exit;}

filearr=($(ls "$file_to_rotate".*|sort -t. -nk2))
numfiles=${#filearr[*]}
((x=$((numfiles>=max?max-2:numfiles-2))))

while (( x >= 0 ))
do
 cp -p "${filearr[$x]}" "${filearr[$((x+1))]}"
 ((x--))
done

((x==-1)) && cp -p "$file_to_rotate" "$file_to_rotate".1

Hope your filenames don't contain spaces.

Try

 ls x.*|sort -nt. -k3,3| while read fn; do echo mv -fv $fn ${fn%.*}.$((++i)); done
mv: `x.log.1' and `x.log.1' are the same file
`x.log.3' -> `x.log.2'
`x.log.5' -> `x.log.3'
`x.log.7' -> `x.log.4'
`x.log.9' -> `x.log.5'
`x.log.11' -> `x.log.6'
`x.log.13' -> `x.log.7'
`x.log.15' -> `x.log.8'
`x.log.17' -> `x.log.9'

You can skip the sort if file ordering doesn't matter.

--------------------------------------------------------
Sorry, I missed the fact you are running ksh. Above example works in bash.