cpio Komutu ile Arşiv Oluşturma, Geri Yükleme ve find ile Entegre Kullanım
Sistem yöneticiliğinde arşivleme denilince akla hemen tar gelir. Haklı da, çünkü tar bugün neredeyse her Linux dağıtımında varsayılan tercih. Ama cpio komutunu hiç ciddi anlamda kullanmadıysanız, masada ciddi bir koz bırakıyorsunuz demektir. Özellikle find ile birleştiğinde cpio, tar’ın kolayca yapamayacağı şeyleri son derece zarif bir şekilde hallediyor. Bu yazıda cpio’yu gerçekten işe yarar şekilde nasıl kullanacağınızı, hangi senaryolarda tar’a tercih etmeniz gerektiğini ve find ile entegrasyonunun neden bu kadar güçlü olduğunu anlatacağım.
cpio Nedir ve Neden Hala Önemlidir
cpio, “copy in/out” kelimelerinin kısaltmasıdır ve 1970’lerin Unix geleneğinden gelen bir arşivleme aracıdır. İlk bakışta eski teknoloji gibi görünebilir ama Linux çekirdeğinin initramfs yapısına bakın: orada cpio formatı kullanılıyor. RPM paketlerinin içine bakın, yine cpio. Yani bu araç sandığınızdan çok daha fazla yerde aktif rol oynuyor.
cpio’nun temel felsefesi şu: araç kendisi dosya listesi üretmiyor, ona bir dosya listesi veriyorsunuz, o da bu listeyi işliyor. Bu tasarım kararı, find ile entegrasyonu neredeyse doğal kılıyor. Karmaşık filtreleme mantığını find’a bırakıyorsunuz, cpio da sadece arşivleme işini yapıyor.
Üç temel mod var:
-o(copy-out): Arşiv oluşturma modu, stdin’den dosya adlarını okur-i(copy-in): Arşivden dosya çıkarma modu-p(pass-through): Bir dizinden diğerine kopyalama modu, arşiv oluşturmadan
Temel Söz Dizimi ve İlk Örnekler
cpio’nun söz dizimi başlangıçta biraz yabancı gelebilir çünkü pipe bağımlı bir yapısı var.
# Basit bir arşiv oluşturma - mevcut dizindeki tüm dosyaları arşivle
find . -type f | cpio -o > arsiv.cpio
# Arşivi geri yükleme
cpio -i < arsiv.cpio
# Arşiv içeriğini listeleme (extract etmeden)
cpio -it < arsiv.cpio
Buraya kadar her şey basit. Şimdi sık kullanılan parametreleri geçelim:
-o: Copy-out modu, arşiv oluşturur
-i: Copy-in modu, arşivden dosya çıkarır
-p: Pass-through modu, doğrudan kopyalama yapar
-v: Verbose, işlenen dosyaları ekrana basar
-d: Gerekli dizinleri otomatik oluşturur (extract sırasında kritik)
-t: İçeriği listeler, extract etmez
-u: Üzerine yaz, varolan dosyaları güncelle
--format=FORMAT: Arşiv formatını belirtir (newc, odc, tar, crc)
-H FORMAT: --format ile aynı, kısa sözdizimi
-m: Dosya değiştirilme zamanlarını koru
-l: Pass-through modunda kopyalamak yerine hard link oluştur
--quiet: “X blocks” çıktısını bastır
-F DOSYA: Arşiv dosyasını belirt (stdin/stdout yerine)
find ile Entegrasyon: Gerçek Güç Burada
cpio’nun tek başına kullanımı sınırlı. Asıl büyüsü find ile birleşince ortaya çıkıyor. find’ın sunduğu granüler filtreleme seçeneklerini arşivleme sürecine dahil edebiliyorsunuz.
# Son 7 günde değişen dosyaları arşivle
find /var/log -mtime -7 -type f | cpio -ov > son_7_gun_loglar.cpio
# Belirli uzantıdaki dosyaları arşivle
find /home/ahmet -name "*.py" -o -name "*.sh" | cpio -ov > scriptler.cpio
# Belirli bir kullanıcıya ait dosyaları arşivle
find /srv/data -user webapp -type f | cpio -ov > webapp_dosyalari.cpio
Bu üçüncü örnek özellikle önemli. Bir kullanıcıya ait tüm dosyaları bulmak ve arşivlemek için tar ile ne yapardınız? Oldukça kıvrık bir yol izlemeniz gerekirdi. cpio ile bu iş tek satırda.
# 100MB'dan büyük dosyaları listele ve arşivle
find /var/www -size +100M -type f | cpio -ov > buyuk_dosyalar.cpio
# Belirli izinlere sahip dosyaları arşivle (SUID/SGID bitleri set edilmiş)
find / -perm /6000 -type f 2>/dev/null | cpio -ov > suid_sgid_dosyalar.cpio
Son örnek güvenlik denetimi senaryolarında işe yarıyor. Sistemdeki tüm SUID/SGID dosyalarını bir arşive almak, sonra başka bir sistemle karşılaştırmak klasik bir güvenlik kontrol yöntemi.
Sıkıştırma ile Kullanım
cpio doğrudan sıkıştırma yapmaz ama pipe zincirinde gzip, bzip2 veya xz kullanabilirsiniz:
# gzip ile sıkıştırılmış arşiv oluştur
find /etc -type f | cpio -ov | gzip > etc_yedek.cpio.gz
# xz ile daha iyi sıkıştırma (daha yavaş ama daha küçük)
find /home -type f | cpio -ov | xz -9 > home_yedek.cpio.xz
# Gzip'li arşivi geri yükle
gunzip -c etc_yedek.cpio.gz | cpio -idv
# xz'li arşivi geri yükle
xz -dc home_yedek.cpio.xz | cpio -idv
Burada küçük ama önemli bir nokta: extract ederken -d parametresini unutmayın. Yoksa hedef dizinler mevcut değilse cpio dosyaları yerleştiremez ve hata verir. Bunu bir kez production’da unuttuğumda restore işlemi sessizce başarısız olmuştu, hiç dosya yazılmamıştı. O günden sonra refleks haline geldi -idv kombinasyonu.
Pass-Through Modu ile Dizin Kopyalama
-p modu az bilinen ama çok kullanışlı bir özellik. Bir dizin ağacını arşiv oluşturmadan başka bir konuma kopyalamanızı sağlıyor ve meta verileri (izinler, zaman damgaları, sahiplik) mükemmel şekilde koruyor.
# /opt/uygulama dizinini /backup/uygulama altına kopyala
find /opt/uygulama -depth | cpio -pdv /backup/uygulama
# Sembolik linkleri de dahil et
find /var/www/html -depth | cpio -pdlv /backup/www
-depth parametresini dikkat ettiniz mi? find’a verilen bu parametre önce dizin içeriğini, sonra dizinin kendisini listeliyor. cpio ile çalışırken bu sıralama izin sorunlarını engelliyor. Özellikle read-only mount edilmiş dizinleri veya özel izinlere sahip dizinleri kopyalarken -depth şart.
rsync ile karşılaştırıldığında pass-through mod ne zaman tercih edilir? Lokal kopyalama senaryolarında ve özellikle hard link’leri korumak istediğinizde cpio daha güvenilir sonuçlar veriyor. -l parametresi ile kopyalama yerine hard link oluşturabilirsiniz:
# Kopyalamak yerine hard link oluştur (disk tasarrufu için)
find /data/kaynak -depth | cpio -pdlv /data/hedef
Gerçek Dünya Senaryosu: Konfigürasyon Dosyaları Yedekleme
Bir web sunucusunda nginx, PHP-FPM, MySQL ve çeşitli uygulama konfigürasyonları var. Tüm konfigürasyon dosyalarını tek bir arşivde toplamak istiyorsunuz:
#!/bin/bash
# konfig_yedek.sh
TARIH=$(date +%Y%m%d_%H%M%S)
HEDEF="/backup/konfig_${TARIH}.cpio.gz"
# Birden fazla find çıktısını birleştir
{
find /etc/nginx -type f -name "*.conf"
find /etc/php -type f -name "*.ini" -o -name "*.conf"
find /etc/mysql -type f
find /etc/systemd/system -name "*.service" -type f
find /home -name ".bashrc" -o -name ".bash_profile" -maxdepth 2
} | sort -u | cpio -ov | gzip > "$HEDEF"
echo "Yedek oluşturuldu: $HEDEF"
echo "Boyut: $(du -sh $HEDEF | cut -f1)"
sort -u burada önemli, çünkü birden fazla find çıktısını birleştirdiğinizde tekrar eden dosyalar olabilir. cpio tekrar eden girişleri işlemeye çalışır ve bu bazen sorun çıkarır.
Arşiv Formatları: newc vs odc
cpio birkaç farklı arşiv formatını destekliyor. Varsayılan genellikle odc (eski POSIX formatı) ama Linux sistemlerinde newc formatı daha yaygın ve tercih edilen.
# newc formatında arşiv oluştur (initramfs için standart)
find . | cpio -o --format=newc > arsiv.cpio
# Veya eşdeğer kısa sözdizimi
find . | cpio -oH newc > arsiv.cpio
# crc formatı (newc + checksum)
find . | cpio -oH crc > arsiv_crc.cpio
odc: POSIX.1 uyumlu eski format, maksimum taşınabilirlik
newc: SVR4 formatı, 4GB üzeri dosya desteği, Linux initramfs standardı
crc: newc + her dosya için checksum, veri bütünlüğü kontrolü
tar: cpio ile tar formatında arşiv oluşturulabilir (nadiren kullanılır)
bin: Eski binary format, modern sistemlerde kullanmayın
initramfs üzerinde çalışıyorsanız kesinlikle newc kullanın. Kernel bu formatı bekliyor.
initramfs ile Çalışma
Linux dünyasında cpio’nun en kritik kullanım alanlarından biri initramfs. Önyükleme sorunlarını debug ederken veya özel bir initramfs oluşturmak istediğinizde bu bilgi hayat kurtarıyor:
# Mevcut initramfs içeriğini görüntüle
mkdir /tmp/initramfs_icerik
cd /tmp/initramfs_icerik
gunzip -c /boot/initramfs-$(uname -r).img | cpio -idv
# Değişiklik yaptıktan sonra yeni initramfs oluştur
find . | cpio -o --format=newc | gzip > /boot/initramfs-custom.img
# Bazı sistemlerde initramfs birleşik format kullanır
# Bu durumda skip-ahead ile gerçek cpio bölümünü bul
skipcpio /boot/initramfs-$(uname -r).img | gunzip | cpio -itv
Initramfs içeriğini kurcalamak zorunda kaldığınızda (ki bazen kalıyorsunuz, özellikle LUKS veya özel driver senaryolarında) cpio olmadan bu işi yapamazsınız.
Seçici Geri Yükleme ve Desen Eşleştirme
Büyük bir arşivden sadece belirli dosyaları çıkarmak istediğinizde:
# Sadece .conf dosyalarını çıkar
cpio -idv "*.conf" < arsiv.cpio
# Belirli bir dizin altındakileri çıkar
cpio -idv "etc/nginx/*" < arsiv.cpio
# Birden fazla desen
cpio -idv "*.py" "*.sh" "*.conf" < arsiv.cpio
# Önce içeriği listele, sonra karar ver
cpio -it < arsiv.cpio | grep ".conf$"
Bu seçici geri yükleme özelliği tar ile de yapılabilir ama cpio’nun sözdizimi burada daha temiz.
Büyük Ölçekli Dosya Taşıma: Gerçek Bir Senaryo
Şirketteki bir migrasyonda karşılaştığım durumu paylaşayım. 2 milyon küçük dosya içeren bir NFS mount’ından başka bir storage’a geçiş yapıyorduk. rsync bu senaryoda inanılmaz yavaştı, her dosya için ayrı metadata sorgusu yaptığı için. tar ile deneyin problemi ise hata toleransının düşük olmasıydı.
# Kaynak sunucuda
find /data/uygulama -depth -print0 |
cpio --null -ov --format=newc |
ssh hedef-sunucu "cd /data/yeni_konum && cpio -idv"
# Veya önce arşiv oluşturup sonra transfer
find /data/uygulama -depth | cpio -ov --format=newc |
pigz -p 4 > /tmp/transfer.cpio.gz
# Hedefte
pigz -dc /tmp/transfer.cpio.gz | cpio -idv
--null ve -print0 kombinasyonu boşluk veya özel karakter içeren dosya adlarını doğru işlemek için kritik. Production’da bu olmadan yaparsanız bir gün patlarsınız.
pigz kullanımı da önemli: çok çekirdekli sıkıştırma ile transfer süresi ciddi ölçüde düşüyor.
Hata Ayıklama ve Doğrulama
Arşiv oluşturduktan sonra doğrulama yapmak iyi bir alışkanlık:
# Arşiv bütünlük kontrolü (extract etmeden)
cpio -it --quiet < arsiv.cpio > /dev/null && echo "Arşiv geçerli" || echo "Arşiv bozuk"
# Dosya sayısını kontrol et
echo "Arşivdeki dosya sayısı: $(cpio -it < arsiv.cpio 2>/dev/null | wc -l)"
# crc formatıyla oluşturulmuş arşivin checksum doğrulaması
cpio -it --format=crc < arsiv_crc.cpio > /dev/null
# Orijinal dosya listesiyle karşılaştır
find /etc -type f | sort > /tmp/orijinal_liste.txt
cpio -it < arsiv.cpio | sort > /tmp/arsiv_listesi.txt
diff /tmp/orijinal_liste.txt /tmp/arsiv_listesi.txt
Yaygın Hatalar ve Çözümleri
Pratikte sık karşılaşılan birkaç durumu ele alalım:
“cpio: warning: skipped N bytes of junk”: Arşiv başında gereksiz veri var, genellikle birden fazla arşiv birleştirilmiş. --quiet ile bastırabilir veya offset atlama yöntemleri kullanabilirsiniz.
İzin reddedilen dosyalar: find ile tarama yaparken 2>/dev/null ekleyin ama bu hataları görmezden gelmek anlamına gelir. Production’da hata logunu ayrıca tutun:
find /etc -type f 2>/tmp/erisim_hatalari.txt | cpio -ov > yedek.cpio
Büyük arşivlerde ilerleme takibi: cpio doğal olarak ilerleme göstermez, pv (pipe viewer) ile bu sorunu çözebilirsiniz:
find /data -type f | cpio -ov 2>&1 | pv -l -s $(find /data -type f | wc -l) > /dev/null
Sonuç
cpio bugün bile sistem yöneticisinin araç kutusunda yerini hak eden bir komut. Özellikle şu senaryolarda tar’a kesinlikle tercih ederim: karmaşık dosya seçim kriterlerine dayalı arşivleme, initramfs işlemleri, hard link koruması gerektiren kopyalama işlemleri ve büyük miktarda küçük dosya taşıma. find ile kurduğu doğal ittifak sayesinde çok satırlı betik yazmadan karmaşık arşivleme görevlerini tek pipe zincirinde halledebiliyorsunuz.
tar daha kullanıcı dostu ve tek başına çalışabilir olduğu için günlük kullanımda tercih edilir, bu anlaşılır bir durum. Ama cpio’yu bilmek sizi daha iyi bir sistem yöneticisi yapıyor çünkü araçların neden var olduğunu, neyi çözmek için tasarlandığını anlıyorsunuz. Linux’un derinliklerinde, initramfs’tan RPM paket formatına kadar her yerde cpio izlerine rastlayacaksınız. O izleri tanıyabilmek önemli.
Son olarak: -idv kombinasyonunu extract yaparken asla ihmal etmeyin, -depth parametresini find ile birlikte kullanın ve özel karakterli dosya adları için her zaman --null/-print0 kullanın. Bu üç kural sizi büyük acılardan korur.
