Bash Scripting හොඳම භාවිතයන්: විශ්වසනීය සහ කාර්ය සාධනය සඳහා ඉක්මන් මාර්ගෝපදේශයක්

Bash Scripting හොඳම භාවිතයන්: විශ්වසනීය සහ කාර්ය සාධනය සඳහා ඉක්මන් මාර්ගෝපදේශයක්
මනාපි මගින් ෂෙල් බිතුපත

bash ස්ක්‍රිප්ට් දෝෂහරණය කිරීම පිදුරු ගොඩක ඉඳිකටුවක් සොයනවා වැනිය, විශේෂයෙන් ව්‍යුහය, ලොග් කිරීම සහ විශ්වසනීයත්වය පිළිබඳ ගැටළු කාලෝචිත ලෙස සැලකිල්ලට නොගෙන පවතින කේත පදනමේ නව එකතු කිරීම් දිස්වන විට. ඔබේම වැරදි නිසා හෝ සංකීර්ණ ස්ක්‍රිප්ට් ගොඩවල් කළමනාකරණය කිරීමේදී ඔබට එවැනි තත්වයන්ට මුහුණ දිය හැකිය.

කණ්ඩායම Mail.ru Cloud Solutions ඔබගේ ස්ක්‍රිප්ට් වඩා හොඳින් ලිවීමට, දෝෂහරණය කිරීමට සහ නඩත්තු කිරීමට උපකාරී වන නිර්දේශ සහිත ලිපියක් පරිවර්තනය කර ඇත. එය විශ්වාස කරන්න හෝ නොවන්න, සෑම විටම ක්‍රියා කරන පිරිසිදු, භාවිතයට සූදානම් bash කේතය ලිවීමේ තෘප්තියට වඩා කිසිවක් නැත.

ලිපියේ, කතුවරයා පසුගිය වසර කිහිපය තුළ ඔහු ඉගෙන ගත් දේ මෙන්ම ඔහුව අල්ලා ගත් පොදු වැරදි කිහිපයක් බෙදා ගනී. මෙය වැදගත් වන්නේ සෑම මෘදුකාංග සංවර්ධකයෙක්ම, තම වෘත්තීය ජීවිතයේ යම් අවස්ථාවක, සාමාන්‍ය වැඩ කාර්යයන් ස්වයංක්‍රීය කිරීමට ස්ක්‍රිප්ට් සමඟ ක්‍රියා කරන බැවිනි.

උගුල් හසුරුවන්නන්

ස්ක්‍රිප්ට් ක්‍රියාත්මක කිරීමේදී අනපේක්ෂිත දෙයක් සිදු වූ විට මා මුහුණ දුන් බොහෝ බැෂ් ස්ක්‍රිප්ට් කිසි විටෙක ඵලදායී පිරිසිදු කිරීමේ යාන්ත්‍රණයක් භාවිතා නොකරයි.

හරයෙන් සංඥාවක් ලැබීම වැනි විස්මයන් පිටතින් මතු විය හැක. නිෂ්පාදන පද්ධති මත ධාවනය කිරීමට තරම් තිර රචන විශ්වාසදායක බව සහතික කිරීම සඳහා එවැනි අවස්ථා හැසිරවීම අතිශයින් වැදගත් වේ. මෙවැනි අවස්ථා වලට ප්‍රතිචාර දැක්වීමට මම බොහෝ විට පිටවීමේ හසුරුවන්න භාවිතා කරමි:

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 යනු කිසියම් සංඥා අවස්ථාවකදී කැඳවනු ලබන පිරිසිදු කිරීමේ කාර්යයක් ලියාපදිංචි කිරීමට ඔබට උපකාර වන shell build-in විධානයකි. කෙසේ වෙතත්, වැනි හසුරුවන්නන් සමඟ විශේෂ සැලකිල්ලක් දැක්විය යුතුය 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
}

සටහන: පරිසර විචල්‍යයන් අහම්බෙන් අභිබවා යාම වැළැක්වීම සඳහා කරුණාකර ඔබ නිර්වචනය කරන විචල්‍ය නම් සමඟ විශේෂයෙන් ප්‍රවේශම් වන්න.

ලොග් කිරීමේ කාර්යයන්

ඔබේ ස්ක්‍රිප්ටයේ ප්‍රතිඵල පහසුවෙන් තේරුම් ගැනීමට අලංකාර සහ ව්‍යුහගත ලොග් කිරීම වැදගත් වේ. අනෙකුත් ඉහළ මට්ටමේ ක්‍රමලේඛන භාෂා මෙන්ම, මම සෑම විටම ස්වදේශීය ලොග් කිරීමේ කාර්යයන් මගේ bash scripts තුළ භාවිතා කරමි. __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 සහ Slack වාර්තා වැනි අනෙකුත් ඒවා වෙන වෙනම අඩංගු වේ 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 වස්තු ගබඩාවේ webhooks මත පදනම් වූ සිද්ධි-ධාවන යෙදුමක උදාහරණයක්.
  3. ඩිජිටල් පරිවර්තනය පිළිබඳ අපගේ විදුලි පණිවුඩ නාලිකාව.

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න