skip to content

Remote access & file transfer

Getting onto other machines and moving files between them over the network, securely and repeatably. Interviewers ask because everything you do to a remote server passes through this layer, and its failure modes — key permissions, interrupted transfers — are the ones people hit most often.

on this pageshow

questions

12

Explain what a trailing slash on an rsync SOURCE path changes, using `rsync -a /var/www /backup/` versus `rsync -a /var/www/ /backup/`, and why getting it wrong is dangerous once `--delete` is added.

level: juniorimportance: must knowfreq 78%

answer

  1. one character changes the whole layout
  2. which side of the command reads it
  3. contents of, versus the directory itself
  4. a stray www/ appears in the destination
  5. --delete then judges everything else extraneous

basics

~20 s

A trailing slash on an rsync source means "copy this directory's contents"; without it rsync copies the directory itself. So /var/www/ fills /backup, while /var/www creates /backup/www. A trailing slash on the destination changes nothing.

solid answer

~40 s

rsync reads the trailing slash on the **source** only, and it means "the contents of this directory" rather than "this directory". `rsync -a /var/www /backup/` produces `/backup/www/...`; `rsync -a /var/www/ /backup/` puts the contents of `/var/www` straight into `/backup`. A slash on the destination makes no difference — when the source is a directory the destination is always treated as one. The danger appears with `--delete`, which removes anything in the destination that has no counterpart in the source. If you meant to fill `/backup` from `/var/www/` but dropped the slash, rsync creates `/backup/www` and then deletes everything else that was already in `/backup`, because relative to the new source those files are extraneous. I run any `--delete` command once with `-n -i` and read the itemised output before letting it run for real.

code

bash · 6 lines
bash
# Contents of /var/www land directly in /backup
rsync -ain --delete /var/www/ /backup/

# /var/www itself lands as /backup/www -- and everything
# already in /backup is now "extraneous" and would be deleted
rsync -ain --delete /var/www  /backup/

go deeper

for a junior

Memorise the rule and be able to say it cleanly: the slash belongs to the source and means "contents of". Show the two-line example with the extra www/ directory appearing, and mention that the destination slash is irrelevant.

for a middle

Explain what --delete actually compares — destination entries with no counterpart in the transferred source tree — and therefore why a missing slash turns a merge into a wipe. Mention that --delete needs recursion to do anything.

for a senior

Demonstrate the operating discipline: dry-run with -i before any destructive mirror, --max-delete as a circuit breaker, a sentinel-file check so an unmounted source cannot present as empty, and a recoverable destination rather than a bare mirror.

for a principal

Frame it as a blast-radius question. Argue where mirroring is acceptable at all versus versioned snapshots, who is allowed to run a --delete job unattended, and how you make the safe form the only form that exists in your tooling instead of relying on operator care.

## The rule, in one line rsync gives the **source** argument one special piece of syntax: a trailing `/` (or the equivalent `/.`) means *the contents of this directory*. Without the trailing slash, the argument means *this directory as an object*, and rsync recreates it by name underneath the destination. Nothing else about the command changes — same flags, same transport, same algorithm. One character decides the shape of the result. ## Worked example Assume `/var/www` contains `index.html` and `assets/`. ``` rsync -a /var/www /backup/ -> /backup/www/index.html /backup/www/assets/ rsync -a /var/www/ /backup/ -> /backup/index.html /backup/assets/ ``` The second form is what people usually mean when they say "mirror this directory to that one". The first form is what they usually type. ## The destination slash does not matter `/backup`, `/backup/` and `/backup/.` behave identically here. When the source is a directory, rsync treats the destination as a directory and creates it if the final component is missing (only the last component — rsync 3.2.3 added `--mkpath` for creating the whole path). Interviewers ask about the destination slash specifically to see whether you have internalised the rule or just memorised "put a slash on both". A good habit for the safe form is `rsync -a /var/www/. /backup/` — the explicit `.` is harder to lose to a shell completion or a copy-paste than a bare slash, and it means the same thing. ## What `--delete` compares `--delete` tells rsync to remove files in the destination that do not exist in the transferred source tree. It only applies to directories rsync is actually recursing into, so it needs `-r`/`-a` (or `-d`) to do anything, and it only judges the parts of the tree the transfer covers — a `--exclude`d path is *not* automatically deleted (that is what `--delete-excluded` is for). Now combine the two rules. You intended: ``` rsync -a --delete /var/www/ /backup/ # /backup becomes a copy of /var/www ``` and you typed: ``` rsync -a --delete /var/www /backup/ # /backup becomes a directory containing only www/ ``` In the second command the transferred source tree, as seen from the destination root, contains exactly one entry: `www`. Every other file in `/backup` — including the previous night's backups of other trees — is extraneous, so rsync deletes it. The destination is not corrupted or half-written; it is exactly what you asked for, which is why the mistake is so easy to make and so expensive. ## Making the mistake impossible - **Dry-run first, always, for anything with `--delete`.** `-n` (`--dry-run`) plus `-i` (`--itemize-changes`) prints one line per action, with `*deleting` lines for removals, and changes nothing. Read those lines; if you see deletions you did not expect, the slash is the first thing to check. - **Bound the blast radius** with `--max-delete=N`: rsync stops deleting once it hits the limit and exits with a non-zero status, so a mirror job that suddenly wants to remove ten thousand files fails loudly instead of succeeding destructively. - **Pin the source in a variable and write the slash once**, so the scheduled job cannot drift from the version you tested. - **Keep the destination recoverable.** A `--link-dest` snapshot chain, filesystem snapshots or object-store versioning means even a correct-but-unwanted deletion is undoable. A mirror is not a backup precisely because it faithfully replicates deletions. ## Two related traps in the same family The slash rule also applies to remote sources: `rsync -a host:/srv/data/ /local/` and `rsync -a host:/srv/data /local/` differ in exactly the same way, and the remote-side path is expanded by a shell on that host, so wildcards behave differently again. And `--delete` has one built-in safety you should know about: if rsync cannot read the source directory because of an I/O error, it aborts rather than treating the tree as empty (unless you pass `--ignore-errors`). That protection does **not** cover the common operational version of the accident — a backup source that is an *empty but successfully readable* mount point because the filesystem failed to mount. Then the source really is empty, rsync does what it was told, and `--delete` empties the destination. Guard the job by checking for a sentinel file in the source before you run it.

  • Does a trailing slash on the destination path ever change what rsync does?
    No. When the source is a directory, `/backup`, `/backup/` and `/backup/.` are equivalent — rsync treats the destination as a directory either way and creates the final component if it is missing. Only the source argument carries the contents-versus-directory meaning. (`--mkpath`, added in rsync 3.2.3, is what creates deeper missing destination components.)
  • How would you preview exactly what a `--delete` run is going to remove before running it?
    Run the identical command with `-n -i` added: `rsync -ain --delete SRC/ DST/`. `-n` performs no changes, and `-i` itemises every action, printing `*deleting` lines for removals and a per-attribute change string for updates. For a scheduled job, also set `--max-delete=N` so a real run aborts instead of proceeding if the deletion count is implausible.
  • Someone argues that a `--delete` mirror is their backup. What is wrong with that?
    A mirror replicates deletions and corruption faithfully — that is its job. If a file is removed or overwritten on the source, tonight's run removes or overwrites it on the destination, and yesterday's good copy is gone. A backup needs history: `--link-dest` snapshot chains, filesystem snapshots, or a versioned object store. Mirroring gives you availability, not recoverability.

saying these in an interview costs you the question

  • Thinks the destination trailing slash matters too
  • Says rsync always merges the source contents into the destination
  • Believes --delete removes files from the source side
  • Runs a --delete mirror without a dry-run first
  • Assumes rsync refuses to delete when a mount is missing

context

open as a page

You generated an SSH key pair on your laptop with `ssh-keygen`. What does `ssh-copy-id deploy@server` then do, which of the two files it produced ends up on the server, and where exactly does it go?

level: juniorimportance: must knowfreq 68%

basics

~20 s

ssh-copy-id logs in with the credentials you already have, then appends your public key file (for example id_ed25519.pub) to the remote account's ~/.ssh/authorized_keys, creating the directory and file with safe permissions. The private key never leaves your machine.

open as a page

A 2 GB file on a remote host changes by a few kilobytes a day, yet `rsync -a` over a slow link finishes in seconds. Describe the delta-transfer algorithm that makes that possible, and name a common situation where rsync does not use it at all.

level: middleimportance: must knowfreq 62%

basics

~20 s

The receiver splits its existing copy into blocks and sends the sender a weak rolling checksum plus a strong checksum for each. The sender rolls a window byte by byte through its version, and transmits only unmatched literal data plus references to blocks the receiver already has. Local-to-local copies skip this and send whole files.

open as a page

Key-based SSH login to a Linux server fails with `Permission denied (publickey)` even though the right public key is present in `/home/deploy/.ssh/authorized_keys`, and the server's auth log shows `Authentication refused: bad ownership or modes for directory /home/deploy/.ssh`. What is sshd checking, and which ownership and permissions does it require?

level: middleimportance: must knowfreq 62%

basics

~20 s

OpenSSH's sshd runs with StrictModes yes by default: it ignores a key file that anyone but the owner could modify. The account's home directory must not be group- or world-writable, ~/.ssh should be 700 and authorized_keys 600, all owned by that user.

open as a page

In rsync, what does the `-a` (archive) option expand to, what does it deliberately not preserve, and which part of it silently does nothing unless the transfer runs with superuser rights?

level: middleimportance: should knowfreq 52%

basics

~20 s

rsync's -a is shorthand for -rlptgoD: recurse, copy symlinks as symlinks, preserve permissions, times, group, owner, and device and special files. It does not cover hard links (-H), ACLs (-A), extended attributes (-X) or sparse files (-S), and preserving owner requires superuser rights on the receiving side.

open as a page

You rebuilt a Linux server and kept its hostname and IP address. Now `ssh` to it aborts with `WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!` and refuses to connect. Why does a rebuild trigger that, and what is the correct way to clear it?

level: middleimportance: should knowfreq 58%

basics

~20 s

Your client pinned the old server's host public key in ~/.ssh/known_hosts, and the rebuild generated fresh host keys in /etc/ssh. Verify the new fingerprint out of band, then drop the stale entry with ssh-keygen -R <host> and reconnect to record the new one.

open as a page

A nightly rsync job over SSH copies the entire dataset every run, although almost nothing changes on the source. What rule does rsync use to decide a file needs transferring, and what are the usual reasons it keeps deciding yes?

level: seniorimportance: should knowfreq 45%

basics

~20 s

By default rsync skips a file only when its size and modification time match on both sides. Anything that stops mtime matching — not passing -t or -a, a destination filesystem with coarse timestamp resolution, or a source process rewriting files — makes every file look changed. Run with -ni to see which attribute differs.

open as a page

You are hardening a nightly `rsync -a --delete` mirror to a remote host over SSH: it is regularly killed part-way through, it saturates the uplink, and once it emptied the destination. Which rsync options make the job resumable, bounded and safe to interrupt?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Use --partial-dir so a killed run resumes instead of restarting large files, --bwlimit to cap throughput, --max-delete as a circuit breaker, --delete-after or --delay-updates so the destination is not pruned before the new data lands, and --timeout to fail a stalled run. Verify the source is really mounted before running.

open as a page

You have edited `/etc/ssh/sshd_config` on a remote Linux server you can only reach over SSH. What do you do before and after restarting sshd so a mistake in that file does not lock you out?

level: seniorimportance: should knowfreq 48%

basics

~20 s

Parse-check the file first with sshd -t, keep your current session open, then reload or restart the unit and prove the change from a brand-new second session before closing the first. Have console access or a timed automatic rollback as the backup.

open as a page

A user reports `Permission denied (publickey)` connecting to a Linux server. Walk through what `ssh -vvv deploy@server` tells you about where the failure lies — and what that output fundamentally cannot tell you.

level: seniorimportance: should knowfreq 44%

basics

~20 s

Verbose client output shows which identities the client offered and which methods the server will accept, so it separates a client that never sent your key from a server that rejected it. It cannot show why the server refused — that reason exists only in the server's auth log.

open as a page

A release script pushes a 4 GB build directory to each server with `scp -r`, and almost nothing changes between releases. What does rsync do differently that makes it the better tool for this, and what changed about scp itself in OpenSSH 9.0?

level: juniorimportance: nice to knowfreq 45%

basics

~20 s

rsync compares source and destination and sends only what differs, can resume an interrupted run and can prune removed files, so a mostly-unchanged 4 GB tree costs seconds; scp re-sends every byte every time. Since OpenSSH 9.0 scp uses the SFTP protocol internally.

open as a page

You inherit SSH access for a few hundred Linux servers where each account's `authorized_keys` file is maintained by hand. What actually breaks at that scale, and how would you choose between config-management-pushed key files, an `AuthorizedKeysCommand` lookup, and SSH certificates?

level: principalimportance: nice to knowfreq 32%

basics

~20 s

Revocation and inventory break first: a departing engineer's key survives on whichever hosts were missed, and nobody can answer who can reach what. The three options trade convergence speed against a runtime dependency, and short-lived certificates remove per-host key files entirely.

open as a page