Mode Ketat dengan set -euo pipefail
Aktifkan perilaku gagal-seketika dan pahami dengan tepat error mana yang ditangkap atau terlewatkan oleh setiap flag mode ketat.
Mode Ketat dengan set -euo pipefail adalah pelajaran DevOps Bootcamp gratis di CoddyKit. Ini adalah pelajaran 1 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 DevOps Bootcamp, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus DevOps Bootcamp mencakup 4 pelajaran total.
Mengapa Bash Gagal Secara Diam-Diam Secara Bawaan
Secara bawaan, Bash tetap berjalan meskipun perintah gagal. Hal ini menyebabkan masalah tersembunyi yang sulit dilacak dalam skrip produksi.
Perhatikan skrip yang mencoba membuat cadangan berikut:
- Salah ketik pada jalur menyebabkan
cpgagal - Bash mengabaikan kegagalan tersebut dan melanjutkan
- Skrip melaporkan keberhasilan meskipun data tidak pernah dicadangkan
Inilah masalah kegagalan diam-diam. Mode ketat mengatasinya dengan membuat Bash berperilaku seperti bahasa terkompilasi: segera berhenti saat terjadi masalah.
#!/usr/bin/env bash
# Without strict mode — dangerous default behavior
cp /important/data /backups/data # fails (path doesn't exist)
echo "Backup complete" # still prints — false confidence!
rm -rf /tmp/staging # still runs — potentially destructiveTiga Tanda Utama: set -euo pipefail
Mode ketat diaktifkan dengan menempatkan baris berikut di dekat bagian atas setiap skrip:
set -euo pipefail
Perintah ini mengaktifkan tiga pengaman berbeda:
-e— Segera keluar jika suatu perintah mengembalikan status bukan nol-u— Perlakukan variabel yang belum ditetapkan sebagai kesalahan (alih-alih mengembangkannya menjadi string kosong)-o pipefail— Alur gagal jika perintah mana pun di dalamnya gagal, bukan hanya perintah terakhir
Bersama-sama, ketiganya membentuk header pertahanan standar untuk skrip Bash yang serius. Setiap tanda menangkap jenis bug yang berbeda.
#!/usr/bin/env bash
set -euo pipefail
echo "Strict mode is now active"
echo "Every command failure will abort the script"Memahami set -e (errexit)
set -e (yang juga ditulis sebagai set -o errexit) menyebabkan skrip segera keluar saat suatu perintah keluar dengan status bukan nol.
Perilaku penting yang perlu diketahui:
- Perintah sederhana:
false,grep pattern file(tidak ada kecocokan), danls /nonexistentsemuanya memicu keluar - Kode keluar dari perintah terakhir dalam skrip menjadi kode keluar skrip
- Perintah dalam kondisi
ifdikecualikan—-etidak aktif untuk ekspresi pengujian - Perintah yang diikuti
|| truejuga dikecualikan (lihat bagian berikutnya)
Anggap -e sebagai garis pertahanan pertama Anda agar skrip tidak terus berjalan secara diam-diam setelah kegagalan.
#!/usr/bin/env bash
set -e
echo "Before failure"
ls /this/path/does/not/exist # exits here with code 2
echo "This line never runs"Memahami set -u (nounset)
set -u (yang juga ditulis sebagai set -o nounset) membuat Bash memperlakukan setiap rujukan ke variabel yang belum ditetapkan sebagai kesalahan fatal.
Tanpa -u, salah ketik seperti $FLENAME alih-alih $FILENAME diam-diam diperluas menjadi string kosong, sehingga perintah berperilaku tidak semestinya—atau bahkan berbahaya (bayangkan rm -rf "$TMPDIR/" saat $TMPDIR belum ditetapkan).
Pengecualian penting:
${VAR:-default}— penggantian nilai bawaan yang aman dan tidak memicu-u${VAR:+value}— ekspansi bersyarat yang juga aman"$@"dan"$*"dikecualikan saat tidak ada argumen posisi yang diberikan
#!/usr/bin/env bash
set -euo pipefail
# Safe: provide a default for optional vars
OUTPUT_DIR="${1:-/tmp/output}"
LOG_LEVEL="${LOG_LEVEL:-info}"
echo "Writing to: $OUTPUT_DIR"
echo "Log level: $LOG_LEVEL"
# This would abort the script:
# echo "$UNDEFINED_VAR" # bash: UNDEFINED_VAR: unbound variableMemahami -o pipefail
Tanpa pipefail, status keluar suatu alur hanya ditentukan oleh perintah terakhir. Kegagalan sebelumnya ditelan secara diam-diam.
Contoh tanpa pipefail:
cat /missing/file | wc -lcatgagal dengan kode keluar 1, tetapiwc -lberhasil dengan kode 0- Alur mengembalikan 0—berhasil! Padahal data telah hilang.
Dengan pipefail diaktifkan, Bash mengembalikan kode keluar dari perintah paling kanan yang gagal. Dengan demikian, kegagalan alur terlihat dan dapat ditangani.
Catatan: pipefail bukan tanda berupa satu huruf—pengaturannya harus menggunakan -o pipefail.
#!/usr/bin/env bash
set -euo pipefail
# With pipefail: this aborts if grep finds nothing (exit 1)
# grep returns 1 when no match found
ps aux | grep "[n]ginx" | awk '{print $2}'
echo "If we reach here, nginx is running"Kegagalan Perintah yang Disengaja — Menggunakan || true
Terkadang suatu perintah boleh gagal. Dengan set -e, Anda harus menyatakan kegagalan yang ditoleransi secara eksplisit; jika tidak, skrip akan berhenti.
Solusi idiomatisnya adalah || true, yang menambahkan pengganti yang selalu berhasil:
command || true— sepenuhnya mengabaikan kegagalancommand || echo "Warning: step failed, continuing"— mencatat peringatan dan melanjutkancommand || { echo "fatal"; exit 1; }— penanganan kegagalan khusus
Pola ini memperjelas maksud Anda dalam kode: perintah biasa berarti “ini harus berhasil”; || true berarti “ini boleh gagal dan tidak masalah”.
#!/usr/bin/env bash
set -euo pipefail
# Remove temp dir if it exists — OK if it doesn't
rm -rf /tmp/my_workspace || true
mkdir -p /tmp/my_workspace
# Check if a service is running — OK if not
if systemctl is-active --quiet nginx 2>/dev/null || true; then
echo "nginx is active"
fi
# Grep that may find nothing — OK
grep 'ERROR' /var/log/app.log || true
echo "Done"Hal yang TIDAK Ditangkap oleh set -e
set -e memiliki pengecualian dan jebakan yang sudah dikenal. Memahaminya mencegah rasa percaya diri yang keliru:
- Perintah dalam kondisi
if/while/until—ekspresi pengujian dikecualikan berdasarkan rancangan - Perintah yang dinegasikan dengan
!—! falsetidak memicu keluar - Perintah terakhir sebelum
||—misalnyafalse || handle_error - Status keluar subshell dalam konteks tertentu—misalnya
VAR=$(failing_command)pada beberapa versi Bash - Nilai pengembalian fungsi—hanya perintah terakhir dalam fungsi yang diperhitungkan
Mode ketat bukan pengganti pemeriksaan kesalahan secara eksplisit—mode ini adalah jaring pengaman yang menangkap sebagian besar kegagalan yang tidak disengaja.
#!/usr/bin/env bash
set -euo pipefail
# These do NOT trigger -e:
if false; then echo "never"; fi # -e exempt in conditions
! false # negation exempts
false || echo "handled" # || exempts the left side
# This DOES trigger -e (no condition, no ||):
# false
echo "Script continues after exempted failures"Subshell dan Fungsi dengan Mode Ketat
Pengaturan mode ketat diwariskan oleh subshell, tetapi berperilaku secara halus dalam fungsi dan substitusi perintah.
Aturan utama:
- Fungsi mewarisi
-e,-u, danpipefaildari shell pemanggil - Pengembalian bukan nol dari suatu fungsi menyebabkan pemanggil keluar (saat
-editetapkan)—kecuali pemanggilan berada dalam kondisi atau setelah|| - Substitusi perintah
$(): pada Bash versi lama, perintah yang gagal di dalam$()mungkin tidak memicu-epada induknya; tetapkan nilainya lalu gunakan secara terpisah agar aman - Subshell eksplisit
()mewarisi semua tanda
#!/usr/bin/env bash
set -euo pipefail
setup_workspace() {
local dir="$1"
mkdir -p "$dir" # fails here if permissions denied
cd "$dir"
echo "Ready in $(pwd)"
}
# Safe pattern: assign result then use it
TODAY=$(date +%Y-%m-%d) # capture separately
WORKDIR="/tmp/run_${TODAY}"
setup_workspace "$WORKDIR"
echo "Workspace: $WORKDIR"Menggabungkan Mode Ketat dengan Penjebakan Kesalahan
Mode ketat memberi tahu Bash kapan harus berhenti. trap pada ERR memungkinkan Anda menjalankan pembersihan atau diagnostik sebelum skrip keluar.
Pola umumnya adalah:
- Tetapkan mode ketat di bagian atas
- Definisikan fungsi
cleanupatauon_error - Daftarkan fungsi tersebut dengan
trap 'on_error' ERR - Jika diperlukan, pasang trap
EXITjuga untuk pembersihan yang terjamin, baik saat berhasil maupun gagal
Penting: gunakan set -E (E kapital, juga disebut errtrace) agar trap ERR juga diwariskan oleh fungsi dan subshell—tanpanya, trap hanya aktif di badan shell utama.
#!/usr/bin/env bash
set -Eeuo pipefail
on_error() {
local exit_code=$?
local line_number=${BASH_LINENO[0]}
echo "ERROR: command failed with code ${exit_code} at line ${line_number}" >&2
}
cleanup() {
echo "Cleaning up temporary files..." >&2
rm -rf /tmp/my_run_dir 2>/dev/null || true
}
trap on_error ERR
trap cleanup EXIT
mkdir -p /tmp/my_run_dir
echo "hello" > /tmp/my_run_dir/output.txt
cat /tmp/my_run_dir/output.txt
echo "Done"Menonaktifkan Mode Ketat Secara Lokal
Terkadang suatu blok kode memang sengaja “berantakan”—misalnya, saat memeriksa keberadaan alat opsional atau menjalankan perintah lama yang mengembalikan nilai bukan nol bukan karena kesalahan. Anda dapat menonaktifkan mode ketat sementara lalu mengaktifkannya kembali.
Pola yang aman:
- Simpan keadaan dengan
set +e(menonaktifkan-e), jalankan blok tersebut, lalu aktifkan kembali denganset -e - Atau gunakan subshell
( set +e; ... )agar tanda pada shell induk tidak pernah terpengaruh - Selalu aktifkan kembali tanda-tanda tersebut segera setelah blok berisiko selesai—membiarkannya nonaktif adalah sumber bug yang umum
Utamakan bentuk subshell jika blok tersebut melibatkan beberapa perintah, karena tanda-tanda akan dipulihkan secara otomatis saat subshell keluar.
#!/usr/bin/env bash
set -euo pipefail
# Probe for optional tools without aborting
HAS_JQ=false
(
set +e
command -v jq > /dev/null 2>&1
[[ $? -eq 0 ]] && echo "jq_found"
) && HAS_JQ=true || true
if [[ "$HAS_JQ" == "true" ]]; then
echo "jq is available — using JSON output"
else
echo "jq not found — using plain text"
fiTemplat Skrip Mode Ketat Lengkap
Berikut templat siap produksi yang menggabungkan semua praktik terbaik mode ketat yang dibahas dalam pelajaran ini:
set -Eeuo pipefail— keempat tanda, termasukerrtraceIFS=$'\n\t'— pemisahan kata yang lebih aman (menghindari pemisahan berdasarkan spasi)- Trap ERR + EXIT untuk diagnostik dan pembersihan
- Nilai bawaan eksplisit untuk parameter opsional
readonlydanlocaluntuk membatasi cakupan variabel
Salin templat ini di awal setiap skrip Bash yang tidak sederhana untuk segera memperoleh manfaat dari perilaku berhenti-cepat dan kesalahan yang dapat dilacak.
#!/usr/bin/env bash
set -Eeuo pipefail
IFS=$'\n\t'
# ── Constants ────────────────────────────────────────────
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_NAME="$(basename "$0")"
# ── Trap handlers ────────────────────────────────────────
err_handler() {
echo "[${SCRIPT_NAME}] ERROR on line ${BASH_LINENO[0]}: exit ${?}" >&2
}
cleanup() {
echo "[${SCRIPT_NAME}] Exiting" >&2
}
trap err_handler ERR
trap cleanup EXIT
# ── Defaults ─────────────────────────────────────────────
ENV="${1:-production}"
MAX_RETRIES="${MAX_RETRIES:-3}"
# ── Main ─────────────────────────────────────────────────
main() {
echo "Running in env=${ENV}, max_retries=${MAX_RETRIES}"
echo "Script dir: ${SCRIPT_DIR}"
}
main "$@"Pemeriksaan Pengetahuan: Perilaku pipefail
Uji pemahaman Anda tentang pengaruh pipefail terhadap kode keluar alur pemrosesan.
Rangkuman: Mode Ketat dengan set -euo pipefail
Dalam pelajaran ini, Anda mempelajari cara membuat skrip Bash gagal dengan cepat dan jelas menggunakan mode ketat.
Tiga opsi dan hal yang dilindunginya:
-e(errexit) — keluar saat status perintah bernilai bukan nol; dikecualikan dalam kondisi dan setelah||-u(nounset) — membatalkan eksekusi saat merujuk variabel yang belum ditetapkan; gunakan${VAR:-default}untuk variabel opsional-o pipefail— membuat seluruh alur pemrosesan gagal jika tahap mana pun gagal, bukan hanya tahap terakhir
Praktik pelengkap:
- Tambahkan
-E(errtrace) agar perangkap ERR diteruskan ke dalam fungsi - Gunakan
trappadaERRdanEXITuntuk diagnosis dan pembersihan - Gunakan
|| trueuntuk sengaja menoleransi kegagalan - Nonaktifkan sementara dengan
set +edi dalam subproses untuk kode lama atau kode pemeriksaan
Mode ketat bukanlah solusi untuk semua masalah — pahami pengecualiannya — tetapi ini adalah kebiasaan tunggal yang paling efektif untuk menulis skrip Bash yang andal dan defensif.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Mode Ketat dengan set -euo pipefail” gratis?
Ya — teks lengkap “Mode Ketat dengan set -euo pipefail” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus DevOps Bootcamp, upgrade ke CoddyKit PRO. Kursus DevOps Bootcamp mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Mode Ketat dengan set -euo pipefail”?
Aktifkan perilaku gagal-seketika dan pahami dengan tepat error mana yang ditangkap atau terlewatkan oleh setiap flag mode ketat. Kamu berlatih DevOps Bootcamp 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 DevOps Bootcamp?
Tidak diperlukan pengalaman sebelumnya. DevOps Bootcamp 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 1 dari 4.
Berapa lama pelajaran “Mode Ketat dengan set -euo pipefail” 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 DevOps Bootcamp ini?
Ya. Setiap pelajaran DevOps Bootcamp 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
- Mode Ketat dengan set -euo pipefail
- Penangan Trap untuk Pembersihan dan Sinyal
- File Sementara yang Aman dan Direktori Kunci
- Skrip Idempoten dan Logika Percobaan Ulang dengan Backoff