Dosya Bulmak, Arşivlemek ve Taşımak: find, xargs, tar, gzip/zstd, zip, rsync, diff ve Checksum
find -mtime +7 sanıldığı gibi 7 günden eski dosyaları değil en az 8 günlükleri bulur; silmeden önce -print ile listeyi oku, -delete'i en sona yaz ve xargs'a dosya adlarını -print0 | xargs -0 ile ver. Bookstore'un release paketini tar --zstd ile hazırlamayı, gzip/xz/zstd farkını, rsync'te sondaki / ile --delete tuzağını ve paketi sha256sum, cmp ve diff ile doğrulamayı gerçek çıktılarla anlatıyoruz.
Sürüm notu: Bu yazıdaki örnekler Ubuntu Server 24.04.5 LTS (GNU findutils 4.9.0, GNU tar 1.35, zstd 1.5.5, gzip 1.12, xz 5.4.5, rsync 3.2.7, OpenSSH 9.6p1, coreutils 9.4) çalıştıran bir test sunucusunda ve istemci olarak kullanılan ikinci bir Ubuntu 24.04 ortamında denenmiştir. Ubuntu 26.04.1 LTS container image'ında findutils 4.10.0, rsync 3.4.1, zstd 1.5.7 ve uutils'in sha256sum'ı geliyor; orada denediğim tar --zstd, find -print0 | xargs -0 ve sha256sum -c aynı çıktıyı verdi. Windows'taki tar.exe çalıştırılmadı.
Önce Tahmin Et
Sitedeki serilerin ortak örnek uygulaması Bookstore'un (bir online kitapçı) veritabanı yedeği her gece 02:30'da /var/lib/bookstore/backup'a yazılıyor. Disk doluyor ve 7 günden eski yedekleri silmek istiyorsun. Saat 07:20 ve klasörde 11 yedek var:
$ sudo ls -l --time-style=+%m-%d\ %H:%M /var/lib/bookstore/backup
total 21516
-rw-r--r-- 1 bookstore bookstore 2000000 11-05 02:30 BookstoreDb-2026-11-05.bak.xz
-rw-r--r-- 1 bookstore bookstore 2000000 11-06 02:30 BookstoreDb-2026-11-06.bak.xz
-rw-r--r-- 1 bookstore bookstore 2000000 11-07 02:30 BookstoreDb-2026-11-07.bak.xz
-rw-r--r-- 1 bookstore bookstore 2000000 11-08 02:30 BookstoreDb-2026-11-08.bak.xz
-rw-r--r-- 1 bookstore bookstore 2000000 11-09 02:30 BookstoreDb-2026-11-09.bak.xz
-rw-r--r-- 1 bookstore bookstore 2000000 11-10 02:30 BookstoreDb-2026-11-10.bak.xz
-rw-r--r-- 1 bookstore bookstore 2000000 11-11 02:30 BookstoreDb-2026-11-11.bak.xz
-rw-r--r-- 1 bookstore bookstore 2000000 11-12 02:30 BookstoreDb-2026-11-12.bak.xz
-rw-r--r-- 1 bookstore bookstore 2000000 11-13 02:30 BookstoreDb-2026-11-13.bak.xz
-rw-r--r-- 1 bookstore bookstore 2000000 11-14 02:30 BookstoreDb-2026-11-14.bak.xz
-rw-r--r-- 1 bookstore bookstore 2000000 11-15 02:30 BookstoreDb-2026-11-15.bak.xz
Bugün 15 Kasım. 8 Kasım 02:30'daki yedek 7 gün 5 saat önce alınmış, yani 7 günden eski. find /var/lib/bookstore/backup -name '*.bak.xz' -mtime +7 kaç dosya bulur: dört mü, üç mü? Cevap bir sonraki bölümde.
Bu yazıda sunucudaki dosyaları bulmayı, paketlemeyi ve taşımayı anlatıyoruz: find ve xargs, tar ile gzip, xz ve zstd, zip, rsync ve paketin yolda bozulmadığını gösteren checksum. Sonunda Bookstore'un release paketini bir makinede hazırlayıp sunucuya taşıyor ve orada doğruluyoruz.
find: Test'ler ve Action'lar
$ sudo find /var/lib/bookstore/backup -name '*.bak.xz' -mtime +7 | sort
/var/lib/bookstore/backup/BookstoreDb-2026-11-05.bak.xz
/var/lib/bookstore/backup/BookstoreDb-2026-11-06.bak.xz
/var/lib/bookstore/backup/BookstoreDb-2026-11-07.bak.xz
$ sudo find /var/lib/bookstore/backup -name '*.bak.xz' -mmin +$((7 * 24 * 60)) | sort
/var/lib/bookstore/backup/BookstoreDb-2026-11-05.bak.xz
/var/lib/bookstore/backup/BookstoreDb-2026-11-06.bak.xz
/var/lib/bookstore/backup/BookstoreDb-2026-11-07.bak.xz
/var/lib/bookstore/backup/BookstoreDb-2026-11-08.bak.xz
Üç. -mtime dosyanın yaşını gün olarak hesaplarken kesirli kısmı atar: 7 gün 5 saat "7 gün" sayılır ve +7 "7'den büyük" demek olduğu için 8 Kasım dışarıda kalır. Pratikte -mtime +7 "en az 8 günlük" demek. Dakikayla hesaplayan -mmin gerçek 7 günü (10080 dakika) kullanır ve dört dosya bulur. Saklama süresi bir kuralsa (örneğin "yedekler 7 gün tutulur") hangi anlamı kastettiğini bil ve komutu ona göre seç.
find'ın ifadesi iki tür parçadan oluşur. Test'ler dosyayı seçer: -name (glob ile ad, tırnak içinde), -type f / -type d (dosya ya da klasör), -mtime / -mmin (değişiklik zamanı), -size +1M (boyut), -newer dosya ya da -newermt "2 days ago" (bir dosyadan ya da tarihten yeni), -maxdepth / -mindepth (ne kadar derine inileceği). Action'lar seçilen dosyaya ne yapılacağını söyler: -print (varsayılan), -delete, -exec.
$ sudo find /var/lib/bookstore -type f -size +1M -newermt "2 days ago" | sort
/var/lib/bookstore/backup/BookstoreDb-2026-11-14.bak.xz
/var/lib/bookstore/backup/BookstoreDb-2026-11-15.bak.xz
$ sudo find /opt/bookstore/releases -mindepth 1 -maxdepth 1 -type d | sort
/opt/bookstore/releases/2026-11-14-6
/opt/bookstore/releases/2026-11-15-1
-exec'in iki biçimi var ve farkı, komutun kaç kez çalıştığı:
$ sudo find /var/lib/bookstore/backup -name '*.bak.xz' -mtime +7 -exec echo rm {} \;
rm /var/lib/bookstore/backup/BookstoreDb-2026-11-07.bak.xz
rm /var/lib/bookstore/backup/BookstoreDb-2026-11-06.bak.xz
rm /var/lib/bookstore/backup/BookstoreDb-2026-11-05.bak.xz
$ sudo find /var/lib/bookstore/backup -name '*.bak.xz' -mtime +7 -exec echo rm {} +
rm /var/lib/bookstore/backup/BookstoreDb-2026-11-07.bak.xz /var/lib/bookstore/backup/BookstoreDb-2026-11-06.bak.xz /var/lib/bookstore/backup/BookstoreDb-2026-11-05.bak.xz
\; her dosya için komutu bir kez çalıştırır; + dosyaları toplayıp komutu olabildiğince az sayıda çalıştırır. Binlerce dosyada fark ciddi, çünkü her çalıştırma yeni bir process. Komutun başına koyduğum echo da bilinçli: silmeden önce ne silineceğini gör. Listeden emin olunca silme işini find'a bırak:
$ sudo find /var/lib/bookstore/backup -name '*.bak.xz' -mtime +7 -print -delete
/var/lib/bookstore/backup/BookstoreDb-2026-11-07.bak.xz
/var/lib/bookstore/backup/BookstoreDb-2026-11-06.bak.xz
/var/lib/bookstore/backup/BookstoreDb-2026-11-05.bak.xz
$ sudo find /var/lib/bookstore/backup -name '*.bak.xz' | wc -l
8
-print -delete sildiği her dosyayı yazar; bir timer'dan çalışıyorsa bu satırlar journal'da iz bırakır (beşinci ve altıncı yazı). find'ın çıktısı dizin sırasıyla gelir, alfabetik değil; okunur olsun diye sort ekledim.
find'da sıra önemli, çünkü ifade soldan sağa değerlendirilir ve -delete bir test değil, bir action:
$ find /tmp/demo -delete -name "*.log"
$ ls -a /tmp/demo
ls: cannot access '/tmp/demo': No such file or directory
Klasörde iki .log ve bir keep.txt vardı. -delete, -name'den önce geldiği için her dosyaya uygulandı, en sonda klasörün kendisine de. find hiçbir uyarı vermedi.
xargs ve Boşluklu Dosya Adları
xargs stdin'den okuduğu satırları bir komutun argümanlarına çevirir. Yedinci yazıdaki pipe'larla birlikte sık kullanılır, ama dosya adlarında bir tuzağı var. Windows'tan gelen rapor dosyaları adında boşluk taşıyorsa:
$ ls /tmp/exports
sales report 2026-10-01.csv
sales report 2026-10-02.csv
sales report 2026-10-03.csv
sales-2026-11-14.csv
$ find /tmp/exports -name '*.csv' -mtime +30 | xargs rm
rm: cannot remove '/tmp/exports/sales': No such file or directory
rm: cannot remove 'report': No such file or directory
rm: cannot remove '2026-10-03.csv': No such file or directory
...
$ find /tmp/exports -name '*.csv' -mtime +30 -print0 | xargs -0 rm -v
removed '/tmp/exports/sales report 2026-10-03.csv'
removed '/tmp/exports/sales report 2026-10-02.csv'
removed '/tmp/exports/sales report 2026-10-01.csv'
xargs varsayılan olarak boşlukta böler ve tek dosya adı üç argümana dönüşür. Burada yalnızca hata aldık; ama boşluktan sonraki parça başka bir dosyanın adına denk gelseydi, rm o dosyayı silerdi. -print0 dosya adlarını boşlukla değil NUL (sıfır byte'ı; dosya adında bulunamayan tek karakter) ile ayırır, xargs -0 da öyle okur. find'dan xargs'a giden her pipe'ı bu çiftle yaz. Aynı işi -exec rm {} + de güvenle yapar; xargs'ın asıl işe yaradığı yer -P 4 ile işi paralel çalıştırmak ya da -n 1 ile her seferinde tek argüman vermek. xargs'ın script'teki kullanımı Bash Scripting serisinin script'te veri akışı yazısında.
tar: Paketlemek, İçine Bakmak, Açmak
Release paketini kendi makinende hazırlıyorsun. Windows'ta çalışıyorsan bu adımı WSL'deki (Windows içinde Linux çalıştıran katman) Ubuntu'da ya da CI'daki Linux runner'ında yap; aşağıdaki komutlar orada aynı. Önce birinci yazıdaki komutla (dotnet publish src/Bookstore.Api -c Release -r linux-x64 --self-contained false -o out/publish) publish et, sonra paketle:
$ tar --zstd -cf bookstore-api-2026-11-15-1.tar.zst -C out/publish .
$ tar -tvf bookstore-api-2026-11-15-1.tar.zst
drwxr-xr-x ada/ada 0 2026-11-15 07:03 ./
-rw-r--r-- ada/ada 22244 2026-11-15 07:03 ./Bookstore.Api.pdb
-rw-r--r-- ada/ada 1198 2026-11-15 07:03 ./Bookstore.Api.deps.json
-rw-r--r-- ada/ada 472 2026-11-15 07:03 ./Bookstore.Api.runtimeconfig.json
-rw-r--r-- ada/ada 53 2026-11-15 07:03 ./Bookstore.Api.staticwebassets.endpoints.json
-rw-r--r-- ada/ada 15360 2026-11-15 07:03 ./Bookstore.Api.dll
-rwxr--r-- ada/ada 24360 2026-10-29 20:16 ./Microsoft.Extensions.Hosting.Systemd.dll
-rw-r--r-- ada/ada 119 2026-11-14 15:51 ./appsettings.json
-rwxr-xr-x ada/ada 78192 2026-11-15 07:03 ./Bookstore.Api
tar'ın harfleri: c oluştur, t listele, x aç; v ayrıntılı, f arşiv dosyasının adı (hemen arkasından gelir). Sıkıştırma -z (gzip), -J (xz) ve --zstd ile seçilir; açarken GNU tar sıkıştırmayı kendisi tanır, -tf ve -xf yeterli. -C out/publish . "önce bu klasöre geç, sonra içindekileri ekle" demek ve arşivdeki yolları belirler. -C'yi unutunca fark şu:
$ tar -czf without-c.tar.gz out/publish && tar -tzf without-c.tar.gz | head -n 3
out/publish/
out/publish/Bookstore.Api.pdb
out/publish/Bookstore.Api.deps.json
$ tar -czf nginx-conf.tar.gz /etc/nginx/sites-available
tar: Removing leading `/' from member names
$ tar -tzf nginx-conf.tar.gz
etc/nginx/sites-available/
etc/nginx/sites-available/default
İlk arşiv açıldığı yerde out/publish/ klasörü oluşturur; release klasörüne açtığında dosyalar bir alt klasörde kalır ve service Bookstore.Api.dll'i bulamaz. Absolute path ile eklemekte GNU tar baştaki /'ı kendisi siler ve uyarır; böylece arşiv açılırken /etc'nin üstüne yazmaz, bulunduğun yere etc/ açar. Bu uyarıyı görünce komutu -C /etc/nginx sites-available biçimine çevir. Hariç tutmak için --exclude: --exclude="*.pdb" ile debug sembollerini pakete koymazsın. Ben koydum, çünkü production'daki bir exception'ın stack trace'inde satır numarası görmek istiyorum.
gzip, xz, zstd ve zip
Bookstore'un framework-dependent paketi 70 KB; sıkıştırma algoritması burada fark etmez. Farkı görmek için aynı uygulamayı runtime'ı içine alarak (self-contained) publish ettim, klasör 106 MB oldu. Üç algoritmayla paketleyip açtım:
| Algoritma | tar bayrağı | Paket boyutu | Paketleme | Açma |
|---|---|---|---|---|
| gzip | -z | 47,9 MB | 2,69 sn | 0,52 sn |
| xz | -J | 35,2 MB | 20,45 sn | 2,03 sn |
| zstd | --zstd | 47,6 MB | 0,26 sn | 0,48 sn |
Süreler bu lab makinesinde ve tek ölçümle; mutlak sayılar sende farklı olur, oranlar benzer kalır. zstd varsayılan seviyesinde (3) gzip'le aynı boyutu on kat daha hızlı üretti. xz paketi dörtte bir küçülttü ama paketleme yaklaşık 80 kat yavaş. Her deploy'da üretilen ve birkaç gün tutulan release paketi için zstd, uzun süre saklanacak ve bir kez açılacak yedekler için xz mantıklı; on ikinci yazıdaki yedek de xz ile sıkıştırılıyordu. gzip her yerde açılabildiği için başkasına gönderdiğin dosyada hâlâ en güvenli seçim.
Paketi Windows kullanan bir ekip arkadaşına göndereceksen zip daha pratik; Windows Explorer zip'i doğrudan açar:
$ zip -qr bookstore-api-2026-11-15-1.zip out/publish && unzip -l bookstore-api-2026-11-15-1.zip | tail -n 3
78192 2026-11-15 07:03 out/publish/Bookstore.Api
--------- -------
141998 9 files
zip Linux'taki dosya sahibini ve grubunu taşımaz; sunucuya giden paket için tar kullan. Sıkıştırılmış tek bir dosyanın içine açmadan bakmak için zcat, xzcat, zstdcat ve yedinci yazıdaki zgrep var.
rsync: Sondaki / ve --delete
rsync iki klasörü karşılaştırır ve yalnızca farkı gönderir. En sık kullanılan bayraklar -a (izinleri, zamanları ve symlink'leri koru), -v (gönderilenleri yaz), -z (yolda sıkıştır) ve --dry-run (-n; hiçbir şey yapmadan ne yapacağını göster). Kaynaktaki sondaki /'ın anlamı:
$ rsync -av --dry-run out/publish bookstore-dev:/tmp/stage/
sending incremental file list
publish/
publish/Bookstore.Api
publish/Bookstore.Api.deps.json
...
$ rsync -av --dry-run out/publish/ bookstore-dev:/tmp/stage/
sending incremental file list
./
Bookstore.Api
Bookstore.Api.deps.json
...
out/publish klasörün kendisini, out/publish/ içindekileri gönderir. Hedefteki sondaki / ise fark etmez. --delete bu ayrımı tehlikeli hâle getirir, çünkü hedefte olup kaynakta olmayan her şeyi siler. Hedefi bir seviye yukarı yazdığımda:
$ rsync -av --delete --dry-run out/publish/ bookstore-dev:/opt/bookstore/
sending incremental file list
deleting releases/2026-11-14-6/web.config
deleting releases/2026-11-14-6/appsettings.json
...
deleting releases/2026-11-14-6/Bookstore.Api
deleting releases/2026-11-14-6/
deleting releases/
deleting current
./
Bookstore.Api
...
--dry-run olmasaydı bütün release'ler ve current link'i gidecekti. --delete'i her seferinde önce --dry-run ile çalıştır ve "deleting" satırlarını oku. Bookstore'da bu riski tamamen kaldırmak için release'i her seferinde yeni ve boş bir klasöre açıyoruz; o zaman --delete'e hiç gerek kalmaz.
rsync, scp ve sftp'nin üçü de SSH (uzak bağlantı protokolü) üzerinden çalışır ve birinci yazıdaki ~/.ssh/config alias'ını kullanır. Seçim yapılacak işe göre: rsync tekrar eden kopyalarda yalnızca farkı gönderir ve yarıda kalan aktarıma --partial ile devam edebilir; scp tek dosya için en kısa yol; sftp ise sunucuda gezinip dosya almak için etkileşimli bir oturum açar (-b ile script'ten de çalışır). OpenSSH 9.0'dan beri scp arka planda SFTP'yi (SSH üzerinden çalışan dosya aktarım protokolü) kullanıyor:
$ scp -v bookstore-api-2026-11-15-1.zip bookstore-dev:/tmp/stage/ 2>&1 | grep -i subsystem
debug1: Sending subsystem: sftp
Yani scp'nin eski protokolündeki dosya adı yorumlama sorunları artık yok; eski protokol gerekirse scp -O ile seçilir.
Bookstore: Paketi Taşımak ve Doğrulamak
Paketle birlikte checksum dosyasını da üret ve ikisini birlikte gönder:
$ sha256sum bookstore-api-2026-11-15-1.tar.zst > bookstore-api-2026-11-15-1.tar.zst.sha256
$ cat bookstore-api-2026-11-15-1.tar.zst.sha256
5f34d38564f81c58bcc4181f53adb823605d06bf59cce89885c5bc38b94d756e bookstore-api-2026-11-15-1.tar.zst
$ rsync -av bookstore-api-2026-11-15-1.tar.zst bookstore-api-2026-11-15-1.tar.zst.sha256 bookstore-dev:/tmp/stage/
sending incremental file list
bookstore-api-2026-11-15-1.tar.zst
bookstore-api-2026-11-15-1.tar.zst.sha256
sent 69,543 bytes received 54 bytes 139,194.00 bytes/sec
total size is 69,335 speedup is 1.00
$ rsync -av bookstore-api-2026-11-15-1.tar.zst bookstore-api-2026-11-15-1.tar.zst.sha256 bookstore-dev:/tmp/stage/
sending incremental file list
sent 106 bytes received 12 bytes 236.00 bytes/sec
total size is 69,335 speedup is 587.58
İkinci çalıştırmada rsync hiçbir şey göndermedi: dosyalar aynı. -z koymadım, çünkü zstd paketi zaten sıkıştırılmış. Sunucuda önce doğrula, sonra yeni ve boş bir release klasörüne deploy kullanıcısı olarak aç:
$ cd /tmp/stage
$ sha256sum -c bookstore-api-2026-11-15-1.tar.zst.sha256
bookstore-api-2026-11-15-1.tar.zst: OK
$ sudo -u deploy mkdir /opt/bookstore/releases/2026-11-15-1
$ sudo -u deploy tar -xf bookstore-api-2026-11-15-1.tar.zst -C /opt/bookstore/releases/2026-11-15-1
$ ls -l /opt/bookstore/releases/2026-11-15-1
total 160
-rwxr-xr-x 1 deploy bookstore 78192 Nov 15 07:03 Bookstore.Api
-rw-r--r-- 1 deploy bookstore 1198 Nov 15 07:03 Bookstore.Api.deps.json
-rw-r--r-- 1 deploy bookstore 15360 Nov 15 07:03 Bookstore.Api.dll
-rw-r--r-- 1 deploy bookstore 22244 Nov 15 07:03 Bookstore.Api.pdb
-rw-r--r-- 1 deploy bookstore 472 Nov 15 07:03 Bookstore.Api.runtimeconfig.json
-rw-r--r-- 1 deploy bookstore 53 Nov 15 07:03 Bookstore.Api.staticwebassets.endpoints.json
-rwxr--r-- 1 deploy bookstore 24360 Oct 29 20:16 Microsoft.Extensions.Hosting.Systemd.dll
-rw-r--r-- 1 deploy bookstore 119 Nov 14 15:51 appsettings.json
Dosyalar deploy'a ait ve grubu bookstore: root olmayan bir kullanıcının açtığı tar dosya sahibini arşivden almaz, grubu da üçüncü yazıdaki setgid release klasörü verir. Checksum'ın neyi yakaladığını görmek için paketin yarıda kesilmiş bir kopyasını denedim:
$ head -c 30000 bookstore-api-2026-11-15-1.tar.zst > /tmp/broken.tar.zst
$ sha256sum /tmp/broken.tar.zst bookstore-api-2026-11-15-1.tar.zst | cut -c1-16
dddd92d2d679eeef
5f34d38564f81c58
$ tar -tf /tmp/broken.tar.zst
/*stdin*\ : Read error (39) : premature end
tar: Child returned status 1
tar: Error is not recoverable: exiting now
$ cmp /tmp/broken.tar.zst bookstore-api-2026-11-15-1.tar.zst
cmp: EOF on /tmp/broken.tar.zst after byte 30000, in line 133
Bu sefer tar da hatayı yakaladı, çünkü zstd arşivin sonunu bulamadı. Ama bir byte'ı değişmiş bir dosyayı açarken tar her zaman hata vermez; checksum ise tek bit farkı bile yakalar. cmp iki dosyayı byte byte karşılaştırır ve ilk farkın yerini söyler; elinde iki kopya varsa checksum'a gerek bırakmaz. Checksum'ın sınırı da var: paketle aynı yoldan gelen bir .sha256 dosyası aktarım hatasını yakalar, ama paketi bilerek değiştiren biri checksum'ı da değiştirebilir. Buna karşı paketin imzalanması gerekir; o bu yazının konusu değil.
Release'i current'a almadan önce bir kontrol daha: sunucudaki mevcut release'te elle değiştirilmiş bir şey var mı?
$ diff -u /opt/bookstore/current/appsettings.json /opt/bookstore/releases/2026-11-15-1/appsettings.json
--- /opt/bookstore/current/appsettings.json 2026-11-14 22:41:00.000000000 +0000
+++ /opt/bookstore/releases/2026-11-15-1/appsettings.json 2026-11-14 15:51:10.000000000 +0000
@@ -1,7 +1,7 @@
{
"Logging": {
"LogLevel": {
- "Default": "Debug",
+ "Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
Biri dün gece 22:41'de sorun ayıklamak için log seviyesini sunucuda Debug'a çekmiş (lab'da bu değişikliği bilerek ben yaptım). Yeni release bunu geri alacak; bu doğru, ama bunu deploy'dan önce bilmek ve o kişiye sormak gerekir. diff -rq eski yeni iki klasörde farklı olan dosyaların listesini verir. Buradan sonrası serinin bildiğin kısmı: ln -sfn ile current'ı yeni release'e çevirmek (ikinci yazı) ve service'i restart etmek (beşinci yazı).
Üretimde Dikkat
Silen her find komutunu önce -print ile (ya da -exec echo ile) çalıştır ve çıktıyı oku; sonra yalnızca -print'i -delete ile değiştir. Bir timer'dan çalışacaksa yolu absolute yaz ve -maxdepth koy; yanlış bir değişken boş geldiğinde find'ın /'dan başlaması bu ikisiyle sınırlanır.
Saklama kuralını dosya yaşıyla değil, kaç yedek kaldığıyla da kontrol et. Yedek iş birkaç gün çalışmazsa "7 günden eskileri sil" bütün yedekleri siler; silmeden önce en az birkaç yedeğin kaldığını kontrol etmek bir script işi ve Bash Scripting serisinin yedek script'i yazısının konusu.
Paketi CI'da bir kez üret, checksum'ını CI'da al ve aynı paketi her ortama taşı; CI/CD Temelleri serisinin "Build Once, Deploy Many" yazısındaki kural. Sunucuda yeniden build etmek ya da paketi farklı makinelerde yeniden oluşturmak, test ettiğin şeyle deploy ettiğin şeyin aynı olmadığı anlamına gelir.
Sık Düşülen Tuzaklar
rsync --delete'i --dry-run'sız çalıştırmak, özellikle kaynakta sondaki /'ı ya da hedefin doğru seviyesini kontrol etmeden.
find'da -delete'i testlerden önce yazmak. Sıra ifadeyi belirler; -delete en sonda olmalı.
find | xargs rm'i boşluklu dosya adlarıyla kullanmak. -print0 | xargs -0 ya da -exec … {} +.
tar'a absolute path ile ya da -C'siz paketlemek. Açıldığında dosyalar beklenmeyen bir alt klasörde kalır.
-mtime +7'yi "7 günden eski" sanmak. Gerçek 7 gün için -mmin +10080 ya da ! -newermt "7 days ago".
Küçük Bir Deneme
★☆☆ Bir test klasöründe touch -d ile yaşları farklı on dosya oluştur ve -mtime +3, -mtime 3 ve -mtime -3'ün hangi dosyaları bulduğunu bir tabloya yaz.
★★☆ Bookstore'u self-contained publish et ve tar --zstd ile ZSTD_CLEVEL=19 verilmiş hâlini karşılaştır: boyut ne kadar küçüldü, süre ne kadar uzadı?
★★★ Paketi sunucuya rsync'le gönderirken bağlantıyı yarıda kes (Ctrl-C), sonra --partial ile ve onsuz tekrar başlat. Hangi durumda ne kadar veri yeniden gönderildi? Sonunda sha256sum -c ile doğrula.
Dosyaları sunucuya taşırken SSH'ı hep birinci yazıdaki tek bir alias ile kullandık. Bir sonraki ve serinin son yazısında SSH'ın daha derin kısmına iniyoruz: ~/.ssh/config'in ayrıntıları, bastion üzerinden private sunuculara bağlanmak, port forwarding ile uzak veritabanına tünel kurmak ve agent forwarding'in riski.