Хичээлийн тойм + Shell
Бид хэн бэ?
Энэ хичээлийг Anish, Jon, Jose гурав хамт заадаг. Бид бүгд MIT-д оюутан байхдаа энэ IAP хичээлийг эхлүүлсэн төгсөгчид. Бидэнтэй missing-semester@mit.edu хаягаар холбогдож болно.
Бид энэ хичээлээс цалин, ашиг авдаггүй. Бүх материал болон лекцийн бичлэг-ийг интернэтэд үнэгүй тавьсан. Дэмжихийг хүсвэл бусдад хэлж түгээхэд л хангалттай. Хэрэв та энэ агуулгыг компани, их сургууль эсвэл өөр байгууллагад олон хүнд заадаг бол туршлага, санал хүсэлтээ имэйлээр явуулаарай :)
Сэдэл, зорилго
CS-ийн хүмүүс бид компьютер давтагддаг ажлыг автоматжуулахдаа сайн гэдгийг мэддэг. Гэхдээ энэ санаа зөвхөн бидний бичдэг програмд биш, компьютерээ ашиглаж байгаа арга барилд ч хамаатай гэдгийг амархан мартчихдаг. Илүү бүтээмжтэй ажиллах, илүү төвөгтэй асуудал шийдэхэд туслах олон tool бидний гарт бэлэн байдаг. Гэтэл ихэнхдээ цээжилсэн хэдэн command-аа л хэрэглээд, гацахаараа интернэтээс command хуулж тавьдаг.
Энэ хичээл нь үүнийг засах зорилготой юм.
Бид таны аль хэдийн мэддэг tool-уудыг илүү сайн ашиглуулж, toolbox-д тань шинэ tool нэмээд, цаашдаа өөрөө судалж, хэрэгтэй бол өөрөө tool бичдэг болгохыг хүсэж байна. Энэ бол ихэнх CS хөтөлбөрөөс орхигдсон нэг бүтэн семестр гэж бид боддог.
Хичээлийн бүтэц
Энэ кредитгүй хичээл 1 цагийн 9 лекцтэй. Лекц бүр тусдаа сэдэвтэй. Ерөнхийдөө бие даасан ч хичээл ахих тусам өмнөх лекцүүдийн санааг мэддэг гэж үзнэ. Тэмдэглэлүүд нь онлайн байгаа, гэхдээ хичээл дээр live demo хэлбэрээр үзүүлсэн зарим зүйл тэмдэглэлд бүрэн ороогүй байж магадгүй. Өмнөх жилүүдийн адил лекцүүдийг бичээд онлайнд тавина.
Цөөн цагт олон сэдэв багтааж байгаа болохоор лекцүүд нэлээд нягт. Өөрийн хурдаар давтаж, гол санааг гараар туршиж үзэг гээд лекц бүрд дасгал оруулсан. Тусдаа office hour байхгүй, гэхдээ асуултаа OSSU Discord-ийн #missing-semester-forum сувагт асууж болно, эсвэл missing-semester@mit.edu рүү имэйл бичээрэй.
Цаг бага тул tool бүрийг гүнзгий ухаж амжихгүй. Харин боломжтой үедээ цааш унших материал, сайн resource зааж өгнө. Ямар нэг сэдэв онцгой сонирхолтой санагдвал бидэнтэй холбогдоод асуугаарай.
Энэ хичээлийн талаар санал хүсэлт байвал missing-semester@mit.edu хаягаар имэйл илгээнэ үү.
Сэдэв 1: Shell
Shell гэж юу вэ?
Өнөөдөр компьютерт command өгөх олон интерфейс бий: GUI, voice interface, AR/VR, сүүлийн үед LLM хүртэл. Эдгээр нь өдөр тутмын олон ажилд эвтэйхэн ч хязгаартай. Байхгүй товчлуурыг дарж чадахгүй, програмчлаагүй voice command өгч чадахгүй. Компьютерийнхээ боломжийг бүрэн ашиглая гэвэл хуучны боловч хамгийн уян хатан интерфейс болох текстэн Shell рүү орно.
Бараг бүх систем ямар нэг хэлбэрийн shell-тэй. Зарим нь бүр хэд хэдэн shell сонгох боломжтой. Дотроо ялгаатай ч гол үүрэг нь адилхан: програм ажиллуулах, оролт өгөх, гаралтыг нь хагас бүтэцтэй байдлаар харах.
Command бичих shell prompt нээхийн тулд эхлээд shell-ийн харагдах цонх болох Terminal хэрэгтэй. Ихэнх төхөөрөмж дээр Terminal суусан байдаг, эсвэл амархан суулгаж болно:
- Linux:
ихэнх тархацууд дээр
Ctrl + Alt + Tдарна. Эсвэл өөрийн програмуудын цэснээс “Terminal” гэж хайна. - Windows:
Win + Rдарж,cmdэсвэлpowershellгэж бичээд Enter дарна. Эсвэл Эхлүүлэх цэснээс “Terminal” эсвэл “Command Prompt” гэж хайна. - macOS:
Spotlight-ийг нээхийн тулд
Cmd + Spaceдарж, “Terminal” гэж бичээд Enter дарна. Эсвэл Applications → Utilities → Terminal гэж хайж олно.
Linux болон macOS дээр энэ нь ихэвчлэн Bourne Again SHell буюу товчоор “bash”-ийг нээдэг. Энэ нь хамгийн өргөн хэрэглэгддэг shell-үүдийн нэг бөгөөд түүний синтакс нь бусад олон shell-тэй төстэй байдаг. Windows дээр таны ажиллуулсан commandаас хамааран “batch” эсвэл “powershell” нээгдэх болно. Эдгээр нь Windows-д зориулагдсан бөгөөд энэ хичээлээр үзэх гол сэдэв биш юм. Үүний оронд та Windows Subsystem for Linux (WSL) эсвэл Linux виртуал машин ашиглавал дээр.
Bash-аас гадна хэрэглэхэд илүү хялбар, тохиромжтой өөр олон shell-үүд байдаг (fish болон zsh нь хамгийн түгээмэл нь юм). Эдгээр нь маш алдартай боловч (багш нар бүгд ашигладаг) bash шиг хаа сайгүй байдаггүй бөгөөд ижил төстэй ойлголтууд дээр суурилдаг тул бид энэ лекцээр тэдгээрт анхаарлаа хандуулахгүй.
Та яагаад үүнийг анхаарах ёстой вэ?
Shell нь зүгээр нэг “mouse-оор товшихоос хурдан” хэрэгсэл биш. График app-уудаас олоход хэцүү уян хатан, хүчтэй илэрхийлэлтэй. Цааш үзэхээр shell-ийн гол давуу тал нь програмуудыг хооронд нь эвлүүлж бараг ямар ч ажлыг автоматжуулж болдогт байгаа.
Shell дээр ажиллаж сурах нь нээлттэй эхийн програм хангамжийн ертөнцөд ажиллахад (тэдгээр нь ихэвчлэн shell ашиглахыг шаарддаг суулгах заавартай ирдэг), төслүүддээ тасралтгүй интеграци бэлтгэхэд (Кодын чанар лекц-нд тайлбарласнаар), мөн бусад програмууд ажиллахгүй алдаа заах үед алдааг илрүүлж засахад их хэрэг болдог.
Shell дотор шилжих
Терминалыг ажиллуулахад ихэвчлэн ингэж prompt харагдана:
missing:~$
Энэ бол shell-ийн үндсэн текстэн интерфейс юм. Энэ нь таныг missing нэртэй компьютер дээр байгаа бөгөөд таны “одоогийн ажиллаж буй folder” (current working directory) буюу одоо байгаа байршил тань ~ (home folder-ийн товчлол) болохыг илтгэнэ. $ тэмдэг нь таныг root хэрэглэгч биш болохыг илэрхийлнэ (энэ талаар дараа дэлгэрэнгүй үзнэ). Энэ prompt дээр та shell-ээр тайлбарлуулах command бичиж болно. Хамгийн энгийн command бол програмыг ажиллуулах юм:
missing:~$ date
Fri 10 Jan 2020 11:49:31 AM EST
missing:~$
Энд бид одоогийн огноо, цагийг хэвлэдэг date програмыг ажиллууллаа. Дараа нь shell биднээс дараагийн ажиллуулах command-ыг асууж байна. Бид мөн command-ыг аргумент-тэй хамт ажиллуулж болно:
missing:~$ echo hello
hello
Энэ тохиолдолд бид shell-д echo програмыг hello гэсэн аргументтай ажиллуулахыг тушаасан. echo програм нь өөрт нь өгсөн аргументуудыг зүгээр л хэвлэж харуулдаг. Shell нь command-ыг хоосон зайгаар нь салгаж задлан шинжлээд, эхний үгээр заасан програмыг ажиллуулж, дараагийн үг бүрийг програмд аргумент болгон дамжуулдаг. Хэрэв та хоосон зай эсвэл бусад тусгай тэмдэгт агуулсан аргумент (жишээлбэл, “My Photos” нэртэй folder) дамжуулахыг хүсвэл аргументыг ' эсвэл " ашиглан хашиж ("My Photos"), эсвэл тусгай тэмдэгтүүдийн өмнө \ тавьж хувиргаж (My\ Photos) болно.
Шинээр сурч эхэлж буй хүмүүсийн хувьд магадгүй хамгийн чухал command бол “гарын авлага” гэсэн үгний товчлол болох man юм. man програм нь систем дэх дурын command-ын талаарх дэлгэрэнгүй мэдээллийг харах боломж өгдөг. Жишээлбэл, хэрэв та man date гэж ажиллуулбал date гэж юу болох, түүний ажиллагааг өөрчлөхөд ашиглаж болох янз бүрийн аргументуудыг тайлбарлах болно. Мөн ихэнх command-уудад аргумент болгон --help дамжуулж тусламжийн товч хувилбарыг харж болно.
Терминал дээр шууд түгээмэл хэрэглэгддэг жишээнүүдийг харахын тулд
man-аас гаднаtldr-ийг суулгаад ашиглаад үзээрэй. Мөн LLM загварууд нь command-уудын ажиллах зарчмыг тайлбарлах болон таны хүссэн үр дүнд хүрэхийн тулд тэдгээрийг хэрхэн дуудахыг зааж өгөхдөө маш сайн байдаг.
man-ы дараа заавал мэдэх command бол directory солиход ашигладаг cd юм. Энэ нь тусдаа програм биш, shell-ийн built-in command (өөрөөр хэлбэл which cd гэж ажиллуулбал “no cd found” гэж гарна). cd-д path дамжуулахад тэр path таны current working directory болно. Одоо хаана байгаагаа shell prompt-оос ч харж болно:
missing:~$ cd /bin
missing:/bin$ cd /
missing:/$ cd ~
missing:~$
Shell-д автомат нөхөлт (auto-completion) байдаг тул та
<TAB>товчлуурыг дарж замыг илүү хурдан гүйцээж бичих боломжтой!
Ихэнх command тусгай path заагаагүй үед current working directory дээр ажилладаг. Хаана байгаагаа мэдэхгүй байвал pwd ажиллуулах, эсвэл $PWD environment variable-ийг хэвлэх (echo $PWD)эд хангалттай.
Current working directory-тэй байх нь relative path ашиглах боломж өгдөг учраас маш хэрэгтэй. Өмнө үзсэн path-ууд бүгд absolute path байсан — /-оор эхэлж, файлын системийн root (/) directory-оос тухайн байршил хүртэлх бүх directory-г заадаг. Харин өдөр тутамдаа relative path илүү их хэрэглэнэ: энэ нь current working directory-ээс харьцуулж бичсэн path гэсэн үг. Relative path (/-оор эхлээгүй path) дээр эхний directory-ийн нэрийг current working directory-ээс хайгаад, цаашаа дараагийн directory-үүд рүү явна. Жишээ нь:
missing:~$ cd /
missing:/$ cd bin
missing:/bin$
Directory бүрд байдаг хоёр “тусгай” тэмдэглэгээ бий: . болон ... . нь “энэ directory”, харин .. нь “эцэг directory” гэсэн үг. Жишээ нь:
missing:~$ cd /
missing:/$ cd bin/../bin/../bin/././../bin/..
missing:/$
Command-ын аргументэд absolute болон relative path-ыг хольж ашиглаж болно. Relative path бичихдээ л current working directory-гээ санаарай.
cdхийхээ хурдан болгоё гэвэлzoxide-ийг туршаад үзээрэй.zтаны байнга ордог path-уудыг санаж, хэдхэн тэмдэгтээр тийшээ шилжихэд тусална.
Shell-д юу ашиглах боломжтой вэ?
Shell date, echo зэрэг програмыг хаанаас олохоо яаж мэддэг вэ? Shell-д command өгөхөд тэр програм хайх directory-үүдийн жагсаалт хадгалсан $PATH нэртэй environment variable-ийг хардаг:
missing:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
missing:~$ which echo
/bin/echo
missing:~$ /bin/echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
echo command ажиллуулахад shell эхлээд echo нэртэй програм хайх ёстойгоо ойлгоно. Дараа нь $PATH дотор :-оор тусгаарлагдсан directory-үүдээс тэр нэртэй файлыг хайж, олмогцоо ажиллуулна (мэдээж тухайн файл executable байх ёстой; энэ талаар дараа үзнэ). Яг аль файл ажиллаж байгааг which програмаар харж болно. Мөн ажиллуулах файлынхаа path-ыг шууд заавал $PATH-ыг бүр алгасна.
Эндээс shell ажиллуулж чадах бүх програмыг яаж харах нь ч ойлгогдоно: $PATH дээрх directory бүрийн дотор юу байгааг жагсаахад болно. Үүнийг файл жагсаадаг ls програмд directory-ийн path-ыг аргумент болгон өгөөд хийж болно:
missing:~$ ls /bin
ls-ийн илүү уншихад эвтэйхэн хувилбар хэрэгтэй болeza-г туршаад үзээрэй.
Ихэнх компьютерт энэ command маш олон програм хэвлэнэ. Бид эндээс хамгийн хэрэгтэй хэдийг нь л авч үзье. Эхлээд энгийн command-ууд:
cat file:file-ын агуулгыг хэвлэнэ.sort file:file-ын мөрүүдийг эрэмбэлж хэвлэнэ.uniq file:file-аас дараалсан давхардсан мөрүүдийг устгана.head fileболонtail file:file-ын эхний болон сүүлийн хэдэн мөрийг хэвлэнэ.
Syntax highlight болон гүйлгэж харах view-тэй
bat-ийгcat-ын оронд ашиглаад үзээрэй.
Мөн grep pattern file гэж бий. Энэ нь file дотроос pattern-тэй таарсан мөрүүдийг олдог. Маш хэрэгтэй, бас таны төсөөлснөөс олон юм хийж чаддаг тул тусад нь сайн анхаарах үнэ цэнтэй. pattern нь үнэндээ нэлээд нарийн хэв загварыг илэрхийлж чаддаг regular expression юм — бид үүнийг Кодын чанар лекц-ээр үзнэ. Файлын оронд directory зааж өгөөд (эсвэл current directory хайх бол хоосон үлдээгээд), доторх бүх файлыг recursive хайхдаа -r аргумент дамжуулж болно.
grep-ийн илүү хурдан, хэрэглэхэд эвтэйхэн хувилбар хэрэгтэй болripgrep-ийг ашиглаад үзээрэй.ripgrepdefault-аараа current directory дотор recursive хайлт хийдэг нь том давуу тал.
Мөн ашиглахад арай илүү төвөгтэй интерфейстэй хэд хэдэн маш хэрэгтэй хэрэгслүүд бий. Тэдгээрийн эхнийх нь програмчлагддаг файл засварлагч болох sed юм. Энэ нь файлуудад автомат өөрчлөлт хийх өөрийн програмчлалын хэлтэй боловч хамгийн түгээмэл хэрэглээ нь:
missing:~$ sed -i 's/pattern/replacement/g' file
Энэ нь file доторх pattern-ийг replacement-ээр солино. -i аргумент нь өөрчлөлтийг файл дээр нь шууд бичнэ гэсэн үг (өөрчилсөн агуулгыг зүгээр stdout руу хэвлэхийн оронд). s/ нь sed-ийн хэл дээр “солих” үйлдлийг заадаг хэлбэр. / тэмдэгт pattern болон replacement текстийг тусгаарлана. Төгсгөлийн /g нь мөр бүр дээр зөвхөн эхний таарцыг биш, бүх таарцыг солихыг хэлнэ. grep-тэй адил эндэх pattern нь regular expression тул нэлээд уян хатан. Regex replace хийхдээ replacement хэсэгт таарсан pattern-ы зарим хэсгийг буцааж ашиглаж болдог; удахгүй жишээг нь үзнэ.
Дараа нь бид тодорхой нөхцөлтэй таарч буй файлуудыг (рекурсив байдлаар) хайх боломжийг олгодог find хэрэгслийг авч үзнэ. Жишээлбэл:
missing:~$ find ~/Downloads -type f -name "*.zip" -mtime +30
Энэ нь Downloads directory дотроос 30-аас дээш хоногийн өмнөх ZIP файлуудыг хайна.
missing:~$ find ~ -type f -size +100M -exec ls -lh {} \;
Энэ нь таны home directory дотроос 100M-ээс том файлуудыг олж жагсаана. -exec аргумент нь ажиллуулах command-ыг авна. Тэр command нь дан ; тэмдэгтээр төгсөх ёстой (түүнийг shell-д тусгай тэмдэгт гэж ойлгуулахгүйн тулд escape хийх хэрэгтэй), харин {}-ийн оронд find-ын олсон файл бүрийн path орж ажиллана.
missing:~$ find . -name "*.py" -exec grep -l "TODO" {} \;
Энэ нь TODO тэмдэглэл агуулсан дурын .py файлуудыг хайна.
find командын синтакс нь эхэндээ бага зэрэг төвөгтэй санагдаж болох ч энэ нь ямар хэрэгцээтэй хэрэгсэл болохыг ойлгоход тань тусална гэж найдаж байна!
Илүү хялбар бөгөөд тохиромжтой ашиглахын тулд
find-ын орондfdхэрэгслийг суулгаад ашиглаад үзээрэй.
Дараагийн хэрэгсэл бол sed-тэй адил өөрийн програмчлалын хэлтэй awk юм. sed нь файлыг засварлахад зориулагдсан байдаг бол awk нь тэдгээрийг задлан шинжлэхэд зориулагдсан. awk-ийн хамгийн түгээмэл хэрэглээ бол тогтмол синтакс бүхий өгөгдлийн файлуудаас (CSV файл гэх мэт) мөр бүрийн зөвхөн тодорхой хэсгийг салгаж авах юм:
missing:~$ awk '{print $2}' file
Энэ нь file-ын мөр бүрийн хоосон зайгаар тусгаарлагдсан хоёр дахь баганыг хэвлэнэ. Хэрэв та -F, аргумент дамжуулбал таслалаар тусгаарлагдсан хоёр дахь баганыг хэвлэх болно. awk нь мөрүүдийг шүүх, нэгтгэсэн тооцоолол хийх зэрэг олон зүйлийг хийж чаддаг — дасгалаас сонирхоорой.
Эдгээр хэрэгслийг хамтатган ашигласнаар бид дараах нарийн төвөгтэй зүйлсийг хийж чадна:
missing:~$ ssh myserver 'journalctl -u sshd -b-1 | grep "Disconnected from"' \
| sed -E 's/.*Disconnected from .* user (.*) [^ ]+ port.*/\1/' \
| sort | uniq -c \
| sort -nk1,1 | tail -n10 \
| awk '{print $2}' | paste -sd,
postgres,mysql,oracle,dell,ubuntu,inspur,test,admin,user,root
Энэ command нь алсын серверээс SSH логуудыг авч (бид дараагийн лекцээр ssh-ийн талаар дэлгэрэнгүй үзэх болно), холболт тасарсан тухай мэдээллүүдийг хайж, мэдээлэл бүрээс хэрэглэгчийн нэрийг салгаж аваад хамгийн их давтагдсан 10 хэрэглэгчийн нэрийг таслалаар тусгаарлан хэвлэдэг. Энэ бүгдийг ганцхан command-аар хийж байна! Алхам бүрийг задлан шинжлэхийг дасгал ажил болгон үлдээе.
Shell хэл (bash)
Өмнөх жишээнд пайп (|) гэх шинэ ойлголт гарч ирсэн. Энэ нь нэг програмын гаралтыг нөгөө програмын оролттой холбох боломж өгдөг. Энэ нь ихэнх CLI програмууд ямар нэгэн file аргумент өгөөгүй тохиолдолд өөрсдийн “стандарт оролт” (stdin) дээр ажилладагтай холбоотой. | тэмдэгт нь өмнөх програмын “стандарт гаралт” (stdout)-ыг аваад, дараагийн програмын стандарт оролт болгодог. Энэ нь танд shell програмуудыг хамтатгах (compose) боломж өгдөг бөгөөд shell-ийг маш бүтээмжтэй ажиллах орчин болгодог гол хүчин зүйлсийн нэг юм!
Үнэндээ ихэнх shell-үүд нь Python эсвэл Ruby-тэй адил бүрэн хэмжээний програмчлалын хэлийг хэрэгжүүлсэн байдаг. Үүнд хувьсагч, нөхцөл шалгах үйлдэл, давталт болон функцууд байдаг. Shell-д command ажиллуулах үед та үнэндээ shell-ээр тайлбарлагдах жижиг хэмжээний код бичиж байна гэсэн үг юм. Бид өнөөдөр bash-ийг бүхэлд нь заахгүй ч танд их хэрэгтэй зарим хэсгийг дурдъя:
Эхлээд чиглүүлэлтүүд (redirects): >file нь програмын стандарт гаралтыг терминал руу биш, харин file руу бичих боломж өгдөг. Энэ нь гаралтыг дараа нь шинжлэхэд хялбар болгодог. >>file нь файлыг дахин бичихийн оронд файл руу агуулга нэмж (append) бичнэ. Мөн <file байгаа бөгөөд нь гараас бичих оролтын оронд file-аас уншиж програмд дамжуулахыг shell-д заадаг.
Энд
teeпрограмыг дурдах нь зүйтэй.teeнь стандарт оролтыг стандарт гаралт руу хэвлэдэг (яг лcatшиг!) боловч үүний зэрэгцээ файл руу бичдэг. Тиймээсverbose cmd | tee verbose.log | grep CRITICALнь бүх дэлгэрэнгүй логийг файл руу хадгалахын зэрэгцээ таны терминалыг цэвэрхэн байлгах болно!
Дараа нь нөхцөлт оператор: if command1; then command2; command3; fi нь command1-ийг ажиллуулаад, хэрэв ямар нэгэн алдаа гараагүй бол command2 болон command3-ийг ажиллуулна. Хэрэв хүсвэл else салбарыг нэмж болно. command1 болгон ашигладаг хамгийн түгээмэл command бол нөхцөлийг шалгадаг test command бөгөөд үүнийг ихэвчлэн зүгээр л [ гэж товчилдог. Энэ нь “файл байна уу” (test -f file / [ -f file ]) эсвэл “тэмдэгт мөрүүд тэнцүү байна уу” ([ "$var" = "string" ]) гэх мэт нөхцөлүүдийг шалгах боломж өгдөг. Bash-д мөн [[ ]] байдаг бөгөөд энэ нь хашилтын тэмдэгттэй холбоотой алдаа бага гардаг, илүү “аюулгүй” суурилагдсан хувилбар юм.
Bash-д мөн while болон for гэсэн хоёр төрлийн давталт байдаг. while command1; do command2; command3; done нь command1 алдаа заахгүй байх хугацаанд бүх зүйлийг дахин дахин ажиллуулна. for varname in a b c d; do command; done нь $varname-ын утгыг a, b, c, d болгон өөрчилж command-ыг 4 удаа ажиллуулна. Утгуудыг шууд жагсаан бичихийн оронд та ихэвчлэн “command орлуулалт” (command substitution) ашиглаж болно, жишээ нь:
for i in $(seq 1 10); do
Энэ нь 1-ээс 10 хүртэлх тоог хэвлэдэг seq 1 10 command-ыг ажиллуулаад, бүхэл хаалттай хэсгийг уг command-ын гаралтаар орлуулж, 10 удаа давтах давталтыг үүсгэдэг. Хуучин кодонд та $()-ийн оронд бэктек (for i in `seq 1 10`; do) ашигласныг харж болох ч дараалан ашиглаж болно тул $() хэлбэрийг ашиглаарай.
Та урт хэмжээний shell скриптийг терминал дээр шууд бичиж болох ч тэдгээрийг .sh өргөтгөлтэй файл болгон хадгалах нь илүү тохиромжтой байдаг. Жишээлбэл, програмыг алдаа заах хүртэл нь давталтаар ажиллуулж, зөвхөн алдаа гарсан үеийн гаралтыг хэвлэхийн зэрэгцээ цаана нь (background) процессорын ачааллыг нэмэгдүүлдэг скриптийг доор үзүүлэв (энэ нь тогтворгүй тестүүдийг илрүүлэхэд их хэрэгтэй):
#!/bin/bash
set -euo pipefail
# Start CPU stress in background
stress --cpu 8 &
STRESS_PID=$!
# Setup log file
LOGFILE="test_runs_$(date +%s).log"
echo "Logging to $LOGFILE"
# Run tests until one fails
RUN=1
while cargo test my_test > "$LOGFILE" 2>&1; do
echo "Run $RUN passed"
((RUN++))
done
# Cleanup and report
kill $STRESS_PID
echo "Test failed on run $RUN"
echo "Last 20 lines of output:"
tail -n 20 "$LOGFILE"
echo "Full log: $LOGFILE"
Энд background job (&), shell redirection, арифметик expansion зэрэг хэд хэдэн шинэ зүйл гарч ирж байгаа. Эдгээрийг дараа нь өөрөө тусад нь ухаж үзвэл их хэрэг болно.
Гэхдээ програмын эхний хоёр мөрөнд хэсэг хугацаа зарцуулж тайлбарлая. Эхний мөр нь “shebang” бөгөөд та үүнийг shell скриптээс гадна өөр файлуудын эхэнд харж болно. #!/path гэж эхэлсэн файл ажиллуулах үед shell /path дээрх програмыг ажиллуулаад, файлын агуулгыг түүнд оролт болгон дамжуулдаг. Shell скриптийн хувьд энэ нь скриптийн агуулгыг /bin/bash руу дамжуулж байгаа хэрэг юм, гэхдээ та Python скриптийг мөн адил /usr/bin/python гэсэн shebang-тай бичиж болно!
Хоёр дахь мөр нь bash-ийг илүү “хатуу” дүрэмтэй болгож, shell скрипт бичих явцад гардаг зарим аюултай алдаанаас сэргийлдэг. set command нь маш олон аргумент авч болох ч товчхондоо: -e нь аль нэг command алдаа заавал скриптийг шууд зогсоодог; -u нь тодорхойлогдоогүй хувьсагчийг ашиглавал скриптийг шууд зогсоож алдаа заадаг; -o pipefail нь | пайп ашигласан дараалсан command-ын аль нэг нь алдаа заавал скриптийг мөн шууд зогсоодог болгоно.
Shell програмчлал нь ямар ч програмчлалын хэлний адил гүнзгий сэдэв боловч анхаараарай: bash нь маш олон гэнэтийн алдаа дагуулдаг тул үүнд зориулагдсан олон вэбсайтууд байдаг. Скрипт бичихдээ shellcheck-ийг тогтмол ашиглаарай. Мөн LLM загварууд нь скрипт бичих, алдааг олох болон скрипт хэтэрхий томрох үед (100-аас олон мөр) түүнийг Python зэрэг “жинхэнэ” програмчлалын хэл рүү хөрвүүлэхэд маш сайн туслагч болдог.
Дараагийн алхмууд
Энд хүрэхэд та shell-ээр үндсэн ажлуудаа хийх хэмжээний суурьтай болсон байх ёстой. Хэрэгтэй файлаа олох, програмуудын үндсэн боломжуудыг ашиглах, command-уудыг хооронд нь эвлүүлэх зэрэг нь одоо ойлгомжтой болсон байх. Дараагийн лекцээр shell болон бусад CLI tool ашиглаад илүү төвөгтэй ажлуудыг автоматжуулна.
Дасгал ажил
Энэ хичээлийн лекц бүр дасгалтай. Зарим нь тодорхой даалгавар, зарим нь “X, Y tool-ийг ашиглаад үз” гэсэн нээлттэй хэлбэртэй. Аль болох гараараа хийж үзээрэй.
Дасгалын бэлэн хариуг бид оруулаагүй. Гацвал Discord дээрх #missing-semester-forum сувагт асууж болно, эсвэл юу хийснээ тайлбарлаад бидэнд имэйл бичээрэй, туслахыг хичээнэ. Эдгээр дасгал LLM-тэй ярилцахад ч сайн материал болно. Гол үнэ цэнэ нь зөвхөн богино зам олохдоо биш, хариу хайж байх явцдаа асууж, туршиж, гүнзгий ойлгоход байгаа.
-
Энэ хичээлийг үзэхийн тулд та Bash эсвэл ZSH зэрэг Unix shell-ийг ашиглах шаардлагатай. Хэрэв та Linux эсвэл macOS дээр байгаа бол нэмэлт зүйл хийх шаардлагагүй. Хэрэв та Windows дээр байгаа бол cmd.exe эсвэл PowerShell биш, харин Unix маягийн CLI хэрэгслүүдийг ашиглахын тулд Windows Subsystem for Linux (WSL) эсвэл Linux виртуал машин ашиглах хэрэгтэй. Тохирох shell ажиллаж байгаа эсэхийг шалгахын тулд
echo $SHELLcommand-ыг ажиллуулж болно. Хэрэв энэ нь/bin/bashэсвэл/usr/bin/zshгэх мэт утга буцааж байвал та зөв програм ажиллуулж байна гэсэн үг юм. -
lscommand-ын-lаргумент ямар үүрэгтэй вэ?ls -l /гэж ажиллуулаад гаралтыг шалгана уу. Мөр бүрийн эхний 10 тэмдэгт ямар утгатай вэ? (Сэжүүр:man ls) -
find ~/Downloads -type f -name "*.zip" -mtime +30command дахь*.zipнь “глоб” (glob) юм. Glob гэж юу вэ? Туршилтын folder үүсгэж, хэдэн файл хийгээдls *.txt,ls file?.txt, болонls {a,b,c}.txtзэрэг загваруудыг туршиж үзнэ үү. Bash гарын авлагын Pattern Matching хэсгийг үзнэ үү. -
'single quotes',"double quotes", болон$'ANSI quotes'зэргийн ялгаа нь юу вэ? Дотор нь$,!, болон шинэ мөр шилжүүлэх тэмдэгт агуулсан тэмдэгт мөрийг хэвлэх command бичнэ үү. Quoting хэсгийг үзнэ үү. -
Shell-д stdin (0), stdout (1), болон stderr (2) гэсэн гурван стандарт урсгал байдаг.
ls /nonexistent /tmpгэж ажиллуулаад стандарт гаралтыг нэг файл руу, харин стандарт алдааг өөр файл руу чиглүүлнэ үү. Хоёуланг нь ижил файл руу хэрхэн чиглүүлэх вэ? Redirections хэсгийг үзнэ үү. -
$?хувьсагч нь хамгийн сүүлд ажилласан command-ын гаралтын төлөвийг хадгалдаг (0 = амжилттай).&&нь өмнөх command амжилттай болсон тохиолдолд дараагийн command-ыг ажиллуулдаг бол||нь өмнөх command алдаа заасан тохиолдолд ажиллуулдаг. Хэрэв байхгүй бол/tmp/mydirfolder-ийг үүсгэх нэг мөрт command бичнэ үү. Exit Status хэсгийг үзнэ үү. -
Яагаад
cdcommand нь тусдаа програм биш, харин shell-ийн built-in command байх ёстой вэ? (Сэжүүр: хүү процесс нь өөрийн эцэг процесст юуг нөлөөлж чадах, юуг нөлөөлж чадахгүй талаар бодно уу.) -
Аргумент болгон файлын нэр авдаг (
$1), мөнtest -fэсвэл[ -f ... ]ашиглан уг файл байгаа эсэхийг шалгадаг скрипт бичнэ үү. Энэ нь файл байгаа эсэхээс хамаарч өөр өөр мэдээлэл хэвлэх ёстой. Bash Conditional Expressions хэсгийг үзнэ үү. -
Өмнөх дасгалын скриптийг файл болгон хадгална уу (жишээ нь,
check.sh). Үүнийг./check.sh somefileгэж ажиллуулаад үзээрэй. Юу болох вэ? Одооchmod +x check.shгэж ажиллуулаад дахин туршаад үз. Яагаад энэ алхам шаардлагатай вэ? (Сэжүүр:chmodхийхийн өмнөх болон дараахls -l check.shгаралтыг харьцуулна уу.) -
Хэрэв та скриптийн
setflag-ууд дээр-xнэмбэл юу болох вэ? Энгийн скрипт дээр туршиж үзээд гаралтыг ажиглана уу. The Set Builtin хэсгийг үзнэ үү. -
Файлыг өнөөдрийн огноо бүхий нэртэй хуулбар файл болгон хадгалдаг command бичнэ үү (жишээ нь,
notes.txt→notes_2026-01-12.txt). (Сэжүүр:$(date +%Y-%m-%d)). Command Substitution хэсгийг үзнэ үү. -
Лекц дээр үзсэн тогтворгүй тестийг шалгах скриптийг cargo test-ийг хатуу зааж өгөхийн оронд тестийн command-ыг аргумент болгон авдаг болгон өөрчилнө үү. (Сэжүүр:
$1эсвэл$@). Special Parameters хэсгийг үзнэ үү. -
Пайп (pipes) ашиглан өөрийн home folder доторх хамгийн түгээмэл 5 файлын өргөтгөлийг олно уу. (Сэжүүр:
find,grepэсвэлsedэсвэлawk,sort,uniq -c, болонheadcommand-уудыг хамтатгана уу.) -
xargsнь стандарт оролтоос ирсэн мөрүүдийг command-ын аргумент болгон хөрвүүлдэг.findболонxargs-ийг хамт ашиглан (find -execбиш) folder доторх бүх.shфайлуудыг олж, файл бүрийн мөрийн тоогwc -lcommand-аар тоолно уу. Бонус: хоосон зай агуулсан файлын нэрийг зөв боловсруулдаг болгох. (Сэжүүр:-print0болон-0).man xargsүзнэ үү. -
Хичээлийн вэбсайт (
https://missing.csail.mit.edu/)-ийн HTML кодыгcurl-ээр татаж аваад,grepрүү дамжуулан нийт хэдэн лекц жагсаагдсаныг тоолно уу. (Сэжүүр: лекц бүрд нэг удаа гарч ирдэг загварыг хайна уу;curl-ийн ахицын гаралтыг хаахын тулдcurl -sашиглана.) -
jqнь JSON өгөгдлийг боловсруулах сайн хэрэгсэл юм.https://microsoftedge.github.io/Demos/json-dummy-data/64KB.jsonхаяг дахь өгөгдлийгcurl-ээр татаж аваад,jqашиглан version нь 6-аас их хүмүүсийн нэрийг салгаж авна уу. (Сэжүүр: эхлээд бүтцийг харахын тулдjq .рүү дамжуулна уу; дараа ньjq '.[] | select(...) | .name'гэж туршина уу.) -
awkнь баганы утга дээр суурилан мөрүүдийг шүүж, гаралтыг удирдах чадвартай. Жишээлбэл,awk '$3 ~ /pattern/ {$4=""; print}'нь гурав дахь багана ньpattern-тэй таарч буй мөрүүдийг хэвлэхдээ дөрөв дэх баганыг алгасдаг. Хоёр дахь багана нь 100-аас их байх мөрүүдийг хэвлэхдээ эхний болон гурав дахь баганыг сольж хэвлэхawkcommand бичнэ үү. Турших өгөгдөл:printf 'a 50 x\nb 150 y\nc 200 z\n' -
Лекц дээр үзсэн SSH лог боловсруулах дарааллыг задлан шинжлээрэй: алхам бүр юу хийж байна вэ? Дараа нь үүнтэй төстэй command ашиглан өөрийн түүхээс хамгийн их ашигласан shell command-уудыг олно уу. (
~/.bash_historyэсвэл~/.zsh_history).
Лиценз: CC BY-NC-SA.