1

I am currently writing a bash script for rsync. I am pretty sure I am doing something wrong. But I can't tell what it is. I will try to elaborate everything in detail so hopefully someone can help me.

The goal of script is to do full backups and incremental ones using rsync. Everything seems to work perfectly well, besides one crucial thing. It seems like even though using the --link-dest parameter, it still copies all the files. I have checked the file sizes with du -chs.

First here is my script:

#!/bin/sh
while getopts m:p: flags
do
  case "$flags" in
    m) mode=${OPTARG};;
    p) prev=${OPTARG};;
    *) echo "usage: $0 [-m] [-p]" >&2
       exit 1 ;;
  esac
done

date="$(date '+%Y-%m-%d')";


#Create Folders If They Do Not Exist (-p paramter)
mkdir -p /Backups/Full && mkdir -p /Backups/Inc

FullBackup() {
  #Backup Content Of Website
  mkdir -p /Backups/Full/$date/Web/html
  rsync -av user@IP:/var/www/html/ /Backups/Full/$date/Web/html/

  #Backup All Config Files NEEDED. Saving Storage Is Key ;)
  mkdir -p /Backups/Full/$date/Web/etc
  rsync -av user@IP:/etc/apache2/ /Backups/Full/$date/Web/etc/

  #Backup Fileserver
  mkdir -p /Backups/Full/$date/Fileserver
  rsync -av user@IP:/srv/samba/private/ /Backups/Full/$date/Fileserver/

  #Backup MongoDB
  ssh user@IP /usr/bin/mongodump --out /home/DB
  rsync -av root@BackupServerIP:/home/DB/ /Backups/Full/$date/DB
  ssh user@IP rm -rf /home/DB
}

IncrementalBackup(){
  Method="";
  if [ "$prev" == "full" ]
  then
    Method="Full";
  elif [ "$prev" == "inc" ]
  then
    Method="Inc";
  fi

  if [ -z "$prev" ]
  then
  echo "-p Parameter Empty";
  else
  #Get Latest Folder - Ignore the hacky method, it works.
  cd /Backups/$Method
  NewestBackup=$(find . ! -path . -type d | sort -nr | head -1 | sed s@^./@@)
  IFS='/'
  read -a strarr <<< "$NewestBackup"
  Latest_Backup="${strarr[0]}";
  cd /Backups/

  #Incremental-Backup Content Of Website
  mkdir -p /Backups/Inc/$date/Web/html
  rsync -av --link-dest /Backups/$Method/"$Latest_Backup"/Web/html/ user@IP:/var/www/html/ /Backups/Inc/$date/Web/html/

  #Incremental-Backup All Config Files NEEDED
  mkdir -p /Backups/Inc/$date/Web/etc
  rsync -av --link-dest /Backups/$Method/"$Latest_Backup"/Web/etc/ user@IP:/etc/apache2/ /Backups/Inc/$date/Web/etc/

  #Incremental-Backup Fileserver
  mkdir -p /Backups/Inc/$date/Fileserver
  rsync -av --link-dest /Backups/$Method/"$Latest_Backup"/Fileserver/ user@IP:/srv/samba/private/ /Backups/Inc/$date/Fileserver/

  #Backup MongoDB
  ssh user@IP /usr/bin/mongodump --out /home/DB
  rsync -av root@BackupServerIP:/home/DB/ /Backups/Full/$date/DB
  ssh user@IP rm -rf /home/DB
  fi
}

if [ "$mode" == "full" ]
then
  FullBackup;
elif [ "$mode" == "inc" ]
then
  IncrementalBackup;
fi

The command i used: Full-Backup bash script.sh -m full

Incremental bash script.sh -m inc -p full

Executing the script is not giving any errors at all. As I mentioned above, it just seems like it's still copying all the files. Here are some tests I did.

Output of du -chs

root@Backup:/Backups# du -chs /Backups/Full/2021-11-20/*
36K     /Backups/Full/2021-11-20/DB
6.5M    /Backups/Full/2021-11-20/Fileserver
696K    /Backups/Full/2021-11-20/Web
7.2M    total
root@Backup:/Backups# du -chs /Backups/Inc/2021-11-20/*
36K     /Backups/Inc/2021-11-20/DB
6.5M    /Backups/Inc/2021-11-20/Fileserver
696K    /Backups/Inc/2021-11-20/Web
7.2M    total

Output of ls -li

root@Backup:/Backups# ls -li /Backups/Full/2021-11-20/
total 12
1290476 drwxr-xr-x 4 root root 4096 Nov 20 19:26 DB
1290445 drwxrwxr-x 6 root root 4096 Nov 20 18:54 Fileserver
1290246 drwxr-xr-x 4 root root 4096 Nov 20 19:26 Web
root@Backup:/Backups# ls -li /Backups/Inc/2021-11-20/
total 12
1290506 drwxr-xr-x 4 root root 4096 Nov 20 19:28 DB
1290496 drwxrwxr-x 6 root root 4096 Nov 20 18:54 Fileserver
1290486 drwxr-xr-x 4 root root 4096 Nov 20 19:28 Web

Rsync Output when doing the incremental backup and changing/adding a file

receiving incremental file list
./
lol.html

sent 53 bytes  received 194 bytes  164.67 bytes/sec
total size is 606  speedup is 2.45
receiving incremental file list
./

sent 33 bytes  received 5,468 bytes  11,002.00 bytes/sec
total size is 93,851  speedup is 17.06
receiving incremental file list
./

sent 36 bytes  received 1,105 bytes  760.67 bytes/sec
total size is 6,688,227  speedup is 5,861.72
*Irrelevant MongoDB Dump Text*

sent 146 bytes  received 2,671 bytes  1,878.00 bytes/sec
total size is 2,163  speedup is 0.77

I suspect that the ./ has something to do with that. I might be wrong, but it looks suspicious. Though when executing the same command again, the ./ are not in the log, probably because I did it on the same day, so it was overwriting in the /Backup/Inc/2021-11-20 Folder.

Output of ls -l

root@Backup:/Backups# ls -l /Backups/Inc/2021-11-20/
total 12
drwxr-xr-x 4 root root 4096 Nov 20 19:49 DB
drwxrwxr-x 6 root root 4096 Nov 20 18:54 Fileserver
drwxr-xr-x 4 root root 4096 Nov 20 19:49 Web
root@Backup:/Backups# ls -l /Backups/Full/2021-11-20/
total 12
drwxr-xr-x 4 root root 4096 Nov 20 19:26 DB
drwxrwxr-x 6 root root 4096 Nov 20 18:54 Fileserver
drwxr-xr-x 4 root root 4096 Nov 20 19:26 Web

Edit For Commentar:

root@Backup:/Backups# ls -al --time-style=full-iso /Backups/Full/2021-11-20/Web/html/
total 20
drwxr-xr-x 2 root root 4096 2021-11-20 19:49:31.701680076 +0000 .
drwxr-xr-x 4 root root 4096 2021-11-20 23:16:17.586745740 +0000 ..
-rw-r--r-- 2 root root  158 2021-11-16 15:40:30.000000000 +0000 index.html
-rw-r--r-- 1 root root   34 2021-11-20 19:49:31.701680076 +0000 lol.html
-rw-r--r-- 2 root root  414 2021-11-16 15:53:52.000000000 +0000 stylesheet.css
root@Backup:/Backups# ls -al --time-style=full-iso /Backups/Inc/2021-11-20/Web/html/
total 20
drwxr-xr-x 2 root root 4096 2021-11-20 23:16:47.673977833 +0000 .
drwxr-xr-x 4 root root 4096 2021-11-20 23:16:54.903294115 +0000 ..
-rw-r--r-- 2 root root  158 2021-11-16 15:40:30.000000000 +0000 index.html
-rw-r--r-- 1 root root   44 2021-11-20 23:16:47.673977833 +0000 lol.html
-rw-r--r-- 2 root root  414 2021-11-16 15:53:52.000000000 +0000 stylesheet.css

Let me know for more information. I have been trying around for a long time now. Maybe I am simply wrong and there are links made and disk space economized.

8
  • Have you come across rsnapshot? It might be worth you investigating it
    – roaima
    Nov 20, 2021 at 22:23
  • Please run ls -l in one of the backup directories, making sure it includes some of the unchanged files. Look at the link count (first number after the permissions). If it's more than 1 then it's working correctly
    – roaima
    Nov 20, 2021 at 22:26
  • Also look in your run output, "speedup is 17.06" - the copy ran 17x as fast as it could if the file was copied normally. Good news
    – roaima
    Nov 20, 2021 at 22:28
  • @roaima Edited/added in the post. Hm seems weird, both have the same amount
    – Sam
    Nov 20, 2021 at 22:43
  • Those files you've shown with a link count of more than one are linked in multiple places. I'd say that --link-dest is working
    – roaima
    Nov 20, 2021 at 23:33

1 Answer 1

1

The confusion arises because linked files exist in two places in the filesystem. When you use du to look at used disk, the files are in both trees, so each invocation of du found all the files. You've added the top-level results together and concluded that the files are taking up twice as much space as you had hoped, i.e. the hard linking hasn't worked.

The mistake is in adding the top-level disk usage results together. Instead, try running a single du that covers both backup trees. You'll find that you start to see disk savings because du counts a file only once regardless of the number of times it's found.

Here's a worked example:

mkdir /tmp/a                       # Working directories
cp -a /etc/* /tmp/a 2>/dev/null    # Generate some data in /tmp/a
cp -al /tmp/a /tmp/b               # Link it into /tmp/b

Now let's measure the amount of disk used in each tree. It should be same because all the files are linked. (You can verify this with ls -l, looking at the link count for all files.)

du -ms /tmp/a                      # Disk usage summary
8       /tmp/a                     # Result

du -ms /tmp/b                      # Disk usage summary
8       /tmp/b                     # Result

Notice that here, both directory trees appear to be using around 8 MB. Now we'll look at the two trees together:

du -ms /tmp/a /tmp/b               # Disk usage summaries
8       /tmp/a
1       /tmp/b

You can see that /tmp/a is still using around 8 MB, but /tmp/b is now no longer using 8 MB but instead it's using only an additional 1 MB. This is because the other files have already been counted so they don't take up any extra disk space. (Directory structures take up the extra.)

The ratios get far better with larger datasets; here's a segment from a backup taken from one of my smaller systems with rsnapshot, showing that of the 30 GB or so, less than 1 GB changed in the 24 hour period between these backups:

du -ms daily.{0,1}
30752   daily.0
782     daily.1
3
  • When running du, it still gives out the same exact number.
    – Sam
    Nov 21, 2021 at 9:49
  • @Sam Run du -h /Backups/Full/2021-11-20/Web/html /Backups/Inc/2021-11-20/Web/html. One command, both directories at once.
    – they
    Nov 21, 2021 at 10:31
  • @Sam I've provided a worked example for you; hopefully this will make it easier for you to identify what to look for
    – roaima
    Nov 21, 2021 at 13:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.