Командын мөрийн орчин
Өмнөх лекцээр үзсэнчлэн, ихэнх shell-үүд нь зөвхөн бусад програмыг ажиллуулагч төдийгүй практикт тэдгээр нь түгээмэл хэв маяг, абстрактуудыг агуулсан бүрэн хэмжээний програмчлалын хэлийг санал болгодог. Гэсэн хэдий ч бусад ихэнх програмчлалын хэлнүүдээс ялгаатай нь shell скрипт бичихэд бүх зүйл програмуудыг ажиллуулах болон тэдгээрийг хооронд нь хялбар бөгөөд үр дүнтэй харилцуулахад чиглэгдсэн байдаг.
Ялангуяа, shell скрипт нь дүрмүүд-тэй (conventions) маш нягт холбоотой байдаг. Командын мөрийн интерфейстэй (CLI) програм нь shell-ийн орчинд саадгүй ажиллахын тулд дагаж мөрдөх ёстой зарим нийтлэг загварууд бий. Бид одоо командын мөрийн програмууд хэрхэн ажилладаг талаарх ойлголтууд болон тэдгээрийг хэрхэн ашиглах, тохируулах түгээмэл дүрмүүдийг үзэх болно.
Командын мөрийн интерфейс
Ихэнх програмчлалын хэл дээр функц бичихэд дараах байдалтай харагддаг:
def add(x: int, y: int) -> int:
return x + y
Эндээс бид програмын оролт болон гаралтыг тодорхой харж болно. Харин үүний эсрэгээр shell скриптүүд эхлээд харахад огт өөр харагдаж болно.
#!/usr/bin/env bash
if [[ -f $1 ]]; then
echo "Target file already exists"
exit 1
else
if $DEBUG; then
grep 'error' - | tee $1
else
grep 'error' - > $1
fi
exit 0
fi
Ийм скриптүүдэд юу болж байгааг зөв ойлгохын тулд эхлээд shell програмууд хоорондоо эсвэл shell орчинтой харилцах үед байнга гарч ирдэг хэд хэдэн ойлголтыг танилцуулах шаардлагатай:
- Аргументууд (Arguments)
- Урсгалууд (Streams)
- Орчны хувьсагчид (Environment variables)
- Гаралтын кодууд (Return codes)
- Сигналууд (Signals)
Аргументууд
Shell програмууд ажиллах үедээ аргументуудын жагсаалтыг хүлээн авдаг. Аргументууд нь shell-д ердийн тэмдэгт мөр хэлбэрээр дамжих ба тэдгээрийг хэрхэн тайлбарлах нь тухайн програмаас хамаарна. Жишээлбэл, бид ls -l folder/ гэж ажиллуулах үед /bin/ls програмыг ['-l', 'folder/'] гэсэн аргументуудтай ажиллуулж байгаа хэрэг юм.
Shell скрипт дотроос бид эдгээрийг shell-ийн тусгай синтакс ашиглан авч ашигладаг. Эхний аргументыг авахын тулд $1, хоёр дахь аргументыг авахын тулд $2 гэх мэтээр $9 хүртэл ашиглана. Бүх аргументыг жагсаалт байдлаар авахын тулд $@, харин аргументын тоог авахын тулд $# ашигладаг. Үүнээс гадна ажиллуулж буй програмын нэрийг $0 хувьсагчаар дамжуулан авч болно.
Ихэнх програмын хувьд аргументууд нь flags (тугууд) болон ердийн тэмдэгт мөрүүдийн холимог байдаг. Flags-ийг нэг зураас (-) эсвэл давхар зураас (--)-аар эхэлсэн байдлаар нь ялгаж болно. Flags нь ихэвчлэн сонголтоор ашиглагддаг бөгөөд тэдгээрийн үүрэг нь програмын ажиллагааг өөрчлөх явдал юм. Жишээлбэл, ls -l нь ls командын гаралтыг хэрхэн форматлахыг өөрчилдөг.
Та --all гэх мэт урт нэртэй давхар зураастай flags болон ихэвчлэн ганц үсгээс бүрдэх -a гэх мэт нэг зураастай flags-ийг харах болно. Ижил тохиргоог хоёр форматаар зааж өгч болно, ls -a болон ls --all нь ижил утгатай. Нэг зураастай flags-ийг ихэвчлэн нэгтгэж бичдэг тул ls -l -a болон ls -la нь мөн ижил утгатай. Flags-ийн дараалал нь мөн гаралтын үр дүнд нөлөөлөхгүй, ls -la болон ls -al нь ижил үр дүн үзүүлнэ. Зарим flags нь маш түгээмэл ашиглагддаг бөгөөд та shell орчинтой илүү танилцах тусам тэдгээрийг шууд ашиглах болно (жишээ нь, --help, --verbose, --version).
Flags нь shell-ийн дүрмүүдийн (conventions) маш сайн жишээ юм. Shell хэл нь програмаа заавал
-эсвэл--ашиглахыг шаарддаггүй. Таныгmyprogram +myoption myfileгэсэн синтакс ашиглан програм бичихэд юу ч саад болохгүй боловч энэ нь бусад хүмүүсийг төөрөгдүүлэх болно, учир нь хүмүүс зураас ашиглахыг хүлээж байдаг. Практикт ихэнх програмчлалын хэлнүүд CLI flags задлан шинжлэх бэлэн сангуудыг (жишээ нь, Python дээрхargparse) санал болгодог.
CLI програмуудын өөр нэг нийтлэг дүрэм бол програмууд нь ижил төрлийн олон тооны аргумент хүлээн авдаг явдал юм. Ийм байдлаар аргумент өгөхөд команд нь тэдгээрийн файл/хавтас бүр дээр ижил үйлдлийг гүйцэтгэдэг.
mkdir src
mkdir docs
# нь дараахтай ижил утгатай
mkdir src docs
Энэхүү хялбар синтакс нь эхлээд харахад шаардлагагүй мэт санагдаж болох ч globbing-той хамтран ашиглах үед маш хүчирхэг болж ирдэг. Globbing эсвэл globs нь shell програмыг дуудахаас өмнө өргөжүүлэн хувиргадаг тусгай хэв маяг юм.
Бид одоогийн хавтас доторх бүх .py файлуудыг рекурсив бус байдлаар устгахыг хүссэн гэж бодъё. Өмнөх лекцээр сурсан зүйлээр бол бид үүнийг дараах байдлаар хийж болно:
for file in $(ls | grep -P '\.py$'); do
rm "$file"
done
Гэвч бид үүнийг ердөө rm *.py гэж орлуулж болно!
Бид терминал дээр rm *.py гэж бичих үед shell /bin/rm програмыг ['*.py'] гэсэн аргументтай ажиллуулдаггүй. Үүний оронд shell одоогийн хавтаснаас *.py загварт таарч буй файлуудыг хайдаг бөгөөд эндэх * нь ямар ч төрлийн тэмдэгтээс бүрдсэн хоосон буюу түүнээс олон тэмдэгт мөрийг илэрхийлнэ. Тиймээс хэрэв манай хавтас дотор main.py болон utils.py байгаа бол rm програм ['main.py', 'utils.py'] гэсэн аргументуудыг хүлээн авах болно.
Хамгийн түгээмэл хэрэглэгддэг globs нь орлуулах тэмдэгт * (юу ч байж болох хоосон эсвэл олон тэмдэгт), ? (яг нэг дурын тэмдэгт) болон хаалт {} юм. Хаалт {} нь таслалаар тусгаарлагдсан загваруудын жагсаалтыг олон аргумент болгон задлан өргөжүүлдэг.
Практикт globs-ийг тодорхой жишээнүүдээр ойлгох нь илүү хялбар байдаг.
touch folder/{a,b,c}.py
# нь дараах байдлаар өргөжнө
touch folder/a.py folder/b.py folder/c.py
convert image.{png,jpg}
# нь дараах байдлаар өргөжнө
convert image.png image.jpg
cp /path/to/project/{setup,build,deploy}.sh /newpath
# нь дараах байдлаар өргөжнө
cp /path/to/project/setup.sh /path/to/project/build.sh /path/to/project/deploy.sh /newpath
# Globbing аргуудыг хослуулж болно
mv *{.py,.sh} folder
# Бүх *.py болон *.sh файлуудыг зөөнө
Зарим shell-үүд (жишээ нь, zsh) рекурсив замыг багтаасан
**зэрэг илүү нарийн globbing-ийг дэмждэг. Тиймээсrm **/*.pyнь бүх.pyфайлуудыг рекурсив байдлаар устгах болно.
Урсгалууд
Бид дараах байдалтай програмуудын дарааллыг ажиллуулах үед:
cat myfile | grep -P '\d+' | uniq -c
grep програм нь cat болон uniq програмуудын аль алинтай нь харилцаж байгааг харж болно.
Энд анхаарах чухал зүйл бол бүх гурван програм нэгэн зэрэг ажиллаж байгаа явдал юм. Өөрөөр хэлбэл, shell эхлээд cat-ыг ажиллуулаад, дараа нь grep-ийг, дараа нь uniq-ийг ажиллуулдаггүй. Үүний оронд бүх гурван процесс нэгэн зэрэг үүсч, shell нь cat-ын гаралтыг grep-ийн оролттой, grep-ийн гаралтыг uniq-ийн оролттой холбодог. Пайп (|) операторыг ашиглах үед shell нь дарааллын дагуу нэг програмаас дараагийн програм руу урсах өгөгдлийн урсгал дээр ажилладаг.
Бид энэхүү зэрэгцээ ажиллагааг дараах байдлаар баталж болно, дамжуулах хоолой дахь бүх тушаалууд шууд эхэлдэг:
$ (sleep 15 && cat numbers.txt) | grep -P '^\d$' | sort | uniq &
[1] 12345
$ ps | grep -P '(sleep|cat|grep|sort|uniq)'
32930 pts/1 00:00:00 sleep
32931 pts/1 00:00:00 grep
32932 pts/1 00:00:00 sort
32933 pts/1 00:00:00 uniq
32948 pts/1 00:00:00 grep
Бид cat-аас бусад бүх процессууд шууд ажиллаж байгааг харж байна. Shell нь аль нэг процесс дуусахаас өмнө бүх процессуудыг үүсгэж, тэдгээрийн урсгалуудыг холбодог. cat нь зөвхөн sleep дууссаны дараа эхлэх бөгөөд cat-ын гаралт grep руу дамжих гэх мэтээр үргэлжилнэ.
Програм бүр standard input буюу stdin гэж нэрлэгддэг оролтын урсгалтай байдаг. Pipe хийх үед stdin автоматаар холбогддог. Скрипт дотор олон програмууд stdin-ээс уншихыг илэрхийлэхийн тулд файлын нэрний оронд - тэмдэгтийг хүлээн авдаг:
# Өгөгдөл пайпоор ирэх үед эдгээр нь ижил утгатай
echo "hello" | grep "hello"
echo "hello" | grep "hello" -
Үүнтэй адилаар програм бүр standard output буюу stdout, мөн standard error буюу stderr гэсэн хоёр гаралтын урсгалтай байдаг. stdout нь хамгийн түгээмэл хэрэглэгддэг урсгал бөгөөд програмын гаралтыг дараагийн команд руу pipe хийхэд ашиглагддаг. stderr нь програмын анхааруулга болон бусад алдааны мэдээллүүдийг хэвлэхэд зориулагдсан урсгал бөгөөд ингэснээр уг гаралт дараагийн команд руу дамжин боловсруулагдахаас сэргийлдэг.
$ ls /nonexistent
ls: cannot access '/nonexistent': No such file or directory
$ ls /nonexistent | grep "pattern"
ls: cannot access '/nonexistent': No such file or directory
# Алдааны мэдээлэл гарсаар байна, учир нь stderr-ийг пайп хийгээгүй
$ ls /nonexistent 2>/dev/null
# Гаралт байхгүй - stderr-ийг /dev/null руу чиглүүлсэн
Shell нь эдгээр урсгалуудыг чиглүүлэх (redirecting) синтаксийг санал болгодог. Жишээнүүд:
# stdout-ийг файл руу чиглүүлэх (дахин бичих)
echo "hello" > output.txt
# stdout-ийг файл руу чиглүүлэх (файл руу нэмж бичих)
echo "world" >> output.txt
# stderr-ийг файл руу чиглүүлэх
ls foobar 2> errors.txt
# stdout болон stderr-ийг хоёуланг нь ижил файл руу чиглүүлэх
ls foobar &> all_output.txt
# stdin-ийг файлаас унших
grep "pattern" < input.txt
# Гаралтыг /dev/null руу чиглүүлж хаях
cmd > /dev/null 2>&1
Unix философийг илтгэх өөр нэг хүчирхэг хэрэгсэл бол fzf fuzzy finder юм. Энэ нь stdin-ээс мөрүүдийг уншиж, шүүх болон сонгох боломжтой интерактив интерфейсийг үзүүлдэг:
$ ls | fzf
$ cat ~/.bash_history | fzf
fzf нь shell-ийн олон үйлдлүүдтэй нэгдэн ажиллах боломжтой. Shell-ийг өөрчлөх хэсэгт бид үүнийг хэрхэн ашиглах талаар дэлгэрэнгүй үзэх болно.
Орчны хувьсагчид
Bash-д хувьсагч оноохдоо foo=bar гэсэн синтакс ашиглах ба хувьсагчийн утгыг авахдаа $foo гэж бичнэ. foo = bar гэж бичих нь буруу синтакс бөгөөд shell үүнийг foo програмыг ['=', 'bar'] аргументуудтай дуудаж байна гэж задлан шинжлэх болно. Shell скрипт дээр хоосон зайны үүрэг нь аргументуудыг салгах явдал байдаг. Энэ ажиллагаа нь эхэндээ гэнэтийн алдаа дагуулж болох тул үүнийг анхаарна уу.
Shell хувьсагчид төрөл гэж байхгүй бөгөөд бүгд тэмдэгт мөр байдаг. Shell дээр тэмдэгт мөр бичихэд дан хашилт болон давхар хашилтын тэмдэгтүүд өөр өөр үүрэгтэй гэдгийг санаарай. '-оор хашсан тэмдэгт мөр нь хувьсагчийг задлахгүй, команд орлуулахгүй, мөн тусгай тэмдэгтүүдийг хөрвүүлэхгүйгээр шууд утгыг хадгалдаг бол "-оор хашсан тэмдэгт мөр нь эдгээрийг ажиллуулж хувиргадаг.
foo=bar
echo "$foo"
# bar гэж хэвлэнэ
echo '$foo'
# $foo гэж хэвлэнэ
Командын гаралтыг хувьсагчид хадгалахын тулд бид command substitution-ыг ашигладаг. Бид дараах кодыг ажиллуулахад:
files=$(ls)
echo "$files" | grep README
echo "$files" | grep ".py"
ls-ийн гаралт (тодруулбал stdout) $files хувьсагчид хадгалагдах бөгөөд бид үүнийг дараа нь ашиглаж болно. $files хувьсагчийн агуулга нь ls-ийн гаралтын шинэ мөр шилжүүлэх тэмдэгтүүдийг хадгалдаг тул grep зэрэг програмууд мөр бүр дээр бие даан ажиллах боломжтой байдаг.
Үүнтэй төстэй, арай бага дурдагддаг өөр нэг боломж бол process substitution бөгөөд <( CMD ) нь CMD тушаалыг ажиллуулж, гаралтыг нь түр зуурын файлд хадгалаад уг түр файлын нэрийг <()-ийн оронд орлуулан тавьдаг. Энэ нь програмууд утгыг STDIN-ээр биш харин файлаар дамжуулан авахыг хүлээж байгаа үед маш хэрэгтэй байдаг. Жишээлбэл, diff <(ls src) <(ls docs) нь src болон docs хавтас доторх файлуудын ялгааг харуулах болно.
Shell-ээс өөр нэг програмыг ажиллуулах бүрд тэрээр environment variables (орчны хувьсагчид) гэж нэрлэгддэг хувьсагчдын багцыг дамжуулдаг. Бид shell дээр printenv тушаалыг ажиллуулан одоогийн environment variables-ийг харах боломжтой. Environment variable-ийг тодорхой програмд зориулан дамжуулахын тулд тушаалын өмнө хувьсагч оноох үйлдлийг бичнэ:
Орчны хувьсагчдыг ТОМ ҮСГЭЭР (жишээ нь,
HOME,PATH,DEBUG) бичих журамтай. Энэ нь техникийн шаардлага биш боловч локал хувьсагчдаас (ихэвчлэн жижиг үсгээр бичигддэг) ялгахад тусалдаг.
TZ=Asia/Tokyo date # Токиогийн одоогийн цагийг хэвлэнэ
echo $TZ # TZ нь зөвхөн хүү тушаалд зориулан оноогдсон тул энэ нь хоосон байна
Үүний оронд бид одоогийн орчныг өөрчлөх export суурилагдсан функцийг ашиглаж болох бөгөөд ингэснээр дараах бүх хүү процессууд уг хувьсагчийг өвлөн авах болно:
export DEBUG=1
# Энэ мөчөөс эхлэн бүх програмуудын орчинд DEBUG=1 байх болно
bash -c 'echo $DEBUG'
# 1 гэж хэвлэнэ
Хувьсагчийг устгахын тулд unset суурилагдсан тушаалыг ашиглана, жишээ нь unset DEBUG.
Орчны хувьсагчид нь shell-ийн өөр нэгэн дүрэм юм. Тэдгээрийг олон програмын ажиллагааг шууд бусаар өөрчлөхөд ашиглаж болно. Жишээлбэл, shell нь одоогийн хэрэглэгчийн home хавтасны замыг
$HOMEорчны хувьсагчид хадгалдаг. Ингэснээр програмууд--home /home/aliceгэж зааж өгөхийг шаардалгүйгээр энэ хувьсагчаас мэдээллийг авч чаддаг. Өөр нэг жишээ бол олон програмууд огноо, цагийг форматыг тодорхойлоход ашигладаг$TZхувьсагч юм.
Гаралтын кодууд
Бидний өмнө үзсэнчлэн, shell програмын үндсэн гаралт нь stdout/stderr урсгалууд болон файлын систем дэх өөрчлөлтүүдээр илэрхийлэгддэг.
Анхны тохиргоогоор shell скрипт нь гаралтын код (exit code) тэг утгыг буцаадаг. Дүрмийн дагуу тэг гаралтын код нь бүх зүйл амжилттай болсныг илтгэдэг бол тэгээс өөр утга нь алдаа гарсан болохыг илэрхийлнэ. Тэгээс өөр код буцаахын тулд бид shell-ийн exit NUM суурилагдсан тушаалыг ашиглах ёстой. Хамгийн сүүлд ажилласан тушаалын гаралтын кодыг бид тусгай $? хувьсагчаар дамжуулан авч болно.
Shell-д AND болон OR үйлдлүүдийг гүйцэтгэх && болон || логик операторууд байдаг. Ердийн програмчлалын хэлнээс ялгаатай нь shell дэх эдгээр операторууд нь програмуудын гаралтын кодууд дээр ажилладаг. Тэд хоёулаа богино холболтын (short-circuiting) операторууд юм. Энэ нь өмнөх командын амжилттай (код 0) эсвэл амжилтгүй (тэгээс өөр код) болсон дээр үндэслэн дараагийн командуудыг нөхцөлтэйгөөр ажиллуулахад ашиглагдаж болно гэсэн үг юм. Жишээнүүд:
# grep амжилттай болсон тохиолдолд л (загварыг олбол) echo ажиллана
grep -q "pattern" file.txt && echo "Pattern found"
# grep алдаа заасан тохиолдолд л (загвар олдоогүй) echo ажиллана
grep -q "pattern" file.txt || echo "Pattern not found"
# true нь үргэлж амжилттай ажилладаг програм юм
true && echo "This will always print"
# харин false нь үргэлж алдаа заадаг програм юм
false || echo "This will always print"
Үүнтэй ижил зарчим if болон while нөхцөлүүдэд хамаарна, тэд хоёулаа гаралтын кодуудыг ашиглан шийдвэр гаргадаг:
# if нь нөхцөлт командын гаралтын кодыг ашигладаг (0 = үнэн, тэгээс өөр = худал)
if grep -q "pattern" file.txt; then
echo "Found"
fi
# while давталт нь команд 0 код буцааж байгаа хугацаанд үргэлжилнэ
while read line; do
echo "$line"
done < file.txt
Сигналууд
Зарим тохиолдолд та ажиллаж байгаа програмыг зогсоох шаардлагатай болдог, жишээлбэл тушаал хэтэрхий удаан ажиллах үед. Програмыг зогсоох хамгийн энгийн арга бол Ctrl-C дарах бөгөөд үүний дараа тушаал зогсох болно. Гэхдээ энэ нь цаанаа хэрхэн ажилладаг, яагаад заримдаа процессыг зогсоож чаддаггүй вэ?
$ sleep 100
^C
$
Энд
^Cнь терминал дээрCtrl-Cдарах үед харагдах тэмдэглэгээ юм.
Цаанаа дараах үйл явц өрнөсөн:
- Бид
Ctrl-Cдарсан - Shell энэхүү тусгай тэмдэгтүүдийг таньсан
- Shell процесс
sleepпроцесс рууSIGINTсигналыг илгээсэн - Сигнал нь
sleepпроцессын ажиллагааг зогсоосон
Сигналууд (Signals) нь тусгай харилцааны механизм юм. Процесс сигнал хүлээн авах үедээ ажиллагаагаа зогсоож, сигналыг боловсруулаад, сигналын өгсөн мэдээлэлд үндэслэн ажиллагааны урсгалаа өөрчлөх боломжтой байдаг. Ийм учраас сигналуудыг програм хангамжийн тасалдал (software interrupts) гэж нэрлэдэг.
Бидний хувьг Ctrl-C дарах нь shell-ийг процесс руу SIGINT сигналыг илгээхэд хүргэдэг. SIGINT-ийг барьж аваад үл тоомсорлодог, ажиллагаагаа зогсоодоггүй Python програмын жижиг жишээг доор харуулав. Энэ програмыг зогсоохын тулд бид Ctrl-\ дарж SIGQUIT сигналыг илгээх хэрэгтэй.
#!/usr/bin/env python
import signal, time
def handler(signum, time):
print("\nI got a SIGINT, but I am not stopping")
signal.signal(signal.SIGINT, handler)
i = 0
while True:
time.sleep(.1)
print("\r{}".format(i), end="")
i += 1
Энэ програмд SIGINT-ийг хоёр удаа илгээж, дараа нь SIGQUIT илгээхэд юу болохыг доор харуулав. ^ нь терминал дээр Ctrl товчлуурыг илэрхийлнэ.
$ python sigint.py
24^C
I got a SIGINT, but I am not stopping
26^C
I got a SIGINT, but I am not stopping
30^\[1] 39913 quit python sigint.py
SIGINT болон SIGQUIT нь терминалтай холбоотой хүсэлтүүдэд ашиглагддаг бол процессыг аюулгүй, зөв зогсоох ерөнхий сигнал бол SIGTERM юм. Энэ сигналыг илгээхийн тулд бид kill командыг kill -TERM <PID> синтакс ашиглан дуудаж болно.
Сигнал нь процессыг устгахаас гадна өөр зүйлсийг хийж чадна. Жишээлбэл, SIGSTOP нь процессыг түр зогсооно. Терминал дээр Ctrl-Z дарах нь shell-ийг SIGTSTP (Terminal Stop - терминалын SIGSTOP хувилбар) сигнал илгээхэд хүргэдэг.
Бид түр зогссон ажлыг fg эсвэл bg тушаалуудаар харгалзан урд талд (foreground) эсвэл ард (background) үргэлжлүүлэн ажиллуулж болно.
jobs команд нь одоогийн терминалын сесстэй холбоотой дуусаагүй байгаа ажлуудыг жагсаадаг. Та эдгээр ажлуудыг pid-ээр нь зааж өгч болно (pid-ийг олохын тулд pgrep-ийг ашиглана). Мөн процессыг хувийн тэмдэгт % болон ажлын дугаараар (jobs командын харуулдаг дугаар) зааж өгөх боломжтой. Хамгийн сүүлд ард ажиллуулсан ажлыг тусгай $! параметрээр авна.
Командын төгсгөлд & залгаж бичвэл командыг шууд ард ажиллуулж, prompt-ийг танд буцааж өгөх болно. Гэхдээ энэ нь shell-ийн STDOUT-ийг ашигласаар байх тул гаралт хэвлэгдээд төвөгтэй байж болно (үүнийг шийдэхийн тулд гаралтыг чиглүүлнэ үү). Үүнтэй ижил үр дүнд хүрэхийн тулд ажиллаж байгаа програмыг Ctrl-Z дарж зогсоогоод дараа нь bg гэж ажиллуулж болно.
Ард ажиллаж байгаа процессууд нь таны терминалын хүү процессууд хэвээр байх бөгөөд хэрэв та терминалыг хаавал тэд устгагдах болно (терминал хаагдахад тэдэнд SIGHUP сигнал очих болно). Үүнээс сэргийлэхийн тулд програмыг nohup (SIGHUP сигналыг үл тоомсорлогч wrapper) ашиглан ажиллуулах эсвэл ажиллаж эхэлсэн процессыг disown тушаалаар салгаж болно. Эсвэл дараагийн хэсэгт үзэх терминал үржүүлэгчийг ашиглаж болно.
Доорх жишээнд эдгээр ойлголтуудыг харуулав.
$ sleep 1000
^Z
[1] + 18653 suspended sleep 1000
$ nohup sleep 2000 &
[2] 18745
appending output to nohup.out
$ jobs
[1] + suspended sleep 1000
[2] - running nohup sleep 2000
$ kill -SIGHUP %1
[1] + 18653 hangup sleep 1000
$ kill -SIGHUP %2 # nohup нь SIGHUP-ээс хамгаална
$ jobs
[2] + running nohup sleep 2000
$ kill %2
[2] + 18745 terminated nohup sleep 2000
SIGKILL нь тусгай сигнал бөгөөд үүнийг процесс барьж авч чадахгүй тул процессыг шууд зогсоодог. Гэхдээ энэ нь системд өнчин хүү процессуудыг үлдээх зэрэг сөрөг үр дагавартай байж болно.
Та эдгээр болон бусад сигналуудын талаар эндээс эсвэл man signal, kill -l тушаалаар дэлгэрүүлж үзнэ үү.
Shell скрипт дотор сигнал хүлээн авах үед тушаалуудыг ажиллуулахын тулд trap суурилагдсан тушаалыг ашиглаж болно. Энэ нь цэвэрлэгээ хийх үйлдлүүдэд маш хэрэгтэй байдаг:
#!/usr/bin/env bash
cleanup() {
echo "Cleaning up temporary files..."
rm -f /tmp/mytemp.*
}
trap cleanup EXIT # Скрипт дуусах үед цэвэрлэгээг ажиллуулах
trap cleanup SIGINT SIGTERM # Мөн Ctrl-C болон kill хийх үед ажиллуулах
Алсын серверүүд
Өнөө үед програмчид өдөр тутмын ажилдаа алсын серверүүдтэй ажиллах нь улам бүр түгээмэл болж байна. Үүний тулд хамгийн түгээмэл ашиглагддаг хэрэгсэл бол SSH (Secure Shell) бөгөөд энэ нь алсын сервертэй холбогдож танил shell интерфейсийг олгодог. Бид сервертэй дараах тушаалаар холбогдоно:
ssh alice@server.mit.edu
Энд бид server.mit.edu сервер рүү alice хэрэглэгчээр нэвтрэхийг оролдож байна.
ssh-ийн ихэвчлэн анзаарагддаггүй нэг давуу тал бол тушаалуудыг интерактив бус байдлаар ажиллуулах боломж юм. ssh нь тушаалын stdin-ийг дамжуулж, stdout-ийг хүлээн авах үйлдлийг зөв гүйцэтгэдэг тул үүнийг бусад тушаалуудтай хослуулах боломжтой:
# Энд ls нь алсын сервер дээр, харин wc нь локал дээр ажиллана
ssh alice@server ls | wc -l
# Энд ls болон wc хоёулаа алсын сервер дээр ажиллана
ssh alice@server 'ls | wc -l'
Сүлжээ тасрах, унтах горимд шилжих, сүлжээ солигдох болон сүлжээний хоцролт ихтэй үед найдвартай ажилладаг SSH-ийг орлох Mosh хэрэгслийг суулгаж ашиглахыг зөвлөж байна.
ssh нь алсын сервер дээр тушаал ажиллуулахын тулд таныг зөвшөөрөлтэй хэрээгч мөн болохыг нотлохыг шаарддаг. Үүнийг нууц үг эсвэл ssh түлхүүр ашиглан хийж болно. Түлхүүрт суурилсан баталгаажуулалт нь нийтийн түлхүүрийн криптограф ашиглан нууц хувийн түлхүүрийг задлахгүйгээр серверт өөрийгөө таниулдаг. Түлхүүрт суурилсан баталгаажуулалт нь илүү хялбар бөгөөд илүү аюулгүй тул үүнийг сонгох нь зүйтэй. Хувийн түлхүүр (ихэвчлэн ~/.ssh/id_rsa эсвэл сүүлийн үед ~/.ssh/id_ed25519) нь таны нууц үгтэй ижил үүрэгтэй тул түүнийг маш сайн нууцалж, хэзээ ч бусадтай хуваалцаж болохгүй.
Түлхүүрийн хослолыг үүсгэхийн тулд ssh-keygen ажиллуулна.
ssh-keygen -a 100 -t ed25519 -f ~/.ssh/id_ed25519
Хэрэв та GitHub руу SSH түлхүүр ашиглан ханддаг бол энд дурдсан алхмуудыг аль хэдийн хийсэн бөгөөд хүчинтэй түлхүүрийн хослолтой байгаа байх. Түлхүүрийн нууц үгийг шалгаж, баталгаажуулахын тулд ssh-keygen -y -f /path/to/key тушаалыг ажиллуулж болно.
Сервер тал дээр ssh нь аль үйлчлүүлэгчийг нэвтрүүлэхээ шийдэхийн тулд .ssh/authorized_keys файлыг шалгадаг. Өөрийн нийтийн түлхүүрийг сервер рүү хуулахын тулд:
cat .ssh/id_ed25519.pub | ssh alice@remote 'cat >> ~/.ssh/authorized_keys'
# эсвэл илүү хялбар (хэрэв ssh-copy-id боломжтой бол)
ssh-copy-id -i .ssh/id_ed25519 alice@remote
Тушаал ажиллуулахаас гадна ssh-ийн үүсгэсэн холболтыг ашиглан файлыг сервер рүү болон серверээс найдвартай дамжуулж болно. scp нь хамгийн уламжлалт хэрэгсэл бөгөөд синтакс нь scp path/to/local_file remote_host:path/to/remote_file байна. rsync нь локал болон алсын сервер дээрх ижил файлуудыг таньж, дахин хуулахаас сэргийлдэг давуу талтай тул scp-ээс илүү сайн байдаг. Энэ нь мөн симлинкүүд, зөвшөөрлийг удирдах болон өмнө тасарсан хуулах үйлдлийг үргэлжлүүлэх --partial туг зэрэг нэмэлт боломжуудыг олгодог. rsync нь scp-тэй ижил синтакс ашигладаг.
SSH үйлчлүүлэгчийн тохиргоо ~/.ssh/config файлд байрлах бөгөөд энд бид серверүүд болон тэдгээрийн анхны тохиргоог тодорхойлж болно. Энэхүү тохиргооны файлыг зөвхөн ssh бус, мөн scp, rsync, mosh зэрэг бусад програмууд уншиж ашигладаг.
Host vm
User alice
HostName 172.16.174.141
Port 2222
IdentityFile ~/.ssh/id_ed25519
# Тохиргоонд мөн глоб ашиглаж болно
Host *.mit.edu
User alice
Терминал үржүүлэгчид
Командын мөрийн интерфейсийг ашиглах үед та нэгэн зэрэг олон зүйл ажиллуулах шаардлагатай болдог. Жишээлбэл, код засварлагч болон програмаа зэрэгцүүлж харахыг хүсэж болно. Үүнийг олон терминалын цонх нээж хийж болох ч terminal multiplexer ашиглах нь илүү тохиромжтой шийдэл юм.
tmux зэрэг terminal multiplexers нь терминалын цонхыг хэсгүүд (panes) болон таб (windows) болгон хувааж ашиглах боломжийг олгосноор олон shell сессүүдтэй үр дүнтэй ажиллах нөхцөлийг бүрдүүлдэг. Түүнчлэн, terminal multiplexer нь одоогийн терминалын сессийг detach хийгээд, дараа нь reattach хийх боломжийг олгодог. Үүнээс шалтгаалан terminal multiplexers нь алсын сервертэй ажиллах үед nohup зэрэг аргуудыг ашиглах шаардлагагүй болгодог тул маш тохиромжтой байдаг.
Өнөө үед хамгийн алдартай terminal multiplexer бол tmux юм. tmux нь тохируулах өндөр боломжтой бөгөөд холбогдох товчны хослолуудыг ашиглан олон таб, хэсгүүдийг үүсгэж тэдгээрийн хооронд хурдан шилжиж болно.
tmux-ийг ашиглахын тулд түүний товчны хослолуудыг мэдэх шаардлагатай бөгөөд тэдгээр нь бүгд <C-b> x хэлбэртэй байна: (1) Ctrl+b дарж, (2) Ctrl+b-ийг суллаад, (3) x товчлуурыг дарна. tmux нь дараах шатлал бүхий объектуудтай:
- Сессүүд (Sessions) - сесс нь нэг буюу хэд хэдэн цонх агуулсан бие даасан ажлын талбар юм.
tmuxнь шинэ сесс эхлүүлнэ.tmux new -s NAMEнь сессийг нэр өгч эхлүүлнэ.tmux lsнь одоо байгаа идэвхтэй сессүүдийг жагсаана.tmuxдотор<C-b> dдарах нь одоогийн сессийг салгана.tmux aнь хамгийн сүүлийн сесстэй эргэж холбогдоно. Сонгож холбогдохын тулд-tаргумент ашиглана.
- Цонхнууд (Windows) - Засварлагч эсвэл хөтөч дээрх табтай адил бөгөөд нэг сессийн доторх тусдаа хэсгүүд юм.
<C-b> cШинэ цонх үүсгэнэ. Хаахын тулд бүрхүүлийг<C-d>дарж хаахад хангалттай.<C-b> NN дэх цонх руу шилжинэ. Цонхнууд дугаарлагдсан байдгийг анхаарна уу.<C-b> pӨмнөх цонх руу шилжинэ.<C-b> nДараагийн цонх руу шилжинэ.<C-b> ,Одоогийн цонхны нэрийг өөрчилнө.<C-b> wОдоогийн цонхнуудыг жагсаана.
- Хэсгүүд (Panes) - Vim хуваалттай адил бөгөөд нэг дэлгэц дээр олон shell зэрэг ажиллуулах боломжийг олгоно.
<C-b> "Одоогийн хэсгийг хөндлөн хуваана.<C-b> %Одоогийн хэсгийг босоо хуваана.<C-b> <чиглэл>Заасан чиглэл рүү шилжинэ. Чиглэл гэдэг нь сумтай товчлуурууд юм.<C-b> zОдоогийн хэсгийг дэлгэц дүүргэх байдлаар томруулна / жижигсгэнэ.<C-b> [Гүйлгэж харах горимыг эхлүүлнэ. Та<space>дарж сонгож эхлээд,<enter>дарж сонгосон хэсгийг хуулж авч болно.<C-b> <space>Хэсгүүдийн байршлыг сольж өөрчилнө.
tmux-ийн талаар илүү iихийг мэдэхийн тулд энэ богино заавар болон энэ дэлгэрэнгүй тайлбарыг уншина уу.
tmux болон SSH ашиглаж сурсны дараа та өөрийн ажиллах орчныг дурын машин дээр өөрийнхөөрөө байлгахыг хүсэх болно. Энд shell тохиргоо (shell customization) хэрэг болно.
Бүрхүүлийг өөртөө тааруулан өөрчлөх
Олон тооны командын мөрийн програмууд нь dotfiles гэж нэрлэгддэг plain-text файлуудаар тохируулагддаг (файлын нэр нь .-оор эхэлдэг тул, жишээ нь ~/.vimrc, ийм файлууд ls хийхэд харагддаггүй нуугдмал байдаг).
Dotfiles нь shell-ийн өөр нэгэн дүрэм юм. Эхэнд байгаа цэг нь тэдгээрийг жагсаалтад харуулахгүй нуух зорилготой байдаг.
Shell-үүд нь ийм файлуудаар тохируулагддаг програмуудын нэг жишээ юм. Ажиллаж эхлэхдээ shell нь тохиргоогоо ачаалахын тулд олон файл уншдаг. Shell-ийн төрөл болон нэвтрэх сесс (login session) эсвэл интерактив сессээс хамааран энэ үйл явц нь нэлээд нарийн төвөгтэй байж болно. Сэдвийн талаарх маш сайн нөөцийг эндээс үзнэ үү.
bash-ийн хувьд .bashrc эсвэл .bash_profile файлыг засварлах нь ихэнх системд тохирдог. Dotfiles ашиглан тохируулж болох зарим хэрэгслүүд:
bash-~/.bashrc,~/.bash_profilegit-~/.gitconfigvim-~/.vimrcболон~/.vimхавтасssh-~/.ssh/configtmux-~/.tmux.conf
Түгээмэл хийгддэг тохиргооны өөрчлөлт бол shell програм хайх шинэ байршлуудыг нэмэх явдал юм. Програм хангамж суулгах үед та энэхүү загвартай таарах болно:
export PATH="$PATH:path/to/append"
Энд бид shell-д $PATH хувьсагчийн утгыг одоогийн утга дээр шинэ замыг нэмж оноож, бүх хүү процессууд PATH-ийн энэхүү шинэ утгыг өвлөн авахыг зааж байна. Энэ нь хүү процессуудад path/to/append хавтсан доор байрлах програмуудыг олох боломжийг олгоно.
Shell-ээ өөрчлөх нь ихэвчлэн шинэ командын мөрийн хэрэгслүүдийг суулгахыг шаарддаг. Багц удирдагчид (package managers) үүнийг хялбар болгодог. Тэд програм татах, суулгах, шинэчлэх үйлдлүүдийг хариуцдаг. Үйлдлийн систем бүр өөр өөрийн багц удирдагчтай байдаг: macOS нь Homebrew, Ubuntu/Debian нь apt, Fedora нь dnf, харин Arch нь pacman ашигладаг. Бид багц удирдагчдын талаар кодын тээвэрлэлт лекцээр дэлгэрэнгүй үзэх болно.
macOS дээр Homebrew ашиглан хоёр хэрэгтэй програмыг хэрхэн суулгахыг доор харуулав:
# ripgrep: илүү сайн тохиргоотой, илүү хурдан grep
brew install ripgrep
# fd: ашиглахад хялбар бөгөөд илүү хурдан find
brew install fd
Эдгээрийг суулгаснаар та grep-ийн оронд rg, харин find-ын оронд fd тушаалыг ашиглах боломжтой болно.
curl | bashанхааруулга: Таcurl -fsSL https://example.com/install.sh | bashгэх мэт суулгах зааврыг олноор харах болно. Энэ арга нь скриптийг татаж аваад шууд ажиллуулдаг тул маш хялбар боловч эрсдэлтэй; та шалгаагүй кодоо шууд ажиллуулж байна гэсэн үг юм. Илүү аюулгүй арга бол эхлээд татаж аваад, кодыг шалгаад дараа нь ажиллуулах явдал юм:curl -fsSL https://example.com/install.sh -o install.sh less install.sh # кодыг шалгах bash install.shЗарим суулгацууд арай аюулгүй хувилбарыг ашигладаг:
/bin/bash -c "$(curl -fsSL https://url)"нь дор хаяж одоогийн shell-ээс биш харин bash-аар скриптийг ажиллуулахыг баталгаажуулдаг.
Суулгаагүй командыг ажиллуулахыг оролдох үед shell command not found алдааг заах болно. command-not-found.com вэбсайт нь дурын командыг хайж олон, түүнийг үйлдлийн систем болон багц удирдагч бүр дээр хэрхэн суулгах зааврыг харахад маш хэрэгтэй нөөц юм.
Өөр нэгэн хэрэгтэй хэрэгсэл бол маш товч бөгөөд жишээн дээр суурилсан man хуудсуудыг харуулдаг tldr юм. Маш урт баримт бичгийг уншихын оронд та түүний түгээмэл хэрэглэгддэг хэлбэрүүдийг хурдан харах боломжтой:
$ tldr fd
An alternative to find.
Aims to be faster and easier to use than find.
Recursively find files matching a pattern in the current directory:
fd "pattern"
Find files that begin with "foo":
fd "^foo"
Find files with a specific extension:
fd --extension txt
Заримдаа танд шинэ програм хэрэггүй бөгөөд зөвхөн бэлэн байгаа командуудыг тодорхой flags-тай ашиглах товчлол хэрэгтэй байдаг. Энд алиасууд (aliases) хэрэг болно.
Бид shell-ийн суурилагдсан alias тушаалыг ашиглан өөрсдийн командын товчлолыг үүсгэж болно. Shell alias нь өөр командын богино хэлбэр бөгөөд shell тушаалыг ажиллуулахаас өмнө автоматаар солих болно. Жишээлбэл, bash дээрх alias нь дараах бүтэцтэй байна:
alias alias_name="command_to_alias arg1 arg2"
Тэнцүүгийн тэмдэг
=орчимд сул зай байж болохгүй, учир ньaliasнь ганц аргумент авдаг shell команд юм.
Алиасууд нь маш олон давуу талтай:
# Түгээмэл flags-д зориулсан товчлол үүсгэх
alias ll="ls -lh"
# Байнга бичдэг урт командуудыг хурдан бичих
alias gs="git status"
alias gc="git commit"
# Буруу бичихээс сэргийлэх
alias sl=ls
# Програмуудыг илүү найдвартай тохиргоотой болгох
alias mv="mv -i" # -i нь файлыг дахин бичихээс өмнө асууна
alias mkdir="mkdir -p" # -p нь эцэг хавтас байхгүй бол үүсгэнэ
alias df="df -h" # -h нь хэмжээг хүнд уншихад хялбар форматоор харуулна
# Алиасуудыг хослуулж болно
alias la="ls -A"
alias lla="la -l"
# Алиасыг үл тоомсорлон жинхэнэ тушаалыг ажиллуулахдаа өмнө нь \ тавина
\ls
# Эсвэл unalias ашиглан алиасыг бүрмөсөн идэвхгүй болгоно
unalias la
# Алиасын тодорхойлолтыг харахын тулд alias-ийг дуудна
alias ll
# ll='ls -lh' гэж хэвлэнэ
Алиасууд нь хязгаарлалттай: тэд тушаалын дундуур аргумент авч чаддаггүй. Илүү нарийн төвөгтэй үйлдлүүдэд та үүний оронд shell функцуудыг (shell functions) ашиглах хэрэгтэй.
Ихэнх shell-үүд түүхээс ухрааж хайх Ctrl-R товчны хослолыг дэмждэг. Ctrl-R дараад өмнө ажиллуулсан командынхаа хэсгийг бичиж хайна уу. Өмнө нь бид fzf-ийг fuzzy finder байдлаар танилцуулсан; fzf-ийн shell-тэй нэгдсэн тохиргоог хийснээр Ctrl-R нь таны түүхээс интерактив fuzzy хайлтыг хийдэг болох бөгөөд энэ нь анхны тохиргооноос хамаагүй хүчирхэг юм.
Өөрийн dotfiles-ийг хэрхэн зохион байгуулах вэ? Тэдгээрийг өөрийн гэсэн хавтаст хийж, хувилбарын хяналтад оруулан, скрипт ашиглан symlink (тэмдэгт холбоос) хийх нь зүйтэй. Энэ нь дараах давуу талуудтай:
- Суулгахад хялбар: хэрэв та шинэ машин руу нэвтэрвэл өөрийн тохиргоог хэрэглэхэд ердөө нэг минут шаардагдана.
- Зөөвөрлөх боломжтой: таны хэрэгслүүд хаана ч байсан яг ижилхэн ажиллах болно.
- Синхрончлол: та dotfiles-оо хаана ч шинэчилсэн тэдгээрийг хооронд нь ижил байлгаж чадна.
- Өөрчлөлтийг хянах: та програмчлалын замналдаа dotfiles-оо маш урт хугацаанд ашиглах тул өөрчлөлтийн түүхтэй байх нь маш хэрэгтэй.
Өөрийн dotfiles-д юу оруулах вэ? Та тохиргооны заавруудыг онлайн баримт бичиг эсвэл man хуудаснаас уншиж сурах боломжтой. Мөн өөр нэг сайн арга бол бусад хүмүүсийн dotfiles-ийг судлах явдал юм: та GitHub дээрээс маш олон dotfiles repositories олох боломжтой бөгөөд хамгийн алдартайг нь эндээс үзэж болно (гэхдээ тохиргоог сохроор хуулж болохгүй). Энд өөр нэгэн сайн нөөц бий.
Энэхүү хичээлийн багш нарын dotfiles нээлттэй байдаг: Anish, Jon, Jose.
Фрэймворк болон залгаасууд (frameworks and plugins) нь мөн таны shell-ийг сайжруулахад туслах болно. Түгээмэл хэрэглэгддэг фрэймворкууд гэвэл prezto эсвэл oh-my-zsh байдаг бол тодорхой боломжид чиглэсэн жижиг залгаасууд ч бий:
- zsh-syntax-highlighting - тушаалыг бичиж байх явцад зөв / бурууг өнгөөр ялгаж харуулна
- zsh-autosuggestions - бичих явцад түүхээс командуудыг санал болгоно
- zsh-completions - нэмэлт автомат нөхөлтийн тодорхойлолтууд
- zsh-history-substring-search - fish шиг түүхээс хайх боломж
- powerlevel10k - хурдан бөгөөд өөрчлөх боломжтой prompt загвар
fish зэрэг shell-үүд эдгээр боломжуудыг анхнаасаа агуулсан байдаг.
Эдгээр боломжуудыг авахын тулд oh-my-zsh шиг том фрэймворк заавал шаардлагагүй. Тусдаа залгаасуудыг суулгах нь илүү хурдан бөгөөд танд илүү их хяналтыг олгоно. Том фрэймворкууд нь shell-ийн ачааллах хугацааг мэдэгдэхүйц удаашруулдаг тул зөвхөн ашигладаг зүйлсээ суулгахыг анхаарна уу.
Бүрхүүл дэх хиймэл оюун ухаан (AI)
Бүрхүүлд хиймэл оюун ухааны (AI) хэрэгслийг ашиглах олон арга бий. Дараах хэдэн жишээг харуулъя:
Тушаал үүсгэх: simonw/llm зэрэг хэрэгслүүд нь байгалийн хэлээр бичсэн тайлбараас shell тушаал үүсгэхэд тусална:
$ llm cmd "find all python files modified in the last week"
find . -name "*.py" -mtime -7
Pipeline integration: LLM загваруудыг өгөгдөл боловсруулах болон хөрвүүлэхэд shell pipes-тай нэгтгэж болно. Тогтмол бус форматаас мэдээллийг салгахад regex бичихэд хүндрэлтэй үед тэд маш хэрэгтэй байдаг:
$ cat users.txt
Contact: john.doe@example.com
User 'alice_smith' logged in at 3pm
Posted by: @bob_jones on Twitter
Author: Jane Doe (jdoe)
Message from mike_wilson yesterday
Submitted by user: sarah.connor
$ INSTRUCTIONS="Extract just the username from each line, one per line, nothing else"
$ llm "$INSTRUCTIONS" < users.txt
john.doe
alice_smith
bob_jones
jdoe
mike_wilson
sarah.connor
Бид хувьсагч дотор хоосон зай байгаа тул "$INSTRUCTIONS" (хашилттай) ашиглаж байгааг болон файлын агуулгыг stdin рүү чиглүүлэхийн тулд < users.txt-ийг ашиглаж байгааг анхаарна уу.
AI shell-үүд: Claude Code зэрэг хэрэгслүүд нь англи хэлээр өгсөн тушаалыг shell-ийн үйлдэл, файл засварлах болон олон алхамт нарийн төвөгтэй ажлууд болгон хөрвүүлдэг мета-бүрхүүлийн (meta-shell) үүргийг гүйцэтгэдэг.
Терминал эмуляторууд
Shell-ээ тохируулахаас гадна өөрийн ашиглах terminal emulator (терминал эмулятор) болон түүний тохиргоог сонгоход хэсэг хугацаа зарцуулах нь зүйтэй. Terminal emulator нь таны shell ажилладаг текстэн интерфейсийг олгодог GUI програм юм. Маш олон terminal emulators байдаг.
Терминал дээрээ олон зуун, магадгүй олон мянган цагийг зарцуулах тул түүний тохиргоог анхаарах нь үр өгөөжтэй байдаг. Та терминал дээрээ дараах зүйлсийг өөрчилж болно:
- Шрифтийн сонголт (Font selection)
- Өнгөний зохицол (Color scheme)
- Гарын товчлолууд (Keyboard shortcuts)
- Таб/Хэсгийн дэмжлэг (Tabs/Panes support)
- Гүйлгэж харах тохиргоо (Scrollback configuration)
- Хурд, гүйцэтгэл (үүний тулд Alacritty эсвэл Ghostty зэрэг GPU хурдатгалтай шинэ терминалуудыг ашиглаж болно).
Дасгал ажил
Энэхүү хичээлийн бүх лекцүүд нь цуврал дасгал ажлуудтай ирдэг. Зарим нь тодорхой даалгавар өгөх бол зарим нь “X болон Y програмыг ашиглаад үзээрэй” гэх мэт нээлттэй байдаг. Бид таныг эдгээрийг туршиж үзэхийг зөвлөж байна.
Бид дасгал ажлын хариуг бичээгүй болно. Хэрэв танд хүндрэл гарвал Discord дээрх #missing-semester-forum сувагт асуух эсвэл хийсэн зүйлээ тайлбарлаж бидэнд имэйл илгээгээрэй, бид туслахыг хичээх болно. Эдгээр дасгалууд нь LLM-тэй хийх хэлэлцүүлэгт ч сайн сэдэв болох болно. Дасгал ажлын гол үнэ цэнэ нь хариултыг олох явцад суралцах бөгөөд зөвхөн хамгийн дөхөм замыг хайхаас илүү асуулт тавьж, гүнзгийрүүлэн судлахыг зөвлөж байна.
-
Та заримдаа
cmd --flag -- --notaflagгэх мэт тушаалуудыг харах болно.--нь програмд тугуудыг задлан шинжлэхийг зогсоохыг заадаг тусгай аргумент юм.---ийн дараа байгаа бүх зүйлийг байрлалын аргумент (positional argument) гэж үзнэ. Энэ нь яагаад хэрэгтэй байж болох вэ?touch -- -myfileгэж ажиллуулан файл үүсгээд, дараа нь--ашиглахгүйгээр устгахыг оролдоно уу. man lsхуудсыг уншаад дараах байдлаар файлуудыг жагсаахlsтушаал бичнэ үү:- Нууц файлыг оролцуулан бүх файлыг харуулна
- Хэмжээг хүнд уншихад хялбар форматоор харуулна (жишээ нь 454279954-ийн оронд 454M)
- Файлуудыг сүүлд өөрчлөгдсөн хугацаагаар нь эрэмбэлнэ
- Гаралт нь өнгөтэй байна
Жишээ гаралт иймэрхүү харагдана:
-rw-r--r-- 1 user group 1.1M Jan 14 09:53 baz drwxr-xr-x 5 user group 160 Jan 14 09:53 . -rw-r--r-- 1 user group 514 Jan 14 06:42 bar -rw-r--r-- 1 user group 106M Jan 13 12:12 foo drwx------+ 47 user group 1.5K Jan 12 18:08 ..-
Процесс орлуулалт (process substitution)
<( CMD )нь тушаалын гаралтыг файл шиг ашиглах боломжийг олгодог. Процесс орлуулалттайdiffашигланprintenvболонexport-ийн гаралтыг харьцуулна уу. Тэд юугаараа ялгаатай вэ? (Сэжүүр:diff <(printenv | sort) <(export | sort)ажиллуулна уу). -
Дараах үйлдлийг гүйцэтгэх bash функцууд болох
marcoболонpolo-г бичнэ үү: таныгmarcoажиллуулах бүрд одоогийн ажиллаж буй хавтас хадгалагдах бөгөөд таныг ямар ч хавтас дотор байсанpoloажиллуулахадcdхийж таныгmarco-г ажиллуулсан хавтас руу буцаах болно. Алдааг хялбар засахын тулд кодыгmarco.shфайлд бичиж,source marco.shажиллуулан өөрийн shell-д ачаалж туршина уу. -
Танд хааяа нэг алдаа заадаг тушаал байна гэж бодъё. Алдааг илрүүлэхийн тулд гаралтыг хадгалах шаардлагатай боловч алдаа заах хүртэл гараар ажиллуулах нь цаг их үрнэ. Дараах скриптийг алдаа заах хүртэл нь ажиллуулах бөгөөд түүний стандарт гаралт болон алдааны урсгалуудыг файлд хадгалж, төгсгөлд нь бүх гаралтыг хэвлэдэг bash скрипт бичнэ үү. Хэрэв скрипт алдаа заах хүртэл нийт хэдэн удаа ажилласныг хэвлэж чадвал бонус оноо болно.
#!/usr/bin/env bash n=$(( RANDOM % 100 )) if [[ n -eq 42 ]]; then echo "Something went wrong" >&2 echo "The error was using magic numbers" exit 1 fi echo "Everything went according to plan" -
Терминал дээр
sleep 10000ажлыг эхлүүлээд,Ctrl-Zдарж түр зогсоонbgтушаалаар ард ажиллуулна уу. Одооpgrepашиглан түүний pid-ийг олж,pkillашиглан pid-ийг гараар бичихгүйгээр устгана уу. (Сэжүүр:-afаргументуудыг ашиглана уу). -
Та нэг процессыг дуустал өөр процессыг ажиллуулахгүй хүлээхийг хүсэж байна гэж бодъё. Үүнийг хэрхэн шийдэх вэ? Энэ дасгалд хүлээх процесс маань үргэлж
sleep 60 &байна. Үүнд хүрэх нэг арга болwaitкомандыг ашиглах явдал юм. Sleep командыг ажиллуулаад,lsкомандыг арын процесс дуустал хүлээдэг болгон туршина уу.Гэвч, хэрэв бид өөр багц сессээс эхлүүлбэл энэ арга ажиллахгүй, учир нь
waitнь зөвхөн хүү процессууд дээр ажилладаг. Тэмдэглэлд дурдаагүй нэг зүйл болkillкомандын гаралтын төлөв амжилттай бол 0, үгүй бол тэгээс өөр утга буцаадаг явдал юм.kill -0нь сигнал илгээдэггүй боловч процесс байхгүй тохиолдолд тэгээс өөр код буцаана. PID авдаг бөгөөд уг процесс дуусах хүртэл хүлээдэгpidwaitнэртэй bash функц бичнэ үү. CPU-ийг дэмий үрэхээс сэргийлэхийн тулдsleepашиглах хэрэгтэй. -
(Гүнзгийрүүлсэн) Хавтас дотроос хамгийн сүүлд өөрчлөгдсөн 파일을 рекурсив байдлаар олдог тушаал эсвэл скрипт бичнэ үү. Илүү ерөнхий байдлаар, бүх файлыг өөрчлөгдсөн хугацаагаар нь жагсааж чадах уу?
-
Энэхүү
tmuxзааврыг дагаж суралцаад, дараа нь эдгээр алхмуудын дагуу үндсэн тохиргоонуудыг хийж сурна уу. -
Командыг буруу бичих үед зориулан
cdрүү хөрвөхdcалиасыг (alias) үүсгэнэ үү. -
history | awk '{$1="";print substr($0,2)}' | sort | uniq -c | sort -n | tail -n 10ажиллуулан өөрийн хамгийн их ашигласан 10 командыг олж, тэдгээрт зориулсан богино алиас бичих талаар бодно уу. Тэмдэглэл: энэ нь Bash дээр ажиллана; хэрэв та ZSH ашиглаж байгаа бол зүгээрhistoryбишhistory 1ашиглана уу. -
Өөрийн dotfiles-д зориулж хавтас үүсгэн хувилбарын хяналтад (Git) оруулна уу.
-
Ядаж нэг програмын тохиргоог (эхлэхдээ бүрхүүлийн prompt-ийг өөрчлөх
$PS1тохиргоо байж болно) өөрийн dotfiles-д нэмнэ үү. -
Өөрийн dotfiles-ыг шинэ машин дээр хурдан (мөн механик ажиллагаагүй) суулгах аргыг бэлтгэнэ үү. Энэ нь файл бүрд
ln -sхийдэг энгийн скрипт эсвэл тусгай хэрэгсэл ашигласан байж болно. -
Суулгах скриптээ шинэ виртуал машин дээр туршиж үзнэ үү.
-
Өөрийн одоогийн ашиглаж буй хэрэгслүүдийн бүх тохиргоог dotfiles сан руугаа шилжүүлнэ үү.
-
Өөрийн dotfiles-оо GitHub дээр нийтэлнэ үү.
-
~/.ssh/хавтас руу орж SSH түлхүүр байгаа эсэхийг шалгана уу. Хэрэв байхгүй болssh-keygen -a 100 -t ed25519ашиглан үүсгэнэ үү. Нууц үг ашиглах болонssh-agentашиглахыг зөвлөж байна, дэлгэрэнгүй мэдээлэл энд бий. -
.ssh/configфайлыг дараах байдлаар засварлана уу:Host vm User username_goes_here HostName ip_goes_here IdentityFile ~/.ssh/id_ed25519 LocalForward 9999 localhost:8888 -
ssh-copy-id vmажиллуулан өөрийн ssh нийтийн түлхүүрийг сервер рүү хуулна уу. -
Өөрийн VM дотор
python -m http.server 8888ажиллуулан вэб сервер эхлүүлнэ үү. Өөрийн локал машин дээр хөтчөөрөөhttp://localhost:9999хаягаар орон VM-ийн вэб сервер рүү хандана уу. -
Өөрийн SSH серверийн тохиргоог
sudo vim /etc/ssh/sshd_configтушаалаар нээжPasswordAuthenticationутгыг өөрчлөн нууц үгээр нэвтрэхийг хаана уу. МөнPermitRootLoginутгыг өөрчлөн root хэрэглэгчээр нэвтрэхийг хаана уу. SSH үйлчилгээгsudo service sshd restartажиллуулан дахин ачаалж, дахин нэвтэрч туршина уу. -
(Асуулт) VM дотор
mosh-ийг суулгаж холболт үүсгэнэ үү. Дараа нь серверийн сүлжээний холболтыг салгана уу. Mosh холболтыг буцааж сэргээж чадаж байна уу? - (Асуулт)
sshкомандын-Nболон-fтугуудын үүргийг судалж, арын горимд портыг чиглүүлэх тушаалыг олно уу.
Лиценз: CC BY-NC-SA.