0Pricing
DevOps Bootcamp · Ders

Güvenli Geçici Dosyalar ve Kilit Dizinleri

Yarış durumlarını önleyen geçici kaynaklar oluşturmak ve betiklerin eşzamanlı çalışmasını engellemek için mktemp ve flock kullanın.

Güvenli Geçici Dosyalar ve Kilit Dizinleri, CoddyKit'te ücretsiz bir DevOps Bootcamp dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, DevOps Bootcamp öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. DevOps Bootcamp kursu toplamda 4 dersten oluşur.

Geçici Dosyalar Neden Güvenlik Riski Oluşturur

Bash betikleri sıklıkla geçici depolamaya ihtiyaç duyar: ara sonuçlar, kilit işaretleri ve hazırlama alanları. Ancak geçici dosyaları dikkatsizce oluşturmak ciddi güvenlik açıklarına yol açar.

  • Yarış durumları: Başka bir işlem dosya adınızı tahmin edip dosyayı önce oluşturabilir ve yazma işlemlerinizi başka yöne yönlendirebilir.
  • Sembolik bağ saldırıları: Saldırgan, beklediğiniz yolda /etc/passwd gibi hassas bir dosyaya işaret eden bir sembolik bağ oluşturabilir.
  • Artakalan dosyalar: Bir betik çökerse geçici dosyalar birikir ve hassas verileri açığa çıkarabilir.

Bu sorunları ortadan kaldıran iki temel araç mktemp ve flock'tur. Bu derste ikisini de güvenli ve savunmacı biçimde nasıl kullanacağınızı göstereceğiz.

mktemp ile Güvenli Geçici Dosyalar Oluşturma

mktemp, rastgele ve öngörülemez bir ada sahip geçici bir dosya oluşturur ve yolunu döndürür. Dosyayı atomik olarak oluşturduğundan başka hiçbir işlem adı önce alamaz.

  • Sözdizimi: mktemp [TEMPLATE] — şablon en az üç X karakteriyle bitmelidir.
  • Her X rastgele bir karakterle değiştirilir ve /tmp/script.aB3kQz gibi benzersiz bir ad oluşturulur.
  • Dosya otomatik olarak 0600 izinleriyle oluşturulur (yalnızca sahibi tarafından okunabilir).

Döndürülen yolu daha sonra başvurup temizleyebilmek için her zaman hemen bir değişkene alın.

#!/usr/bin/env bash
set -euo pipefail

# Create a secure temp file
TMPFILE=$(mktemp /tmp/myapp.XXXXXX)
echo "Temp file created at: $TMPFILE"

# Write data to it
echo "some intermediate result" > "$TMPFILE"

# Read it back
cat "$TMPFILE"

# Clean up
rm -f "$TMPFILE"

trap ile Her Zaman Temizleme Yapma

Betiğiniz beklenmedik biçimde çıkarsa (bir hata, sinyal veya set -e tetiklenmesi nedeniyle), bir temizleme işleyicisi kaydetmediğiniz sürece geçici dosyalar geride kalır.

trap yerleşik komutu, kabuk bir sinyal aldığında veya çıktığında bir komut çalıştırır. Geçici dosya temizleme için standart yaklaşım şöyledir:

  • Tuzak kaydını geçici dosyayı oluşturduktan hemen sonra yapın.
  • Temizlemenin hem normal hem de anormal çıkışta çalışması için EXIT üzerinde tuzak kurun.
  • Betiğiniz uzun süre çalışıyorsa veya etkileşimliyse ayrıca INT ve TERM üzerinde de tuzak kurun.

Bu, betik yürütme sırasında sonlandırılsa bile geride sahipsiz dosya kalmamasını garanti eder.

#!/usr/bin/env bash
set -euo pipefail

TMPFILE=$(mktemp /tmp/report.XXXXXX)

# Register cleanup before doing any real work
cleanup() {
    rm -f "$TMPFILE"
    echo "Cleaned up $TMPFILE" >&2
}
trap cleanup EXIT

# Do work — even if this fails, cleanup() will run
echo "Processing..." > "$TMPFILE"
grep "result" "$TMPFILE" || true

echo "Done. File will be removed on exit."

mktemp -d ile Geçici Dizinler Oluşturma

Bazen birden çok dosyayı hazırlamak için bütün bir dizine ihtiyaç duyarsınız; örneğin bir arşiv oluştururken veya işlemeden önce bir tar arşivini açarken. Güvenli bir geçici dizin oluşturmak için mktemp -d kullanın.

  • Dizin, 0700 izinleriyle (yalnızca sahibinin erişebileceği şekilde) oluşturulur.
  • trap içinde rm -rf ile temizleyin; yalnızca değişkeni silmeye ve sabit kodlanmış bir yolu asla silmemeye dikkat edin.
  • Ek bir güvenlik kontrolü olarak çift tırnak kullanın ve rm -rf çağrılmadan önce değişkenin boş olmadığını doğrulayın.
#!/usr/bin/env bash
set -euo pipefail

TMPDIR=$(mktemp -d /tmp/extract.XXXXXX)

cleanup() {
    # Guard: only rm if variable is set and non-empty
    [[ -n "${TMPDIR:-}" ]] && rm -rf "$TMPDIR"
}
trap cleanup EXIT

echo "Working in $TMPDIR"

# Simulate staging files
echo "file one" > "$TMPDIR/part1.txt"
echo "file two" > "$TMPDIR/part2.txt"

ls "$TMPDIR"
echo "All done."

Eşzamanlı Betik Çalıştırma Sorunu

Cron işleri, systemd zamanlayıcıları ve elle tetiklenen betikler aynı betiğin birden çok örneğini kolayca eşzamanlı olarak başlatabilir. Bu durum şunlara yol açar:

  • Yinelenen işleme: Aynı veritabanı kayıtları veya dosyalar iki kez işlenir.
  • Bozulmuş çıktı: İki örnek aynı çıktı dosyasına eşzamanlı olarak yazar.
  • Kilitlenmeler veya kısmi durum: Her iki örnek de paylaşılan kaynakları öngörülemeyen, iç içe geçmiş bir sırayla değiştirir.

Geleneksel çözüm, bir PID dosyası yazıp başlangıçta bunu denetlemekti; ancak bu yaklaşım denetim ile yazma arasında bir yarış aralığı oluşturur. Doğru ve modern çözüm, çekirdeğin danışma amaçlı kilitleme mekanizmasını kullanarak yarışsız bir kilidi garanti eden flock'tur.

flock ile Kilitleme: Tek Satırlık Kalıp

flock, bir komutu çalıştırmadan önce bir dosya tanımlayıcısı üzerinde danışma amaçlı bir kilit alır. En basit kullanım, bütün betiğinizi komut satırından sarmalamaktır:

flock -n /var/lock/myscript.lock bash myscript.sh

  • -n (engellemesiz): Kilit zaten alınmışsa beklemek yerine durum 1 ile hemen çıkar.
  • -n olmadan flock, kilit kullanılabilir olana kadar engellenir; bu, sıraya alma için kullanışlıdır.
  • Kilit dosyasının kendisi yalnızca bir işarettir; içeriğinin önemi yoktur. Dosyayı çalıştırmalar arasında tutmak güvenlidir.
  • Kilidi tutan işlem sona erdiğinde çekirdek kilidi otomatik olarak serbest bırakır; elle temizleme gerekmez.
#!/usr/bin/env bash
# launcher.sh — prevents concurrent runs of worker.sh
set -euo pipefail

LOCKFILE="/tmp/myworker.lock"

if ! flock -n "$LOCKFILE" bash -c 'echo "Running worker..."; sleep 2; echo "Done."'; then
    echo "Another instance is already running. Exiting." >&2
    exit 1
fi

Dosya Tanımlayıcısı Kullanarak Betik İçinde flock

Bir betiği dışarıdan sarmalamak yerine betiğin içinde kilitleme yapmak için exec kullanarak bir dosya tanımlayıcısı açın ve ardından bu tanımlayıcı üzerinde flock çağırın. Bu, üretim betiklerinde kullanılan deyimsel kalıptır.

  • exec 200>"$LOCKFILE", dosyayı yazma amacıyla 200 numaralı tanımlayıcıda açar (gerekirse dosyayı oluşturur).
  • flock -n 200, 200 numaralı tanımlayıcıyı engellemesiz olarak kilitlemeyi dener.
  • Kilit dosya adına değil dosya tanımlayıcısına bağlı olduğundan, kabuk işlemi sona erdiğinde otomatik olarak serbest bırakılır.
  • Standart girdi/standart çıktı/standart hata ile çakışmayı önlemek için 200-299 arasındaki tanımlayıcı numaraları geleneksel olarak kullanılır.
#!/usr/bin/env bash
set -euo pipefail

LOCKFILE="/tmp/myjob.lock"

# Open lock file on FD 200
exec 200>"$LOCKFILE"

# Attempt non-blocking lock
if ! flock -n 200; then
    echo "ERROR: Another instance of this script is running." >&2
    exit 1
fi

echo "Lock acquired. Starting work..."
sleep 1
echo "Work complete. Lock will be released on exit."

Tek Bir Betikte mktemp ve flock Birleştirme

Gerçek savunmacı betiklerin her ikisine de ihtiyacı vardır: eşzamanlı çalışmaları önlemek için bir kilit ve ara veriler için güvenli geçici dosyalar. Aşağıda her iki tekniği birleştiren eksiksiz kalıp verilmiştir:

  • Önce kilidi alın; herhangi bir geçici dosya oluşturmadan önce kilidi alarak hiçbir işi yalnızca tek bir örneğin yapmasını sağlayın.
  • Kilit doğrulandıktan sonra geçici kaynakları oluşturun.
  • Temizlemenin, betiğin nasıl sona erdiğinden bağımsız olarak garanti edilmesi için geçicileri oluşturduktan hemen sonra trap kaydedin.
  • Kilit dosyası asla geçici dizinde bulunmamalıdır; flock'un ona başvurabilmesi için çalıştırmalar arasında kalıcı olmalıdır.
#!/usr/bin/env bash
set -euo pipefail

LOCKFILE="/tmp/report_builder.lock"
exec 200>"$LOCKFILE"

if ! flock -n 200; then
    echo "Already running — aborting." >&2
    exit 1
fi

# Now safe to create temp resources
TMPDIR=$(mktemp -d /tmp/report.XXXXXX)
TMPLOG=$(mktemp /tmp/report_log.XXXXXX)

cleanup() {
    rm -rf "${TMPDIR:-}"
    rm -f  "${TMPLOG:-}"
}
trap cleanup EXIT

echo "Building report in $TMPDIR" | tee "$TMPLOG"
echo "Step 1 complete"             >> "$TMPLOG"
cat "$TMPLOG"

Alternatif Kilitleme Mekanizması Olarak Kilit Dizinleri

flock'un kullanılamadığı sistemlerde (bazı gömülü sistemler veya NFS gibi ağ dosya sistemlerinde) bunun yerine kilit dizinlerini kullanabilirsiniz. mkdir, POSIX sistemlerinde atomiktir: yalnızca dizin henüz mevcut değilse başarılı olur.

  • mkdir /tmp/myscript.lock.d ile kilit dizinini oluşturun; başka bir örnek onu zaten oluşturmuşsa mkdir hemen başarısız olur.
  • Açıklama amacıyla meta verileri (PID gibi) dizinin içinde saklayın.
  • Dizini her zaman EXIT durumunda bir trap içinde kaldırın.
  • Dikkat: flock'un aksine, işlem -9 ile sonlandırılırsa veya makine yeniden başlatılırsa dizin kilidi otomatik olarak serbest bırakılmaz; artık kilit algılama denetimi ekleyin.
#!/usr/bin/env bash
set -euo pipefail

LOCKDIR="/tmp/myscript.lock.d"

# Atomic mkdir — fails if directory already exists
if ! mkdir "$LOCKDIR" 2>/dev/null; then
    # Check if the holding PID is still alive
    HOLDER_PID=$(cat "$LOCKDIR/pid" 2>/dev/null || echo "")
    if [[ -n "$HOLDER_PID" ]] && kill -0 "$HOLDER_PID" 2>/dev/null; then
        echo "Locked by PID $HOLDER_PID. Exiting." >&2
        exit 1
    else
        echo "Stale lock detected. Removing and continuing." >&2
        rm -rf "$LOCKDIR"
        mkdir "$LOCKDIR"
    fi
fi

echo "$$" > "$LOCKDIR/pid"
trap 'rm -rf "$LOCKDIR"' EXIT

echo "Lock acquired via directory. Running..."
sleep 1
echo "Done."

flock ile Zaman Aşımına Dayalı Bekleme

Bazen bir kilit için hemen başarısız olmak yerine beklemek, ancak sonsuza kadar beklememek istersiniz. flock, -w seçeneğiyle zaman aşımını destekler.

  • flock -w 10 200, kilit için en fazla 10 saniye bekler; kilit hâlâ kullanılamıyorsa durum 1 ile çıkar.
  • Bu, kısa süreli bir önceki işlemin arkasında sıraya girmesi, ancak önceki işlem takılı kalırsa vazgeçmesi gereken betikler için idealdir.
  • -w seçeneğini bağlam içeren anlamlı bir hata iletisiyle birleştirin; kilit dosyasının yolunu ve ne kadar beklediğinizi belirtmek, işleçlerin takılmaları hızla tanılamasını sağlar.
#!/usr/bin/env bash
set -euo pipefail

LOCKFILE="/tmp/data_sync.lock"
TIMEOUT=15

exec 200>"$LOCKFILE"

echo "Waiting up to ${TIMEOUT}s for lock on $LOCKFILE..."

if ! flock -w "$TIMEOUT" 200; then
    echo "ERROR: Could not acquire lock after ${TIMEOUT}s." \
         "Another instance may be hung." >&2
    exit 1
fi

echo "Lock acquired. Syncing data..."
sleep 1
echo "Sync complete."

Savunmacı Denetim Listesi: Güvenli Geçici Kaynaklar

Geçici dosya veya kilitleme kullanan herhangi bir betiği yayımlamadan önce bu denetim listesini uygulayın:

  • Sabit kodlanmış yollar yerine mktemp kullanın — /tmp/myapp.tmp tahmin edilebilir ve kötüye kullanılabilir.
  • Yolu hemen alın — başka bir komuttan önce TMPFILE=$(mktemp ...).
  • Oluşturmadan hemen sonra trap cleanup EXIT kaydedin — betiğin sonuna bırakmayın.
  • Tüm değişken kullanımlarını çift tırnak içine alın — rm -f "$TMPFILE" kullanın, hiçbir zaman rm -f $TMPFILE kullanmayın.
  • PID dosyaları yerine flock'u tercih edin — çekirdek tarafından yönetilir ve çökme durumunda otomatik olarak serbest bırakılır.
  • Varsayılan olarak engellemesiz -n kullanın — sessizce engelleyen kilitler performans sorunlarını gizler.
  • Kilit dosyasını geçici dizinin dışında tutun — böylece temizleme tuzağından etkilenmez.
  • Temizleme davranışını sınayın — betiğinizi çalıştırın ve yürütme sırasında kill -9 ile sonlandırın; geride hiçbir dosya kalmadığını doğrulayın (flock tabanlı betikler için; dizin kilitleri ek özen gerektirir).

Bilgi Kontrolü: flock Seçeneklerinin Davranışı

Bir cron işi her dakika çalışıyor ve paylaşılan bir dosyayı işliyor. Önceki çalıştırma hâlâ etkinse yeni çağrının beklemeden hemen bir hatayla çıkmasını istiyorsunuz. Bunu doğru biçimde gerçekleştiren flock çağrısı hangisidir?

Özet: Güvenli Geçici Dosyalar ve Kilit Dizinleri

Bu derste Bash'te savunmacı kaynak yönetimi için iki temel aracı öğrendiniz:

  • mktemp, tahmin edilemeyen ve güvenli izinlerle oluşturulmuş geçici dosyalar (0600) ve dizinler (0700) oluşturur; böylece sabit kodlanmış yolların yol açtığı yarış koşullarını ve sembolik bağlantı saldırılarını ortadan kaldırır.
  • trap cleanup EXIT, oluşturulduktan hemen sonra kaydedildiğinde, normal, hata kaynaklı veya sinyal kaynaklı her çıkışta geçici dosyanın kaldırılmasını garanti eder.
  • flock, çekirdek tarafından uygulanan danışma amaçlı kilitleme sağlar: çakışmada hızla başarısız olmak için -n, zaman aşımıyla beklemek için -w N ve çekirdeğin işlem sona erdiğinde otomatik olarak serbest bıraktığı betik içi kilitleme için exec 200>file kalıbını kullanın.
  • Kilit dizinleri (mkdir), flock'un kullanılamadığı ortamlarda taşınabilir bir geri dönüş seçeneği sunar; ancak artık kilit algılamasının açıkça yapılmasını gerektirir.
  • Kilit dosyasını her zaman geçici dizinin dışında tutun ve temizleme sırasında kullanılan her değişkeni çift tırnak içine alın.

mktemp + flock + trap birleşimi, betiklerinizin eşzamanlı çağrılara, öngörülemeyen çökmelere ve kötü amaçlı dosya sistemi değişikliklerine karşı güvenli olmasını sağlar.

Sıkça Sorulan Sorular

“Güvenli Geçici Dosyalar ve Kilit Dizinleri” dersi ücretsiz mi?

Evet — “Güvenli Geçici Dosyalar ve Kilit Dizinleri” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve DevOps Bootcamp kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. DevOps Bootcamp kursu toplamda 4 dersten oluşur.

“Güvenli Geçici Dosyalar ve Kilit Dizinleri” dersinde ne öğreneceğim?

Yarış durumlarını önleyen geçici kaynaklar oluşturmak ve betiklerin eşzamanlı çalışmasını engellemek için mktemp ve flock kullanın. DevOps Bootcamp ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

DevOps Bootcamp öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te DevOps Bootcamp, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.

“Güvenli Geçici Dosyalar ve Kilit Dizinleri” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu DevOps Bootcamp dersinde kod yazıp çalıştırabilir miyim?

Evet. Her DevOps Bootcamp dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. set -euo pipefail ile Katı Mod
  2. Temizleme ve Sinyaller için Trap İşleyicileri
  3. Güvenli Geçici Dosyalar ve Kilit Dizinleri
  4. İdempotent Betikler ve Geri Çekilmeli Yeniden Deneme Mantığı
← DevOps Bootcamp Sayfasına Dön