CrackOps
Interview PrepTracksLinuxAWS LabSoonInterview RoomSoon
Sign inStart free
CrackOps

Interview prep for the people who keep production up.

[email protected]
ProductInterview PrepTracksDashboardInterview Room
RolesDevOpsSREPlatformCloud
CompanyAboutContactPrivacyTerms
© CrackOps
Linux / Backup & Restore / rsync --link-dest

rsync --link-dest

Daily full snapshots for the price of changes (rsync)

Advancedbackuprsynchard-links

rsync --link-dest builds each day's backup as a complete, browsable copy of the source, but hard-links every unchanged file to the previous snapshot instead of copying it. You get many full snapshots while paying disk space only for what changed, the trick behind rsnapshot and Time Machine.

Syntaxrsync -a --delete --link-dest=PREVIOUS_SNAPSHOT SOURCE/ NEW_SNAPSHOT/

Watch it run

You back up /srv/app (4.1 GB of uploads and config) to a backup disk every night and want 30 days of full copies.

devops@devops-lab: ~ — zsh — 96×28
➜ ~
Step 1 of 4
sudo rsync -aH --delete /srv/app/ /backup/app/2026-10-27/

The first snapshot has nothing to link to, so it's a plain full copy.

Anatomy of a command

$
commandrsync

The file synchroniser; locally or over ssh.

How it works

rsync builds a list of source files and, for each one, looks for it in the destination and then in the --link-dest directory. If the file there matches by rsync's quick check (same size and modification time, and with -a the same permissions and owner), rsync calls link() to create a new name for the existing inode in today's snapshot: no data is copied and no new data blocks are used. Files that changed or are new are copied normally (or with the delta algorithm when the source is remote). The result is that every snapshot directory is a complete tree you can browse, diff and restore from with cp, yet unchanged files exist on disk once, with a link count equal to the number of snapshots that contain them. Deleting an old snapshot only decrements link counts; blocks are freed when the last link goes. Limits: hard links only work within one filesystem, a changed file is stored again in full (a 1-byte change to a 10 GB file costs 10 GB), and all snapshots share the same inodes, so modifying a file in place inside one snapshot changes it in all of them.

Each snapshot is a full tree, but unchanged files are extra names for the same inode, so only changes use new space.

file listcopy allname 1/srv/app48,121 filesrsync--link-dest2026-10-27/full copy4.1G used2026-10-28/new snapshotimg-00001.jpginode 9254333app.conf v2new inode
1/7
Night 1: a full copy

The first run has nothing to link to, so rsync copies all 4.1 GB into 2026-10-27/. Every file there has one name and link count 1.

4.1GDisk used
← → to step

Options you'll actually use

-aArchive: -rlptgoD (recursive, links, perms, times, group, owner, devices)
-HPreserve hard links that exist inside the source
--link-dest=DIRHard-link unchanged files from DIR (relative paths are relative to the destination!)
--deleteRemove files in the destination that are gone from the source
-n / --dry-runShow what would happen, change nothing
-i / --itemize-changesOne line per change with a code like >f.st......
--statsSummary: files, transferred bytes, speedup
--numeric-idsKeep uid/gid numbers (restoring on another host)
-xDon't cross filesystem boundaries
--exclude=PATTERNSkip caches, temp files, sockets
-e ssh / -zPull from a remote host over ssh / compress in transit

Common mistakes

--link-dest=2026-10-28 (a relative path)

It's resolved relative to the destination directory; rsync only warns 'arg does not exist' and makes a full copy every night.

--link-dest=/backup/app/2026-10-28 (or a 'latest' symlink with an absolute path)
Keeping snapshots on the same disk as the data

Hard links only work within one filesystem, so the backup and the data die together.

A separate disk or host, and an off-site copy
Pointing --link-dest at a snapshot from a run that crashed

Files missing from the partial snapshot are copied in full again, and you may prune the last good snapshot.

Write to NAME.partial, rename on success, and move 'latest' last
Using this for database files or VM images

A live database copied file by file is inconsistent, and any change to a big file stores it again in full.

pg_dump/mysqldump or volume snapshots for databases; rsync snapshots for file trees

Interview questions

Practice

Try these on a Linux machine of your own. Each task has a hint and a solution.

  1. 1

    Make a first snapshot of ~/app in ~/snap/day1, then change one file in ~/app and make ~/snap/day2 using day1 as the link reference.

  2. 2

    Show that an unchanged file in day1 and day2 is the same inode.

  3. 3

    Compare how much space both snapshots use together versus day2 alone.

  4. 4

    Preview, without changing anything, what restoring day1 over ~/app would do.

Related commands

rsyncSync files and directories efficientlytar --listed-incrementalFull and incremental backups with GNU tarlnCreate hard links and symbolic linksduFind out which files and directories use the space
Previouspg_dumpNexttar --listed-incremental
Linux / Backup & Restore / rsync --link-dest

rsync --link-dest

Daily full snapshots for the price of changes (rsync)

Advancedbackuprsynchard-links

rsync --link-dest builds each day's backup as a complete, browsable copy of the source, but hard-links every unchanged file to the previous snapshot instead of copying it. You get many full snapshots while paying disk space only for what changed, the trick behind rsnapshot and Time Machine.

Syntaxrsync -a --delete --link-dest=PREVIOUS_SNAPSHOT SOURCE/ NEW_SNAPSHOT/

Watch it run

You back up /srv/app (4.1 GB of uploads and config) to a backup disk every night and want 30 days of full copies.

devops@devops-lab: ~ — zsh — 96×28
➜ ~
Step 1 of 4
sudo rsync -aH --delete /srv/app/ /backup/app/2026-10-27/

The first snapshot has nothing to link to, so it's a plain full copy.

Anatomy of a command

$
commandrsync

The file synchroniser; locally or over ssh.

How it works

rsync builds a list of source files and, for each one, looks for it in the destination and then in the --link-dest directory. If the file there matches by rsync's quick check (same size and modification time, and with -a the same permissions and owner), rsync calls link() to create a new name for the existing inode in today's snapshot: no data is copied and no new data blocks are used. Files that changed or are new are copied normally (or with the delta algorithm when the source is remote). The result is that every snapshot directory is a complete tree you can browse, diff and restore from with cp, yet unchanged files exist on disk once, with a link count equal to the number of snapshots that contain them. Deleting an old snapshot only decrements link counts; blocks are freed when the last link goes. Limits: hard links only work within one filesystem, a changed file is stored again in full (a 1-byte change to a 10 GB file costs 10 GB), and all snapshots share the same inodes, so modifying a file in place inside one snapshot changes it in all of them.

Each snapshot is a full tree, but unchanged files are extra names for the same inode, so only changes use new space.

file listcopy allname 1/srv/app48,121 filesrsync--link-dest2026-10-27/full copy4.1G used2026-10-28/new snapshotimg-00001.jpginode 9254333app.conf v2new inode
1/7
Night 1: a full copy

The first run has nothing to link to, so rsync copies all 4.1 GB into 2026-10-27/. Every file there has one name and link count 1.

4.1GDisk used
← → to step

Options you'll actually use

-aArchive: -rlptgoD (recursive, links, perms, times, group, owner, devices)
-HPreserve hard links that exist inside the source
--link-dest=DIRHard-link unchanged files from DIR (relative paths are relative to the destination!)
--deleteRemove files in the destination that are gone from the source
-n / --dry-runShow what would happen, change nothing
-i / --itemize-changesOne line per change with a code like >f.st......
--statsSummary: files, transferred bytes, speedup
--numeric-idsKeep uid/gid numbers (restoring on another host)
-xDon't cross filesystem boundaries
--exclude=PATTERNSkip caches, temp files, sockets
-e ssh / -zPull from a remote host over ssh / compress in transit

Common mistakes

--link-dest=2026-10-28 (a relative path)

It's resolved relative to the destination directory; rsync only warns 'arg does not exist' and makes a full copy every night.

--link-dest=/backup/app/2026-10-28 (or a 'latest' symlink with an absolute path)
Keeping snapshots on the same disk as the data

Hard links only work within one filesystem, so the backup and the data die together.

A separate disk or host, and an off-site copy
Pointing --link-dest at a snapshot from a run that crashed

Files missing from the partial snapshot are copied in full again, and you may prune the last good snapshot.

Write to NAME.partial, rename on success, and move 'latest' last
Using this for database files or VM images

A live database copied file by file is inconsistent, and any change to a big file stores it again in full.

pg_dump/mysqldump or volume snapshots for databases; rsync snapshots for file trees

Interview questions

Practice

Try these on a Linux machine of your own. Each task has a hint and a solution.

  1. 1

    Make a first snapshot of ~/app in ~/snap/day1, then change one file in ~/app and make ~/snap/day2 using day1 as the link reference.

  2. 2

    Show that an unchanged file in day1 and day2 is the same inode.

  3. 3

    Compare how much space both snapshots use together versus day2 alone.

  4. 4

    Preview, without changing anything, what restoring day1 over ~/app would do.

Related commands

rsyncSync files and directories efficientlytar --listed-incrementalFull and incremental backups with GNU tarlnCreate hard links and symbolic linksduFind out which files and directories use the space
Previouspg_dumpNexttar --listed-incremental