Bash Scripting L-Aħjar Prattiċi: Gwida Rapida għal Bash Scripts Affidabbli u ta' Prestazzjoni

Bash Scripting L-Aħjar Prattiċi: Gwida Rapida għal Bash Scripts Affidabbli u ta' Prestazzjoni
Wallpaper tal-qoxra minn manapi

Id-debugging tal-iskripts bash huwa simili li tfittex labra f'haystack, speċjalment meta jidhru żidiet ġodda fil-codebase eżistenti mingħajr konsiderazzjoni f'waqtha ta 'kwistjonijiet ta' struttura, qtugħ u affidabilità. Tista' ssib ruħek f'sitwazzjonijiet bħal dawn jew minħabba l-iżbalji tiegħek stess jew meta timmaniġġja munzelli kumplessi ta' skripts.

Team Mail.ru Soluzzjonijiet Cloud ittraduċiet artiklu b’rakkomandazzjonijiet li jgħinuk tikteb, tiddibaggja u żżomm l-iskripts tiegħek aħjar. Temmnu jew le, xejn ma jegħleb is-sodisfazzjon li tikteb kodiċi bash nadif, lest għall-użu li jaħdem kull darba.

Fl-artiklu, l-awtur jaqsam dak li tgħallem matul dawn l-aħħar snin, kif ukoll xi żbalji komuni li qabduh dispjaċevoli. Dan huwa importanti għaliex kull żviluppatur ta 'softwer, f'xi punt fil-karriera tiegħu, jaħdem bi skripts biex awtomat kompiti ta' rutina ta 'xogħol.

Maniġers tan-nases

Ħafna mill-iskripts bash li ltqajt magħhom qatt ma jużaw mekkaniżmu ta’ tindif effettiv meta jiġri xi ħaġa mhux mistennija waqt l-eżekuzzjoni tal-iskript.

Jistgħu jinqalgħu sorpriżi minn barra, bħal meta tirċievi sinjal mill-qalba. L-immaniġġjar ta 'każijiet bħal dawn huwa estremament importanti biex jiġi żgurat li l-iskripts huma affidabbli biżżejjed biex jaħdmu fuq sistemi ta' produzzjoni. Spiss nuża exit handlers biex nirrispondi għal xenarji bħal dawn:

function handle_exit() {
  // Add cleanup code here
  // for eg. rm -f "/tmp/${lock_file}.lock"
  // exit with an appropriate status code
}
  
// trap <HANDLER_FXN> <LIST OF SIGNALS TO TRAP>
trap handle_exit 0 SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM

trap huwa kmand shell built-in li jgħinek tirreġistra funzjoni ta 'tindif li tissejjaħ f'każ ta' xi sinjali. Madankollu, għandha tingħata attenzjoni speċjali ma 'handlers bħal SIGINT, li tikkawża li l-iskript jaborta.

Barra minn hekk, f'ħafna każijiet għandek taqbad biss EXIT, iżda l-idea hija li fil-fatt tista 'tippersonalizza l-imġieba tal-iskrittura għal kull sinjal individwali.

Funzjonijiet stabbiliti integrati - terminazzjoni veloċi fuq żball

Huwa importanti ħafna li tirrispondi għall-iżbalji hekk kif iseħħu u twaqqaf l-eżekuzzjoni malajr. Xejn ma jista 'jkun agħar milli tkompli tmexxi kmand bħal dan:

rm -rf ${directory_name}/*

Jekk jogħġbok innota li l-varjabbli directory_name mhux determinat.

Huwa importanti li tuża funzjonijiet integrati biex timmaniġġja xenarji bħal dawn setbħal set -o errexit, set -o pipefail jew set -o nounset fil-bidu tal-iskrittura. Dawn il-funzjonijiet jiżguraw li l-iskript tiegħek joħroġ malli tiltaqa' ma' kwalunkwe kodiċi ta' ħruġ mhux żero, użu ta' varjabbli mhux definiti, kmandi invalidi mgħoddija minn pajp, eċċ:

#!/usr/bin/env bash

set -o errexit
set -o nounset
set -o pipefail

function print_var() {
  echo "${var_value}"
}

print_var

$ ./sample.sh
./sample.sh: line 8: var_value: unbound variable

Nota: funzjonijiet built-in bħal set -o errexit, se toħroġ mill-iskript malli jkun hemm kodiċi ta 'ritorn "mhux maħdum" (minbarra żero). Għalhekk huwa aħjar li tintroduċi l-immaniġġjar tal-iżbalji tad-dwana, pereżempju:

#!/bin/bash
error_exit() {
  line=$1
  shift 1
  echo "ERROR: non zero return code from line: $line -- $@"
  exit 1
}
a=0
let a++ || error_exit "$LINENO" "let operation returned non 0 code"
echo "you will never see me"
# run it, now we have useful debugging output
$ bash foo.sh
ERROR: non zero return code from line: 9 -- let operation returned non 0 code

Il-kitba ta' skripts b'dan il-mod iġġiegħlek toqgħod aktar attent dwar l-imġieba tal-kmandi kollha fl-iskrittura u tantiċipa l-possibbiltà ta' żball qabel ma tieħu b'sorpriża.

ShellCheck biex tiskopri żbalji waqt l-iżvilupp

Ta 'min jintegra xi ħaġa simili ShellCheck fil-pipelines tal-iżvilupp u tal-ittestjar tiegħek biex tiċċekkja l-kodiċi bash tiegħek mal-aħjar prattiki.

Jiena nużah fl-ambjenti tal-iżvilupp lokali tiegħi biex nikseb rapporti dwar is-sintassi, is-semantika, u xi żbalji fil-kodiċi li stajt tlift waqt l-iżvilupp. Din hija għodda ta 'analiżi statika għall-iskripts bash tiegħek u nirrakkomanda ħafna li tużaha.

Tuża l-kodiċi tal-ħruġ tiegħek stess

Il-kodiċijiet tar-ritorn f'POSIX mhumiex biss żero jew wieħed, iżda żero jew valur mhux żero. Uża dawn il-karatteristiċi biex tirritorna kodiċijiet ta 'żball tad-dwana (bejn 201-254) għal diversi każijiet ta' żball.

Din l-informazzjoni mbagħad tista' tintuża minn skripts oħra li jkebbew tiegħek biex tifhem eżattament x'tip ta' żball seħħ u jirreaġixxu kif xieraq:

#!/usr/bin/env bash

SUCCESS=0
FILE_NOT_FOUND=240
DOWNLOAD_FAILED=241

function read_file() {
  if ${file_not_found}; then
    return ${FILE_NOT_FOUND}
  fi
}

Nota: jekk jogħġbok oqgħod attent b'mod speċjali bl-ismijiet tal-varjabbli li tiddefinixxi biex tevita li aċċidentalment tevita l-varjabbli tal-ambjent.

Funzjonijiet ta 'logging

Il-qtugħ sabiħ u strutturat huwa importanti biex tifhem faċilment ir-riżultati tal-iskrittura tiegħek. Bħal lingwi oħra ta' programmar ta' livell għoli, jien dejjem nuża funzjonijiet ta' illoggjar indiġeni fl-iskripts bash tiegħi, bħal __msg_info, __msg_error u l-bqija.

Dan jgħin biex tiġi pprovduta struttura standardizzata ta’ illoggjar billi tagħmel bidliet f’post wieħed biss:

#!/usr/bin/env bash

function __msg_error() {
    [[ "${ERROR}" == "1" ]] && echo -e "[ERROR]: $*"
}

function __msg_debug() {
    [[ "${DEBUG}" == "1" ]] && echo -e "[DEBUG]: $*"
}

function __msg_info() {
    [[ "${INFO}" == "1" ]] && echo -e "[INFO]: $*"
}

__msg_error "File could not be found. Cannot proceed"

__msg_debug "Starting script execution with 276MB of available RAM"

Normalment nipprova jkolli xi tip ta' mekkaniżmu fl-iskripts tiegħi __init, fejn tali varjabbli tal-logger u varjabbli oħra tas-sistema huma inizjalizzati jew issettjati għal valuri default. Dawn il-varjabbli jistgħu wkoll jiġu stabbiliti mill-għażliet tal-linja tal-kmand waqt l-invokazzjoni tal-iskript.

Per eżempju, xi ħaġa bħal:

$ ./run-script.sh --debug

Meta skript bħal dan jiġi eżegwit, jiżgura li s-settings tas-sistema kollha jkunu ssettjati għal valuri awtomatiċi jekk ikunu meħtieġa, jew għall-inqas inizjalizzati għal xi ħaġa xierqa jekk meħtieġ.

Normalment nibbaża l-għażla ta' x'għandek inizjalizza u x'm'għandhiex tagħmel fuq kompromess bejn l-interface tal-utent u d-dettalji tal-konfigurazzjonijiet li l-utent jista'/għandu jidħol fihom.

Arkitettura għall-użu mill-ġdid u l-istat tas-sistema nadifa

Kodiċi modulari/li jistgħu jerġgħu jintużaw

├── framework
│   ├── common
│   │   ├── loggers.sh
│   │   ├── mail_reports.sh
│   │   └── slack_reports.sh
│   └── daily_database_operation.sh

Jien inżomm repożitorju separat li nista' nuża biex inizjalizza script ġdid ta' proġett/bash li nixtieq niżviluppa. Kwalunkwe ħaġa li tista 'terġa' tintuża tista 'tinħażen f'repożitorju u rkuprata minn proġetti oħra li jridu jużaw dik il-funzjonalità. L-organizzazzjoni tal-proġetti b'dan il-mod tnaqqas b'mod sinifikanti d-daqs ta 'skripts oħra u tiżgura wkoll li l-bażi tal-kodiċi hija żgħira u faċli biex tittestja.

Bħal fl-eżempju ta 'hawn fuq, il-funzjonijiet kollha tal-illoggjar bħal __msg_info, __msg_error u oħrajn, bħal rapporti Slack, jinsabu separatament fi common/* u qabbad dinamikament f'xenarji oħra bħal daily_database_operation.sh.

Ħalli warajh sistema nadifa

Jekk qed tagħbija xi riżorsi waqt li l-iskript ikun qed jaħdem, huwa rakkomandat li taħżen id-data kollha bħal din f'direttorju kondiviż b'isem każwali, eż. /tmp/AlRhYbD97/*. Tista 'tuża ġeneraturi ta' test każwali biex tagħżel l-isem tad-direttorju:

rand_dir_name="$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)"

Wara t-tlestija tax-xogħol, it-tindif ta 'direttorji bħal dawn jista' jiġi pprovdut fil-handlers tal-ganċ diskussi hawn fuq. Jekk id-direttorji temporanji ma jittieħdux ħsieb, jakkumulaw u f'xi stadju jikkawżaw problemi mhux mistennija fuq il-host, bħal disk sħiħ.

Uża fajls tal-lock

Ħafna drabi għandek bżonn tiżgura li istanza waħda biss ta 'kitba tkun qed taħdem fuq host fi kwalunkwe ħin partikolari. Dan jista 'jsir bl-użu ta' fajls lock.

Normalment noħloq fajls tal-lock fil /tmp/project_name/*.lock u ċċekkja għall-preżenza tagħhom fil-bidu tal-iskrittura. Dan jgħin lill-iskript jintemm b'mod grazzjuż u jevita bidliet mhux mistennija fl-istat tas-sistema minn skript ieħor li jaħdem b'mod parallel. Il-fajls tal-lock mhumiex meħtieġa jekk għandek bżonn li l-istess script jiġi esegwit b'mod parallel fuq host partikolari.

Kejjel u ttejjeb

Ħafna drabi għandna bżonn naħdmu bi skripts li jħaddmu fuq perjodi twal ta 'żmien, bħal operazzjonijiet ta' database ta 'kuljum. Operazzjonijiet bħal dawn tipikament jinvolvu sekwenza ta 'passi: tagħbija ta' dejta, verifika ta 'anomaliji, importazzjoni ta' dejta, tibgħat rapporti ta 'status, eċċ.

F'każijiet bħal dawn, dejjem nipprova nkisser l-iskript fi skripts żgħar separati u nirrapporta l-istatus u l-ħin tal-eżekuzzjoni tagħhom billi tuża:

time source "${filepath}" "${args}">> "${LOG_DIR}/RUN_LOG" 2>&1

Aktar tard nista' nara l-ħin tal-eżekuzzjoni bi:

tac "${LOG_DIR}/RUN_LOG.txt" | grep -m1 "real"

Dan jgħinni nidentifika oqsma problematiċi/bil-mod fi skripts li jeħtieġu ottimizzazzjoni.

Xorti tajba!

X'iktar għandek taqra:

  1. Mur u GPU caches.
  2. Eżempju ta 'applikazzjoni mmexxija mill-avvenimenti bbażata fuq webhooks fil-ħażna tal-oġġett S3 ta' Mail.ru Cloud Solutions.
  3. Il-kanal tat-telegramma tagħna dwar it-trasformazzjoni diġitali.

Sors: www.habr.com

Żid kumment