Sari la conținut

Acasă › Blog › Crearea de backupuri automate cu cron și rsync în Linux

Crearea de backupuri automate cu cron și rsync în Linux

12 august 2025 · , specialist în servicii SEO din 2007 · Linux

Crearea de backupuri automate cu cron și rsync în Linux

Crearea de backupuri automate cu cron și rsync în Linux este sistemul pe care îl punem pe fiecare server pe care îl administrăm, înaintea oricărui alt serviciu: un script de 40 de rânduri, o intrare în cron și un al doilea server care primește copiile. Nu depinde de un furnizor, nu costă licențe și, cel mai important, se poate verifica.

Ghidul construiește sistemul pas cu pas: ce copiați, scriptul cu baza de date și fișierele, instantaneele zilnice care nu ocupă spațiu dublu, trimiterea pe alt server, programarea, jurnalul și testul de restaurare. Comenzile de bază ale rsync, folosite aici fără explicații, sunt în ghidul comenzilor rsync.

Crearea de backupuri automate cu cron și rsync în Linux

Ce copiați și ce nu

  • Fișierele site-urilor: /var/www sau /home/*/public_html, fără dosarele de cache și fără fișierele temporare.
  • Bazele de date: prin export (mysqldump), nu prin copierea fișierelor din /var/lib/mysql, care sunt inconsistente la cald.
  • Configurațiile: /etc (server web, PHP, cron, SSH, firewall), certificatele, cheile.
  • E-mailul, dacă serverul îl găzduiește: dosarele mail ale utilizatorilor.
  • Nu copiați: jurnalele mari (se rotesc singure), cache-urile, dosarele de sistem (/proc, /sys, /dev), pachetele instalate (se reinstalează).

Structura

Pe serverul de producție, un dosar de lucru unde se produc exporturile: /var/backups/local. Pe serverul de copii, un dosar pe fiecare server sursă, cu instantanee zilnice: /backup/server1/2026-09-09, /backup/server1/2026-09-10 și așa mai departe. Fiecare instantaneu arată ca o copie completă, dar fișierele neschimbate sunt legături fizice spre instantaneul anterior, deci 30 de zile ocupă puțin peste o singură copie plus diferențele.

Scriptul

Salvați-l în /usr/local/sbin/backup-zilnic.sh, cu permisiuni 700 și proprietar root, fiindcă citește fișiere ale tuturor utilizatorilor. Parola bazei de date nu stă în script, ci în /root/.my.cnf cu 600.

#!/bin/bash
set -euo pipefail
LOCAL=/var/backups/local
DEST=backup@203.0.113.9:/backup/server1
AZI=$(date +%F)
JURNAL=/var/log/backup-zilnic.log
exec >>"$JURNAL" 2>&1
echo "=== $(date '+%F %T') start"

# 1. bazele de date, câte un fișier comprimat pe bază
mkdir -p "$LOCAL/mysql"
for baza in $(mysql -N -e "SHOW DATABASES" | grep -Ev '^(information_schema|performance_schema|sys|mysql)$'); do
  mysqldump --single-transaction --quick --routines --triggers "$baza" | gzip > "$LOCAL/mysql/$baza.sql.gz"
done

# 2. configurațiile și lista pachetelor
mkdir -p "$LOCAL/etc"
rsync -a --delete /etc/ "$LOCAL/etc/"
dpkg --get-selections > "$LOCAL/pachete.txt" 2>/dev/null || rpm -qa > "$LOCAL/pachete.txt"

# 3. instantaneul de azi pe serverul de copii, cu legături spre cel de ieri
ssh backup@203.0.113.9 "mkdir -p /backup/server1/$AZI"
ULTIM=$(ssh backup@203.0.113.9 "ls -d /backup/server1/20* 2>/dev/null | grep -v $AZI | tail -n 1" || true)
OPT=()
[ -n "$ULTIM" ] && OPT=(--link-dest="$ULTIM")
rsync -a --delete "${OPT[@]}" \
  --exclude 'cache/' --exclude '*.log' --exclude 'tmp/' \
  /var/www/ "$LOCAL/" "$DEST/$AZI/"

# 4. rotație: păstrăm 30 de instantanee
ssh backup@203.0.113.9 "ls -d /backup/server1/20* | head -n -30 | xargs -r rm -rf"
echo "=== $(date '+%F %T') gata"

Ce face fiecare parte. set -euo pipefail oprește scriptul la prima eroare, ca să nu rotească copii vechi după un transfer eșuat. mysqldump cu --single-transaction exportă tabelele InnoDB consistent, fără blocare. Pasul 3 copiază într-un singur rsync fișierele site-urilor și dosarul local cu exporturi, în instantaneul zilei; --link-dest face legăturile spre instantaneul anterior. Pasul 4 șterge instantaneele mai vechi de 30 de zile; legăturile fizice fac ștergerea sigură, fiindcă un fișier dispare doar când nu îl mai referă niciun instantaneu.

Pregătirea serverului de copii

Pe serverul de destinație creați utilizatorul backup, fără sudo, cu dosarul /backup/server1 al lui, și instalați cheia publică a lui root de pe serverul sursă în authorized_keys. Restricționați cheia la rsync și la comenzile din script, cu o linie de forma command= în authorized_keys sau, mai simplu, cu un utilizator care nu poate face altceva, după regulile din ghidul despre utilizatorii cu acces limitat. Sistemul de fișiere al destinației trebuie să suporte legături fizice (ext4, xfs, btrfs da; sistemele de rețea de tip SMB, nu).

Direcția transferului contează pentru securitate. În scriptul de mai sus, serverul de producție împinge spre serverul de copii, deci cheia de pe producție dă acces la copii. Varianta inversă, în care serverul de copii trage de pe producție cu o cheie limitată la citire, este mai sigură: un atacator care compromite producția nu poate șterge copiile. Pentru servere cu date importante, folosim varianta inversă și un al treilea loc, offline sau în cloud, pentru copia lunară.

Programarea din cron

sudo crontab -e
# copie zilnică la 3:15, cu încuietoare ca două rulări să nu se suprapună
15 3 * * * flock -n /run/backup-zilnic.lock /usr/local/sbin/backup-zilnic.sh

Ora se alege în afara vârfului de trafic și în afara altor sarcini grele (reindexări, curățări). Pe servere cu mai multe site-uri mari, exportul bazelor de date poate dura zeci de minute; opțiunea --quick din mysqldump și un server de copii pe aceeași rețea reduc timpul. Dacă serverul rulează cPanel, aceeași logică se aplică prin cronurile din cPanel, cu scriptul rulat ca utilizatorul contului și cu exporturile făcute cu utilizatorul bazei de date a contului.

Jurnalul și alertele

Scriptul scrie tot în /var/log/backup-zilnic.log. Un backup care nu rulează nu anunță nimic, deci verificarea trebuie să fie activă: un al doilea cron, dimineața, care se uită dacă jurnalul are un rând „gata” de azi și dacă instantaneul de azi există pe destinație, și trimite e-mail dacă nu:

0 8 * * * grep -q "$(date +%F).*gata" /var/log/backup-zilnic.log || echo "backup lipsă $(hostname)" | mail -s "ALERTĂ backup" admin@firma.ro

Adăugați rotația jurnalului în /etc/logrotate.d/, ca fișierul să nu crească la nesfârșit, și citiți-l cu ochii o dată pe săptămână; erorile de tip „Permission denied” pe un dosar nou apar acolo mult înainte să aveți nevoie de copie.

Restaurarea

Fișierele se restaurează cu rsync în sens invers, dintr-un instantaneu ales:

rsync -a backup@203.0.113.9:/backup/server1/2026-09-05/var/www/site/ /var/www/site/
gunzip -c /backup/server1/2026-09-05/local/mysql/site_ro.sql.gz | mysql site_ro

Pentru un singur fișier șters din greșeală, calea completă din instantaneu (de exemplu .../2026-09-05/var/www/site/imagini/logo.png) se copiază cu scp. După restaurarea fișierelor, verificați proprietarii și permisiunile, conform ghidului despre chmod și chown, fiindcă rsync rulat ca root le păstrează, dar utilizatorii de pe un server reinstalat pot avea alte id-uri.

Testul lunar

O dată pe lună, restaurați un site întreg dintr-un instantaneu într-un dosar și o bază de date de test, porniți-l pe un subdomeniu și deschideți-l în browser. Notați data și durata. Este singurul moment în care aflați că exportul unei baze era trunchiat sau că un dosar nou de încărcări nu intra în copie. Un test de restaurare care durează 20 de minute pe lună a salvat, la un client, un magazin întreg după o ștergere accidentală a dosarului de imagini.

Ce verificați în prima săptămână

Un sistem de copii nou are nevoie de o săptămână de supraveghere. În prima zi, rulați scriptul manual, cu bash -x, ca să vedeți fiecare comandă și durata ei; notați cât durează exportul bazelor și cât transferul. În a doua zi, verificați că instantaneul al doilea a folosit link-dest: comanda du -sh pe cele două dosare de pe serverul de copii trebuie să arate al doilea instantaneu mult mai mic decât primul când e măsurat separat cu du -sh --apparent-size față de du -sh. În a treia zi, ștergeți un fișier de test de pe producție și restaurați-l din instantaneul zilei precedente. La finalul săptămânii, citiți jurnalul cap-coadă și verificați că rotația nu a șters nimic din primele zile.

Greșeli care fac copiile inutile

  • Exportul bazei fără --single-transaction pe un magazin activ: fișierul conține comenzi pe jumătate scrise, iar restaurarea eșuează la mijloc.
  • Scriptul rulează, dar rsync eșuează silențios fiindcă lipsește set -e: rotația șterge copiile vechi, iar cea nouă nu există.
  • Cheia SSH de pe producție cu drepturi complete pe serverul de copii: un atacator șterge și copiile.
  • Copiile pe același disc sau pe același server virtual: o defecțiune sau o ștergere de cont le pierde pe toate.
  • Dosarul de încărcări al unui site nou, adăugat după scrierea scriptului și neinclus niciodată.
  • Restaurarea netestată: prima restaurare reală este și primul test, la ora cea mai nepotrivită.

Variante și extinderi

  • Instantanee la nivel de sistem de fișiere (btrfs sau ZFS pe destinație) în locul link-dest, cu deduplicare și verificare a integrității incluse.
  • Criptarea copiilor înainte de trimitere în cloud, cu gpg sau cu o unealtă precum restic, care face și deduplicare și rotație.
  • Copii mai dese pentru baza de date (la fiecare oră, doar exportul, câteva zeci de MB) pe un magazin cu comenzi continue.
  • Excluderea dosarelor mari și statice (arhive video) din instantaneele zilnice și copierea lor separată, săptămânal.
  • Copia serverului de copii: un al treilea loc, offline, pentru instantaneul lunar.

Pentru containere, volumele se arhivează separat, așa cum arătăm în ghidul despre Docker pe Linux; pentru site-urile WordPress, strategiile pe niveluri, cu și fără module, sunt în articolul despre copiile de siguranță automate pentru WordPress. Iar dacă serverul este pe cPanel și nu vreți scripturi proprii, unealta din panou, descrisă în ghidul pentru backup automat în cPanel, acoperă cazurile simple.

Surse

Cum a fost realizat acest articol

Autor
Publicat
12 august 2025
Ultima actualizare
18 septembrie 2026
Surse

Lucrăm după principiile noastre de publicare, politica pentru corectare, politica pentru etică.

Articole similare