Meyè Pratik Bash Scripting: Yon Gid Rapid pou Scripts Bash serye ak pèfòmans

Meyè Pratik Bash Scripting: Yon Gid Rapid pou Scripts Bash serye ak pèfòmans
Shell photo pa manapi

Debogaj scripts bash se tankou chèche yon zegwi nan yon pile zèb, espesyalman lè nouvo adisyon parèt nan baz kod ki egziste deja san yo pa konsidere alè pwoblèm nan estrikti, antre ak fyab. Ou ka jwenn tèt ou nan sitiyasyon sa yo swa akòz pwòp erè ou oswa lè w ap jere pil konplèks nan scripts.

Ekip Mail.ru Cloud Solutions tradui yon atik ak rekòmandasyon ki pral ede w ekri, debogaj ak kenbe scripts ou yo pi byen. Kwè li oswa ou pa, pa gen anyen ki bat satisfaksyon nan ekri pwòp, pare pou itilize kòd bash ki travay chak fwa.

Nan atik la, otè a pataje sa li te aprann pandan kèk ane ki sot pase yo, ansanm ak kèk erè komen ki te kenbe l 'sou gad. Sa a enpòtan paske chak pwomotè lojisyèl, nan kèk pwen nan karyè yo, travay ak scripts pou otomatize travay woutin yo.

Moun k ap okipe pèlen

Pifò scripts bash mwen te rankontre pa janm sèvi ak yon mekanis netwayaj efikas lè yon bagay inatandi rive pandan ekzekisyon script.

Sipriz ka leve soti deyò a, tankou resevwa yon siyal nan nwayo a. Manyen ka sa yo trè enpòtan pou asire ke scripts yo serye ase pou kouri sou sistèm pwodiksyon an. Mwen souvan itilize moun kap okipe sòti pou reponn a senaryo tankou sa a:

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 se yon kokiy bati-an kòmand ki ede ou anrejistre yon fonksyon netwayaj ki rele nan ka ta gen nenpòt siyal. Sepandan, atansyon espesyal yo ta dwe pran ak moun kap okipe yo tankou SIGINT, ki lakòz script la avòte.

Anplis de sa, nan pifò ka ou ta dwe sèlman trape EXIT, men lide a se ke ou ka aktyèlman Customize konpòtman an nan script la pou chak siyal endividyèl.

Bati-an mete fonksyon - revokasyon rapid sou erè

Li trè enpòtan pou reponn a erè le pli vit ke yo rive epi sispann ekzekisyon byen vit. Pa gen anyen ki ka pi mal pase kontinye kouri yon kòmandman tankou sa a:

rm -rf ${directory_name}/*

Tanpri sonje ke varyab la directory_name pa detèmine.

Li enpòtan pou itilize fonksyon entegre pou okipe senaryo sa yo set, tankou set -o errexit, set -o pipefail oswa set -o nounset nan kòmansman an nan script la. Fonksyon sa yo asire ke script ou a ap sòti le pli vit ke li rankontre nenpòt kòd sòti ki pa zewo, itilizasyon varyab ki pa defini, kòmandman envalid pase sou yon tiyo, ak sou sa:

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

Remak: fonksyon entegre tankou set -o errexit, pral sòti script la le pli vit ke gen yon kòd retounen "kri" (lòt pase zewo). Se poutèt sa li se pi bon prezante manyen erè koutim, pou egzanp:

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

Ekri scripts fason sa a fòse ou fè plis atansyon sou konpòtman an nan tout kòmandman yo nan script la ak antisipe posibilite pou yon erè anvan li pran ou pa sipriz.

ShellCheck pou detekte erè pandan devlopman

Li vo entegre yon bagay tankou ShellCheck nan devlopman ak tiyo tès ou yo pou tcheke kòd bash ou a ak pi bon pratik.

Mwen sèvi ak li nan anviwònman devlopman lokal mwen an pou jwenn rapò sou sentaks, semantik, ak kèk erè nan kòd la ke mwen ta ka rate pandan y ap devlope. Sa a se yon zouti analiz estatik pou scripts bash ou yo e mwen trè rekòmande pou itilize li.

Sèvi ak pwòp kòd sòti ou

Kòd retounen nan POSIX yo pa sèlman zewo oswa yon sèl, men zewo oswa yon valè ki pa zewo. Sèvi ak karakteristik sa yo pou retounen kòd erè koutim (ant 201-254) pou plizyè ka erè.

Lè sa a, enfòmasyon sa a ka itilize pa lòt scripts ki vlope pa w la pou konprann egzakteman ki kalite erè ki te fèt epi reyaji kòmsadwa:

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

Remak: tanpri fè atansyon espesyalman ak non varyab ou defini yo pou evite aksidantèlman depase varyab anviwònman yo.

Fonksyon antre

Bèl ak estriktire antre enpòtan pou konprann fasil rezilta yo nan script ou a. Menm jan ak lòt lang pwogramasyon wo nivo, mwen toujou sèvi ak fonksyon natif natal nan scripts bash mwen yo, tankou __msg_info, __msg_error ak sou sa.

Sa a ede bay yon estrikti anrejistreman estanda lè w fè chanjman nan yon sèl kote:

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

Anjeneral mwen eseye gen kèk kalite mekanis nan scripts mwen yo __init, kote varyab logger sa yo ak lòt varyab sistèm yo inisyalize oswa mete nan valè default. Varyab sa yo ka mete tou nan opsyon liy kòmand pandan envokasyon script.

Pou egzanp, yon bagay tankou:

$ ./run-script.sh --debug

Lè yon script konsa egzekite, li asire ke paramèt tout sistèm yo mete nan valè default si yo nesesè, oswa omwen inisyalize nan yon bagay ki apwopriye si sa nesesè.

Anjeneral mwen baze chwa pou yo inisyalize ak sa yo pa dwe fè sou yon echanj ant koòdone itilizatè a ak detay yo nan konfigirasyon yo ke itilizatè a ka / ta dwe fouye nan.

Achitekti pou réutilisation ak pwòp eta sistèm

Kòd modilè / ki kapab itilize ankò

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

Mwen kenbe yon depo separe ke mwen ka itilize pou inisyalize yon nouvo script pwojè/bash ke mwen vle devlope. Nenpòt bagay ki ka reyitilize ka estoke nan yon depo epi rekipere pa lòt pwojè ki vle sèvi ak fonksyonalite sa a. Òganize pwojè fason sa a siyifikativman diminye gwosè lòt scripts epi tou asire ke baz kòd la piti epi fasil pou teste.

Kòm nan egzanp ki anwo a, tout fonksyon antre tankou __msg_info, __msg_error ak lòt moun, tankou rapò Slack, yo genyen separeman nan common/* ak dinamik konekte nan lòt senaryo tankou daily_database_operation.sh.

Kite dèyè yon sistèm pwòp

Si w ap chaje nenpòt resous pandan script la ap kouri, li rekòmande pou estoke tout done sa yo nan yon anyè pataje ak yon non o aza, pa egzanp. /tmp/AlRhYbD97/*. Ou ka itilize jeneratè tèks o aza pou chwazi non anyè a:

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

Apre travay fini, yo ka bay netwayaj nan repèrtwar sa yo nan moun k ap okipe yo ki te diskite pi wo a. Si anyè tanporè yo pa pran swen, yo akimile epi nan kèk etap lakòz pwoblèm inatandi sou lame a, tankou yon disk plen.

Sèvi ak dosye fèmen

Souvan ou bezwen asire ke yon sèl egzanp yon script ap kouri sou yon lame a nenpòt ki lè. Sa a ka fè lè l sèvi avèk dosye fèmen.

Mwen anjeneral kreye dosye fèmen nan /tmp/project_name/*.lock epi tcheke pou prezans yo nan kòmansman an nan script la. Sa a ede script la fini ak grasyeuz epi evite chanjman inatandi nan eta sistèm nan pa yon lòt script kouri nan paralèl. Fichye fèmen yo pa nesesè si ou bezwen menm script la dwe egzekite an paralèl sou yon lame bay yo.

Mezire ak amelyore

Nou souvan bezwen travay ak scripts ki kouri sou peryòd tan ki long, tankou operasyon baz done chak jou. Operasyon sa yo anjeneral enplike yon sekans etap: chaje done, tcheke pou anomali, enpòte done, voye rapò sou sitiyasyon, ak sou sa.

Nan ka sa yo, mwen toujou eseye kraze script la an ti script separe epi rapòte estati yo ak tan ekzekisyon yo lè l sèvi avèk:

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

Apre sa, mwen ka wè tan egzekisyon an ak:

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

Sa a ede m idantifye pwoblèm / zòn ralanti nan scripts ki bezwen optimize.

Bon chans!

Ki lòt bagay pou li:

  1. Ale ak kachèt GPU.
  2. Yon egzanp yon aplikasyon evènman-kondwi ki baze sou webhooks nan depo objè S3 nan Mail.ru Cloud Solutions.
  3. Chanèl telegram nou an sou transfòmasyon dijital.

Sous: www.habr.com

Add nouvo kòmantè