Skip to content

Shell va Bash qanday ishlaydi

Terminal oynasi Linux buyruqlarini o'zi bajarmaydi. U sizga matnli interfeys taqdim etadi, kiritgan ma’lumotlaringizni shell’ga yuboradi va qaytib kelgan natijani ekranda ko'rsatadi.

Shell

Shell — buyruq qatorini o'qiydigan, o'z qoidalarini qo'llaydigan hamda ichki amalni bajaradigan yoki boshqa dasturni ishga tushiradigan dastur.

Ubuntu Serverda buyruqlarni qabul qilib, bajarishga tayyorlaydigan dastur shell deb ataladi. Ubuntu Serverda shell sifatida ko'pincha Bash ishlatiladi.

Terminalga yozgan har bir buyruq avval Bash tomonidan tekshiriladi va tayyorlanadi, keyin kerakli dastur ishga tushiriladi. Masalan, ls *.log deb yozsangiz, Bash avval *.log o'rniga .log bilan tugaydigan fayllar nomini qo'yadi. Shundan keyingina ls buyrug'ini ishga tushiradi.

Ba’zi buyruqlar esa alohida dastur emas, Bashning o'ziga tegishli buyruqlardir. Masalan, cd shunday buyruq. Shu sababli tizimda /usr/bin/cd nomli dastur bo'lmasa ham, cd ishlaydi va joriy katalogni o'zgartiradi.

Ushbu bo'limdagi misollar Ubuntu Server LTS va Bash muhiti uchun berilgan. Buyruqlar boshidagi $ belgisi yozilmaydi. U faqat terminal buyruq kiritishga tayyorligini ko'rsatadi.

Terminal, shell, dastur va yadro

Terminalda buyruq yozganimizda bir nechta qatlam birgalikda ishlaydi. Ularning har biri alohida vazifani bajaradi:

  • Terminal emulyatori — buyruqlarni klaviatura orqali kiritish va natijani ekranda ko'rish uchun ishlatiladigan dastur.
  • GNOME Terminal va Windows Terminal terminal emulyatorlariga misol bo'ladi. SSH klienti esa masofadagi server terminaliga ulanish imkonini beradi.
  • Shell — foydalanuvchi yozgan buyruqlarni qabul qiladigan, tushunadigan va bajarishga tayyorlaydigan dastur. Bash, Zsh, Fish va Dash shell turlaridir.
  • Dastur — ma’lum bir vazifani bajaradigan kod. Masalan, /usr/bin/ls fayllar ro'yxatini chiqaradigan tashqi dasturdir. cd esa alohida dastur emas, Bash ichida mavjud bo'lgan buyruqdir.
  • Yadro — Linux tizimining asosiy qismi. U jarayonlar, tezkor xotira, fayl tizimlari, qurilmalar, tarmoq va ruxsatlarni boshqaradi.

Terminalga buyruq yozganingizdan boshlab, amal bajarilguncha jarayon taxminan quyidagi tartibda davom etadi:

foydalanuvchi
  -> terminal yoki SSH klienti
  -> Bash
  -> Bash ichki buyrug'i yoki tashqi dastur
  -> Linux yadrosi
  -> fayllar, qurilmalar, jarayonlar yoki tarmoq

Masalan, quyidagi buyruqni ko'rib chiqamiz:

cat /etc/hostname

Bu buyruq bajarilganda quyidagilar sodir bo'ladi:

  1. Bash cat nomli dasturni qidiradi.
  2. /etc/hostname qiymatini cat dasturiga argument sifatida beradi.
  3. Bash cat dasturini yangi jarayon sifatida ishga tushiradi.
  4. cat faylni o'qish uchun Linux yadrosiga murojaat qiladi.
  5. Yadro fayldagi ma’lumotni cat dasturiga beradi.
  6. cat natijani terminalga chiqaradi.

Endi quyidagi buyruqni ko'rib chiqamiz:

cd /var/log

cd alohida tashqi dastur emas. U Bash ichida mavjud bo'lgan ichki buyruqdir.

cd buyrug'i ayni vaqtda ishlayotgan Bashning joriy katalogini o'zgartirishi kerak. Shu sababli u alohida dastur sifatida emas, Bashning ichki buyrug'i sifatida ishlaydi.

Agar cd alohida dastur bo'lganida, u vaqtincha yangi jarayonda ishga tushardi. Bu jarayon faqat o'z katalogini o'zgartira olardi. Jarayon yopilgach, asosiy Bash avvalgi katalogida qolaverardi.

Shuning uchun cd bevosita Bash ichida bajariladi va foydalanuvchi turgan joriy katalogni o'zgartiradi.

Joriy shell’ni aniqlash

Terminaldagi prompt ko'rinishiga qarab qaysi shell ishlayotganini aniq bilib bo'lmaydi. Chunki promptni istalgan ko'rinishga sozlash mumkin.

Joriy muhit haqida ma’lumot olish uchun quyidagi buyruqlardan foydalaning:

echo "login shell: $SHELL"
echo "bash version: $BASH_VERSION"
ps -p $$ -o pid=,ppid=,comm=,args=

Odatdagi natija quyidagicha bo'lishi mumkin:

login shell: /bin/bash
bash version: 5.2.21(1)-release
 2140  2139 bash            -bash

Har bir qatorning ma’nosi:

  • $SHELL foydalanuvchi hisobi uchun tanlangan login shell’ni ko'rsatadi. Masalan, /bin/bash.
  • Lekin $SHELL ayni vaqtda ishlayotgan shell’ni har doim ham aniq ko'rsatmaydi. Masalan, Bash ichidan vaqtincha Zsh ishga tushirilsa ham, $SHELL eski qiymatda qolishi mumkin.
  • $BASH_VERSION faqat joriy shell Bash bo'lsa qiymatga ega bo'ladi. U Bash versiyasini ko'rsatadi.
  • $$ joriy shell jarayonining PID raqamini bildiradi.
  • ps -p $$ aynan shu PID bilan ishlayotgan jarayon haqida ma’lumot chiqaradi.
  • Natijadagi -bash yozuvi Bash login shell sifatida ishga tushirilganini bildiradi.

Tizimda login shell sifatida ishlatishga ruxsat berilgan shell’lar odatda quyidagi faylda yoziladi:

cat /etc/shells

Bu fayl tizimdagi barcha shell dasturlarini ko'rsatishi shart emas. U faqat login qilish uchun yaroqli deb hisoblangan shell’lar ro'yxatini saqlaydi.

Promptni o'qish

Terminal prompti ko'pincha quyidagicha ko'rinadi:

admin@web01:~/project$

Bu qismlar odatda quyidagi ma’noni anglatadi:

  • admin — joriy foydalanuvchi nomi.
  • web01 — kompyuter yoki server nomi.
  • ~/project — joriy ish katalogi.
  • ~ — foydalanuvchining uy katalogi. Masalan, admin foydalanuvchisi uchun u odatda /home/admin katalogini bildiradi.
  • $ — odatda oddiy foydalanuvchi ishlayotganini bildiradigan prompt belgisi.

Root foydalanuvchisining prompti ko'pincha # belgisi bilan tugaydi. Lekin bu faqat odatiy ko'rinish. Promptni o'zgartirish mumkin, shuning uchun faqat $ yoki # belgisiga ishonmang.

Joriy foydalanuvchi va huquqlarni quyidagi buyruqlar yordamida tekshiring:

id
id -u
whoami
pwd

Bu buyruqlarning vazifasi:

  • id — foydalanuvchi UID raqami, asosiy guruhi va boshqa guruhlarini ko'rsatadi.
  • id -u — faqat joriy foydalanuvchining UID raqamini chiqaradi.
  • whoami — joriy foydalanuvchi nomini ko'rsatadi.
  • pwd — ayni vaqtda qaysi katalogda turganingizni ko'rsatadi.

Agar id -u buyrug'i 0 chiqarsa, siz root huquqi bilan ishlayapsiz. Bu ma’lumot promptdagi belgidan ko'ra ishonchliroq.

Warning

Root — UID raqami 0 bo'lgan, tizimda deyarli barcha amallarni bajarish huquqiga ega superfoydalanuvchi.

Linux fayl tizimining eng yuqori / katalogi ham root katalog deb ataladi. Lekin root foydalanuvchi va root katalog ikki xil tushunchadir.

Kundalik ishlarni doimiy ravishda root shell ichida bajarmang. Ma’muriy huquq talab qiladigan aniq buyruqlardagina sudo ishlating.

Ichki buyruqlar, aliaslar, funksiyalar va tashqi buyruqlar

Terminalga yozilgan buyruq nomi har doim ham diskdagi bitta dastur faylini anglatmaydi.

Masalan, ls quyidagilardan biri bo'lishi mumkin:

  • Bash ichki buyrug'i;
  • alias;
  • shell funksiyasi;
  • diskdagi tashqi dastur.

Buyruq nomi nimani anglatishini tekshirish uchun quyidagi buyruqlardan foydalaning:

type -a cd echo pwd ls
command -V ls

Mumkin bo'lgan natija:

cd is a shell builtin
echo is a shell builtin
pwd is a shell builtin
pwd is /usr/bin/pwd
ls is aliased to `ls --color=auto'
ls is /usr/bin/ls

Bu natijani quyidagicha o'qish mumkin:

  • cd — Bashning ichki buyrug'i.
  • echo — Bashning ichki buyrug'i.
  • pwd — Bash ichida ham mavjud.
  • /usr/bin/pwd nomli tashqi dastur ham mavjud.
  • ls uchun ls --color=auto aliasi yaratilgan.
  • Asl tashqi ls dasturi /usr/bin/ls manzilida joylashgan.

Demak, “buyruq” deganda har doim bitta bajariladigan fayl nazarda tutilmaydi.

Bash buyruqni bajarishdan oldin uning:

  1. alias ekanini;
  2. funksiya ekanini;
  3. ichki buyruq ekanini;
  4. yoki PATH orqali topiladigan tashqi dastur ekanini aniqlaydi.

Bir xil buyruq ikki serverda turlicha ishlasa, darhol tizimda muammo bor deb o'ylamang. Avval buyruq manbasini tekshiring:

type -a <buyruq_nomi>

Masalan:

type -a ls

Bash ichki buyruqlari bo'yicha yordam olish uchun help ishlatiladi:

help cd
help type

Tashqi GNU dasturlari odatda --help parametriga va man qo'llanma sahifasiga ega:

ls --help
man ls

Keyingi maqola — Buyruq sintaksisi va yordam hujjatlari — yordam hujjatlaridagi sintaksisni qanday o'qishni tushuntiradi.

Dastur ishga tushishidan oldin Bash nima qiladi?

Terminalga buyruq yozib Enter tugmasini bosganingizda, Bash uni darhol tashqi dasturga yubormaydi.

Bash avval buyruq qatorini tahlil qiladi va kerakli o'zgartirishlarni bajaradi. Soddalashtirilgan tartib quyidagicha:

  1. Buyruq qatorini so'zlar va maxsus operatorlarga ajratadi.
  2. Alias mavjud bo'lsa, uni haqiqiy qiymatiga almashtiradi.
  3. O'zgaruvchilar, $(...) buyruq almashtirishi, arifmetik ifodalar va ~ belgisini kengaytiradi.
  4. Zarur joylarda matnni alohida argumentlarga ajratadi.
  5. *.conf kabi wildcard andozalarini mos fayl nomlariga almashtiradi.
  6. >, < va boshqa qayta yo'naltirishlarni tayyorlaydi.
  7. Bash ichki buyrug'ini bajaradi yoki tashqi dasturni ishga tushiradi.
  8. Buyruqning natija kodini $? o'zgaruvchisiga saqlaydi.

Wildcard kengayishini oddiy misolda ko'ramiz:

mkdir -p ~/lab/shell
touch ~/lab/shell/a.conf ~/lab/shell/b.conf
echo ~/lab/shell/*.conf

Kutiladigan natija:

/home/<username>/lab/shell/a.conf /home/<username>/lab/shell/b.conf

Siz echo buyrug'iga faqat ~/lab/shell/*.conf deb yozdingiz. Lekin echo dasturi *.conf matnini olmadi.

Avval Bash shu andozaga mos fayllarni topdi:

a.conf
b.conf

Keyin Bash echo buyrug'ini taxminan quyidagi ko'rinishda bajardi:

echo ~/lab/shell/a.conf ~/lab/shell/b.conf

Demak, wildcard kengayishini echo emas, Bash bajardi.

Agar andozaga mos fayl topilmasa, Bash odatda andozani o'z holicha qoldiradi. Masalan:

echo *.not-found

Mos fayl bo'lmasa, natija quyidagicha chiqishi mumkin:

*.not-found

Bu xatti-harakat nullglob kabi Bash sozlamalariga bog'liq. Shu sababli skript yozayotganda wildcard har doim kamida bitta fayl topadi, deb hisoblash xavfli.

IFS va so'zlarga ajratish

Bash ayrim qiymatlarni alohida so'zlarga ajratishda IFS nomli o'zgaruvchidan foydalanadi.

IFSInternal Field Separator, ya’ni ichki maydon ajratgichi degani.

Standart holatda IFS quyidagi belgilarni ajratuvchi sifatida ishlatadi:

  • bo'shliq;
  • tabulyatsiya;
  • yangi qator.

Masalan, o'zgaruvchida bo'shliq bo'lsa va u qo'shtirnoqsiz ishlatilsa, Bash uni bir nechta argumentga ajratishi mumkin.

Ba’zan ma’lumot boshqa belgi bilan ajratilgan bo'ladi. Masalan:

admin:1001:/home/admin

Bu qatorda qiymatlar : belgisi bilan ajratilgan. Uni qismlarga bo'lish uchun IFS qiymatini vaqtincha : qilib belgilash mumkin:

line='admin:1001:/home/admin'
IFS=':' read -r username uid home <<< "$line"
printf 'user=%s uid=%s home=%s\n' "$username" "$uid" "$home"

Natija:

user=admin uid=1001 home=/home/admin

Bu yerda:

  • username o'zgaruvchisiga admin;
  • uid o'zgaruvchisiga 1001;
  • home o'zgaruvchisiga /home/admin yozildi.

IFS qiymatini butun shell uchun o'zgartirib qo'yish ehtiyotkorlikni talab qiladi. Aks holda, keyingi buyruqlardagi matnlarning qanday ajratilishiga ham ta’sir qilishi mumkin.

Yuqoridagi misolda IFS=':' faqat read buyrug'i uchun qo'llanmoqda. Bu xavfsizroq usuldir.

Qo'shtirnoqlar argumentlarni o'zgartiradi

Quyidagi o'zgaruvchining qiymatida bo'shliq mavjud:

project='demo api'

Endi uni qo'shtirnoq bilan va qo'shtirnoqsiz ishlatamiz:

printf '<%s>\n' "$project"
printf '<%s>\n' $project

Natija:

<demo api>
<demo>
<api>

Birinchi buyruqda:

"$project"

qiymat bitta argument sifatida uzatildi. Shuning uchun demo api bir qatorda chiqdi.

Ikkinchi buyruqda:

$project

qiymat qo'shtirnoqsiz yozildi. Bash bo'shliq bo'yicha uni ikkita argumentga ajratdi:

demo
api

Shuning uchun o'zgaruvchi qiymatini buyruqqa uzatishda odatda quyidagi shakl xavfsiz hisoblanadi:

"$variable"

Bir tirnoq va qo'shtirnoq farqi

Bir tirnoq va qo'shtirnoq Bashda bir xil vazifani bajarmaydi:

name='admin'
echo "$name"
echo '$name'

Natija:

admin
$name

Qo'shtirnoq ichida:

"$name"

Bash o'zgaruvchini qiymatiga almashtiradi.

Bir tirnoq ichida:

'$name'

Bash matnni o'zgartirmaydi. U $name yozuvini aynan o'z holicha chiqaradi.

Soddalashtirib aytganda:

  • "..." ichida o'zgaruvchilar ishlaydi;
  • '...' ichidagi matn o'zgarmaydi.

Buyruq almashtirishi

Bir buyruq chiqargan natijani o'zgaruvchiga yozish uchun $(...) ishlatiladi:

kernel_release=$(uname -r)
echo "kernel=$kernel_release"

Avval quyidagi buyruq bajariladi:

uname -r

U Linux yadrosi versiyasini chiqaradi. Bash ushbu natijani kernel_release o'zgaruvchisiga yozadi.

Masalan, o'zgaruvchining qiymati quyidagicha bo'lishi mumkin:

6.8.0-40-generic

Keyin:

echo "kernel=$kernel_release"

taxminan quyidagi natijani chiqaradi:

kernel=6.8.0-40-generic

Buyruq natijasini eval orqali qayta bajarmang. Ayniqsa, qiymat foydalanuvchi, tarmoq, fayl yoki boshqa ishonchsiz manbadan kelgan bo'lsa, bu xavfsizlik muammosiga olib kelishi mumkin.

eval nima uchun xavfli?

eval berilgan matnni oddiy ma’lumot sifatida emas, yangi Bash buyrug'i sifatida qayta o'qiydi va bajaradi.

Masalan:

filename='report.txt; echo INJECTED'
eval "cat $filename"

filename o'zgaruvchisida quyidagi matn mavjud:

report.txt; echo INJECTED

eval uni qayta tahlil qilgach, Bash quyidagi ikkita buyruqni ko'radi:

cat report.txt
echo INJECTED

Natijada:

cat: report.txt: No such file or directory
INJECTED

echo INJECTED alohida buyruq sifatida bajarildi.

Bu yerda oddiy ma’lumot Bash kodiga aylandi. Agar qiymatni hujumchi boshqarsa, u o'z buyrug'ini kiritishi mumkin.

Endi xuddi shu qiymatni eval ishlatmasdan tekshiramiz:

filename='report.txt; echo INJECTED'
cat $filename

Natija:

cat: report.txt;: No such file or directory
cat: echo: No such file or directory
cat: INJECTED: No such file or directory

Bu safar Bash echo INJECTED ni yangi buyruq sifatida bajarmadi. cat shunchaki uchta fayl nomini ochishga urindi:

report.txt;
echo
INJECTED

Fayllar mavjud bo'lmagani uchun xatolik chiqdi, lekin yangi buyruq ishga tushmadi.

Demak, xavfning asosiy sababi — eval ma’lumotni qayta Bash kodi sifatida talqin qilishidir.

Foydalanuvchi, tarmoq so'rovi, tashqi fayl yoki ishonchsiz konfiguratsiyadan kelgan qiymatlarni eval bilan ishlatmang.

Interaktiv, login va nointeraktiv shell’lar

Bash har doim bir xil usulda ishga tushmaydi. Uning qanday ishlashi qaysi turdagi shell sifatida ochilganiga bog'liq.

Interaktiv shell

Interaktiv shell foydalanuvchi bilan to'g'ridan-to'g'ri ishlaydi:

  • prompt ko'rsatadi;
  • klaviaturadan buyruq qabul qiladi;
  • natijani terminalga chiqaradi.

Masalan, SSH orqali serverga kirib, buyruqlar yozayotganingizda odatda interaktiv shell ishlaydi.

Login shell

Login shell foydalanuvchi tizimga kirganida sessiyani boshlaydigan shell hisoblanadi.

U ishga tushganda login uchun mo'ljallangan sozlama fayllarini o'qiydi.

SSH orqali serverga odatiy kirishda Bash ko'pincha login shell sifatida ishlaydi.

Nointeraktiv shell

Nointeraktiv shell foydalanuvchidan buyruq kutmaydi va odatda prompt ko'rsatmaydi.

U quyidagi holatlarda ishlatiladi:

  • Bash skripti bajarilganda;
  • bash -c 'buyruq' ishlatilganda;
  • ayrim cron yoki avtomatlashtirilgan vazifalarda.

Shell interaktiv ekanini tekshirish uchun:

case $- in
    *i*) echo "interactive shell" ;;
    *) echo "non-interactive shell" ;;
esac

Bu yerda $- joriy shell bayroqlarini saqlaydi. Agar uning ichida i harfi bo'lsa, shell interaktiv hisoblanadi.

Shell login shell ekanini tekshirish uchun:

shopt -q login_shell && echo "login shell" || echo "not a login shell"

Debian va Ubuntu tizimlarida Bash o'qiydigan sozlama fayllari shell turiga qarab farq qiladi.

Interaktiv, ammo login bo'lmagan Bash odatda quyidagi fayllarni o'qiydi:

/etc/bash.bashrc
~/.bashrc

Interaktiv login Bash odatda avval:

/etc/profile

faylini o'qiydi. Keyin quyidagi fayllardan mavjud va o'qish mumkin bo'lgan birinchisini o'qiydi:

~/.bash_profile
~/.bash_login
~/.profile

Nointeraktiv Bash esa standart holatda ~/.bashrc faylini o'qimaydi.

Bu production muhitida juda muhim.

Masalan, terminalda ishlayotgan buyruq quyidagi muhitlarda boshqacha ishlashi mumkin:

  • SSH sessiyasida;
  • cron ichida;
  • systemd servisida;
  • Docker konteynerida;
  • Bash skriptida.

Buning sababi shundaki, bu muhitlarning har biri bir xil sozlama fayllarini o'qimasligi mumkin. Natijada terminalingizdagi aliaslar, PATH qiymati yoki boshqa muhit o'zgaruvchilari avtomatik ravishda mavjud bo'lmaydi.

Aliaslar va muhit o'zgaruvchilari maqolasida sozlamalarni turli jarayonlar uchun to'g'ri saqlash tushuntiriladi.

Chiqish holati

Har bir buyruq bajarilgandan keyin sonli natija kodi qaytaradi. Bu kod chiqish holati yoki exit status deb ataladi.

Shell va skriptlar shu kod orqali buyruq muvaffaqiyatli yoki xato bilan tugaganini biladi.

Misol:

ls -ld /etc
echo "status=$?"

ls -ld /path/that/does/not/exist
echo "status=$?"

Odatdagi natija:

drwxr-xr-x 160 root root 12288 Jul 29 12:00 /etc
status=0
ls: cannot access '/path/that/does/not/exist': No such file or directory
status=2

Birinchi ls buyrug'i mavjud /etc katalogini topdi. Shu sababli uning chiqish holati:

0

bo'ldi.

Ikkinchi ls buyrug'i mavjud bo'lmagan katalogni ochishga urindi. Shu sababli xatolik yuz berdi va chiqish holati:

2

bo'ldi.

Umumiy qoida:

  • 0 — buyruq muvaffaqiyatli bajarildi;
  • 0 dan boshqa qiymat — buyruq boshqa holat yoki xatolik bilan tugadi.

Noldan boshqa har bir kod aynan bir xil ma’noni anglatmaydi. Masalan, 1, 2 yoki 127 kodlarining ma’nosi buyruqqa qarab farq qilishi mumkin. Aniq ma’noni buyruqning qo'llanmasidan tekshirish kerak.

Oxirgi bajarilgan buyruqning chiqish holati $? ichida saqlanadi.

Muhim jihat: $? har bir yangi buyruqdan keyin yangilanadi.

Masalan:

ls -ld /etc
echo "status=$?"

Bu yerda $? ls buyrug'ining holatini ko'rsatadi.

Agar qiymatni keyinroq ishlatmoqchi bo'lsangiz, uni darhol boshqa o'zgaruvchiga saqlang:

ls -ld /etc
status=$?
echo "ls status=$status"

Bu usulda ls natija kodi status o'zgaruvchisida saqlanadi va keyingi buyruqlardan keyin ham yo'qolmaydi.

Amaliy vaziyat: ls nima uchun boshqacha ishladi?

Quyidagi vaziyatni tasavvur qiling:

  • birinchi serverda ls natijasi rangli chiqadi;
  • ll buyrug'i fayllarni batafsil ko'rsatadi;
  • ikkinchi serverda esa ls rangsiz chiqadi;
  • ll buyrug'i topilmaydi.

Bu farq ls dasturining turli versiyasi sababli bo'lishi shart emas. Ko'pincha sabab shell sozlamalari va aliaslarda bo'ladi.

Avval buyruq nomlari nimani anglatishini tekshiring:

type -a ll ls
alias ll 2>/dev/null

Masalan, birinchi serverda quyidagiga o'xshash aliaslar mavjud bo'lishi mumkin:

alias ls='ls --color=auto'
alias ll='ls -alF'

Bu holda:

ls

aslida quyidagicha bajariladi:

ls --color=auto

ll esa alohida dastur emas. U ls -alF uchun yaratilgan qisqa aliasdir.

Shell interaktiv ekanini ham tekshiring:

echo "shell=$SHELL bash=$BASH_VERSION flags=$-"

Agar shell interaktiv bo'lmasa, ~/.bashrc ichidagi aliaslar yuklanmagan bo'lishi mumkin.

Aliasni ishlatmasdan, tashqi ls dasturini ishga tushirish uchun:

command ls -lah ~/lab

command Bashga alias yoki funksiyani chetlab o'tib, ko'rsatilgan buyruqni bajarishni aytadi.

Xulosa: ikki serverdagi farq ko'pincha Linux yadrosi yoki fayl tizimidan kelib chiqmaydi. Farq shell sozlamalarida bo'ladi.

Masalan:

  • bir serverda ~/.bashrc ichida ll aliasi bor;
  • ikkinchi serverda esa bu alias yo'q;
  • yoki ~/.bashrc umuman o'qilmagan.

Keng tarqalgan xatolar

  • Terminal va shell’ni bir xil narsa deb o'ylash. Terminal buyruq kiritish va natijani ko'rsatish uchun oynadir. Bash esa buyruqlarni tushunadi va bajarishga tayyorlaydi.
  • $SHELL ayni vaqtda ishlayotgan shell’ni doim aniq ko'rsatadi deb o'ylash. Joriy jarayonni $BASH_VERSION va ps -p $$ bilan tekshirish ishonchliroq.
  • cd, alias, export va type alohida tashqi dastur deb o'ylash. Ular Bashning ichki buyruqlaridir.
  • Promptdagi # belgisiga qarab root huquqi bor deb xulosa qilish. Prompt o'zgartirilishi mumkin. Huquqlarni id yoki id -u bilan tekshiring.
  • O'zgaruvchini qo'shtirnoqsiz ishlatish. Bu bitta qiymatning bir nechta argumentga ajralishiga yoki wildcard kengayishiga olib kelishi mumkin.
  • ~/.bashrc ichidagi aliaslar cron, skript va systemd servisida ham avtomatik ishlaydi deb kutish. Nointeraktiv jarayonlar bu faylni ko'pincha o'qimaydi.

Mashqlar

  1. Quyidagi buyruqni bajaring:

    type -a cd pwd echo ls
    

    Natijada qaysi buyruq Bashning ichki buyrug'i, qaysi biri alias va qaysi biri tashqi dastur ekanini aniqlang.

  2. Bo'shliq qatnashgan va qatnashmagan fayllarni yarating:

    mkdir -p ~/lab/shell
    touch "~/lab/shell/demo one.txt"
    touch ~/lab/shell/demo-two.txt
    

    Keyin qo'shtirnoq bilan va qo'shtirnoqsiz yozish o'rtasidagi farqni printf '<%s>\n' yordamida tekshiring.

  3. Yangi Bash jarayonini ishga tushiring:

    bash
    

    Yangi shell ichida quyidagilarni tekshiring:

    echo "$$"
    echo "$PPID"
    pwd
    

    $$ joriy Bash jarayonining PID raqamini, $PPID esa uni ishga tushirgan ota jarayon PID raqamini ko'rsatadi.

    Ishni tugatgach:

    exit
    

    orqali oldingi shell’ga qayting.

  4. Yangi shell interaktiv va login shell ekanini tekshiring:

    case $- in
        *i*) echo "interactive shell" ;;
        *) echo "non-interactive shell" ;;
    esac
    
    shopt -q login_shell && echo "login shell" || echo "not a login shell"
    

Manbalar

  1. Bash qo'llanma sahifasi: https://man7.org/linux/man-pages/man1/bash.1.html
  2. GNU Bash Reference Manual:https://www.gnu.org/software/bash/manual/bash.html
  3. execve(2) Linux qo'llanma sahifasi: https://man7.org/linux/man-pages/man2/execve.2.html
  4. environ(7) Linux qo'llanma sahifasi: https://man7.org/linux/man-pages/man7/environ.7.html
  5. GNU Coreutils qo'llanmasi: https://www.gnu.org/software/coreutils/manual/coreutils.html