DevOps-bootcamp · Oppitunti

Trap-käsittelijät siivousta ja signaaleja varten

Rekisteröi EXIT-, ERR- ja INT-trapit väliaikaistiedostojen poistamiseen ja keskeneräisten toimintojen luotettavaan peruuttamiseen.

Oppitunti 2/413 vaihetta

Trap-käsittelijät siivousta ja signaaleja varten on ilmainen DevOps-bootcamp-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu DevOps-bootcamp-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. DevOps-bootcamp-kurssilla on yhteensä 4 oppituntia.

Trap-käsittelijöiden merkitys

Kun Bash-komentosarja päättyy — normaalisti, virheen vuoksi tai käyttäjän painettua Ctrl+C — jäljelle voi jäädä väliaikaisia tiedostoja, keskeneräisiä tietoja tai rikkoutunut tila. Ilman siivousta nämä jäänteet kasaantuvat ja aiheuttavat vaikeasti jäljitettäviä ongelmia.

Trap-käsittelijät ratkaisevat tämän rekisteröimällä funktion tai komennon, jonka Bash suorittaa automaattisesti, kun tietty signaali tai pseudosignaali vastaanotetaan.

  • EXIT — suoritetaan aina, kun komentosarja päättyy syystä riippumatta
  • ERR — suoritetaan, kun jokin komento palauttaa nollasta poikkeavan poistumistilan
  • INT — suoritetaan, kun käyttäjä lähettää SIGINT-signaalin (Ctrl+C)
  • TERM — suoritetaan SIGTERM-signaalin yhteydessä (esimerkiksi komennosta kill)

Hyvin kirjoitettu komentosarja rekisteröi nämä trap-käsittelijät heti alussa, ennen riskialttiiden toimintojen aloittamista.

trap-sisäänrakennetun komennon syntaksi

trap-sisäänrakennettu komento rekisteröi käsittelijän yhdelle tai useammalle signaalille tai pseudosignaalille. Yleinen syntaksi on:

trap 'command_or_function' SIGNAL [SIGNAL...]

Tärkeät säännöt:

  • Ensimmäinen argumentti on lainausmerkeissä oleva shell-koodimerkkijono (tai funktion nimi), joka suoritetaan signaalin tapahtuessa.
  • Käsittelijän jälkeen voi luetella useita signaaleja.
  • trap '' SIGNAL ohittaa kyseisen signaalin (tyhjä käsittelijä).
  • trap - SIGNAL palauttaa signaalin oletustoiminnan.

Saman shellin kutsumat funktiot perivät trap-käsittelijät, mutta ( )- tai &-syntaksilla käynnistetyt alikomennot eivät peri niitä.

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

EXIT-trap — turvaverkko

EXIT-pseudosignaali on tärkein rekisteröitävä trap-käsittelijä. Se suoritetaan, kun shell päättyy mistä tahansa syystä: normaalin suorituksen päättyessä, komennon exit N seurauksena, käsittelemättömän virheen vuoksi tai signaalin takia. Siksi se sopii erinomaisesti väliaikaisten tiedostojen poistamiseen.

Hyvä käytäntö:

  • Luokaa väliaikaiset tiedostot komennolla mktemp, jotta niiden nimet ovat yksilöllisiä ja ennalta arvaamattomia.
  • Tallentakaa polku heti muuttujaan.
  • Rekisteröikää EXIT-trap heti luomisen jälkeen, jotta siivous suoritetaan aina.

Komentosarjan poistumiskoodi säilytetään — trap-käsittelijän poistumiskoodi ohitetaan, ellette kutsu sen sisällä nimenomaisesti komentoa exit.

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

Useiden väliaikaisten tiedostojen ja hakemistojen käsittely

Oikeat komentosarjat luovat usein useita väliaikaisia resursseja — tiedostoja, hakemistoja, FIFO-putkia ja lukitustiedostoja. Sen sijaan että seuraisitte jokaista erikseen, kerätkää ne taulukkoon ja poistakaa kaikki yhdellä siivousfunktiolla.

Tämä malli skaalautuu siististi: aina kun luotte uuden väliaikaisen resurssin, lisätkää se taulukkoon. EXIT-trap käsittelee aina koko luettelon riippumatta siitä, missä kohdassa komentosarja päättyy.

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

ERR-trap — virheiden sieppaaminen

ERR-pseudosignaali suoritetaan, kun jokin yksinkertainen komento palauttaa nollasta poikkeavan poistumistilan, edellyttäen, että shell-asetus set -e (errexit) on käytössä tai komento ei ole if-, while- tai ||/&&-rakenteen sisällä.

Käyttäkää ERR-trapia seuraaviin tarkoituksiin:

  • Kirjatkaa epäonnistunut rivi muuttujien $LINENO ja $BASH_COMMAND avulla.
  • Käynnistäkää palautuslogiikka ennen EXIT-trapin suorittamista.
  • Tuottakaa jäsenneltyjä virheilmoituksia vakiovirtaan.

Tärkeää: ERR-trapeja ei suoriteta funktioiden sisällä, ellette suorita nimenomaisesti komentoa set -E (errtrace), jotta funktiot perivät ERR-trapin kutsuvalta shelliltä.

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

INT-trap — hallittu Ctrl+C-keskeytys

Ctrl+C-näppäinyhdistelmän painaminen lähettää SIGINT-signaalin edustalla olevalle prosessiryhmälle. Ilman trapiä Bash päättyy heti, jolloin keskeneräistä työtä voi jäädä jäljelle.

INT-trapin rekisteröiminen mahdollistaa seuraavat toimet:

  • Tulostakaa käyttäjäystävällinen peruutusviesti.
  • Tehkää tarvittava palautus ennen siirtymistä EXIT-trapille.
  • Poistukaa merkityksellisellä tilakoodilla (130 on SIGINT-signaalin tavanomainen koodi: 128 + 2).

Kun INT-käsittelijä on valmis, kutsukaa komentoa exit 130 oikean poistumiskoodin välittämiseksi. EXIT-trap suoritetaan tämän jälkeen automaattisesti.

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

EXIT-, ERR- ja INT-trapien yhdistäminen

Tuotantokäyttöön tarkoitetuissa komentosarjoissa rekisteröidään yleensä kaikki kolme trapiä yhdessä, jotta kaikki poistumisreitit katetaan:

  • EXIT — suoritetaan aina ja huolehtii tiedostojen siivouksesta.
  • ERR — kirjaa epäonnistuneen komennon ja rivinumeron.
  • INT — tulostaa peruutusviestin ja poistuu koodilla 130.

Koska EXIT suoritetaan aina viimeisenä, siivouslogiikan tarvitsee olla vain yhdessä paikassa. ERR- ja INT-käsittelijät voivat keskittyä kirjaamiseen ja tilan asettamiseen ja jättää varsinaisen siivouksen EXIT-käsittelijälle kutsumalla komentoa exit.

Käyttäkää komennon set -eEuo pipefail yläosassa, jotta myös funktioiden virheet käynnistävät ERR-trapin ja pipefail havaitsee putkien sisäiset virheet.

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

Trapien dynaaminen palauttaminen ja poistaminen käytöstä

Joskus trapia on muokattava kesken komentosarjan — esimerkiksi kertaluonteisen siivouksen jälkeen, kun kriittinen osuus on valmis, jotta myöhemmät normaalit toiminnot eivät käynnistä tarpeetonta palautusta.

  • trap - SIGNAL palauttaa signaalin sisäänrakennetun oletustoiminnan.
  • trap '' SIGNAL ohittaa signaalin kokonaan (prosessi ei voi joutua sen lopettamaksi).
  • Uuden käsittelijän voi rekisteröidä milloin tahansa; viimeisin trap-kutsu on voimassa.

Yleinen toimintamalli on päivittää EXIT-trap riskialttiin toiminnon onnistuttua ja vaihtaa palautuskäsittelijä yksinkertaiseen siivouskäsittelijään.

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

Poistumiskoodien välittäminen trapien kautta

Hienovarainen ongelmakohta: jos siivousfunktio sisältää komentoja, jotka voivat epäonnistua, komentosarjan lopullinen poistumiskoodi saattaa muuttua. Säilyttäkää alkuperäinen poistumiskoodi nimenomaisesti.

Trap-käsittelijän sisällä $? sisältää trapin laukaisseen poistumiskoodin. Tallentakaa se käsittelijän ensimmäisellä rivillä ennen muita komentoja, jotka voisivat muuttaa sen.

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

Trapit funktioissa ja alikomennoissa

Trapien periytymisen ymmärtäminen on olennaista oikeiden komentosarjojen kirjoittamisessa:

  • Funktiot suoritetaan samassa shellissä ja perivät trapit — mutta ERR välittyy funktioihin vain, kun set -E (errtrace) on käytössä.
  • Alikomennot (( ... )) aloittavat suorituksen vanhemman trapien kopiolla, mutta alikomennossa tehdyt muutokset eivät vaikuta vanhempaan.
  • Taustatyöt (cmd &) ovat alikomentoja eivätkä peri vanhemman INT/TERM-trapeja (ne käyttävät signaalien oletuskäsittelyä).

Käytännön sääntö: pitäkää trapien rekisteröinti pääkomentosarjan rungossa, käyttäkää set -E-asetusta, kun ERR:n on välityttävä funktioihin, älkääkä koskaan luottako trapien periytymiseen &-rakenteen kautta.

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

Käytännön malli: tiedoston atominen korvaaminen

Klassinen vikasietoinen Bash-malli on tiedoston atominen korvaaminen: kirjoittakaa väliaikaiseen tiedostoon ja nimetkää se sitten kohteensa paikalle. Jos jokin epäonnistuu ennen nimeämistä, alkuperäinen tiedosto säilyy muuttumattomana. Trapit tekevät tästä erittäin luotettavan.

Vaiheet:

  1. Luokaa väliaikainen tiedosto samassa tiedostojärjestelmässä kuin kohde, jotta mv on atominen.
  2. Rekisteröikää EXIT-trap poistamaan väliaikainen tiedosto, jos suoritus päättyy ennenaikaisesti.
  3. Kirjoittakaa uusi sisältö ja tarkistakaa se.
  4. Nimetkää tiedosto atomisesti uudelleen komennolla (mv) — vasta nyt alkuperäinen korvataan.
  5. EXIT-trap poistaa väliaikaisen tiedoston vain, jos se on edelleen olemassa (onnistuneen mv-komennon jälkeen se on poistettu).
#!/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"

Tietotesti: ERR-trapin periytyminen

Testatkaa, miten ERR-trap toimii Bashin funktioiden kanssa.

Kertaus: trap-käsittelijät siivousta ja signaaleja varten

Tässä oppitunnissa opitte tekemään Bash-komentosarjoista vikasietoisia trap-käsittelijöiden avulla:

  • EXIT on yleinen turvaverkko — rekisteröikää se heti minkä tahansa väliaikaisen resurssin luomisen jälkeen ja tallentakaa aina ensin $?, jotta alkuperäinen poistumiskoodi säilyy.
  • ERR mahdollistaa virheiden kirjaamisen muuttujien $LINENO ja $BASH_COMMAND avulla; käyttäkää set -E-asetusta, jotta funktiot perivät sen.
  • INT käsittelee Ctrl+C:n hallitusti — tulostakaa viesti ja poistukaa koodilla 130, jolloin EXIT huolehtii siivouksesta.
  • Kerätkää väliaikaiset resurssit taulukkoon ja poistakaa ne kaikki yhdellä siivousfunktiolla.
  • Käyttäkää komentoa trap - SIGNAL signaalin palauttamiseen ja komentoa trap '' SIGNAL signaalien dynaamiseen ohittamiseen.
  • Atominen uudelleennimeämismalli (mktemp → kirjoitus → tarkistus → mv) yhdistettynä EXIT-trapiin takaa, etteivät keskeneräiset kirjoitukset koskaan vioita kohdetiedostoa.

Komennon set -eEuo pipefail yhdistäminen oikein sijoitettuihin trapeihin tarjoaa vankan vikasietoisen perustan kaikille tuotantokäyttöön tarkoitetuille Bash-komentosarjoille.

Aloita maksutta

Opi DevOps-bootcamp tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
142
Oppitunnit
568

Usein kysytyt kysymykset

Onko oppitunti ”Trap-käsittelijät siivousta ja signaaleja varten” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa DevOps-bootcamp-oppimispolun 3 oppituntia, myös oppitunnin “Trap-käsittelijät siivousta ja signaaleja varten”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. DevOps-bootcamp-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Trap-käsittelijät siivousta ja signaaleja varten”?

Rekisteröi EXIT-, ERR- ja INT-trapit väliaikaistiedostojen poistamiseen ja keskeneräisten toimintojen luotettavaan peruuttamiseen. Harjoittelet DevOps-bootcamp-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni DevOps-bootcamp-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin DevOps-bootcamp-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.

Kuinka kauan ”Trap-käsittelijät siivousta ja signaaleja varten”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä DevOps-bootcamp-oppitunnilla?

Kyllä. Jokainen DevOps-bootcamp-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Tiukka tila komennolla set -euo pipefail
  2. Trap-käsittelijät siivousta ja signaaleja varten
  3. Turvalliset väliaikaistiedostot ja lukitushakemistot
  4. Idempotentit skriptit ja uudelleenyritys viiveen kasvaessa
← Takaisin: DevOps-bootcamp