பாஷ் ஸ்கிரிப்டிங் சிறந்த நடைமுறைகள்: நம்பகமான மற்றும் செயல்திறன் பேஷ் ஸ்கிரிப்ட்களுக்கான விரைவான வழிகாட்டி

பாஷ் ஸ்கிரிப்டிங் சிறந்த நடைமுறைகள்: நம்பகமான மற்றும் செயல்திறன் பேஷ் ஸ்கிரிப்ட்களுக்கான விரைவான வழிகாட்டி
மனாபியின் ஷெல் வால்பேப்பர்

பாஷ் ஸ்கிரிப்ட்களை பிழைத்திருத்துவது, வைக்கோல் அடுக்கில் ஊசியைத் தேடுவது போன்றது, குறிப்பாக அமைப்பு, பதிவு செய்தல் மற்றும் நம்பகத்தன்மை போன்ற சிக்கல்களை சரியான நேரத்தில் கருத்தில் கொள்ளாமல், ஏற்கனவே உள்ள கோட்பேஸில் புதிய சேர்த்தல்கள் தோன்றும் போது. உங்கள் சொந்த தவறுகளால் அல்லது சிக்கலான ஸ்கிரிப்ட்களை நிர்வகிக்கும் போது இதுபோன்ற சூழ்நிலைகளில் நீங்கள் உங்களைக் காணலாம்.

அணி Mail.ru கிளவுட் தீர்வுகள் உங்கள் ஸ்கிரிப்ட்களை சிறப்பாக எழுதவும், பிழைத்திருத்தவும் மற்றும் பராமரிக்கவும் உதவும் பரிந்துரைகளைக் கொண்ட கட்டுரையை மொழிபெயர்த்தது. நம்பினாலும் நம்பாவிட்டாலும், ஒவ்வொரு முறையும் செயல்படும் சுத்தமான, பயன்படுத்தத் தயாராக இருக்கும் பாஷ் குறியீட்டை எழுதுவதில் உள்ள திருப்தியை எதுவும் மிஞ்சவில்லை.

கட்டுரையில், ஆசிரியர் கடந்த சில ஆண்டுகளாக அவர் கற்றுக்கொண்டதையும், அதே போல் அவரைப் பிடிக்காத சில பொதுவான தவறுகளையும் பகிர்ந்து கொள்கிறார். இது முக்கியமானது, ஏனென்றால் ஒவ்வொரு மென்பொருள் உருவாக்குநரும், தங்கள் தொழில் வாழ்க்கையில் ஒரு கட்டத்தில், வழக்கமான வேலை பணிகளை தானியக்கமாக்க ஸ்கிரிப்ட்களுடன் வேலை செய்கிறார்கள்.

பொறி கையாளுபவர்கள்

நான் எதிர்கொண்ட பெரும்பாலான பாஷ் ஸ்கிரிப்ட்கள், ஸ்கிரிப்ட் செயல்படுத்தும் போது எதிர்பாராதது ஏதேனும் நடந்தால், பயனுள்ள சுத்தப்படுத்தும் பொறிமுறையைப் பயன்படுத்துவதில்லை.

மையத்திலிருந்து ஒரு சமிக்ஞையைப் பெறுவது போன்ற ஆச்சரியங்கள் வெளியில் இருந்து எழலாம். உற்பத்தி முறைமைகளில் இயங்கும் அளவுக்கு ஸ்கிரிப்டுகள் நம்பகமானவை என்பதை உறுதிப்படுத்த, இதுபோன்ற நிகழ்வுகளைக் கையாள்வது மிகவும் முக்கியமானது. இது போன்ற காட்சிகளுக்கு பதிலளிக்க நான் அடிக்கடி வெளியேறும் ஹேண்ட்லர்களைப் பயன்படுத்துகிறேன்:

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 ஒரு ஷெல் உள்ளமைக்கப்பட்ட கட்டளையாகும், இது ஏதேனும் சிக்னல்கள் ஏற்பட்டால் அழைக்கப்படும் தூய்மைப்படுத்தும் செயல்பாட்டைப் பதிவுசெய்ய உதவுகிறது. இருப்பினும், போன்ற கையாளுபவர்களுடன் சிறப்பு கவனம் எடுக்கப்பட வேண்டும் SIGINT, இது ஸ்கிரிப்ட் செயலிழக்கச் செய்கிறது.

கூடுதலாக, பெரும்பாலான சந்தர்ப்பங்களில் நீங்கள் மட்டுமே பிடிக்க வேண்டும் EXIT, ஆனால் ஒவ்வொரு சிக்னலுக்குமான ஸ்கிரிப்ட்டின் நடத்தையை நீங்கள் உண்மையில் தனிப்பயனாக்கலாம் என்பது யோசனை.

உள்ளமைக்கப்பட்ட செட் செயல்பாடுகள் - பிழையின் போது வேகமாக நிறுத்தப்படும்

பிழைகள் ஏற்பட்டவுடன் அதற்குப் பதிலளிப்பது மற்றும் விரைவாக செயல்படுத்துவதை நிறுத்துவது மிகவும் முக்கியம். இது போன்ற கட்டளையை தொடர்ந்து இயக்குவதை விட மோசமாக எதுவும் இருக்க முடியாது:

rm -rf ${directory_name}/*

மாறி என்பதை நினைவில் கொள்ளவும் directory_name தீர்மானிக்கப்படவில்லை.

அத்தகைய காட்சிகளைக் கையாள உள்ளமைக்கப்பட்ட செயல்பாடுகளைப் பயன்படுத்துவது முக்கியம் setபோன்றவை set -o errexit, set -o pipefail அல்லது set -o nounset ஸ்கிரிப்ட்டின் தொடக்கத்தில். பூஜ்ஜியமற்ற வெளியேறும் குறியீடு, வரையறுக்கப்படாத மாறிகளின் பயன்பாடு, குழாய் வழியாக அனுப்பப்பட்ட தவறான கட்டளைகள் மற்றும் பலவற்றைச் சந்தித்தவுடன் உங்கள் ஸ்கிரிப்ட் வெளியேறும் என்பதை இந்தச் செயல்பாடுகள் உறுதி செய்கின்றன:

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

குறிப்பு: போன்ற உள்ளமைக்கப்பட்ட செயல்பாடுகள் set -o errexit, "ரா" ரிட்டர்ன் குறியீடு (பூஜ்ஜியத்தைத் தவிர) இருக்கும்போதே ஸ்கிரிப்டில் இருந்து வெளியேறும். எனவே தனிப்பயன் பிழை கையாளுதலை அறிமுகப்படுத்துவது நல்லது, எடுத்துக்காட்டாக:

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

இந்த வழியில் ஸ்கிரிப்ட்களை எழுதுவது, ஸ்கிரிப்டில் உள்ள அனைத்து கட்டளைகளின் நடத்தை பற்றியும் மிகவும் கவனமாக இருக்க உங்களைத் தூண்டுகிறது மற்றும் அது உங்களை ஆச்சரியத்தில் ஆழ்த்தும் முன் ஒரு பிழையின் சாத்தியத்தை எதிர்பார்க்கலாம்.

வளர்ச்சியின் போது பிழைகளைக் கண்டறிய ShellCheck

இது போன்ற ஒன்றை ஒருங்கிணைப்பது மதிப்பு ஷெல் செக் சிறந்த நடைமுறைகளுக்கு எதிராக உங்கள் பேஷ் குறியீட்டைச் சரிபார்க்க உங்கள் மேம்பாடு மற்றும் சோதனை பைப்லைன்களில்.

தொடரியல், சொற்பொருள் மற்றும் குறியீட்டில் உள்ள சில பிழைகள் பற்றிய அறிக்கைகளைப் பெற எனது உள்ளூர் மேம்பாட்டு சூழல்களில் இதைப் பயன்படுத்துகிறேன். இது உங்கள் பாஷ் ஸ்கிரிப்டுகளுக்கான நிலையான பகுப்பாய்வுக் கருவியாகும், இதைப் பயன்படுத்த நான் மிகவும் பரிந்துரைக்கிறேன்.

உங்கள் சொந்த வெளியேறும் குறியீடுகளைப் பயன்படுத்துதல்

POSIX இல் உள்ள ரிட்டர்ன் குறியீடுகள் பூஜ்யம் அல்லது ஒன்று மட்டுமல்ல, பூஜ்ஜியம் அல்லது பூஜ்ஜியம் அல்லாத மதிப்பு. பல்வேறு பிழை நிகழ்வுகளுக்கு தனிப்பயன் பிழைக் குறியீடுகளை (201-254 க்கு இடையில்) வழங்க இந்த அம்சங்களைப் பயன்படுத்தவும்.

இந்தத் தகவலைப் பிற ஸ்கிரிப்ட்கள் பயன்படுத்தி, எந்த வகையான பிழை ஏற்பட்டது என்பதைப் புரிந்துகொண்டு அதற்கேற்ப செயல்படலாம்:

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

குறிப்பு: தற்செயலாக சூழல் மாறிகளை மீறுவதைத் தவிர்க்க, நீங்கள் வரையறுக்கும் மாறி பெயர்களில் குறிப்பாக கவனமாக இருக்கவும்.

பதிவு செயல்பாடுகள்

உங்கள் ஸ்கிரிப்ட்டின் முடிவுகளை எளிதில் புரிந்து கொள்ள அழகான மற்றும் கட்டமைக்கப்பட்ட பதிவு முக்கியமானது. மற்ற உயர்நிலை நிரலாக்க மொழிகளைப் போலவே, எனது பாஷ் ஸ்கிரிப்ட்களில் நான் எப்போதும் சொந்த பதிவு செயல்பாடுகளைப் பயன்படுத்துகிறேன். __msg_info, __msg_error மற்றும் பல.

ஒரே இடத்தில் மாற்றங்களைச் செய்து தரப்படுத்தப்பட்ட பதிவு கட்டமைப்பை வழங்க இது உதவுகிறது:

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

நான் வழக்கமாக எனது ஸ்கிரிப்ட்களில் ஒருவித பொறிமுறையை வைத்திருக்க முயற்சிப்பேன் __init, அத்தகைய லாகர் மாறிகள் மற்றும் பிற கணினி மாறிகள் துவக்கப்படும் அல்லது இயல்புநிலை மதிப்புகளுக்கு அமைக்கப்படும். இந்த மாறிகள் ஸ்கிரிப்ட் அழைப்பின் போது கட்டளை வரி விருப்பங்களிலிருந்தும் அமைக்கப்படலாம்.

உதாரணமாக, இது போன்ற ஒன்று:

$ ./run-script.sh --debug

அத்தகைய ஸ்கிரிப்ட் செயல்படுத்தப்படும்போது, ​​கணினி அளவிலான அமைப்புகள் தேவைப்பட்டால் இயல்புநிலை மதிப்புகளுக்கு அமைக்கப்படுவதை உறுதிசெய்கிறது, அல்லது தேவைப்பட்டால் குறைந்தபட்சம் ஏதேனும் பொருத்தமானதாக துவக்கப்படும்.

பயனர் இடைமுகம் மற்றும் பயனர் ஆராயக்கூடிய/ஆய்வு செய்ய வேண்டிய உள்ளமைவுகளின் விவரங்களுக்கு இடையேயான வர்த்தகத்தில் எதைத் தொடங்குவது மற்றும் என்ன செய்யக்கூடாது என்பதை நான் வழக்கமாகத் தேர்வு செய்கிறேன்.

மறுபயன்பாடு மற்றும் சுத்தமான அமைப்பு நிலைக்கான கட்டிடக்கலை

மாடுலர்/மீண்டும் பயன்படுத்தக்கூடிய குறியீடு

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

நான் உருவாக்க விரும்பும் புதிய ப்ராஜெக்ட்/பாஷ் ஸ்கிரிப்டை துவக்குவதற்கு நான் பயன்படுத்தக்கூடிய ஒரு தனி களஞ்சியத்தை வைத்திருக்கிறேன். மீண்டும் பயன்படுத்தக்கூடிய எதையும் ஒரு களஞ்சியத்தில் சேமித்து, அந்த செயல்பாட்டைப் பயன்படுத்த விரும்பும் பிற திட்டங்களால் மீட்டெடுக்க முடியும். இந்த வழியில் திட்டப்பணிகளை ஒழுங்கமைப்பது மற்ற ஸ்கிரிப்ட்களின் அளவைக் கணிசமாகக் குறைக்கிறது, மேலும் குறியீடு அடிப்படை சிறியதாகவும் சோதனைக்கு எளிதாகவும் இருப்பதை உறுதி செய்கிறது.

மேலே உள்ள எடுத்துக்காட்டில் உள்ளதைப் போல, அனைத்து பதிவு செயல்பாடுகளும் __msg_info, __msg_error மற்றும் ஸ்லாக் அறிக்கைகள் போன்ற மற்றவை தனித்தனியாக உள்ளன common/* மற்றும் போன்ற பிற காட்சிகளில் மாறும் வகையில் இணைக்கவும் daily_database_operation.sh.

ஒரு சுத்தமான அமைப்பை விட்டு விடுங்கள்

ஸ்கிரிப்ட் இயங்கும் போது நீங்கள் ஏதேனும் ஆதாரங்களை ஏற்றினால், அது போன்ற எல்லா தரவையும் சீரற்ற பெயருடன் பகிரப்பட்ட கோப்பகத்தில் சேமிக்க பரிந்துரைக்கப்படுகிறது, எ.கா. /tmp/AlRhYbD97/*. கோப்பகத்தின் பெயரைத் தேர்ந்தெடுக்க, சீரற்ற உரை ஜெனரேட்டர்களைப் பயன்படுத்தலாம்:

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

வேலை முடிந்த பிறகு, அத்தகைய கோப்பகங்களை சுத்தம் செய்வது மேலே விவாதிக்கப்பட்ட ஹூக் ஹேண்ட்லர்களில் வழங்கப்படலாம். தற்காலிக அடைவுகள் கவனிக்கப்படாவிட்டால், அவை குவிந்து சில கட்டத்தில் ஹோஸ்டில் எதிர்பாராத சிக்கல்களை ஏற்படுத்தும், அதாவது முழு வட்டு.

பூட்டு கோப்புகளைப் பயன்படுத்துதல்

எந்த நேரத்திலும் ஒரு ஸ்கிரிப்ட்டின் ஒரு நிகழ்வு மட்டுமே ஹோஸ்டில் இயங்குவதை நீங்கள் அடிக்கடி உறுதிசெய்ய வேண்டும். பூட்டு கோப்புகளைப் பயன்படுத்தி இதைச் செய்யலாம்.

நான் வழக்கமாக பூட்டு கோப்புகளை உருவாக்குவேன் /tmp/project_name/*.lock மற்றும் ஸ்கிரிப்ட்டின் தொடக்கத்தில் அவர்களின் இருப்பை சரிபார்க்கவும். இது ஸ்கிரிப்டை லாவகமாக முடிக்கவும், இணையாக இயங்கும் மற்றொரு ஸ்கிரிப்ட் மூலம் கணினி நிலையில் எதிர்பாராத மாற்றங்களைத் தவிர்க்கவும் உதவுகிறது. கொடுக்கப்பட்ட ஹோஸ்டில் இணையாக அதே ஸ்கிரிப்ட் செயல்படுத்தப்பட வேண்டும் என்றால், பூட்டு கோப்புகள் தேவையில்லை.

அளவிடவும் மேம்படுத்தவும்

தினசரி தரவுத்தள செயல்பாடுகள் போன்ற நீண்ட காலத்திற்கு இயங்கும் ஸ்கிரிப்ட்களுடன் நாம் அடிக்கடி வேலை செய்ய வேண்டும். இத்தகைய செயல்பாடுகள் பொதுவாக படிகளின் வரிசையை உள்ளடக்கியது: தரவை ஏற்றுதல், முரண்பாடுகளை சரிபார்த்தல், தரவை இறக்குமதி செய்தல், நிலை அறிக்கைகளை அனுப்புதல் மற்றும் பல.

இதுபோன்ற சந்தர்ப்பங்களில், ஸ்கிரிப்டை தனித்தனி சிறிய ஸ்கிரிப்ட்களாக உடைத்து, அவற்றின் நிலை மற்றும் செயலாக்க நேரத்தைப் பயன்படுத்திப் புகாரளிக்க நான் எப்போதும் முயற்சிப்பேன்:

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

பின்னர் நான் செயல்படுத்தும் நேரத்தை இதனுடன் பார்க்க முடியும்:

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

மேம்படுத்தல் தேவைப்படும் ஸ்கிரிப்ட்களில் சிக்கல்/மெதுவான பகுதிகளைக் கண்டறிய இது எனக்கு உதவுகிறது.

நல்ல அதிர்ஷ்டம்!

வேறு என்ன படிக்க வேண்டும்:

  1. கோ மற்றும் GPU தற்காலிக சேமிப்புகள்.
  2. Mail.ru Cloud Solutions இன் S3 ஆப்ஜெக்ட் சேமிப்பகத்தில் வெப்ஹூக்குகளை அடிப்படையாகக் கொண்ட நிகழ்வு-உந்துதல் பயன்பாட்டின் எடுத்துக்காட்டு.
  3. டிஜிட்டல் மாற்றம் பற்றிய எங்கள் டெலிகிராம் சேனல்.

ஆதாரம்: www.habr.com

கருத்தைச் சேர்