Mbinu Bora za Kuandika Bash: Mwongozo wa Haraka wa Hati za Bash za Kutegemewa na Utendaji

Mbinu Bora za Kuandika Bash: Mwongozo wa Haraka wa Hati za Bash za Kutegemewa na Utendaji
Shell wallpaper by manapi

Kutatua hati za bash ni kama kutafuta sindano kwenye safu ya nyasi, haswa wakati nyongeza mpya zinaonekana kwenye msingi uliopo bila kuzingatia kwa wakati maswala ya muundo, ukataji miti na kuegemea. Unaweza kujikuta katika hali kama hizi ama kwa sababu ya makosa yako mwenyewe au wakati wa kudhibiti rundo ngumu za maandishi.

Timu Mail.ru Cloud Solutions ilitafsiri makala yenye mapendekezo ambayo yatakusaidia kuandika, kurekebisha na kudumisha hati zako bora. Amini usiamini, hakuna kitu kinachopita kuridhika kwa kuandika nambari safi ya bash, tayari kutumia ambayo inafanya kazi kila wakati.

Katika makala hiyo, mwandishi anashiriki kile alichojifunza katika miaka michache iliyopita, pamoja na makosa ya kawaida ambayo yamempata. Hii ni muhimu kwa sababu kila msanidi programu, wakati fulani katika kazi yake, hufanya kazi na hati ili kurekebisha kazi za kawaida za kazi.

Washikaji mitego

Maandishi mengi ya bash ambayo nimekutana nayo kamwe hayatumii utaratibu mzuri wa kusafisha wakati kitu kisichotarajiwa kinatokea wakati wa utekelezaji wa hati.

Mshangao unaweza kutokea kutoka nje, kama vile kupokea ishara kutoka kwa msingi. Kushughulikia kesi kama hizi ni muhimu sana ili kuhakikisha kuwa hati zinategemewa vya kutosha kuendeshwa kwenye mifumo ya uzalishaji. Mara nyingi mimi hutumia vidhibiti vya kutoka kujibu hali kama hii:

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 ni amri iliyojengewa ndani ya ganda ambayo hukusaidia kusajili kitendakazi cha kusafisha ambacho huitwa iwapo kuna ishara zozote. Walakini, utunzaji maalum unapaswa kuchukuliwa na washughulikiaji kama vile SIGINT, ambayo husababisha hati kuacha.

Kwa kuongeza, katika hali nyingi unapaswa kukamata tu EXIT, lakini wazo ni kwamba unaweza kweli kubinafsisha tabia ya hati kwa kila ishara ya mtu binafsi.

Seti za kukokotoa zilizojumuishwa - kukomesha haraka kwa hitilafu

Ni muhimu sana kujibu makosa mara tu yanapotokea na kuacha utekelezaji haraka. Hakuna kinachoweza kuwa mbaya zaidi kuliko kuendelea kutekeleza amri kama hii:

rm -rf ${directory_name}/*

Tafadhali kumbuka kuwa kutofautisha directory_name haijaamuliwa.

Ni muhimu kutumia kazi zilizojengwa ili kushughulikia matukio hayo set, Kama vile set -o errexit, set -o pipefail au set -o nounset mwanzoni mwa hati. Vitendaji hivi vinahakikisha kuwa hati yako itatoka mara tu itakapokutana na nambari yoyote ya kutoka isiyo ya sifuri, matumizi ya vigeu visivyofafanuliwa, amri batili zinazopitishwa kwenye bomba, na kadhalika:

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

Kumbuka: vitendaji vilivyojengwa ndani kama vile set -o errexit, itatoka kwenye hati mara tu kutakapokuwa na nambari "mbichi" ya kurudisha (isipokuwa sifuri). Kwa hivyo ni bora kuanzisha utunzaji wa makosa maalum, kwa mfano:

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

Kuandika hati kwa njia hii hukulazimu kuwa mwangalifu zaidi kuhusu tabia ya amri zote kwenye hati na kutarajia uwezekano wa hitilafu kabla ya kukuchukua kwa mshangao.

ShellCheck ili kugundua makosa wakati wa usanidi

Inastahili kuunganisha kitu kama hicho Angalia Shell katika ukuzaji wako na bomba za majaribio ili kuangalia nambari yako ya bash dhidi ya mazoea bora.

Ninaitumia katika mazingira yangu ya ukuzaji wa ndani kupata ripoti juu ya sintaksia, semantiki, na makosa kadhaa kwenye nambari ambayo ningeweza kukosa wakati wa kuunda. Hii ni zana ya uchambuzi tuli ya maandishi yako ya bash na ninapendekeza sana kuitumia.

Kwa kutumia misimbo yako ya kutoka

Nambari za kurejesha katika POSIX sio tu sifuri au moja, lakini sifuri au thamani isiyo ya sifuri. Tumia vipengele hivi kurejesha misimbo maalum ya hitilafu (kati ya 201-254) kwa matukio mbalimbali ya hitilafu.

Habari hii basi inaweza kutumika na hati zingine ambazo hufunga yako ili kuelewa ni aina gani ya kosa lililotokea na kujibu ipasavyo:

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

Kumbuka: tafadhali kuwa mwangalifu haswa na majina tofauti unayofafanua ili kuzuia kubatilisha vigeu vya mazingira kwa bahati mbaya.

Kazi za ukataji miti

Uwekaji miti mzuri na uliopangwa ni muhimu ili kuelewa kwa urahisi matokeo ya hati yako. Kama ilivyo kwa lugha zingine za kiwango cha juu cha programu, mimi hutumia kila wakati kazi za ukataji miti asilia kwenye hati zangu za bash, kama vile. __msg_info, __msg_error na kadhalika.

Hii husaidia kutoa muundo sanifu wa ukataji miti kwa kufanya mabadiliko katika sehemu moja tu:

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

Kawaida mimi hujaribu kuwa na aina fulani ya utaratibu kwenye maandishi yangu __init, ambapo vibarua vile vya kiweka kumbukumbu na vigeu vingine vya mfumo vinaanzishwa au kuwekwa kwa maadili chaguo-msingi. Vigezo hivi vinaweza pia kuwekwa kutoka kwa chaguo za mstari wa amri wakati wa ombi la hati.

Kwa mfano, kitu kama:

$ ./run-script.sh --debug

Hati kama hii inapotekelezwa, inahakikisha kuwa mipangilio ya mfumo mzima imewekwa kwa maadili chaguo-msingi ikiwa inahitajika, au angalau kuanzishwa kwa kitu kinachofaa ikiwa ni lazima.

Kawaida mimi huweka chaguo la nini cha kuanzisha na kile ambacho nisifanye kwenye biashara kati ya kiolesura cha mtumiaji na maelezo ya usanidi ambao mtumiaji anaweza/anapaswa kuangazia.

Usanifu wa kutumia tena na hali safi ya mfumo

Msimbo wa msimu/unayoweza kutumika tena

β”œβ”€β”€ framework
β”‚   β”œβ”€β”€ common
β”‚   β”‚   β”œβ”€β”€ loggers.sh
β”‚   β”‚   β”œβ”€β”€ mail_reports.sh
β”‚   β”‚   └── slack_reports.sh
β”‚   └── daily_database_operation.sh

Ninaweka hazina tofauti ambayo ninaweza kutumia kuanzisha hati mpya ya mradi/bash ambayo ninataka kukuza. Kitu chochote kinachoweza kutumika tena kinaweza kuhifadhiwa kwenye hazina na kurejeshwa na miradi mingine inayotaka kutumia utendakazi huo. Kupanga miradi kwa njia hii hupunguza kwa kiasi kikubwa saizi ya hati zingine na pia kuhakikisha kuwa msingi wa msimbo ni mdogo na rahisi kujaribu.

Kama katika mfano hapo juu, kazi zote za ukataji miti kama vile __msg_info, __msg_error na zingine, kama vile ripoti za Slack, ziko tofauti ndani common/* na unganisha kwa nguvu katika hali zingine kama vile daily_database_operation.sh.

Acha mfumo safi

Ikiwa unapakia rasilimali yoyote wakati hati inaendeshwa, inashauriwa kuhifadhi data zote kama hizo kwenye saraka iliyoshirikiwa na jina la nasibu, k.m. /tmp/AlRhYbD97/*. Unaweza kutumia jenereta za maandishi bila mpangilio kuchagua jina la saraka:

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

Baada ya kukamilika kwa kazi, usafishaji wa saraka kama hizo unaweza kutolewa katika washughulikiaji wa ndoano zilizojadiliwa hapo juu. Saraka za muda zisipotunzwa, hujilimbikiza na katika hatua fulani husababisha matatizo yasiyotarajiwa kwa seva pangishi, kama vile diski kamili.

Kutumia faili za kufuli

Mara nyingi unahitaji kuhakikisha kuwa mfano mmoja tu wa hati unaendeshwa kwa mwenyeji wakati wowote. Hii inaweza kufanywa kwa kutumia faili za kufuli.

Kawaida mimi huunda faili za kufuli ndani /tmp/project_name/*.lock na uangalie uwepo wao mwanzoni mwa hati. Hii husaidia hati kusitishwa kwa uzuri na kuepuka mabadiliko yasiyotarajiwa kwa hali ya mfumo kwa hati nyingine inayoendesha sambamba. Faili za kufuli hazihitajiki ikiwa unahitaji hati sawa kutekelezwa sambamba kwenye seva pangishi uliyopewa.

Pima na uboresha

Mara nyingi tunahitaji kufanya kazi na hati zinazoendelea kwa muda mrefu, kama vile shughuli za kila siku za hifadhidata. Shughuli kama hizi kwa kawaida huhusisha mfuatano wa hatua: kupakia data, kuangalia hitilafu, kuleta data, kutuma ripoti za hali, na kadhalika.

Katika hali kama hizi, mimi hujaribu kila wakati kuvunja hati katika hati ndogo tofauti na kuripoti hali yao na wakati wa utekelezaji kwa kutumia:

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

Baadaye naweza kuona wakati wa utekelezaji na:

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

Hii hunisaidia kutambua maeneo ya tatizo/polepole katika hati zinazohitaji uboreshaji.

Bahati nzuri!

Nini kingine cha kusoma:

  1. Nenda na akiba za GPU.
  2. Mfano wa programu inayoendeshwa na tukio kulingana na viboreshaji vya wavuti katika hifadhi ya kitu cha S3 cha Mail.ru Cloud Solutions.
  3. Chaneli yetu ya telegramu kuhusu mabadiliko ya kidijitali.

Chanzo: mapenzi.com

Kuongeza maoni