]> git.sesse.net Git - backup.sh/blob - backup.sh
Various bug fixes and improvements
[backup.sh] / backup.sh
1 #!/bin/sh
2
3 #dirs
4 confdir=/home/backup/conf/           #configuration files
5 storagedir=/backup                   #mountpoint of huge disc
6 ###
7
8 #exclude-pattern
9 exclude=$confdir/exclude
10 [ ! -f $exclude ] && printf "tmp\ncore\n" > $exclude
11 ###
12
13 #syntax of remotestat:
14 #hostname:/directory/
15 remotestatf=$confdir/remotestat
16 [ -f $remotestatf ] && remotestat=`cat $remotestatf`
17 ###
18
19 PATH=/local/bin:$PATH:/store/bin
20 export PATH
21
22 #start the logfile
23 echo `date`": Backup run starting"
24 echo "Exclude pattern:"
25 cat $exclude
26 echo "End exclude pattern"
27
28 umask 027
29
30 # The computers we want to back up
31 unixcomputers=`cat $confdir/computers.unix \
32   | grep -v "^#" \
33   | grep -v "^$" `
34
35
36 if [ $1 ] ; then 
37   unixcomputers=$1
38 fi;
39 ###
40
41 #disse bør kunne varieres fra fs til fs?
42 maksantallfulle=3          #hvor mange fulle vi tar vare på
43 dagermellomfulle=30        #antall dager før det er på tide med ny full
44 logw=40
45 ###
46
47 #lager datovariabeler
48 DATE=`date "+%Y%m%d%H%M"`            #format: touch
49 DATEs=`date "+%Y-%m-%d %H:%M"`       #format: tar
50 ###
51
52 #selve backupen
53 # krever at noen variabler er satt
54 # krever at vi er i rett katalog
55 backup()
56 {
57
58  printf "%-${logw}s %s\n" "$computer:$filesystem" "$backuplevel backup"
59
60  if [ "$backuplevel" = "daglig" ] || [ "$backuplevel" = "incremental" ]
61  then
62   lastd=`cat ../.date`
63   lastcmd="--newer='$lastd'"
64  else
65   lastcmd=""
66  fi
67
68  #if this client has a special tar
69  #we need to find a better solution to this conf-issue
70  if [ -f $confdir/tar.$computer ] ; then
71    tar=`cat $confdir/tar.$computer`
72  else 
73    tar=tar
74  fi
75
76  #expand the exclude-path for use with tar
77  exf=`ssh $computer "ls ~/.backup/exclude"`
78
79  #We try to run tar on the remote computer
80  #    c create archive
81  #    C change to directory first
82  #    - output to stdout (we pipe to gzip, then to dd)
83  #    . where to start taring (see C)
84  #    $lastcmd only files newer than this
85  #    --exclude-from file to get exclusion pattern from
86  #    pipe to gzip, which in turn pipes over the ssh-stream
87  #    ..to dd, to output to a file. We surpress messages from dd.
88  #    And at last, redirect stderr to stdout, to get output logged.
89  TARFILE=$DATE.tmp
90  TARCMD="ssh $computer \"$tar --one-file-system -cf - -C $filesystem . $lastcmd \
91         --exclude-from=$exf | gzip\" | (dd of=$TARFILE 2> /dev/null) 2>&1"
92  echo "cmdline: $TARCMD"
93  eval $TARCMD
94
95  # Ideally, we should check wether the tar command returned 0 or not, but it
96  # seems a pipe in bash returns the value of the last command in the pipe.
97  # Instead, we check wether the resulting file has zero size, in which case we
98  # consider it an error.
99  if [ -s $TARFILE ]; then
100   echo `date`": command probably ran without errors."
101   #perhaps it did work
102   mv $TARFILE $DATE.tgz
103   #make a filelist.
104   #update the datefile if the filelist is ok.
105   tar tvfz $DATE.tgz > $DATE.idx 2>&1 &&
106     echo $DATEs > ../.date            &&
107     touch -t $DATE ../.date
108
109   #make a sortet filelist
110   grep -v ^d $DATE.idx | sort -n -r +2 > $DATE.sdx
111
112   #fix perm
113   chmod 600 *tgz                      #only for us
114   chmod 644 *sdx *idx 2>/dev/null     #everyone can read
115
116  else
117   #it did not work
118   rm $TARFILE
119   echo `date`": $TARFILE empty. $backuplevel backup of $computer:$filesystem failed and deleted"
120  fi
121
122 }
123
124 #Løper gjennom listen av unixmaskiner som vi skal ta backup av
125 for computer in $unixcomputers
126 do
127
128  echo `date`": Backing up $computer"
129
130  # Try to SSH to the computer without entering a password.
131  if `ssh -n -o NumberOfPasswordPrompts=0 $computer /bin/true`; then
132   echo "Passwordless SSH to $computer works."
133  else
134   echo "Could not use passwordless SSH to $computer."
135   break;
136  fi
137  
138  #tømmer variabelen for sikkerhets skyld
139  filesystems=""
140
141  #Sjekker nest siste felt i fstab. Om det er 0 tar vi ikke backup
142  filesystems=`ssh -n $computer "cat /etc/fstab" \
143   | grep -v nfs \
144   | grep -v "^#" \
145   | grep -v "^$" \
146   | awk '{ if ( $(NF-1) != "0" ) print $2}' `
147
148  echo "Filesystems to backup on $computer: $filesystems"
149
150  #clean up our dir at this client
151  if ! ssh $computer "rm -r ~/.backup ; mkdir -m 700 ~/.backup"; then
152   echo "Could not create backup staging area at $computer:~/.backup"
153   break;
154  fi
155
156  #try to copy $exclude to $computer
157  if ! scp $exclude $computer:~/.backup/exclude > /dev/null; then
158   echo "Could not copy exclude.txt to $computer"
159   break;
160  fi
161
162  #try to copy preeexec and postexec if they exist
163  [ -f $confdir/preexec.$computer ] && (
164     scp $confdir/preexec.$computer  $computer:~/.backup/preexec ||
165      ( echo "Could not copy preexec.$computer to $computer:~/.backup/preexec"; break )
166     )
167  [ -f $confdir/postexec.$computer ] && (
168     scp $confdir/postexec.$computer $computer:~/.backup/postexec ||
169      ( echo "Could not copy postexec.$computer to $computer:~/.backup/postexec"; break )
170     )
171
172  #try to run preexec if it exist
173  ssh $computer "[ -f ~/.backup/preexec ] && /bin/bash -x ~/.backup/preexec"
174
175  for filesystem in $filesystems
176  do
177   #lager en variant uten tegnet "/" eller $ (gjelder NT)
178   sfilesystem=`echo $filesystem | tr '\/\$' '__'`
179
180   #lager det som trengs av kataloger
181   mkdir -m 755 -p $storagedir/$computer/$sfilesystem/{full,daglig} 2>/dev/null
182
183   echo $filesystem > ${storagedir}/${computer}/.${sfilesystem}.name 
184   chmod 644 ${storagedir}/${computer}/.${sfilesystem}.name
185
186   #set default backuplevel
187   backuplevel=daglig
188
189   if [ ! -f $storagedir/$computer/$sfilesystem/.date ]
190   then
191    #take the first full backup of this filesystem on this computer
192    backuplevel=full
193    echo $DATEs > $storagedir/$computer/$sfilesystem/.date
194   fi
195
196   #sjekker om det er på tide med en full
197   if [ -z "`find $storagedir/$computer/$sfilesystem/full/ -name \*tgz -mtime -$dagermellomfulle`" ]; then
198    backuplevel=full
199   fi
200  
201   #gå ned i rett katalog, eller dø 
202   # TODO bør sende mail om dette skjer!
203   cd $storagedir/$computer/$sfilesystem/$backuplevel || exit 1
204
205   #perform the actual backup
206   backup
207
208   # Sjekk om det skal være et annet antall fulle backuper av en boks
209   if [ -f $confdir/maksfulle.$computer ] ; then
210     mf=$((`cat $confdir/maksfulle.$computer`+1))
211   else
212     mf=$(($maksantallfulle+1))
213   fi
214
215   #delete complete backups
216   for full in `ls -1t $storagedir/$computer/$sfilesystem/full/*tgz | tail +$mf`
217   do
218    prefix=`echo $full | sed "s/\.[^.]*$//"`
219    echo "$computer:$filesystem sletter full $prefix (for mange)"
220    rm $prefix*
221   done
222
223   #delete incremental backups older than the oldest complete backup
224   oldf=`ls -t1 $storagedir/$computer/$sfilesystem/full/*tgz | tail -1`
225   find \
226      $storagedir/$computer/$sfilesystem/daglig \
227      -type f \
228      \! -newer $oldf \
229      -exec rm {} \;
230 #     #denne funker bare med gnu find
231 #     #-printf "$computer:$filesystem sletter daglig %f (for gammel)\n"
232  done
233
234  #try to run postexec if it exist
235  ssh $computer "[ -f ~/.backup/postexec ] && /bin/bash -x ~/.backup/postexec"
236
237 )  
238 done &
239
240 wait
241
242 #create report
243 # (Hasn't been working for years -berge)
244 #/home/backup/report.sh $storagedir > /tmp/report.txt
245 #[ ! -z $remotestat ] && scp /tmp/report.txt $remotestat
246 ###
247
248 # print diskusage to logfile
249 echo "Current disk usage:"
250 df -k
251
252 echo `date`": Backup run ended"