Хичээлийн тойм + Shell

Бид хэн бэ?

Энэхүү хичээлийг Anish, Jon, болон Jose нар хамтран заадаг. Бид бүгд оюутан байхдаа энэхүү MIT IAP хичээлийг эхлүүлсэн MIT-ийн төгсөгчид юм. Та бидэнтэй missing-semester@mit.edu хаягаар холбогдох боломжтой.

Бид энэ хичээлийг заасныхаа төлөө цалин авдаггүй бөгөөд ямар нэгэн байдлаар ашиг олдоггүй. Бид бүх хичээлийн материал болон лекцийн бичлэгүүд-ийг интернэтэд үнэ төлбөргүй байршуулсан. Хэрэв та бидний ажлыг дэмжихийг хүсвэл хичээлийн талаар бусдад дуулгахад л хангалттай. Хэрэв та энэхүү хичээлийн агуулгыг олон хүнд заадаг компани, их сургууль эсвэл бусад байгууллага бол бидэнд туршлага, сэтгэгдлээ имэйлээр илгээнэ үү :)

Сэдэл, зорилго

Компьютерийн ухааны мэргэжилтнүүдийн хувьд компьютер нь давтагддаг ажлуудыг автоматжуулахад маш сайн гэдгийг бид мэддэг. Гэвч энэ нь зөвхөн програмуудын маань хийх тооцоололд төдийгүй бидний компьютерийг ашиглах явцад ч мөн адил хамаатай гэдгийг бид маш олон удаа мартдаг. Компьютертой холбоотой аливаа асуудлыг шийдвэрлэхэд биднийг илүү бүтээмжтэй ажиллаж, илүү төвөгтэй асуудлуудыг шийдвэрлэхэд туслах асар олон төрлийн хэрэгслүүд хурууны үзүүрт бэлэн байдаг. Гэсэн хэдий ч бидний ихэнх нь эдгээр хэрэгслийн зөвхөн багахан хэсгийг л ашигладаг; бид зөвхөн ажиллах төдий цээжилсэн тушаалуудыг ашиглаж, мухардах үедээ интернэтээс тушаалуудыг сохроор хуулж тавьдаг.

Энэхүү хичээл нь үүнийг засах зорилготой юм.

Бид танд өөрийн мэддэг хэрэгслүүдийг хэрхэн дээд зэргээр ашиглахыг зааж, таны хэрэгслийн хайрцагт шинэ хэрэгслүүдийг нэмж, улмаар өөрөө бие даан илүү олон хэрэгслийг судалж (магадгүй бүтээх) хүсэл эрмэлзэлтэй болгохыг хүсэж байна. Энэ сэдэв бол ихэнх Компьютерийн ухааны (CS) сургалтын хөтөлбөрөөс орхигдсон семестр гэдэгт бид итгэдэг.

Хичээлийн бүтэц

Энэхүү кредитгүй хичээл нь тус бүр 1 цаг үргэлжлэх 9 лекцээс бүрдэх бөгөөд лекц бүр тодорхой сэдэвт чиглэнэ. Лекцүүд нь ерөнхийдөө бие даасан байх боловч семестр ахих тусам өмнөх лекцийн агуулгыг мэддэг гэж үзнэ. Лекцийн тэмдэглэлүүд онлайнд байгаа ч хичээл дээр үзүүлсэн зарим үзүүлэн дасгалууд тэмдэглэлд ороогүй байж болно. Өмнөх жилүүдийн адил бид лекцүүдийг бичиж аваад онлайнд байршуулах болно.

Бид ердөө хэдхэн цагийн лекцээр маш олон сэдвийг хамрахыг хичээж байгаа тул лекцүүд нэлээд нягт, мэдээлэл ихтэй байна. Та өөрийн хурдаар агуулгатай танилцах боломжийг олгох үүднээс лекц бүрд гол санааг бататгах дасгал ажлуудыг оруулсан. Бид тусгайлсан зөвлөгөө өгөх цаг гаргахгүй боловч асуултаа OSSU Discord-ийн #missing-semester-forum сувагт асуух эсвэл missing-semester@mit.edu хаягаар имэйл илгээхийг зөвлөж байна.

Цаг хугацаа хязгаарлагдмал тул бид бүх хэрэгслийг бүтэн хичээлийн хэмжээнд нарийвчлан авч үзэж чадахгүй. Боломжтой бол бид тухайн хэрэгсэл эсвэл сэдвийг илүү гүнзгийрүүлэн судлах нөөцүүдийг зааж өгөхийг хичээх болно. Хэрэв танд ямар нэгэн зүйл онцгой сонирхолтой санагдвал бидэнтэй холбогдож зөвлөгөө авахаас бүү эргэлзээрэй!

Энэхүү хичээлийн талаар санал хүсэлт байвал missing-semester@mit.edu хаягаар имэйл илгээнэ үү.

Сэдэв 1: Shell

Shell гэж юу вэ?

Өнөө үед компьютерууд тушаал өгөхөд зориулагдсан график хэрэглэгчийн интерфейс (GUI), дуу хоолойны интерфейс, AR/VR, сүүлийн үед LLM зэрэг олон төрлийн интерфейстэй болсон. Эдгээр нь нийт тохиолдлын 80%-д маш сайн тохирдог боловч хийж чадах зүйл нь үндсэндээ хязгаарлагдмал байдаг — та байхгүй товчлуурыг дарж чадахгүй эсвэл програмчлагдаагүй дуут тушаал өгч чадахгүй. Компьютерын тань өгч буй хэрэгслүүдийг бүрэн ашиглахын тулд бид хуучны уламжлалт арга руу буцаж, текстэн интерфейс буюу Shell-ийг ашиглах хэрэгтэй.

Таны ашиглаж болох бараг бүх систем ямар нэгэн хэлбэрээр shell-тэй байдаг бөгөөд тэдгээрийн ихэнх нь сонгож ашиглах хэд хэдэн shell-ийг санал болгодог. Нарийн ширийн зүйлсээрээ ялгаатай байж болох ч тэдгээрийн үндсэн үүрэг нь ижил: тэдгээр нь програмуудыг ажиллуулах, тэдгээрт оролт өгөх, гаралтыг нь хагас бүтэцлэгдсэн хэлбэрээр шалгах боломжийг олгодог.

Тушаалуудыг бичих shell prompt-ийг нээхийн тулд танд эхлээд shell-ийн визуал интерфейс болох Терминал хэрэгтэй. Таны төхөөрөмж үйлдвэрээсээ суурилагдсан терминалтай ирдэг эсвэл та өөрөө хялбархан суулгаж болно:

Linux болон macOS дээр энэ нь ихэвчлэн Bourne Again SHell буюу товчоор “bash”-ийг нээдэг. Энэ нь хамгийн өргөн хэрэглэгддэг shell-үүдийн нэг бөгөөд түүний синтакс нь бусад олон shell-тэй төстэй байдаг. Windows дээр таны ажиллуулсан тушаалаас хамааран “batch” эсвэл “powershell” нээгдэх болно. Эдгээр нь Windows-д зориулагдсан бөгөөд энэ хичээлээр үзэх гол сэдэв биш юм. Үүний оронд та Windows Subsystem for Linux (WSL) эсвэл Linux виртуал машин ашиглах нь зүйтэй.

Bash-аас гадна хэрэглэхэд илүү хялбар, тохиромжтой өөр олон shell-үүд байдаг (fish болон zsh нь хамгийн түгээмэл нь юм). Эдгээр нь маш алдартай боловч (багш нар бүгд ашигладаг) bash шиг хаа сайгүй байдаггүй бөгөөд ижил төстэй ойлголтууд дээр суурилдаг тул бид энэ лекцээр тэдгээрт анхаарлаа хандуулахгүй.

Та яагаад үүнийг анхаарах ёстой вэ?

Shell нь зүгээр л “хулганаар товшиж” ажиллахаас хамаагүй хурдан төдийгүй ямар ч график програмоос амархан олж чадахгүй илэрхийлэх хүчийг агуулдаг. Цаашид үзэхээр shell нь бараг ямар ч ажлыг автоматжуулахын тулд програмуудыг бүтээлч байдлаар хамт ажиллуулах боломж олгодог.

Shell дээр ажиллаж сурах нь нээлттэй эхийн програм хангамжийн ертөнцөд ажиллахад (тэдгээр нь ихэвчлэн shell ашиглахыг шаарддаг суулгах заавартай ирдэг), төслүүддээ тасралтгүй интеграци бэлтгэхэд (Кодын чанар лекц-нд тайлбарласнаар), мөн бусад програмууд ажиллахгүй алдаа заах үед алдааг илрүүлж засахад маш хэрэгтэй байдаг.

Shell дотор шилжих

Терминалыг ажиллуулахад ихэвчлэн дараах байдалтай prompt харагдана:

missing:~$

Энэ бол shell-ийн үндсэн текстэн интерфейс юм. Энэ нь таныг missing нэртэй компьютер дээр байгаа бөгөөд таны “одоогийн ажиллаж буй хавтас” (current working directory) буюу одоо байгаа байршил тань ~ (home хавтасны товчлол) болохыг илтгэнэ. $ тэмдэг нь таныг root хэрэглэгч биш болохыг илэрхийлнэ (энэ талаар дараа дэлгэрэнгүй үзнэ). Энэ prompt дээр та shell-ээр тайлбарлуулах команд бичиж болно. Хамгийн энгийн команд бол програмыг ажиллуулах явдал юм:

missing:~$ date
Fri 10 Jan 2020 11:49:31 AM EST
missing:~$

Энд бид одоогийн огноо, цагийг хэвлэдэг date програмыг ажиллууллаа. Дараа нь shell биднээс дараагийн ажиллуулах командыг асууж байна. Бид мөн тушаалыг аргумент-тэй хамт ажиллуулж болно:

missing:~$ echo hello
hello

Энэ тохиолдолд бид shell-д echo програмыг hello гэсэн аргументтай ажиллуулахыг тушаасан. echo програм нь өөрт нь өгсөн аргументуудыг зүгээр л хэвлэж харуулдаг. Shell нь тушаалыг хоосон зайгаар нь салгаж задлан шинжлээд, эхний үгээр заасан програмыг ажиллуулж, дараагийн үг бүрийг програмд аргумент болгон дамжуулдаг. Хэрэв та хоосон зай эсвэл бусад тусгай тэмдэгт агуулсан аргумент (жишээлбэл, “My Photos” нэртэй хавтас) дамжуулахыг хүсвэл аргументыг ' эсвэл " ашиглан хашиж ("My Photos"), эсвэл тусгай тэмдэгтүүдийн өмнө \ тавьж хувиргаж (My\ Photos) болно.

Шинээр сурч эхэлж буй хүмүүсийн хувьд магадгүй хамгийн чухал команд бол “гарын авлага” гэсэн үгний товчлол болох man юм. man програм нь систем дэх дурын командын талаарх дэлгэрэнгүй мэдээллийг харах боломжийг олгодог. Жишээлбэл, хэрэв та man date гэж ажиллуулбал date гэж юу болох, түүний ажиллагааг өөрчлөхөд ашиглаж болох янз бүрийн аргументуудыг тайлбарлах болно. Мөн ихэнх командуудад аргумент болгон --help дамжуулж тусламжийн товч хувилбарыг харах боломжтой.

Терминал дээр шууд түгээмэл хэрэглэгддэг жишээнүүдийг харахын тулд man-аас гадна tldr-ийг суулгаж ашиглахыг зөвлөж байна. Мөн LLM загварууд нь командуудын ажиллах зарчмыг тайлбарлах болон таны хүссэн үр дүнд хүрэхийн тулд тэдгээрийг хэрхэн дуудахыг зааж өгөхдөө маш сайн байдаг.

man-ы дараа сурах хамгийн чухал команд бол “хавтас солих” буюу cd юм. Энэ команд нь үнэндээ тусдаа програм биш, харин shell-д суурилагдсан тушаал юм (өөрөөр хэлбэл which cd гэж ажиллуулбал “no cd found” гэх болно). Та үүнд замыг дамжуулах бөгөөд уг зам нь таны одоогийн ажиллаж буй хавтас болно. Та одоо ажиллаж буй хавтсаа shell prompt-оос харж болно:

missing:~$ cd /bin
missing:/bin$ cd /
missing:/$ cd ~
missing:~$

Shell-д автомат нөхөлт (auto-completion) байдаг тул та <TAB> товчлуурыг дарж замыг илүү хурдан гүйцээж бичих боломжтой!

Хэрэв өөр зүйл заагаагүй бол маш олон командууд одоогийн ажиллаж буй хавтас дээр ажилладаг. Хэрэв та хаана байгаагаа мэдэхгүй байвал pwd тушаалыг ажиллуулах эсвэл $PWD орчны хувьсагчийг хэвлэж (echo $PWD) одоогийн байршлаа мэдэж болно.

Одоогийн ажиллаж буй хавтас нь бидэнд харьцангуй (relative) зам ашиглах боломжийг олгодог тул маш тохиромжтой байдаг. Бидний өмнө үзсэн бүх замууд абсолют (absolute) замууд байсан — тэдгээр нь / тэмдэгтээр эхэлж, файлын системийн root (/) хавтаснаас тухайн байршил хүртэлх бүх хавтсыг заадаг. Практикт та харьцангуй замтай илүү их ажиллах болно; тэдгээрийг одоогийн ажиллаж буй хавтастай харьцуулсан зам гэж нэрлэдэг. Харьцангуй замд (/-оор эхлээгүй зам) эхний хавтасны нэрийг одоогийн ажиллаж буй хавтсаас хайж, дараагийн хавтсуудаар дамжин шилждэг. Жишээлбэл:

missing:~$ cd /
missing:/$ cd bin
missing:/bin$

Мөн хавтас бүрд байдаг хоёр “тусгай” тэмдэглэгээ бий: . болон ... . нь “энэ хавтас”, харин .. нь “эцэг хавтас” юм. Жишээ нь:

missing:~$ cd /
missing:/$ cd bin/../bin/../bin/././../bin/..
missing:/$

Та командын аргументэд абсолют болон харьцангуй замыг хольж ашиглаж болно, зөвхөн харьцангуй зам ашиглах үедээ одоогийн ажиллаж буй хавтсаа санахад л хангалттай!

cd хийх үйлдлээ хурдасгахын тулд zoxide хэрэгслийг суулгаж ашиглахыг зөвлөж байна. z нь таны байнга зочилдог замуудыг санаж, цөөн тэмдэгт бичиж шилжих боломжийг олгоно.

Shell-д юу ашиглах боломжтой вэ?

Shell нь date эсвэл echo зэрэг програмуудыг хаанаас олохоо хэрхэн мэддэг вэ? Shell-д тушаал өгөх үед тэрээр програм хайх хавтаснуудын жагсаалтыг агуулсан $PATH нэртэй орчны хувьсагч-тай зөвлөлддөг:

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 командыг ажиллуулахад shell echo програмыг ажиллуулах ёстойг олж харж, дараа нь $PATH доторх :-оор тусгаарлагдсан хавтаснуудаас уг нэртэй файлыг хайдаг. Олсон даруйдаа түүнийг ажиллуулдаг (тухайн файл нь ажиллуулах боломжтой файл гэж үзвэл; энэ талаар дараа үзнэ). Бид өгөгдсөн програмын нэрээр яг ямар файл ажиллаж байгааг which програмыг ашиглан мэдэж болно. Мөн бид ажиллуулахыг хүссэн файлынхаа замыг шууд зааж өгснөөр $PATH-ыг бүрэн алгасаж болно.

Энэ нь мөн shell-д ажиллуулж болох бүх програмыг хэрхэн олж мэдэх талаар сэжүүр өгдөг: үүний тулд $PATH дээрх бүх хавтсанд юу байгааг жагсаахад л хангалттай. Бид үүнийг файлуудыг жагсаадаг ls програмд хавтасны замыг аргумент болгон өгч хийж болно:

missing:~$ ls /bin

Илүү ойлгомжтой, харахад хялбар ls-ийн оронд eza-г суулгаж ашиглахыг зөвлөж байна.

Ихэнх компьютерт энэ тушаал маш олон програм хэвлэх боловч бид зөвхөн хамгийн чухал заримыг нь авч үзэх болно. Эхлээд хэдэн энгийн тушаал:

Синтакс тодруулагч болон гүйлгэж харах боломжтой bat хэрэгслийг cat-ын оронд суулгаж ашиглахыг зөвлөж байна.

Мөн grep pattern file байгаа бөгөөд энэ нь file-аас pattern-тэй таарч буй мөрүүдийг олдог. Энэ нь маш хэрэгтэй бөгөөд таны бодож байгаагаас хамаагүй илүү олон боломжуудыг агуулдаг тул үүнд илүү анхаарал хандуулах хэрэгтэй. pattern нь үнэндээ маш нарийн төвөгтэй хэв маягийг илэрхийлж чадах тогтмол илэрхийлэл (regular expression) юм — бид үүнийг Кодын чанар лекц-ээр үзэх болно. Та мөн файлын оронд хавтас зааж өгч (эсвэл одоогийн хавтасны хувьд хоосон үлдээж), хавтас доторх бүх файлыг рекурсив хайхын тулд -r аргументыг дамжуулж болно.

Илүү хурдан бөгөөд хэрэглэхэд тохиромжтой хувилбар болох ripgrep-ийг grep-ийн оронд суулгаж ашиглахыг зөвлөж байна. ripgrep нь анхнаасаа одоогийн ажиллаж буй хавтас дотор рекурсив хайлт хийдэг давуу талтай!

Мөн ашиглахад арай илүү төвөгтэй интерфейстэй хэд хэдэн маш хэрэгтэй хэрэгслүүд бий. Тэдгээрийн эхнийх нь програмчлагддаг файл засварлагч болох sed юм. Энэ нь файлуудад автомат өөрчлөлт хийх өөрийн програмчлалын хэлтэй боловч хамгийн түгээмэл хэрэглээ нь:

missing:~$ sed -i 's/pattern/replacement/g' file

Энэ нь file доторх pattern-ийг replacement-ээр солино. -i аргумент нь солих үйлдлийг файл дотор нь шууд хийхийг заана (файлыг өөрчлөхгүйгээр өөрчилсөн агуулгыг хэвлэхийн оронд). s/ нь sed програмчлалын хэл дээр солих үйлдэл хийхийг илэрхийлж байгаа хэлбэр юм. / тэмдэгт нь загварыг солих текстээс тусгаарлана. Төгсгөлийн /g нь мөр болгон дээр зөвхөн эхнийхийг биш, харин бүх таарсан хэсгийг солихыг заана. grep-тэй адил эндэх pattern нь тогтмол илэрхийлэл байдаг тул маш хүчирхэг юм. Тогтмол илэрхийллийн солих үйлдэл нь replacement хэсэгт таарсан загварын зарим хэсгийг эргэж ашиглах боломжийг олгодог; бид үүний жишээг удахгүй үзэх болно.

Дараа нь бид тодорхой нөхцөлтэй таарч буй файлуудыг (рекурсив байдлаар) хайх боломжийг олгодог find хэрэгслийг авч үзнэ. Жишээлбэл:

missing:~$ find ~/Downloads -type f -name "*.zip" -mtime +30

Энэ нь Downloads хавтаснаас 30-аас дээш хоногийн өмнөх ZIP файлуудыг хайна.

missing:~$ find ~ -type f -size +100M -exec ls -lh {} \;

Энэ нь таны home хавтаснаас 100M-ээс их хэмжээтэй файлуудыг олж, тэдгээрийг жагсаана. -exec аргумент нь бидний ажиллуулах тушаалыг авдаг бөгөөд тушаал нь дангаараа байх ; (үүнийг хоосон зайтай адил хувиргах шаардлагатай) тэмдэгтээр төгсөх ба {} тэмдэглэгээний оронд find-ын олсон файл бүрийн замыг орлуулан ажиллуулна.

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

Энэ тушаал нь алсын серверээс SSH логуудыг авч (бид дараагийн лекцээр ssh-ийн талаар дэлгэрэнгүй үзэх болно), холболт тасарсан тухай мэдээллүүдийг хайж, мэдээлэл бүрээс хэрэглэгчийн нэрийг салгаж аваад хамгийн их давтагдсан 10 хэрэглэгчийн нэрийг таслалаар тусгаарлан хэвлэдэг. Энэ бүгдийг ганцхан тушаалаар хийж байна! Алхам бүрийг задлан шинжлэхийг дасгал ажил болгон үлдээе.

Shell хэл (bash)

Өмнөх жишээнд пайп (|) гэх шинэ ойлголт гарч ирсэн. Энэ нь нэг програмын гаралтыг нөгөө програмын оролттой холбох боломжийг олгодог. Энэ нь ихэнх командын мөрийн програмууд ямар нэгэн file аргумент өгөөгүй тохиолдолд өөрсдийн “стандарт оролт” (stdin) дээр ажилладагтай холбоотой. | тэмдэгт нь өмнөх програмын “стандарт гаралт” (stdout)-ыг аваад, дараагийн програмын стандарт оролт болгодог. Энэ нь танд shell програмуудыг хамтатгах (compose) боломжийг олгодог бөгөөд shell-ийг маш бүтээмжтэй ажиллах орчин болгодог гол хүчин зүйлсийн нэг юм!

Үнэндээ ихэнх shell-үүд нь Python эсвэл Ruby-тэй адил бүрэн хэмжээний програмчлалын хэлийг хэрэгжүүлсэн байдаг. Үүнд хувьсагч, нөхцөл шалгах үйлдэл, давталт болон функцууд байдаг. Shell-д тушаал ажиллуулах үед та үнэндээ 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 болгон ашигладаг хамгийн түгээмэл тушаал бол нөхцөлийг шалгадаг test команд бөгөөд үүнийг ихэвчлэн зүгээр л [ гэж товчилдог. Энэ нь “файл байна уу” (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 substitution) ашиглаж болно, жишээ нь:

for i in $(seq 1 10); do

Энэ нь 1-ээс 10 хүртэлх тоог хэвлэдэг seq 1 10 командыг ажиллуулаад, бүхэл хаалттай хэсгийг уг командын гаралтаар орлуулж, 10 удаа давтах давталтыг үүсгэдэг. Хуучин кодонд та $()-ийн оронд бэктек (for i in `seq 1 10`; do) ашигласныг харж болох ч дараалан ашиглах боломжтой тул $() хэлбэрийг ашиглахыг зөвлөж байна.

Та урт хэмжээний shell скриптийг терминал дээр шууд бичиж болох ч тэдгээрийг .sh өргөтгөлтэй файл болгон хадгалах нь илүү тохиромжтой байдаг. Жишээлбэл, програмыг алдаа заах хүртэл нь давталтаар ажиллуулж, зөвхөн алдаа гарсан үеийн гаралтыг хэвлэхийн зэрэгцээ цаана нь (background) процессорын ачааллыг нэмэгдүүлдэг скриптийг доор харуулав (энэ нь тогтворгүй тестүүдийг илрүүлэхэд маш хэрэгтэй):

#!/bin/bash
set -euo pipefail

# Цаана (background) CPU ачааллыг эхлүүлэх
stress --cpu 8 &
STRESS_PID=$!

# Лог файл бэлтгэх
LOGFILE="test_runs_$(date +%s).log"
echo "Logging to $LOGFILE"

# Тест алдаа заах хүртэл ажиллуулах
RUN=1
while cargo test my_test > "$LOGFILE" 2>&1; do
    echo "Run $RUN passed"
    ((RUN++))
done

# Цэвэрлэгээ болон тайлан
kill $STRESS_PID
echo "Test failed on run $RUN"
echo "Last 20 lines of output:"
tail -n 20 "$LOGFILE"
echo "Full log: $LOGFILE"

Энд арын ажил (&), shell чиглүүлэлтүүд болон арифметик үйлдэл зэрэг хэд хэдэн шинэ зүйлс байгаа тул тэдгээрийг бие даан гүнзгийрүүлэн судлахыг зөвлөж байна.

Гэхдээ програмын эхний хоёр мөрөнд хэсэг хугацаа зарцуулж тайлбарлая. Эхний мөр нь “shebang” бөгөөд та үүнийг shell скриптээс гадна өөр файлуудын эхэнд харж болно. #!/path гэж эхэлсэн файл ажиллуулах үед shell /path дээрх програмыг ажиллуулаад, файлын агуулгыг түүнд оролт болгон дамжуулдаг. Shell скриптийн хувьд энэ нь скриптийн агуулгыг /bin/bash руу дамжуулж байгаа хэрэг юм, гэхдээ та Python скриптийг мөн адил /usr/bin/python гэсэн shebang-тай бичиж болно!

Хоёр дахь мөр нь bash-ийг илүү “хатуу” дүрэмтэй болгож, shell скрипт бичих явцад гардаг зарим аюултай алдаанаас сэргийлдэг. set тушаал нь маш олон аргумент авч болох ч товчхондоо: -e нь аль нэг тушаал алдаа заавал скриптийг шууд зогсоодог; -u нь тодорхойлогдоогүй хувьсагчийг ашиглавал скриптийг шууд зогсоож алдаа заадаг; -o pipefail нь | пайп ашигласан дараалсан командын аль нэг нь алдаа заавал скриптийг мөн шууд зогсоодог болгоно.

Shell програмчлал нь ямар ч програмчлалын хэлний адил гүнзгий сэдэв боловч анхаараарай: bash нь маш олон гэнэтийн алдаа дагуулдаг тул үүнд зориулагдсан олон вэбсайтууд байдаг. Скрипт бичихдээ shellcheck-ийг тогтмол ашиглахыг зөвлөж байна. Мөн LLM загварууд нь скрипт бичих, алдааг олох болон скрипт хэтэрхий томрох үед (100-аас олон мөр) түүнийг Python зэрэг “жинхэнэ” програмчлалын хэл рүү хөрвүүлэхэд маш сайн туслагч болдог.

Дараагийн алхмууд

Энэ хүртэл та shell-ийг ашиглан үндсэн ажлуудыг гүйцэтгэх хангалттай мэдлэгтэй боллоо. Та хэрэгцээт файлуудаа олж, ихэнх програмын үндсэн функцуудыг ашиглах боломжтой байх ёстой. Дараагийн лекцээр бид shell болон бусад туслах командын мөрийн програмуудыг ашиглан илүү төвөгтэй ажлуудыг хэрхэн гүйцэтгэх, автоматжуулах талаар үзэх болно.

Дасгал ажил

Энэхүү хичээлийн бүх лекцүүд нь цуврал дасгал ажлуудтай ирдэг. Зарим нь тодорхой даалгавар өгөх бол зарим нь “X болон Y програмыг ашиглаад үзээрэй” гэх мэт нээлттэй байдаг. Бид таныг эдгээрийг туршиж үзэхийг зөвлөж байна.

Бид дасгал ажлын хариуг бичээгүй болно. Хэрэв танд хүндрэл гарвал Discord дээрх #missing-semester-forum сувагт асуух эсвэл хийсэн зүйлээ тайлбарлаж бидэнд имэйл илгээгээрэй, бид туслахыг хичээх болно. Эдгээр дасгалууд нь LLM-тэй хийх хэлэлцүүлэгт ч сайн сэдэв болох болно. Дасгал ажлын гол үнэ цэнэ нь хариултыг олох явцад суралцах бөгөөд зөвхөн хамгийн дөхөм замыг хайхаас илүү асуулт тавьж, гүнзгийрүүлэн судлахыг зөвлөж байна.

  1. Энэ хичээлийг үзэхийн тулд та Bash эсвэл ZSH зэрэг Unix shell-ийг ашиглах шаардлагатай. Хэрэв та Linux эсвэл macOS дээр байгаа бол нэмэлт зүйл хийх шаардлагагүй. Хэрэв та Windows дээр байгаа бол cmd.exe эсвэл PowerShell биш, харин Unix маягийн командын мөрийн хэрэгслүүдийг ашиглахын тулд Windows Subsystem for Linux (WSL) эсвэл Linux виртуал машин ашиглах хэрэгтэй. Тохирох shell ажиллаж байгаа эсэхийг шалгахын тулд echo $SHELL тушаалыг ажиллуулж болно. Хэрэв энэ нь /bin/bash эсвэл /usr/bin/zsh гэх мэт утга буцааж байвал та зөв програм ажиллуулж байна гэсэн үг юм.

  2. ls командын -l аргумент ямар үүрэгтэй вэ? ls -l / гэж ажиллуулаад гаралтыг шалгана уу. Мөр бүрийн эхний 10 тэмдэгт ямар утгатай вэ? (Сэжүүр: man ls)

  3. find ~/Downloads -type f -name "*.zip" -mtime +30 команд дахь *.zip нь “глоб” (glob) юм. Glob гэж юу вэ? Туршилтын хавтас үүсгэж, хэдэн файл хийгээд ls *.txt, ls file?.txt, болон ls {a,b,c}.txt зэрэг загваруудыг туршиж үзнэ үү. Bash гарын авлагын Pattern Matching хэсгийг үзнэ үү.

  4. 'дан хашилт' (single quotes), "давхар хашилт" (double quotes), болон $'ANSI хашилт' (ANSI quotes) зэргийн ялгаа нь юу вэ? Дотор нь $, !, болон шинэ мөр шилжүүлэх тэмдэгт агуулсан тэмдэгт мөрийг хэвлэх тушаал бичнэ үү. Quoting хэсгийг үзнэ үү.

  5. Shell-д stdin (0), stdout (1), болон stderr (2) гэсэн гурван стандарт урсгал байдаг. ls /nonexistent /tmp гэж ажиллуулаад стандарт гаралтыг нэг файл руу, харин стандарт алдааг өөр файл руу чиглүүлнэ үү. Хоёуланг нь ижил файл руу хэрхэн чиглүүлэх вэ? Redirections хэсгийг үзнэ үү.

  6. $? хувьсагч нь хамгийн сүүлд ажилласан командын гаралтын төлөвийг хадгалдаг (0 = амжилттай). && нь өмнөх тушаал амжилттай болсон тохиолдолд дараагийн тушаалыг ажиллуулдаг бол || нь өмнөх тушаал алдаа заасан тохиолдолд ажиллуулдаг. Хэрэв байхгүй бол /tmp/mydir хавтсыг үүсгэх нэг мөрт тушаал бичнэ үү. Exit Status хэсгийг үзнэ үү.

  7. Яагаад cd команд нь тусдаа програм биш, харин shell-д суурилагдсан тушаал байх ёстой вэ? (Сэжүүр: хүү процесс нь өөрийн эцэг процесст юуг нөлөөлж чадах, юуг нөлөөлж чадахгүй талаар бодно уу.)

  8. Аргумент болгон файлын нэр авдаг ($1), мөн test -f эсвэл [ -f ... ] ашиглан уг файл байгаа эсэхийг шалгадаг скрипт бичнэ үү. Энэ нь файл байгаа эсэхээс хамаарч өөр өөр мэдээлэл хэвлэх ёстой. Bash Conditional Expressions хэсгийг үзнэ үү.

  9. Өмнөх дасгалын скриптийг файл болгон хадгална уу (жишээ нь, check.sh). Үүнийг ./check.sh somefile гэж ажиллуулаад үзээрэй. Юу болох вэ? Одоо chmod +x check.sh гэж ажиллуулаад дахин туршаад үз. Яагаад энэ алхам шаардлагатай вэ? (Сэжүүр: chmod хийхийн өмнөх болон дараах ls -l check.sh гаралтыг харьцуулна уу.)

  10. Хэрэв та скриптийн set тугууд дээр -x нэмбэл юу болох вэ? Энгийн скрипт дээр туршиж үзээд гаралтыг ажиглана уу. The Set Builtin хэсгийг үзнэ үү.

  11. Файлыг өнөөдрийн огноо бүхий нэртэй хуулбар файл болгон хадгалдаг тушаал бичнэ үү (жишээ нь, notes.txtnotes_2026-01-12.txt). (Сэжүүр: $(date +%Y-%m-%d)). Command Substitution хэсгийг үзнэ үү.

  12. Лекц дээр үзсэн тогтворгүй тестийг шалгах скриптийг cargo test-ийг хатуу зааж өгөхийн оронд тестийн тушаалыг аргумент болгон авдаг болгон өөрчилнө үү. (Сэжүүр: $1 эсвэл $@). Special Parameters хэсгийг үзнэ үү.

  13. Пайп (pipes) ашиглан өөрийн home хавтас доторх хамгийн түгээмэл 5 файлын өргөтгөлийг олно уу. (Сэжүүр: find, grep эсвэл sed эсвэл awk, sort, uniq -c, болон head командуудыг хамтатгана уу.)

  14. xargs нь стандарт оролтоос ирсэн мөрүүдийг командын аргумент болгон хөрвүүлдэг. find болон xargs-ийг хамт ашиглан (find -exec биш) хавтас доторх бүх .sh файлуудыг олж, файл бүрийн мөрийн тоог wc -l тушаалаар тоолно уу. Бонус: хоосон зай агуулсан файлын нэрийг зөв боловсруулдаг болгох. (Сэжүүр: -print0 болон -0). man xargs үзнэ үү.

  15. Хичээлийн вэбсайт (https://missing.csail.mit.edu/)-ийн HTML кодыг curl-ээр татаж аваад, grep рүү дамжуулан нийт хэдэн лекц жагсаагдсаныг тоолно уу. (Сэжүүр: лекц бүрд нэг удаа гарч ирдэг загварыг хайна уу; curl-ийн ахицын гаралтыг хаахын тулд curl -s ашиглана.)

  16. jq нь JSON өгөгдлийг боловсруулах хүчирхэг хэрэгсэл юм. https://microsoftedge.github.io/Demos/json-dummy-data/64KB.json хаяг дахь өгөгдлийг curl-ээр татаж аваад, jq ашиглан version нь 6-аас их хүмүүсийн нэрийг салгаж авна уу. (Сэжүүр: эхлээд бүтцийг харахын тулд jq . рүү дамжуулна уу; дараа нь jq '.[] | select(...) | .name' гэж туршина уу.)

  17. awk нь баганы утга дээр суурилан мөрүүдийг шүүж, гаралтыг удирдах чадвартай. Жишээлбэл, awk '$3 ~ /pattern/ {$4=""; print}' нь гурав дахь багана нь pattern-тэй таарч буй мөрүүдийг хэвлэхдээ дөрөв дэх баганыг алгасдаг. Хоёр дахь багана нь 100-аас их байх мөрүүдийг хэвлэхдээ эхний болон гурав дахь баганыг сольж хэвлэх awk тушаал бичнэ үү. Турших өгөгдөл: printf 'a 50 x\nb 150 y\nc 200 z\n'

  18. Лекц дээр үзсэн SSH лог боловсруулах дарааллыг задлан шинжлээрэй: алхам бүр юу хийж байна вэ? Дараа нь үүнтэй төстэй тушаал ашиглан өөрийн түүхээс хамгийн их ашигласан shell командуудыг олно уу. (~/.bash_history эсвэл ~/.zsh_history).


Энэ хуудсыг засварлах.

Лиценз: CC BY-NC-SA.