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:
/tmpaltında world-writable (777) dizinler symlink attack vektörü oluşturabilir - Sticky bit kullan: Paylaşılan dizinlerde
1777veya1770kullan - Yaş değerini çok kısa tutma: Çok agresif temizlik aktif kullanılan dosyaları silebilir
Ztipini 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.