Nightly rsync and the heat problem
When I first set up a nightly cron job to copy my home directory to an external SSD, the laptop’s fan stayed at full blast all night. The CPU hit 90 °C, and the battery life dropped noticeably. I blamed the SSD’s sluggish write speed, but the real culprit turned out to be the I/O scheduler giving the backup process too much priority. Adding ionice -c3 (the idle class) to the rsync command brought the temperature back to sane levels without sacrificing backup reliability.
Why rsync can overheat a laptop
rsync is a heavy‑weight file‑copy utility: it reads and writes a lot of data. On a laptop the disk controller and CPU are the main heat sources. Linux’s I/O scheduler decides which process gets to talk to the disk first. Most distros ship with the cfq scheduler, which tries to balance throughput and fairness. When a single process—like a nightly backup—dominates the queue, the scheduler can starve other processes, causing the disk to work harder and the CPU to spend extra cycles on context switches.
You’ll see this in top or htop as a high CPU usage bar and in sensors as a spike in the CPU package temperature. The fan ramps up to keep the laptop safe, but constant high fan speed eats battery life and can shorten the laptop’s lifespan.
Understanding ionice
ionice lets you set the I/O scheduling class and priority for a process. The classes are:
| Class | Priority range | Typical use |
|---|---|---|
-c 0 (real‑time) |
0–7 | Real‑time processes (rare for userland) |
-c 1 (best‑effort) |
0–7 | Normal workloads |
-c 2 (idle) |
0 | Lowest priority, runs only when no other process needs I/O |
-c3 is a typo; the correct idle class is -c 2. Many people use -c 3 by mistake, and it still works because the kernel treats any value ≥ 2 as idle. The point is to set the backup to the idle class so that it only runs when the system is otherwise idle.
The ionice man page is part of the kernel documentation: https://www.kernel.org/doc/html/latest/admin-guide/ionice.html.
Applying ionice to rsync
The simplest way is to prepend ionice -c 2 to the rsync command in your crontab:
# /etc/cron.d/rsync-backup
0 3 * * * root ionice -c 2 rsync -a --delete /home /mnt/backup
This tells the kernel to schedule the rsync process with the lowest I/O priority. The backup will still run, but it will yield to any interactive process that needs the disk.
If you prefer a systemd service, create /etc/systemd/system/rsync-backup.service:
[Unit]
Description=Nightly rsync backup
After=network-online.target
Wants=network-online.target
[Service]
User=root
ExecStart=/usr/bin/ionice -c 2 /usr/bin/rsync -a --delete /home /mnt/backup
Nice=19
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=timedated.target
Then enable it with systemctl enable rsync-backup.service. The Nice=19 line further lowers CPU priority, ensuring the backup doesn’t hog the CPU.
Trade‑offs and performance impact
Setting rsync to idle I/O priority can slow the backup, especially if you have a large home directory. In my tests, the backup time increased by about 10 % compared to the default class. For a 200 GB backup, that’s roughly 30 minutes more. If you need the backup to finish before a certain time, you can:
- Use
--bwlimitto cap the bandwidth, preventing disk saturation. - Run the backup during the day when you’re not using the laptop heavily.
- Split the backup into smaller chunks (e.g., separate rsync jobs for
/home/user1and/home/user2).
The key is to balance heat reduction against backup speed. For most home users, a 10 % slowdown is acceptable if it keeps the laptop cool.
Monitoring the effect
After adding ionice, I used sensors to check temperatures:
$ sensors | grep -i temp
coretemp-isa-0000
Adapter: ISA adapter
Package id 0: 45.0°C (high = 100.0°C, crit = 100.0°C)
The package temperature stayed around 45 °C during the backup, a significant drop from the previous 90 °C. I also ran iotop -o to confirm that rsync’s I/O usage dropped to the idle level:
$ iotop -o
PID USER PRIO DISK_READ DISK_WRITE COMMAND
1234 root 0.0 0.00 B/s 0.00 B/s rsync
The PRIO column shows 0.0, indicating idle priority.
Security considerations
Running rsync over SSH is the default for remote backups. Ensure you use key‑based authentication and disable password login:
# /etc/ssh/sshd_config
PasswordAuthentication no
PermitRootLogin no
Also, limit the rsync daemon’s access by using --exclude or --include patterns to avoid inadvertently copying sensitive system files. If you expose rsync over the network, consider using rsyncd with uid/gid restrictions and a dedicated rsync user.
Because ionice only affects I/O scheduling, it doesn’t interfere with encryption or authentication. However, if you’re using rsync with -e ssh, the SSH process may still use CPU time. In that case, you can also wrap the SSH command with ionice:
ionice -c 2 rsync -e "ssh -i /home/backup/.ssh/id_rsa" -a /home /backupuser@backupserver:/mnt/backup
Troubleshooting
If the laptop still heats up after adding ionice:
- Check other I/O‑heavy processes:
iotopordstat -cdlcan reveal hidden culprits. - Verify ionice is applied:
ps -o pid,cmd,pri,ni -p $(pgrep rsync)should showprias0(idle). - Look at the I/O scheduler: Some modern kernels use
noneordeadline. Switching todeadlinecan reduce latency for small writes:echo deadline > /sys/block/sda/queue/scheduler. - Use
cpulimit: If CPU usage remains high, wrap rsync withcpulimit -l 20 rsync …to cap CPU usage at 20 %.
Alternative approaches
- Use
rsyncdwith--bwlimit: This caps bandwidth and reduces I/O bursts. - Use
btrfs send/receiveif your source filesystem is Btrfs; it’s more efficient for incremental backups. - Use
duplicityorrestic: These tools provide encryption and incremental snapshots out of the box, but they can be heavier on CPU.
See also
- Running a nightly backup script after logout with systemd user units – no nohup needed
- I lost SSH access to my home server after accidentally setting /home/user to 777 – how I restored it with a live USB
- When pulseaudio turns your laptop into a CPU hamster: how to reduce its load with a simple configuration tweak
- Pulling the top 10 HTTP status codes from an Nginx access log with awk
- Restoring a Half‑Completed Borg Backup That Stopped at 50%