Kem Intensif DevOps · Pelajaran

Pengendali Trap untuk Pembersihan dan Isyarat

Daftarkan trap EXIT, ERR dan INT untuk membuang fail sementara serta mengembalikan kerja separa dengan boleh dipercayai

Pelajaran 2 daripada 413 langkah

Pengendali Trap untuk Pembersihan dan Isyarat ialah pelajaran Kem Intensif DevOps percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Kem Intensif DevOps, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Kem Intensif DevOps merangkumi sejumlah 4 pelajaran.

Mengapa Pengendali Perangkap Penting

Apabila skrip Bash keluar — sama ada secara normal, disebabkan ralat, atau kerana pengguna menekan Ctrl+C — skrip itu mungkin meninggalkan fail sementara, data yang ditulis separa, atau keadaan yang rosak. Tanpa pembersihan, artifak ini akan terkumpul dan menyebabkan masalah yang sukar dikesan.

Pengendali perangkap menyelesaikan masalah ini dengan mendaftarkan fungsi atau arahan yang dilaksanakan oleh Bash secara automatik apabila isyarat tertentu atau isyarat pseudo diterima.

  • EXIT — dicetuskan setiap kali skrip keluar, atas apa-apa sebab
  • ERR — dicetuskan selepas mana-mana arahan mengembalikan status keluar bukan sifar
  • INT — dicetuskan apabila pengguna menghantar SIGINT (Ctrl+C)
  • TERM — dicetuskan oleh SIGTERM (contohnya daripada kill)

Skrip yang ditulis dengan baik mendaftarkan perangkap ini di bahagian paling atas, sebelum sebarang kerja berisiko bermula.

Sintaks Terbina dalam trap

Terbina dalam trap mendaftarkan pengendali untuk satu atau lebih isyarat atau isyarat pseudo. Sintaks umumnya ialah:

trap 'command_or_function' SIGNAL [SIGNAL...]

Peraturan utama:

  • Argumen pertama ialah rentetan kod shell yang dipetik (atau nama fungsi) untuk dilaksanakan apabila isyarat dicetuskan.
  • Anda boleh menyenaraikan berbilang isyarat selepas pengendali.
  • trap '' SIGNAL mengabaikan isyarat tersebut (pengendali kosong).
  • trap - SIGNAL menetapkan semula isyarat kepada tingkah laku lalainya.

Perangkap diwarisi oleh fungsi yang dipanggil dalam shell yang sama, tetapi tidak oleh subcangkerang yang dimulakan 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 Keselamatan Anda

EXIT ialah isyarat pseudo yang paling penting untuk didaftarkan sebagai perangkap. Isyarat ini dicetuskan apabila shell keluar atas apa-apa sebab: selesai secara normal, exit N, ralat yang tidak dikendalikan, atau isyarat. Oleh itu, isyarat ini sesuai untuk membuang fail sementara.

Amalan terbaik:

  • Cipta fail sementara dengan mktemp supaya namanya unik dan sukar dijangka.
  • Simpan laluan dalam pemboleh ubah dengan segera.
  • Daftarkan perangkap EXIT sejurus selepas penciptaan supaya pembersihan sentiasa dijalankan.

Kod keluar skrip dikekalkan — kod keluar pengendali perangkap diabaikan kecuali anda memanggil exit secara jelas 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."

Mengendalikan Berbilang Fail dan Direktori Sementara

Skrip sebenar sering mencipta berbilang artifak sementara — fail, direktori, FIFO dan fail kunci. Daripada menjejaki setiap satunya secara berasingan, kumpulkan semuanya dalam tatasusunan dan buang kesemuanya dalam satu fungsi pembersihan.

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

Isyarat pseudo ERR dicetuskan selepas mana-mana arahan mudah mengembalikan status keluar bukan sifar, dengan syarat pilihan shell set -e (errexit) aktif atau arahan itu tidak berada dalam gabungan if, while, atau ||/&&.

Gunakan perangkap ERR untuk:

  • Merekod baris yang gagal menggunakan $LINENO dan $BASH_COMMAND.
  • Mencetuskan logik pemulihan sebelum perangkap EXIT dijalankan.
  • Mengeluarkan mesej ralat berstruktur ke stderr.

Penting: Perangkap ERR tidak dicetuskan dalam fungsi melainkan anda menjalankan set -E (errtrace) secara jelas supaya fungsi mewarisi perangkap ERR daripada 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 Secara Berhemah

Menekan Ctrl+C menghantar SIGINT kepada kumpulan proses latar depan. Tanpa perangkap, Bash keluar serta-merta dan mungkin meninggalkan kerja separa.

Mendaftarkan perangkap INT membolehkan anda:

  • Mencetak mesej pembatalan yang mesra pengguna.
  • Melakukan sebarang pemulihan sementara sebelum menyerahkannya kepada perangkap EXIT.
  • Keluar dengan kod status yang bermakna (130 ialah kod lazim untuk SIGINT: 128 + 2).

Selepas pengendali INT anda selesai, panggil exit 130 untuk menyebarkan kod keluar yang betul. Perangkap EXIT kemudiannya akan dijalankan secara automatik.

#!/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 pengeluaran, biasanya anda mendaftarkan ketiga-tiga perangkap bersama-sama untuk merangkumi setiap laluan keluar:

  • EXIT — sentiasa dijalankan; mengendalikan pembersihan fail.
  • ERR — merekod arahan dan nombor baris yang gagal.
  • INT — mencetak mesej pembatalan dan keluar dengan kod 130.

Oleh sebab EXIT sentiasa dijalankan terakhir, logik pembersihan anda hanya perlu berada di satu tempat. Pengendali ERR dan INT boleh menumpukan pada pengelogan dan penetapan keadaan, kemudian menyerahkan pembersihan sebenar kepada EXIT dengan memanggil exit.

Gunakan set -eEuo pipefail di bahagian atas supaya ralat dalam fungsi turut mencetuskan ERR, dan pipefail menangkap kegagalan dalam saluran paip.

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

Menetapkan Semula dan Melumpuhkan Perangkap Secara Dinamik

Sesetengah keadaan memerlukan anda mengubah perangkap di pertengahan skrip — contohnya, pembersihan sekali sahaja selepas bahagian kritikal selesai, supaya operasi normal seterusnya tidak mencetuskan pemulihan yang tidak diperlukan.

  • trap - SIGNAL menetapkan semula isyarat kepada tingkah laku lalai terbina dalamnya.
  • trap '' SIGNAL mengabaikan isyarat itu sepenuhnya (proses tidak boleh dimatikan olehnya).
  • Anda boleh mendaftarkan pengendali baharu pada bila-bila masa; panggilan trap terakhir akan digunakan.

Corak lazim ialah menaik taraf perangkap EXIT setelah operasi berisiko berjaya, dengan menukar pengendali pemulihan kepada pengendali pembersihan mudah.

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

Menyebarkan Kod Keluar melalui Perangkap

Satu perangkap halus: jika fungsi pembersihan anda mengandungi arahan yang boleh gagal, kod keluar akhir skrip mungkin tertulis ganti. Kekalkan kod keluar asal secara jelas.

Dalam pengendali perangkap, $? menyimpan kod keluar yang mencetuskan perangkap tersebut. Tangkap nilainya pada baris pertama pengendali, sebelum sebarang arahan 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 Subcangkerang

Memahami pewarisan perangkap adalah penting untuk menulis skrip yang betul:

  • Fungsi berjalan dalam shell yang sama dan mewarisi perangkap — tetapi ERR hanya disebarkan kepada fungsi apabila set -E (errtrace) aktif.
  • Subcangkerang (( ... )) bermula dengan salinan perangkap induk, tetapi perubahan dalam subcangkerang tidak mempengaruhi induk.
  • Kerja latar belakang (cmd &) ialah subcangkerang dan tidak mewarisi perangkap INT/TERM induk (kerja tersebut menggunakan tindakan isyarat lalai).

Peraturan praktikal: kekalkan pendaftaran perangkap dalam badan skrip utama, gunakan set -E apabila anda memerlukan ERR disebarkan kepada fungsi, dan jangan sekali-kali bergantung pada pewarisan perangkap merentasi &.

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

Corak Dunia Sebenar: Penggantian Fail Atomik

Corak Bash defensif klasik ialah penggantian fail atomik: tulis ke fail sementara, kemudian namakan semula fail itu ke lokasi asal. Jika apa-apa gagal sebelum penamaan semula, fail asal tidak disentuh. Perangkap menjadikan proses ini sangat teguh.

Langkah-langkah:

  1. Cipta fail sementara dalam sistem fail yang sama dengan destinasi (supaya mv bersifat atomik).
  2. Daftarkan perangkap EXIT untuk membuang fail sementara jika kita keluar lebih awal.
  3. Tulis dan sahkan kandungan baharu.
  4. Namakan semula secara atomik (mv) — hanya pada ketika ini fail asal digantikan.
  5. Perangkap EXIT membuang fail sementara hanya jika fail itu masih wujud (selepas mv berjaya, fail itu sudah tiada).
#!/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"

Semakan Pengetahuan: Pewarisan Perangkap ERR

Uji pemahaman anda tentang tingkah laku perangkap ERR dengan fungsi dalam Bash.

Imbas Kembali: Pengendali Perangkap untuk Pembersihan dan Isyarat

Dalam pelajaran ini, anda mempelajari cara menjadikan skrip Bash berdaya tahan melalui pengendali perangkap:

  • EXIT ialah jaring keselamatan universal anda — daftarkannya sejurus selepas mencipta sebarang sumber sementara dan sentiasa tangkap $? terlebih dahulu untuk mengekalkan kod keluar asal.
  • ERR membolehkan anda merekod kegagalan dengan $LINENO dan $BASH_COMMAND; gunakan set -E supaya fungsi mewarisinya.
  • INT mengendalikan Ctrl+C dengan berhemah — cetak mesej dan keluar dengan kod 130 supaya EXIT melakukan pembersihan.
  • Kumpulkan sumber sementara dalam tatasusunan dan buang semuanya dalam satu fungsi pembersihan.
  • Gunakan trap - SIGNAL untuk menetapkan semula dan trap '' SIGNAL untuk mengabaikan isyarat secara dinamik.
  • Corak penamaan semula atomik (mktemp → tulis → sahkan → mv) yang digabungkan dengan perangkap EXIT menjamin bahawa penulisan separa tidak akan merosakkan fail destinasi.

Menggabungkan set -eEuo pipefail dengan perangkap yang ditempatkan dengan baik memberikan asas defensif yang kukuh untuk mana-mana skrip Bash pengeluaran.

Percuma untuk bermula

Pelajari Kem Intensif DevOps dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
142
Pelajaran
568

Soalan Lazim

Adakah pelajaran “Pengendali Trap untuk Pembersihan dan Isyarat” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Kem Intensif DevOps, termasuk “Pengendali Trap untuk Pembersihan dan Isyarat”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Kem Intensif DevOps merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Pengendali Trap untuk Pembersihan dan Isyarat”?

Daftarkan trap EXIT, ERR dan INT untuk membuang fail sementara serta mengembalikan kerja separa dengan boleh dipercayai Anda berlatih Kem Intensif DevOps menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Kem Intensif DevOps?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Kem Intensif DevOps di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.

Berapa lamakah pelajaran “Pengendali Trap untuk Pembersihan dan Isyarat” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Kem Intensif DevOps ini?

Ya. Setiap pelajaran Kem Intensif DevOps menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Mod Ketat dengan set -euo pipefail
  2. Pengendali Trap untuk Pembersihan dan Isyarat
  3. Fail Sementara Selamat dan Direktori Kunci
  4. Skrip Idempoten dan Logik Percubaan Semula dengan Penangguhan
← Kembali ke Kem Intensif DevOps