0Pricing
Linux Command Line & Bash Scripting Mastery · Pelajaran

File Sementara yang Aman dan Direktori Kunci

Gunakan mktemp dan flock untuk membuat resource sementara tanpa kondisi balapan serta mencegah skrip berjalan secara bersamaan.

File Sementara yang Aman dan Direktori Kunci adalah pelajaran Linux Command Line & Bash Scripting Mastery gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Linux Command Line & Bash Scripting Mastery, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Linux Command Line & Bash Scripting Mastery mencakup 4 pelajaran total.

Mengapa Berkas Sementara Berisiko bagi Keamanan

Skrip Bash sering memerlukan penyimpanan sementara — hasil antara, penanda kunci, dan area penahapan. Namun, membuat berkas sementara secara sembarangan dapat membuka kerentanan serius.

  • Kondisi perlombaan: Proses lain dapat menebak nama berkas Anda dan membuat berkas tersebut lebih dahulu, sehingga mengalihkan penulisan Anda.
  • Serangan tautan simbolis: Penyerang membuat tautan simbolis di jalur yang Anda harapkan, yang mengarah ke berkas sensitif seperti /etc/passwd.
  • Berkas tersisa: Jika skrip mogok, berkas sementara akan menumpuk dan dapat membocorkan data sensitif.

Dua alat utama yang menghilangkan masalah ini adalah mktemp dan flock. Pelajaran ini menunjukkan cara menggunakan keduanya dengan aman dan defensif.

Membuat Berkas Sementara yang Aman dengan mktemp

mktemp membuat berkas sementara dengan nama acak yang sulit ditebak dan mengembalikan jalurnya. Perintah ini membuat berkas secara atomik, sehingga tidak ada proses lain yang dapat mengambil nama tersebut lebih dahulu.

  • Sintaks: mktemp [TEMPLATE] — templat harus diakhiri setidaknya oleh tiga karakter X.
  • Setiap X diganti dengan karakter acak, sehingga menghasilkan nama unik seperti /tmp/script.aB3kQz.
  • Berkas secara otomatis dibuat dengan izin 0600 (hanya dapat dibaca oleh pemiliknya).

Selalu simpan jalur yang dikembalikan ke dalam variabel segera agar Anda dapat menggunakannya dan membersihkannya nanti.

#!/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"

Selalu Bersihkan dengan trap

Jika skrip Anda keluar secara tidak terduga — karena kesalahan, sinyal, atau pemicu set -e — berkas sementara akan tertinggal kecuali Anda mendaftarkan penangan pembersihan.

Perintah bawaan trap menjalankan perintah saat shell menerima sinyal atau keluar. Pola baku untuk membersihkan berkas sementara adalah:

  • Daftarkan perangkap segera setelah membuat berkas sementara.
  • Gunakan perangkap pada EXIT agar pembersihan berjalan saat keluar secara normal maupun tidak normal.
  • Gunakan juga perangkap INT dan TERM jika skrip berjalan lama atau bersifat interaktif.

Dengan demikian, tidak ada berkas yatim yang tertinggal, bahkan jika skrip dihentikan di tengah eksekusi.

#!/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."

Membuat Direktori Sementara dengan mktemp -d

Terkadang Anda memerlukan seluruh direktori untuk menampung beberapa berkas sementara—misalnya, saat membuat arsip atau mengekstrak tarball sebelum memprosesnya. Gunakan mktemp -d untuk membuat direktori sementara yang aman.

  • Direktori dibuat dengan izin 0700 (hanya pemilik yang dapat mengaksesnya).
  • Lakukan pembersihan dengan rm -rf di dalam trap Anda—pastikan hanya menghapus variabel, bukan jalur yang ditulis secara langsung.
  • Gunakan tanda kutip ganda dan pastikan variabel tidak kosong sebelum memanggil rm -rf sebagai pemeriksaan keamanan tambahan.
#!/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."

Masalah Eksekusi Skrip Secara Bersamaan

Pekerjaan Cron, pengatur waktu systemd, dan skrip yang dipicu secara manual dapat dengan mudah meluncurkan beberapa instans skrip yang sama secara bersamaan. Hal ini menyebabkan:

  • Pemrosesan duplikat: Catatan basis data atau berkas yang sama diproses dua kali.
  • Keluaran rusak: Dua instans menulis ke berkas keluaran yang sama secara bersamaan.
  • Kebuntuan atau keadaan parsial: Kedua instans mengubah sumber daya bersama dalam urutan yang saling terselip dan tidak dapat diprediksi.

Perbaikan tradisionalnya adalah menulis berkas PID dan memeriksanya saat memulai—tetapi pendekatan ini memiliki celah perlombaan antara pemeriksaan dan penulisan. Solusi modern yang tepat adalah flock, yang menggunakan mekanisme penguncian penasihat dari kernel untuk mendapatkan kunci yang bebas dari kondisi perlombaan.

Penguncian dengan flock: Pola Satu Baris

flock memperoleh kunci penasihat pada deskriptor berkas sebelum menjalankan perintah. Penggunaan paling sederhana membungkus seluruh skrip Anda dari baris perintah:

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

  • -n (tidak memblokir): langsung keluar dengan status 1 jika kunci sudah digunakan, alih-alih menunggu.
  • Tanpa -n, flock memblokir hingga kunci tersedia—berguna untuk membuat antrean.
  • Berkas kunci itu sendiri hanya penanda; isinya tidak penting. Berkas tersebut aman untuk dipertahankan di antara eksekusi.
  • Saat proses yang memegang kunci keluar, kernel secara otomatis melepaskan kunci tersebut—tidak diperlukan pembersihan manual.
#!/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

flock di Dalam Skrip Menggunakan Deskriptor Berkas

Untuk melakukan penguncian di dalam skrip, bukan membungkusnya dari luar, gunakan exec untuk membuka deskriptor berkas, lalu panggil flock pada deskriptor tersebut. Ini adalah pola idiomatis yang digunakan dalam skrip produksi.

  • exec 200>"$LOCKFILE" membuka berkas pada deskriptor 200 untuk ditulis (dan membuatnya jika diperlukan).
  • flock -n 200 mencoba mengunci deskriptor 200 tanpa memblokir.
  • Karena kunci terikat pada deskriptor berkas (bukan nama berkas), kunci tersebut dilepaskan secara otomatis saat proses shell keluar.
  • Nomor deskriptor 200–299 secara konvensional digunakan agar tidak berbenturan dengan stdin/stdout/stderr.
#!/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."

Menggabungkan mktemp dan flock dalam Satu Skrip

Skrip defensif nyata memerlukan keduanya: kunci untuk mencegah eksekusi bersamaan dan berkas sementara yang aman untuk data perantara. Berikut pola lengkap yang menggabungkan kedua teknik tersebut:

  • Dapatkan kunci terlebih dahulu—sebelum membuat berkas sementara apa pun—agar hanya satu instans yang melakukan pekerjaan.
  • Buat sumber daya sementara setelah kunci dipastikan diperoleh.
  • Daftarkan trap segera setelah membuat sumber daya sementara agar pembersihan tetap terjamin, apa pun cara skrip keluar.
  • Berkas kunci tidak pernah diletakkan di direktori sementara—berkas tersebut harus tetap ada di antara eksekusi agar dapat dirujuk oleh flock.
#!/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"

Direktori Kunci sebagai Mekanisme Kunci Alternatif

Pada sistem yang tidak menyediakan flock (seperti beberapa sistem tertanam atau sistem berkas jaringan seperti NFS), Anda dapat menggunakan direktori kunci sebagai gantinya. mkdir bersifat atomik pada sistem POSIX: perintah ini hanya berhasil jika direktori tersebut belum ada.

  • Buat direktori kunci dengan mkdir /tmp/myscript.lock.d—jika instans lain sudah membuatnya, mkdir langsung gagal.
  • Simpan metadata (seperti PID) di dalam direktori untuk keperluan diagnosis.
  • Selalu hapus direktori tersebut dalam trap pada EXIT.
  • Catatan: Berbeda dari flock, kunci direktori TIDAK dilepaskan secara otomatis jika proses dihentikan dengan -9 atau mesin melakukan boot ulang—tambahkan pemeriksaan untuk mendeteksi kunci yang tersisa.
#!/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."

Menunggu dengan Batas Waktu Menggunakan flock

Terkadang Anda ingin menunggu kunci, bukan langsung gagal—tetapi tidak ingin menunggu selamanya. flock mendukung batas waktu dengan opsi -w.

  • flock -w 10 200 menunggu kunci hingga 10 detik, lalu keluar dengan status 1 jika kunci masih tidak tersedia.
  • Ini ideal untuk skrip yang harus mengantre setelah proses sebelumnya yang berlangsung singkat, tetapi menyerah jika proses sebelumnya macet.
  • Gabungkan -w dengan pesan kesalahan yang bermakna dan menyertakan konteks—jalur berkas kunci serta lama waktu Anda menunggu—agar operator dapat mendiagnosis kemacetan dengan cepat.
#!/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."

Daftar Periksa Defensif: Sumber Daya Sementara yang Aman

Sebelum merilis skrip apa pun yang menggunakan berkas sementara atau penguncian, periksa daftar berikut:

  • Gunakan mktemp, jangan pernah menggunakan jalur yang ditulis langsung—/tmp/myapp.tmp dapat diprediksi dan dieksploitasi.
  • Simpan jalur segera—TMPFILE=$(mktemp ...) sebelum perintah lain apa pun.
  • Daftarkan trap cleanup EXIT segera setelah pembuatan—bukan di akhir skrip.
  • Gunakan tanda kutip ganda pada semua penggunaan variabel—rm -f "$TMPFILE", jangan pernah rm -f $TMPFILE.
  • Utamakan flock daripada berkas PID—dikelola kernel dan dilepaskan secara otomatis saat terjadi kerusakan.
  • Gunakan -n tanpa pemblokiran secara bawaan—kunci yang memblokir secara diam-diam dapat menyembunyikan masalah kinerja.
  • Letakkan berkas kunci di luar direktori sementara—agar tetap ada setelah trap pembersihan dijalankan.
  • Uji perilaku pembersihan—jalankan skrip lalu gunakan kill -9 untuk menghentikannya di tengah eksekusi; pastikan tidak ada berkas tersisa (untuk skrip berbasis flock; kunci direktori memerlukan penanganan tambahan).

Pemeriksaan Pengetahuan: Perilaku Opsi flock

Sebuah pekerjaan Cron berjalan setiap menit dan memproses berkas bersama. Anda ingin setiap pemanggilan baru langsung keluar dengan kesalahan jika eksekusi sebelumnya masih aktif, tanpa menunggu. Pemanggilan flock mana yang menerapkan hal ini dengan benar?

Ringkasan: Berkas Sementara yang Aman dan Direktori Kunci

Dalam pelajaran ini, Anda mempelajari dua alat penting untuk pengelolaan sumber daya defensif di Bash:

  • mktemp membuat berkas sementara dengan izin yang tidak dapat diprediksi dan aman (0600) serta direktori (0700), sehingga menghilangkan kondisi perlombaan dan serangan tautan simbolis yang sering terjadi pada jalur yang ditulis langsung.
  • trap cleanup EXIT menjamin penghapusan berkas sementara saat keluar dengan cara apa pun—normal, dipicu kesalahan, atau dipicu sinyal—jika didaftarkan segera setelah pembuatan.
  • flock menyediakan penguncian penasihat yang diberlakukan kernel: gunakan -n untuk segera gagal saat terjadi perebutan kunci, -w N untuk menunggu dengan batas waktu, dan pola exec 200>file untuk penguncian di dalam skrip yang dilepaskan kernel secara otomatis saat proses keluar.
  • Direktori kunci (mkdir) menyediakan cadangan portabel untuk lingkungan yang tidak menyediakan flock, tetapi memerlukan deteksi eksplisit terhadap kunci yang tersisa.
  • Selalu simpan berkas kunci di luar direktori sementara dan gunakan tanda kutip ganda pada setiap variabel yang digunakan dalam pembersihan.

Menggabungkan mktemp + flock + trap menghasilkan skrip yang aman terhadap pemanggilan bersamaan, kerusakan tak terduga, dan manipulasi sistem berkas oleh pihak yang berniat jahat.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “File Sementara yang Aman dan Direktori Kunci” gratis?

Ya — teks lengkap “File Sementara yang Aman dan Direktori Kunci” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Linux Command Line & Bash Scripting Mastery, upgrade ke CoddyKit PRO. Kursus Linux Command Line & Bash Scripting Mastery mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “File Sementara yang Aman dan Direktori Kunci”?

Gunakan mktemp dan flock untuk membuat resource sementara tanpa kondisi balapan serta mencegah skrip berjalan secara bersamaan. Kamu berlatih Linux Command Line & Bash Scripting Mastery dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Linux Command Line & Bash Scripting Mastery?

Tidak diperlukan pengalaman sebelumnya. Linux Command Line & Bash Scripting Mastery di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.

Berapa lama pelajaran “File Sementara yang Aman dan Direktori Kunci” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Linux Command Line & Bash Scripting Mastery ini?

Ya. Setiap pelajaran Linux Command Line & Bash Scripting Mastery menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Mode Ketat dengan set -euo pipefail
  2. Penangan Trap untuk Pembersihan dan Sinyal
  3. File Sementara yang Aman dan Direktori Kunci
  4. Skrip Idempoten dan Logika Percobaan Ulang dengan Backoff
← Kembali ke Linux Command Line & Bash Scripting Mastery