Pengendali Trap untuk Pembersihan dan Isyarat
Daftarkan trap EXIT, ERR dan INT untuk membuang fail sementara serta mengembalikan kerja separa dengan boleh dipercayai
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 '' SIGNALmengabaikan isyarat tersebut (pengendali kosong).trap - SIGNALmenetapkan 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 - PIPEPerangkap 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
mktempsupaya 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
$LINENOdan$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 (
130ialah 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 - SIGNALmenetapkan semula isyarat kepada tingkah laku lalai terbina dalamnya.trap '' SIGNALmengabaikan isyarat itu sepenuhnya (proses tidak boleh dimatikan olehnya).- Anda boleh mendaftarkan pengendali baharu pada bila-bila masa; panggilan
trapterakhir 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_functionCorak 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:
- Cipta fail sementara dalam sistem fail yang sama dengan destinasi (supaya
mvbersifat atomik). - Daftarkan perangkap EXIT untuk membuang fail sementara jika kita keluar lebih awal.
- Tulis dan sahkan kandungan baharu.
- Namakan semula secara atomik (
mv) — hanya pada ketika ini fail asal digantikan. - Perangkap EXIT membuang fail sementara hanya jika fail itu masih wujud (selepas
mvberjaya, 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
$LINENOdan$BASH_COMMAND; gunakanset -Esupaya 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 - SIGNALuntuk menetapkan semula dantrap '' SIGNALuntuk 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.
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
- Mod Ketat dengan set -euo pipefail
- Pengendali Trap untuk Pembersihan dan Isyarat
- Fail Sementara Selamat dan Direktori Kunci
- Skrip Idempoten dan Logik Percubaan Semula dengan Penangguhan