systemd-tmpfiles ile Geçici Dosya Yönetimi

Geçici dosyalar, sistem yöneticilerinin en çok görmezden geldiği ama en fazla baş ağrısı yaratan konuların başında gelir. /tmp altında biriken eski dosyalar, uygulama önbellekleri, pid dosyaları, lock dosyaları… Bunları manuel temizlemek hem zahmetli hem de hata yapmaya açık. İşte tam bu noktada systemd-tmpfiles devreye giriyor ve bu karmaşayı son derece düzenli bir şekilde yönetmeni sağlıyor.

systemd-tmpfiles Nedir ve Neden Önemli?

systemd-tmpfiles, sistemin başlangıcında ve periyodik aralıklarla geçici dizinleri ve dosyaları oluşturan, temizleyen ve yöneten bir systemd bileşenidir. Eski sysadminlerin cron ile yaptığı find /tmp -mtime +7 -delete işlemlerinin çok daha güvenli, tutarlı ve merkezi bir alternatifidir.

Sadece temizlik yapmaz. Aynı zamanda:

  • Belirli dizinleri doğru izinlerle oluşturur
  • Dosyaların sahipliğini (ownership) ayarlar
  • Sembolik linkler kurar
  • Belirli dosyaları önyükleme sırasında temizler veya oluşturur

Bu mekanizma olmadan her uygulama kendi geçici dizinlerini farklı şekillerde yönetmeye çalışır. systemd-tmpfiles ile bu kaos ortadan kalkar.

Yapılandırma Dosyalarının Konumu

systemd-tmpfiles üç farklı dizinden yapılandırma okur ve bunlar arasında öncelik sırası vardır:

  • /etc/tmpfiles.d/: Sistem yöneticisinin özel tanımları, en yüksek öncelik
  • /run/tmpfiles.d/: Çalışma zamanında oluşturulan geçici tanımlar
  • /usr/lib/tmpfiles.d/: Paketler tarafından sağlanan varsayılan tanımlar

Eğer aynı isimde bir dosya hem /etc/tmpfiles.d/ hem de /usr/lib/tmpfiles.d/ altında varsa, /etc/tmpfiles.d/ içindeki kazanır. Bu da sistem paketlerinin davranışını bozma korkusu olmadan özelleştirme yapmanı sağlar.

Mevcut tanımları görmek için şu komutu çalıştırabilirsin:

ls -la /usr/lib/tmpfiles.d/
ls -la /etc/tmpfiles.d/

Sistemde yüklü olan birçok paketin kendi tmpfiles.d tanımlarına sahip olduğunu göreceksin. Mesela systemd, dbus, x11, nginx gibi paketlerin tümü burada dosya bırakır.

Dosya Formatını Anlamak

Her yapılandırma dosyası satır bazlı bir formata sahiptir. Her satır bir kuralı temsil eder ve alanlar boşlukla ayrılır:

Tip  Yol  Mod  Kullanici  Grup  Yas  Arguman

Buradaki alanları açıklayalım:

  • Tip: Ne yapılacağını belirler (d, f, L, z, v, vs.)
  • Yol: Dosya veya dizin yolu
  • Mod: İzin modu (0755 gibi), - ile atlanabilir
  • Kullanici: Dosya sahibi, - ile mevcut bırakılır
  • Grup: Dosya grubu, - ile mevcut bırakılır
  • Yas: Temizleme eşiği (yaşlanan dosyalar için), - ile devre dışı
  • Arguman: Tip’e göre değişen ek parametre

Tip Kodları

En sık kullanılan tip kodları şunlar:

  • d: Dizin oluşturur, belirtilen modda; varsa dokunmaz, yaşlı dosyaları temizler
  • D: Dizin oluşturur ve her seferinde içini temizler
  • f: Dosya oluşturur (varsa dokunmaz)
  • F: Dosya oluşturur veya varsa içeriğini sıfırlar (truncate)
  • L: Sembolik link oluşturur
  • z: Dosya veya dizinin izinlerini ve sahipliğini günceller
  • Z: Dizini özyinelemeli (recursive) olarak günceller
  • r: Dosya veya dizini siler (içi boş olmalı)
  • R: Dizini içiyle birlikte özyinelemeli siler
  • w: Dosyaya içerik yazar
  • c: Karakter cihazı (device) oluşturur
  • v: Subvolume oluşturur (btrfs için), normal sistemlerde dizin gibi davranır
  • x: Temizleme sırasında bu yolu ve altını görmezden gel
  • X: Temizleme sırasında bu yolu görmezden gel ama alt dizinleri temizle
  • e: Sadece temizleme yap, oluşturma

Yaş (Age) Alanı

Yaş alanı özellikle güçlü bir özellik. Şu formatları destekler:

  • 10d: 10 gün
  • 1w: 1 hafta
  • 2h: 2 saat
  • 30m: 30 dakika
  • 1d12h: 1 gün 12 saat (birleştirilebilir)

Sadece d tipiyle kullanıldığında, o dizin içinde belirtilen süre boyunca erişilmemiş dosyalar silinir. Bu oldukça hassas bir mekanizma; dizinin kendisi silinmez, sadece yaşlanan içerik temizlenir.

Gerçek Dünya Senaryosu 1: Uygulama İçin Geçici Dizin

Diyelim ki myapp adında bir uygulama geliştirdin ve bu uygulama /var/run/myapp altında pid dosyası ve socket dosyası oluşturuyor. Sistem her yeniden başladığında bu dizinin doğru izinlerle var olması gerekiyor.

# /etc/tmpfiles.d/myapp.conf
cat > /etc/tmpfiles.d/myapp.conf << 'EOF'
# myapp için runtime dizini
d /run/myapp 0750 myapp myapp -
d /run/myapp/sockets 0750 myapp myapp -
f /run/myapp/myapp.pid 0640 myapp myapp -
EOF

Bu tanımı uygulamak için:

# Sadece oluşturma işlemleri için
systemd-tmpfiles --create /etc/tmpfiles.d/myapp.conf

# Sonucu kontrol et
ls -la /run/myapp/

Sistem yeniden başladığında systemd-tmpfiles-setup.service bu dosyayı okuyacak ve dizini otomatik olarak doğru sahiplik ve izinlerle oluşturacak. Artık ExecStartPre içinde mkdir -p komutu çalıştırmak zorunda değilsin.

Gerçek Dünya Senaryosu 2: Log Rotasyonunda Eski Logları Temizlemek

Bir web uygulamasının debug logları /var/log/myapp/debug/ altında toplanıyor ve bunlar hızla büyüyor. logrotate zaten ana logları hallediyor ama debug dizini için 2 günden eski her şeyin silinmesini istiyorsun:

cat > /etc/tmpfiles.d/myapp-cleanup.conf << 'EOF'
# 2 gunden eski debug loglarini temizle
d /var/log/myapp/debug 0755 myapp myapp 2d

# tmp kopyalar 1 saatten uzun sure kalmamali
d /var/log/myapp/tmp 0750 myapp myapp 1h
EOF

Temizleme işlemini manuel tetiklemek için:

systemd-tmpfiles --clean /etc/tmpfiles.d/myapp-cleanup.conf

Periyodik temizlik için systemd-tmpfiles-clean.timer servisi zaten her günlük çalışıyor. Kontrol etmek için:

systemctl status systemd-tmpfiles-clean.timer
systemctl list-timers systemd-tmpfiles-clean.timer

Gerçek Dünya Senaryosu 3: Güvenli Paylaşılan Geçici Dizin

Birden fazla servisin ortak kullandığı bir geçici dizin kurmak istiyorsun. Ama bu dizin sticky bit ile korunmalı, herkes yazabilmeli ama sadece kendi dosyasını silebilmeli:

cat > /etc/tmpfiles.d/shared-tmp.conf << 'EOF'
# Paylasilan gecici dizin, sticky bit ile
d /var/tmp/shared 1777 root root 7d

# Her uygulamanin kendi alt dizini
d /var/tmp/shared/app1 0770 app1 appgroup 3d
d /var/tmp/shared/app2 0770 app2 appgroup 3d

# Bu dizini temizleme sirasinda atla (onemli veri olabilir)
x /var/tmp/shared/important
EOF

Buradaki 1777 modu, sticky bit + herkes okur/yazar/çalıştırır anlamına gelir. x tipi ise important dizinini temizleme işleminin kapsamı dışında tutar.

Gerçek Dünya Senaryosu 4: Sembolik Link Yönetimi

Bazen uyumluluk için eski konumlara sembolik linkler koymak gerekir. Örneğin bir uygulama /tmp/app-socket bekliyor ama gerçek socket /run/myapp/app.sock altında:

cat > /etc/tmpfiles.d/compat-links.conf << 'EOF'
# Uyumluluk icin sembolik linkler
L /tmp/app-socket - - - - /run/myapp/app.sock

# Eski konumdan yeni konuma yonlendirme
L /var/run/myapp - - - - /run/myapp
EOF

L tipinde mod, kullanıcı, grup ve yaş alanları görmezden gelinir, bu yüzden - yazıyoruz. Son alan ise linkin göstereceği hedef.

Mevcut Yapılandırmaları İnceleme

Sistemde neyin nasıl yönetildiğini anlamak için mevcut tanımları inceleyebilirsin:

# Nginx'in tmpfiles tanımini incele
cat /usr/lib/tmpfiles.d/nginx.conf

# Tum tmpfiles yapilandirmalarini listele
find /usr/lib/tmpfiles.d /etc/tmpfiles.d -name "*.conf" | sort

# Belirli bir yola dokunacak kurallari bul
grep -r "/run/myapp" /usr/lib/tmpfiles.d/ /etc/tmpfiles.d/ 2>/dev/null

Nginx’in tmpfiles tanımı genellikle şuna benzer bir içerik taşır:

cat /usr/lib/tmpfiles.d/nginx.conf
# d /var/log/nginx 0755 root root -
# d /var/lib/nginx 0755 www-data www-data -

Bu tip tanımları görmek, kendi uygulamaların için doğru şablonlar oluşturmana yardımcı olur.

Hata Ayıklama ve Test

Yapılandırmanı uygulamadan önce test etmek çok önemli. --dry-run veya debug modları kullanabilirsin:

# Kurallari kontrol et ama uygulama
systemd-tmpfiles --create --dry-run /etc/tmpfiles.d/myapp.conf

# Hangi dosyalarin temizlenecegini gör
systemd-tmpfiles --clean --dry-run /etc/tmpfiles.d/myapp-cleanup.conf

# Tum tmpfiles kurallarini isle (sistem geneli)
systemd-tmpfiles --create

# Sadece belirli bir prefixle baslayan yollari isle
systemd-tmpfiles --create --prefix=/run/myapp

Bir servis dosyasında tmpfiles entegrasyonu nasıl görünür buna da bakalım:

# /etc/systemd/system/myapp.service
cat > /etc/systemd/system/myapp.service << 'EOF'
[Unit]
Description=MyApp Service
After=network.target

[Service]
Type=simple
User=myapp
Group=myapp
ExecStart=/usr/bin/myapp --config /etc/myapp/config.yaml
RuntimeDirectory=myapp
RuntimeDirectoryMode=0750
# Ya da tmpfiles.d kullanmak istersen:
# ExecStartPre=systemd-tmpfiles --create /etc/tmpfiles.d/myapp.conf

[Install]
WantedBy=multi-user.target
EOF

Burada RuntimeDirectory=myapp seçeneği aslında /run/myapp dizinini otomatik oluşturup servis durduğunda siler. Ama daha karmaşık senaryolarda tmpfiles.d daha fazla kontrol sağlar.

Tmpfiles ve Systemd Timer Entegrasyonu

systemd-tmpfiles-clean.timer varsayılan olarak günde bir kez temizlik yapar. Bunu özelleştirmek isteyebilirsin:

# Timer durumunu kontrol et
systemctl status systemd-tmpfiles-clean.timer

# Timer detaylarini gör
systemctl cat systemd-tmpfiles-clean.timer

Çıktı genellikle şuna benzer:

[Unit]
Description=Daily Cleanup of Temporary Directories
Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)

[Timer]
OnBootSec=15min
OnUnitActiveSec=1d

Eğer daha sık temizlik gerekiyorsa, bunu override edebilirsin:

mkdir -p /etc/systemd/system/systemd-tmpfiles-clean.timer.d/

cat > /etc/systemd/system/systemd-tmpfiles-clean.timer.d/override.conf << 'EOF'
[Timer]
OnBootSec=5min
OnUnitActiveSec=6h
EOF

systemctl daemon-reload
systemctl restart systemd-tmpfiles-clean.timer

Güvenlik Konuları

tmpfiles.d kullanırken birkaç önemli güvenlik noktasına dikkat etmek gerekir:

  • Dosya izinlerini asla gevşek bırakma: /tmp altında world-writable (777) dizinler symlink attack vektörü oluşturabilir
  • Sticky bit kullan: Paylaşılan dizinlerde 1777 veya 1770 kullan
  • Yaş değerini çok kısa tutma: Çok agresif temizlik aktif kullanılan dosyaları silebilir
  • Z tipini dikkatli kullan: Büyük dizin ağaçlarında özyinelemeli izin değişikliği hem yavaş hem de beklenmeyen sonuçlar doğurabilir
# Yanlis - Guclu guvensizlik
d /tmp/myapp 0777 root root -

# Dogru - Sticky bit ile guveli paylasim
d /tmp/myapp 1770 myapp myapp 1d

# Kullanici izolasyonu icin
d /tmp/myapp 0700 myapp myapp 1d

Paket Yönetimi ile Entegrasyon

Kendi uygulamalarını paket olarak dağıtıyorsan, tmpfiles.d dosyalarını pakete dahil etmek iyi bir pratiktir. Debian tabanlı sistemlerde:

# Paket postinst scripti yerine tmpfiles kullan
# /usr/lib/tmpfiles.d/mypackage.conf dosyasini paketle birlikte dagit

# Paketi kurduktan sonra tmpfiles'i elle tetikle
systemd-tmpfiles --create /usr/lib/tmpfiles.d/mypackage.conf

RPM tabanlı sistemlerde spec dosyasına ekleyebilirsin:

%post
systemd-tmpfiles --create %{_tmpfilesdir}/%{name}.conf || :

Systemd-tmpfiles vs Cron Temizliği

Eski yöntemle yeni yöntemi karşılaştıralım. Eski sysadmin alışkanlığı şöyle bir şeydi:

# Eski yontem - crontab'a eklenirdi
# Her gece saat 02:00'de calis
0 2 * * * find /var/tmp/myapp -mtime +7 -type f -delete
0 2 * * * find /var/tmp/myapp -mtime +7 -type d -empty -delete

Bu yaklaşımın sorunları:

  • Race condition riski var
  • Sistem başlangıcında çalışmaz
  • Root crontab’ı kirletir
  • Hata yönetimi zayıf
  • Audit edilmesi güç

tmpfiles.d ile:

# Yeni yontem - temiz, guvenli, denetlenebilir
cat > /etc/tmpfiles.d/myapp.conf << 'EOF'
d /var/tmp/myapp 0750 myapp myapp 7d
EOF

Tek satır, tüm ihtiyacı karşılıyor. Sistem başlangıcında da çalışıyor, timer ile periyodik de. Systemd journal’a log da yazıyor.

Journald ile Log Takibi

Tmpfiles işlemlerini takip etmek için:

# Tmpfiles servisinin loglarini gör
journalctl -u systemd-tmpfiles-setup.service
journalctl -u systemd-tmpfiles-clean.service

# Son temizlik islemini kontrol et
journalctl -u systemd-tmpfiles-clean.service --since today

# Hata olan satirlari filtrele
journalctl -u systemd-tmpfiles-setup.service -p err

Pratik Bir Kontrol Listesi

Yeni bir uygulama deploy ederken izlemen gereken adımlar:

# 1. Yapılandırma dosyasini olustur
vim /etc/tmpfiles.d/yeniuygulama.conf

# 2. Sozdizimini kontrol et
systemd-tmpfiles --create --dry-run /etc/tmpfiles.d/yeniuygulama.conf

# 3. Uygula
systemd-tmpfiles --create /etc/tmpfiles.d/yeniuygulama.conf

# 4. Sonucu dogrula
stat /run/yeniuygulama
ls -la /run/yeniuygulama/

# 5. Timer'in calistigini onayladi
systemctl is-active systemd-tmpfiles-clean.timer

Sonuç

systemd-tmpfiles, sistem yönetimindeki en küçük ama en etkili araçlardan biri. Bir zamanlar cron scriptleri, rc.local yamalamaları ve elle yazılmış init script’leriyle yönettiğimiz geçici dosya karmaşasını artık merkezi, denetlenebilir ve güvenli bir yapıyla hallediyor.

Özellikle microservice mimarileri ve konteyner altyapısıyla uğraşıyorsan, her servisin kendi tmpfiles.d tanımını taşıması idempotent deployment’lar için büyük kolaylık sağlıyor. Sistemi kaç kez yeniden başlatırsan başlat, dizinler ve izinler her seferinde doğru şekilde yerine geliyor.

Eğer hâlâ cron ile geçici dosya temizliği yapıyorsan veya servis başlatma script’lerinde mkdir -p + chmod + chown üçlüsünü tekrarlıyorsan, bugün tmpfiles.d‘ye geçmek için iyi bir zaman. Hem senin hem de sistemi sonra devralacak kişinin işini çok kolaylaştırır.

Yorum yapın