Home / Alt manpages / sync(1)

  • sync(1)
  • User command
  • linux

Make Linux Writes Reach Storage with sync(1)

You will use GNU sync to flush cached writes, either for the whole machine or for a chosen file and its filesystem. You will also see when --data and --file-system are the right fit, and where the command's guarantees stop. Allow about ten minutes. You need a shell and a file you can safely test; no elevated privileges are normally needed.

1. Check the installed command

This guide describes GNU coreutils sync 9.4, installed here as coreutils package version 9.4-3ubuntu6.3. The local manual page is dated August 2026. Check your own version before copying behaviour into a portability-sensitive script:

$ sync --version
sync (GNU coreutils) 9.4
$ sync --help
Usage: sync [OPTION] [FILE]...
Synchronize cached writes to persistent storage

The command normally prints nothing when it succeeds. Its purpose is to ask the operating system to complete cached writes, not to copy files, create backups or prove that a particular physical disk has honoured its own cache policy.

2. Flush all cached writes

Run sync without a file argument when you need a system-wide flush of cached writes:

$ sync
$ printf '%s\n' "$?"
0

The second command must run immediately after sync, because $? is the status of the command that ran most recently. A zero status means the command completed successfully. It does not mean that every block device has made data physically non-volatile, and the manual explicitly warns that persistence guarantees vary by system.

This operation can take time and can create I/O pressure if a machine has a large dirty cache. Avoid using it repeatedly in a tight loop as a substitute for a sensible write design. It is also a poor progress indicator: successful sync produces no normal progress output.

3. Target one file or its filesystem

Pass one or more pathnames when a whole-system flush is broader than necessary:

$ sync /srv/example/report.db
$ printf '%s\n' "$?"
0

With file operands, the manual says that sync synchronises only those files, or their containing filesystems. The exact scope depends on the selected option and the platform implementation. Use an existing, readable path that identifies the filesystem whose writes matter. The command does not edit the file contents or change its permissions.

Checkpoint: if you only need to flush a test file, create one in a directory you own and pass that path. Do not test by pointing at a live database, mounted backup target or removable disk unless you understand the additional I/O and service impact.

4. Choose data-only synchronisation

Use --data, or its short form -d, when you want to synchronise file data but not unneeded metadata:

$ sync --data /srv/example/report.db
$ printf '%s\n' "$?"
0

This is a narrower request than the default file operation. It is useful when the bytes in an existing file are the concern and metadata such as timestamps does not need the same treatment. Do not assume it makes a newly created file fully durable: directory-entry changes and other metadata are outside this request. If your recovery design depends on a new name or directory update surviving a crash, you need a design that explicitly handles directory and filesystem durability, not just a data-only call.

Safety boundary

--data is not a backup and it is not an atomic update. It does not create a second copy, prevent a process from writing again, or replace a temporary-file-and-rename workflow.

5. Synchronise the containing filesystem

Use --file-system, or -f, to synchronise the filesystems containing the supplied files:

$ sync --file-system /srv/example/report.db
$ printf '%s\n' "$?"
0

This mode asks for filesystem-level synchronisation rather than a file-data-only request. It is different from --data: the former names the containing filesystems, while the latter limits the request to file data. If several paths are supplied, make sure they are the filesystems you actually intend to flush. A pathname on a mounted filesystem is not necessarily on the same device as a similarly named pathname elsewhere.

Use the long option in scripts so a reader can see the scope without consulting a manual. Keep the short form for an interactive command where the context is already clear.

6. Verify a test without changing service state

A small temporary file gives you a harmless smoke test for command availability and exit status:

$ test_file=$(mktemp)
$ printf '%s\n' 'sync smoke test' > "$test_file"
$ sync --data "$test_file"
$ status=$?
$ printf 'sync status: %s\n' "$status"
sync status: 0

The test confirms that the installed command accepted a writable file and returned success. It does not measure power-loss durability. Keep the temporary file if you want to inspect it, or remove it later with rm -- "$test_file" once you are certain it is disposable. That removal is irreversible, but it affects only the test file, not the original data.

For a deeper check, use the tracing tools already approved for your system. On this machine, tracing the four modes shows the distinction in the system calls: plain sync calls sync(), --data on a file calls fdatasync(), a default file argument calls fsync(), and --file-system calls syncfs(). Those observations are implementation details of this GNU/Linux installation, not a portable promise for every operating system.

7. Handle common traps

  • Expecting output: successful commands are normally silent. Check the exit status or add your own logging.
  • Using root by habit: flushing a file you can access normally does not require sudo. Extra privilege does not turn sync into a stronger durability guarantee.
  • Confusing cache flushing with atomic replacement: sync does not stop concurrent writers or prevent a partially updated file. Use an application-level atomic-write pattern when readers must see either the old file or the new file.
  • Assuming hardware guarantees: the local manual warns that persistence varies by system. Controller, device and filesystem behaviour still matter after the command returns.
  • Flushing too much: a system-wide call can do more work than a path-targeted request. Choose the smallest scope that matches the recovery requirement.

Done means

  • You checked which GNU coreutils version is installed.
  • You used plain sync only when a system-wide flush was appropriate.
  • You used a pathname for a narrower request and distinguished --data from --file-system.
  • You checked the immediate exit status instead of expecting normal output.
  • You treated sync as a cache-flush request, not as a backup, transaction or universal physical-durability proof.