Baştirîn Pratîkên Nivîsarkirina Bash: Rêbernameyek Bilez ji Nivîsarên Bash ên pêbawer û bikêrhatî

Baştirîn Pratîkên Nivîsarkirina Bash: Rêbernameyek Bilez ji Nivîsarên Bash ên pêbawer û bikêrhatî
Wallpaper Shell ji hêla manapi ve

Debugkirina skrîptên bash mîna lêgerîna derziyek di çolê de ye, nemaze dema ku lêzêdekirinên nû di bingeha kodê ya heyî de bêyî berçavgirtina biwext a pirsgirêkên avahî, têketin û pêbaweriyê xuya dibin. Hûn dikarin xwe di rewşên weha de bibînin an ji ber xeletiyên xwe an jî dema ku pileyên tevlihev ên nivîsariyê birêve dibin.

tîma Mail.ru Cloud Solutions gotarek bi pêşniyarên ku dê ji we re bibe alîkar ku hûn nivîsarên xwe çêtir binivîsin, debug bikin û biparêzin wergerandin. Bawer bikin an na, tiştek ji razîbûna nivîsandina koda bash a paqij, amade-kar-a ku her carê kar dike, nake.

Di gotarê de, nivîskar tiştên ku di van çend salên çûyî de fêr bûye, û hem jî hin xeletiyên hevpar ên ku ew ji hişyariyê girtine parve dike. Ev girîng e ji ber ku her pêşdebirkerê nermalavê, di demek kariyera xwe de, bi nivîsan re dixebite ku karên xebata rûtîn otomatîk bike.

Rêvebirên xefikê

Piraniya nivîsarên bash ên ku min pê re rû bi rû mane, gava ku tiştek neçaverêkirî di dema darvekirina nivîsê de çêdibe, qet mekanîzmayek paqijkirina bi bandor bikar naynin.

Dibe ku surprîz ji derve derkevin, wek wergirtina îşaretek ji bingehê. Birêvebirina dozên weha pir girîng e ku pê ewle bibe ku nivîsar têra xwe pêbawer in ku li ser pergalên hilberînê werin xebitandin. Ez bi gelemperî rêkarên derketinê bikar tînim da ku bersivê bidim senaryoyên bi vî rengî:

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 Fermanek çêkirî ya şêlê ye ku ji we re dibe alîkar ku hûn fonksiyonek paqijkirinê ya ku di rewşek nîşanan de tê gotin tomar bikin. Lêbelê, pêdivî ye ku baldariyek taybetî bi kargêrên wekî SIGINT, ku dibe sedema betalkirina senaryoyê.

Wekî din, di pir rewşan de divê hûn tenê bigirin EXIT, lê fikir ev e ku hûn bi rastî dikarin tevgera nivîsarê ji bo her nîşanek kesane xweş bikin.

Fonksiyonên sazkirî yên çêkirî - bidawîbûna bilez a li ser xeletiyê

Pir girîng e ku meriv zû zû bersivê bide xeletiyan û bi lez darvekirinê rawestîne. Tiştek ji berdewamkirina fermanek bi vî rengî xirabtir nabe:

rm -rf ${directory_name}/*

Ji kerema xwe bala xwe bidin ku guhêrbar directory_name ne diyar kirin.

Girîng e ku meriv fonksiyonên çêkirî bikar bîne da ku bi senaryoyên weha re mijûl bibe setyên wekî set -o errexit, set -o pipefail an set -o nounset di destpêka senaryoyê de. Van fonksiyonan piştrast dikin ku skrîpta we dê zû derkeve gava ku ew bi kodek derketinê ya ne-sifir, karanîna guhêrbarên nediyar, fermanên nederbasdar ên di ser boriyekê re derbas dibin, û hwd.

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

Têbînî: fonksiyonên çêkirî yên wekî set -o errexit, dê ji skrîptê derkeve gava ku kodek vegerê ya "xew" hebe (ji bilî sifirê). Ji ber vê yekê çêtir e ku meriv karanîna xeletiya xwerû destnîşan bike, mînakî:

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

Bi vî rengî nivîsandina senaryoyan we neçar dike ku hûn li ser tevgera hemî fermanên di skrîptê de baldar bin û îhtîmala xeletiyekê pêşbîn bikin berî ku we şaş bike.

ShellCheck ku di dema pêşkeftinê de xeletiyan bibîne

Ev hêjayî entegrasyonê tiştekî wek ShellCheck di boriyên pêşkeftin û ceribandina we de da ku koda bash-a xwe li hember pratîkên çêtirîn kontrol bikin.

Ez wê di hawîrdorên pêşkeftina xweya herêmî de bikar tînim da ku raporên li ser hevoksazî, semantîk, û hin xeletiyên di kodê de ku dibe ku min di dema pêşkeftinê de winda kiribin bistînim. Ev amûrek analîzek statîk e ji bo nivîsarên weya bash û ez pir pêşniyar dikim ku wê bikar bînin.

Kodên derketina xwe bikar tînin

Kodên vegerê yên di POSIX de ne tenê sifir an yek in, lê sifir an nirxek ne-sifir in. Van taybetmendiyan bikar bînin da ku kodên xeletiya xwerû (navbera 201-254) ji bo rewşên xeletiyên cihêreng vegerînin.

Dûv re ev agahdarî dikare ji hêla skrîptên din ve were bikar anîn ku ya we dişewitîne da ku hûn bi rastî fêm bikin ka çi celeb xeletiyek çêbûye û li gorî vê yekê bertek nîşan bide:

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

Têbînî: Ji kerema xwe bi taybetî baldar bin li ser navên guhêrbar ên ku hûn diyar dikin da ku ji guhêrbarên hawîrdorê yên ku bi xeletî derbas dibin nekevin.

fonksiyonên têketinê

Têketinek xweşik û birêkûpêk girîng e ku hûn bi hêsanî encamên nivîsara xwe fam bikin. Wekî zimanên din ên bernamesaziyê yên asta bilind, ez her gav fonksiyonên têketina xwemalî di nivîsarên xwe yên bash de bikar tînim, wek mînak __msg_info, __msg_error û da ser.

Ev bi kirina guheztinan li yek cîhek tenê arîkariyek danûstendina standardkirî peyda dike:

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

Ez bi gelemperî hewl didim ku di senaryoyên xwe de mekanîzmayek hebe __init, li cihê ku guhêrbarên logger û guhêrbarên din ên pergalê têne destpêkirin an li ser nirxên xwerû têne danîn. Van guhêrbar dikarin ji vebijarkên rêzika fermanê jî di dema gazîkirina skrîptê de bêne danîn.

Ji bo nimûne, tiştek wekî:

$ ./run-script.sh --debug

Dema ku skrîptek wusa tête darve kirin, ew piştrast dike ku ger hewce be mîhengên li seranserê pergalê li gorî nirxên xwerû têne danîn, an heke hewce be bi kêmanî tiştek guncan were destpêkirin.

Ez bi gelemperî bijartina tiştê ku were destpêkirin û çi neyê kirin li ser danûstendinek di navbera navgîniya bikarhêner û hûrguliyên veavakirinên ku bikarhêner dikare/divê ku tê de bikole bingeh dikim.

Mîmarî ji bo ji nû ve karanîna û pergala pergala paqij

Modular / koda dubare

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

Ez depoyek veqetandî diparêzim ku ez dikarim bikar bînim da ku projeyek nû / skrîpta bash a ku ez dixwazim pêşve bixim dest pê bikim. Tiştê ku dikare ji nû ve were bikar anîn dikare di depoyek de were hilanîn û ji hêla projeyên din ên ku dixwazin wê fonksiyonê bikar bînin ve were derxistin. Bi vî rengî organîzekirina projeyan bi girîngî mezinahiya nivîsarên din kêm dike û di heman demê de piştrast dike ku bingeha kodê piçûk e û ceribandina wê hêsan e.

Wekî mînaka li jor, hemî fonksiyonên têketinê yên wekî __msg_info, __msg_error û yên din, wekî raporên Slack, di nav de cihêreng hene common/* û bi dînamîk di senaryoyên din de mîna hev ve girêdidin daily_database_operation.sh.

Pergalek paqij li dû xwe bihêlin

Heke hûn di dema ku skrîpt dimeşe hin çavkaniyan bar dikin, tê pêşniyar kirin ku hemî daneyên weha di pelrêçekek hevbeş de bi navek rasthatî hilînin, mînakî. /tmp/AlRhYbD97/*. Hûn dikarin hilberînerên nivîsê yên rasthatî bikar bînin da ku navê pelrêçê hilbijêrin:

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

Piştî qedandina xebatê, paqijkirina pelrêçanên weha dikare di navberên çengelê yên ku li jor hatine nîqaş kirin de bêne peyda kirin. Ger pelrêça demkî neyê girtin, ew kom dibin û di qonaxek de dibe sedema pirsgirêkên neçaverêkirî li ser mêvandar, wekî dîskek tije.

Bikaranîna pelên lock

Bi gelemperî hûn hewce ne ku pê ewle bibin ku tenê yek mînakek nivîsê di her wextê diyarkirî de li ser mêvandar tê xebitandin. Ev dikare bi bikaranîna pelên lock kirin.

Ez bi gelemperî pelên kilît diafirim /tmp/project_name/*.lock û hebûna wan di destpêka senaryoyê de kontrol bikin. Ev dibe alîkar ku skrîpt bi xêrhatinî biqede û ji hêla skrîptek din ve ku paralel dimeşe ji guhertinên nediyar ên rewşa pergalê dûr bixe. Heke hûn hewce ne ku heman skrîptê bi paralelî li ser mêvandarek diyar were darve kirin, pelên kilîtkirinê ne hewce ne.

Pîvan bikin û çêtir bikin

Em bi gelemperî hewce ne ku bi skrîptên ku di demên dirêj de dimeşin re bixebitin, wek mînak karûbarên databasa rojane. Karûbarên weha bi gelemperî rêzek gavan vedihewîne: barkirina daneyan, kontrolkirina anomalî, anîna daneyan, şandina raporên statûyê û hwd.

Di rewşên weha de, ez her gav hewl didim ku skrîptê li nivîsarên piçûk ên cihêreng bişkînim û rewşa wan û dema darvekirinê bi karanîna wan rapor bikim:

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

Dûv re ez dikarim dema darvekirinê bibînim:

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

Ev ji min re dibe alîkar ku di nivîsarên ku hewceyê xweşbîniyê ne de deverên pirsgirêk / hêdî nas bikim.

Bextê te xweş bî

Wekî din çi bixwînin:

  1. Biçe û kaşên GPU.
  2. Nimûneyek serîlêdana bûyer-rêvebirinê ya ku li ser tevnhooks-ê di hilanîna objeya S3 ya Mail.ru Cloud Solutions de ye.
  3. Kanala me ya telegramê di derbarê veguherîna dîjîtal de.

Source: www.habr.com

Add a comment