0Pricing
Linux Command Line & Bash Scripting Mastery · Pelajaran

Penangan Trap untuk Pembersihan dan Sinyal

Daftarkan trap EXIT, ERR, dan INT untuk menghapus file sementara serta membatalkan pekerjaan parsial secara andal.

Penangan Trap untuk Pembersihan dan Sinyal adalah pelajaran Linux Command Line & Bash Scripting Mastery gratis di CoddyKit. Ini adalah pelajaran 2 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 Penangan Perangkap Penting

Saat skrip Bash keluar — baik secara normal, karena kesalahan, maupun karena pengguna menekan Ctrl+C — skrip dapat meninggalkan berkas sementara, data yang ditulis sebagian, atau keadaan yang rusak. Tanpa pembersihan, artefak ini akan menumpuk dan menimbulkan masalah yang sulit dilacak.

Penangan perangkap mengatasi hal ini dengan mendaftarkan fungsi atau perintah yang dijalankan Bash secara otomatis ketika menerima sinyal atau sinyal semu tertentu.

  • EXIT — dijalankan setiap kali skrip keluar, apa pun alasannya
  • ERR — dijalankan setelah perintah apa pun mengembalikan status keluar bukan nol
  • INT — dijalankan saat pengguna mengirim SIGINT (Ctrl+C)
  • TERM — dijalankan saat menerima SIGTERM (misalnya dari kill)

Skrip yang ditulis dengan baik mendaftarkan perangkap ini di bagian paling atas, sebelum pekerjaan yang berisiko dimulai.

Sintaks Bawaan trap

Perintah bawaan trap mendaftarkan penangan untuk satu atau beberapa sinyal atau sinyal semu. Sintaks umumnya adalah:

trap 'command_or_function' SIGNAL [SIGNAL...]

Aturan penting:

  • Argumen pertama adalah string kode shell yang diapit tanda kutip (atau nama fungsi) untuk dijalankan saat sinyal dipicu.
  • Anda dapat mencantumkan beberapa sinyal setelah penangan.
  • trap '' SIGNAL mengabaikan sinyal tersebut (penangan kosong).
  • trap - SIGNAL mengatur ulang sinyal ke perilaku bawaannya.

Perangkap diwarisi oleh fungsi yang dipanggil dalam shell yang sama, tetapi tidak oleh subproses yang dibuat dengan ( ) atau &.

#!/usr/bin/env bash
# Syntax examples — not a full script

# Register a cleanup function on EXIT
trap cleanup EXIT

# Inline handler for INT and TERM
trap 'echo "Interrupted!"; exit 1' INT TERM

# Ignore SIGHUP
trap '' HUP

# Reset SIGPIPE to default
trap - PIPE

Perangkap EXIT — Jaring Pengaman Anda

EXIT adalah sinyal semu terpenting yang perlu didaftarkan sebagai perangkap. Sinyal ini dijalankan saat shell keluar karena alasan apa pun: penyelesaian normal, exit N, kesalahan yang tidak ditangani, atau sinyal. Karena itu, sinyal ini ideal untuk menghapus berkas sementara.

Praktik terbaik:

  • Buat berkas sementara dengan mktemp agar namanya unik dan sulit ditebak.
  • Simpan jalurnya ke dalam variabel segera.
  • Daftarkan perangkap EXIT tepat setelah pembuatan agar pembersihan selalu dijalankan.

Kode keluar skrip dipertahankan — kode keluar penangan perangkap akan diabaikan kecuali Anda secara eksplisit memanggil exit di dalamnya.

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

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

cleanup() {
    echo "Removing temp file: $TMPFILE" >&2
    rm -f "$TMPFILE"
}
trap cleanup EXIT

# Do real work
echo "Processing..." > "$TMPFILE"
sort "$TMPFILE" -o "$TMPFILE"
cp "$TMPFILE" /tmp/myapp_result.txt

echo "Done. Result saved."

Menangani Beberapa Berkas dan Direktori Sementara

Skrip nyata sering membuat beberapa artefak sementara — berkas, direktori, FIFO, dan berkas kunci. Daripada melacaknya satu per satu, kumpulkan semuanya dalam array dan hapus dalam satu fungsi pembersihan.

Pola ini dapat diperluas dengan rapi: setiap kali Anda membuat sumber daya sementara baru, tambahkan ke array. Perangkap EXIT selalu menangani seluruh daftar, di mana pun skrip keluar.

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

CLEANUP_TARGETS=()

add_cleanup() {
    CLEANUP_TARGETS+=("$1")
}

cleanup() {
    echo "Running cleanup..." >&2
    for target in "${CLEANUP_TARGETS[@]:-}"; do
        rm -rf "$target"
        echo "Removed: $target" >&2
    done
}
trap cleanup EXIT

# Create and track temp resources
TMPDIR_WORK=$(mktemp -d /tmp/work.XXXXXX)
add_cleanup "$TMPDIR_WORK"

TMPFILE_LOG=$(mktemp /tmp/run.XXXXXX.log)
add_cleanup "$TMPFILE_LOG"

echo "Working in $TMPDIR_WORK" | tee "$TMPFILE_LOG"
touch "$TMPDIR_WORK/output.txt"
echo "Step complete."

Perangkap ERR — Menangkap Kegagalan

Sinyal semu ERR dijalankan setelah perintah sederhana apa pun mengembalikan status keluar bukan nol, asalkan opsi shell set -e (errexit) aktif atau perintah tersebut tidak berada di dalam gabungan if, while, atau ||/&&.

Gunakan perangkap ERR untuk:

  • Mencatat baris yang gagal menggunakan $LINENO dan $BASH_COMMAND.
  • Memicu logika pemulihan sebelum perangkap EXIT dijalankan.
  • Mengeluarkan pesan kesalahan terstruktur ke stderr.

Penting: Perangkap ERR tidak dijalankan di dalam fungsi kecuali Anda secara eksplisit menjalankan set -E (errtrace) agar fungsi mewarisi perangkap ERR dari shell pemanggil.

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

on_error() {
    local exit_code=$?
    local line=$1
    echo "ERROR: command failed with exit code $exit_code at line $line" >&2
    echo "  Command: $BASH_COMMAND" >&2
}
trap 'on_error $LINENO' ERR

echo "Starting task..."
cp /nonexistent/file /tmp/   # This will fail
echo "This line is never reached."

Perangkap INT — Ctrl+C yang Terkendali

Menekan Ctrl+C mengirimkan SIGINT ke grup proses latar depan. Tanpa perangkap, Bash langsung keluar dan mungkin meninggalkan pekerjaan yang belum selesai.

Mendaftarkan perangkap INT memungkinkan Anda:

  • Menampilkan pesan pembatalan yang mudah dipahami pengguna.
  • Melakukan pemulihan sementara sebelum menyerahkan kendali kepada perangkap EXIT.
  • Keluar dengan kode status yang bermakna (130 adalah kode konvensional untuk SIGINT: 128 + 2).

Setelah penangan INT selesai, panggil exit 130 untuk meneruskan kode keluar yang benar. Perangkap EXIT kemudian akan dijalankan secara otomatis.

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

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

cleanup() {
    rm -f "$TMPFILE"
    echo "Temp file removed." >&2
}

on_interrupt() {
    echo "" >&2
    echo "Caught SIGINT — cancelling gracefully." >&2
    exit 130   # EXIT trap (cleanup) runs automatically after this
}

trap cleanup EXIT
trap on_interrupt INT

echo "Running long task. Press Ctrl+C to cancel."
for i in $(seq 1 10); do
    echo "Step $i/10..."
    sleep 1
done
echo "All steps complete."

Menggabungkan Perangkap EXIT, ERR, dan INT

Dalam skrip produksi, biasanya Anda mendaftarkan ketiga perangkap sekaligus untuk mencakup setiap jalur keluar:

  • EXIT — selalu dijalankan; menangani pembersihan berkas.
  • ERR — mencatat perintah dan nomor baris yang gagal.
  • INT — menampilkan pesan pembatalan dan keluar dengan kode 130.

Karena EXIT selalu dijalankan terakhir, logika pembersihan Anda hanya perlu berada di satu tempat. Penangan ERR dan INT dapat berfokus pada pencatatan dan pengaturan keadaan, lalu menyerahkan pembersihan sebenarnya kepada EXIT dengan memanggil exit.

Gunakan set -eEuo pipefail di bagian atas agar kesalahan dalam fungsi juga memicu ERR, dan pipefail menangkap kegagalan di dalam alur pemrosesan.

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

TMPFILE=$(mktemp /tmp/combined.XXXXXX)
ROLLBACK_NEEDED=false

cleanup() {
    if [[ "$ROLLBACK_NEEDED" == true ]]; then
        echo "Rolling back partial changes..." >&2
    fi
    rm -f "$TMPFILE"
    echo "Cleanup done." >&2
}

on_error() {
    ROLLBACK_NEEDED=true
    echo "ERR at line $1: $BASH_COMMAND" >&2
}

on_interrupt() {
    echo "Interrupted by user." >&2
    exit 130
}

trap cleanup       EXIT
trap 'on_error $LINENO' ERR
trap on_interrupt  INT

echo "hello" > "$TMPFILE"
echo "Script finished successfully."

Mengatur Ulang dan Menonaktifkan Perangkap Secara Dinamis

Terkadang Anda perlu mengubah perangkap di tengah skrip — misalnya, melakukan pembersihan satu kali setelah bagian penting selesai, agar operasi normal berikutnya tidak memicu pemulihan yang tidak diperlukan.

  • trap - SIGNAL mengatur ulang sinyal ke perilaku bawaan sistem.
  • trap '' SIGNAL mengabaikan sinyal sepenuhnya (proses tidak dapat dihentikan oleh sinyal tersebut).
  • Anda dapat mendaftarkan penangan baru kapan saja; pemanggilan trap terakhir yang berlaku.

Pola yang umum adalah memperbarui perangkap EXIT setelah operasi berisiko berhasil, dengan mengganti penangan pemulihan menjadi penangan pembersihan sederhana.

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

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

rollback() {
    echo "ROLLBACK: removing $TMPFILE" >&2
    rm -f "$TMPFILE"
}

cleanup_only() {
    echo "CLEANUP: removing $TMPFILE" >&2
    rm -f "$TMPFILE"
}

# Start with rollback in case something fails during the risky phase
trap rollback EXIT

echo "Performing risky operation..."
echo "critical data" > "$TMPFILE"
# ... imagine more risky steps here ...

# Risky phase succeeded — switch to simple cleanup
trap cleanup_only EXIT

echo "Risky phase done. Now doing safe finalization."
cp "$TMPFILE" /tmp/staged_result.txt
echo "All done."

Meneruskan Kode Keluar melalui Perangkap

Perangkap yang perlu diperhatikan: jika fungsi pembersihan Anda berisi perintah yang dapat gagal, kode keluar akhir skrip mungkin tertimpa. Pertahankan kode keluar asli secara eksplisit.

Di dalam penangan perangkap, $? berisi kode keluar yang memicu perangkap. Simpan nilainya pada baris pertama penangan, sebelum perintah lain mengubahnya.

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

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

cleanup() {
    local original_exit=$?   # capture BEFORE any other command
    echo "Cleaning up (original exit: $original_exit)" >&2
    rm -f "$TMPFILE"
    # Exit with the original code so callers see the real result
    exit "$original_exit"
}
trap cleanup EXIT

echo "Doing work..."
echo "data" > "$TMPFILE"

# Simulate failure
if [[ ! -f /tmp/required_marker ]]; then
    echo "Required marker missing!" >&2
    exit 2
fi

echo "Done."

Perangkap dalam Fungsi dan Subproses

Memahami pewarisan perangkap sangat penting untuk menulis skrip yang benar:

  • Fungsi berjalan dalam shell yang sama dan mewarisi perangkap — tetapi ERR hanya diteruskan ke fungsi jika set -E (errtrace) aktif.
  • Subproses (( ... )) dimulai dengan salinan perangkap milik induknya, tetapi perubahan di dalam subproses tidak memengaruhi induknya.
  • Pekerjaan latar belakang (cmd &) merupakan subproses dan tidak mewarisi perangkap INT/TERM milik induknya (pekerjaan tersebut menggunakan perilaku sinyal bawaan).

Aturan praktis: letakkan pendaftaran perangkap di bagian utama skrip, gunakan set -E saat ERR perlu diteruskan ke fungsi, dan jangan pernah mengandalkan pewarisan perangkap melalui &.

#!/usr/bin/env bash
set -eEuo pipefail   # -E = errtrace: ERR propagates into functions

on_error() {
    echo "ERR in function or main at line $1" >&2
}
trap 'on_error $LINENO' ERR

risky_function() {
    echo "Inside risky_function"
    ls /nonexistent_path   # triggers ERR — works because of set -E
}

# Subshell: has its own copy; changes don't affect parent
(
    trap '' ERR   # disable ERR only inside subshell
    ls /nonexistent_path 2>/dev/null || true
    echo "Subshell completed without triggering parent ERR"
)

risky_function

Pola Dunia Nyata: Penggantian Berkas Atomik

Pola Bash defensif klasik adalah penggantian berkas atomik: tulis ke berkas sementara, lalu ubah namanya ke lokasi tujuan. Jika terjadi kegagalan sebelum pengubahan nama, berkas asli tetap tidak tersentuh. Perangkap membuat pola ini sangat tangguh.

Langkah-langkah:

  1. Buat berkas sementara pada sistem berkas yang sama dengan tujuan (agar mv bersifat atomik).
  2. Daftarkan perangkap EXIT untuk menghapus berkas sementara jika kita keluar lebih awal.
  3. Tulis dan validasi isi baru.
  4. Ubah nama secara atomik (mv) — hanya pada tahap ini berkas asli diganti.
  5. Perangkap EXIT menghapus berkas sementara hanya jika berkas tersebut masih ada (setelah mv berhasil, berkas itu sudah tidak ada).
#!/usr/bin/env bash
set -euo pipefail

DEST="/tmp/important_config.conf"
TMPFILE=$(mktemp "$(dirname "$DEST")/.tmp.XXXXXX")

cleanup() {
    rm -f "$TMPFILE"   # no-op if mv already moved it
}
trap cleanup EXIT

# Write new content to temp file
cat > "$TMPFILE" <<'EOF'
[settings]
version=2
mode=production
EOF

# Validate before replacing
if ! grep -q 'version=' "$TMPFILE"; then
    echo "Validation failed — aborting replacement" >&2
    exit 1
fi

# Atomic rename — DEST is replaced only here
mv "$TMPFILE" "$DEST"
echo "Config updated atomically: $DEST"

Pemeriksaan Pengetahuan: Pewarisan Perangkap ERR

Uji pemahaman Anda tentang perilaku perangkap ERR terhadap fungsi dalam Bash.

Rangkuman: Penangan Perangkap untuk Pembersihan dan Sinyal

Dalam pelajaran ini, Anda mempelajari cara membuat skrip Bash tangguh melalui penangan perangkap:

  • EXIT adalah jaring pengaman universal Anda — daftarkan segera setelah membuat sumber daya sementara apa pun dan selalu simpan $? terlebih dahulu untuk mempertahankan kode keluar asli.
  • ERR memungkinkan Anda mencatat kegagalan dengan $LINENO dan $BASH_COMMAND; gunakan set -E agar fungsi mewarisinya.
  • INT menangani Ctrl+C dengan baik — tampilkan pesan dan keluar dengan kode 130 agar EXIT melakukan pembersihan.
  • Kumpulkan sumber daya sementara dalam sebuah array dan hapus semuanya dalam satu fungsi pembersihan.
  • Gunakan trap - SIGNAL untuk mengatur ulang dan trap '' SIGNAL untuk mengabaikan sinyal secara dinamis.
  • Pola pengubahan nama atomik (mktemp → tulis → validasi → mv) yang digabungkan dengan perangkap EXIT menjamin bahwa penulisan sebagian tidak pernah merusak berkas tujuan.

Menggabungkan set -eEuo pipefail dengan perangkap yang ditempatkan dengan baik memberi Anda dasar defensif yang kuat untuk skrip Bash produksi apa pun.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Penangan Trap untuk Pembersihan dan Sinyal” gratis?

Ya — teks lengkap “Penangan Trap untuk Pembersihan dan Sinyal” 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 “Penangan Trap untuk Pembersihan dan Sinyal”?

Daftarkan trap EXIT, ERR, dan INT untuk menghapus file sementara serta membatalkan pekerjaan parsial secara andal. 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 2 dari 4.

Berapa lama pelajaran “Penangan Trap untuk Pembersihan dan Sinyal” 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