Aliaslar va muhit o'zgaruvchilari
Aliaslar terminalda yoziladigan buyruqlarni qisqartiradi. Muhit o'zgaruvchilari esa dasturlarga nomlangan qiymatlarni uzatadi. Ikkalasi ham shell bilan ishlashni qulaylashtiradi, lekin ular butunlay boshqacha ishlaydi. Aliasni buyruq ishga tushishidan oldin joriy interaktiv shell’ning o'zi almashtiradi. Muhit o'zgaruvchisi esa shell yangi dastur ishga tushirganda o'sha bola jarayonga meros bo'lib o'tadi.
Maqoladagi misollar Ubuntu Server LTS’dagi Bash uchun yozilgan. U Buyruq sintaksisi va yordam hujjatlari maqolasining davomi, ayniqsa qo'shtirnoqlar, type va PATH mavzulariga tayanadi.
Alias, shell o'zgaruvchisi va muhit o'zgaruvchisi
| Tushuncha | Kim ishlatadi | Bola jarayonlarga o'tadimi? | Misol |
|---|---|---|---|
| Alias | Joriy interaktiv Bash buyruq qatori | Yo'q | alias ll='ls -lah' |
| Shell o'zgaruvchisi | Joriy shell | Faqat export qilinsa | project='demo api' |
| Muhit o'zgaruvchisi | Shell va uning bola jarayonlari | Ha | export EDITOR='nano' |
Export qilingan o'zgaruvchi ota shell’da baribir oddiy shell o'zgaruvchisi bo'lib qoladi. Farqi shundaki, Bash uni keyin ishga tushadigan bola jarayonlar muhitiga nusxalanadigan qilib belgilab qo'yadi. Bola jarayon qiymatning nusxasini oladi. Ishga tushib bo'lgach, u ota shell’ning muhitini o'zgartira olmaydi.
Aliaslar bilan ishlash
Mavjud aliaslarni ko'rish:
Ubuntu’ning standart interaktiv Bash sozlamalarida ll aliasi bo'lishi mumkin, minimal o'rnatilgan serverda esa bo'lmasligi mumkin.
Alias yaratish:
Kutiladigan natija:
= belgisining ikki tomonida bo'sh joy bo'lmasligi kerak. Shell alias qiymatini yaratish paytida bitta qiymat sifatida saqlashi uchun uni qo'shtirnoqqa oling.
Alias to'laqonli parametrlar tizimi emas. U buyruqning doim bir xil boshlanadigan qismini qisqartirish uchun yaxshi ishlaydi:
Lekin argumentni buyruqning o'rtasiga qo'yish kerak bo'lsa, alias to'g'ri vosita emas. Buning uchun funksiyadan foydalaning:
Bu misol laboratoriya uchun qulay. Production’da ishlatiladigan funksiya esa argument berilmagan holatni va xatolarni alohida tekshirishi kerak.
Aliasni chetlab o'tish yoki o'chirish
Bitta nom nimalarni anglatishi mumkinligini to'liq ko'rish:
Aliasni chetlab o'tish:
command ls aliaslar bilan birga shell funksiyalarini ham chetlab o'tadi va buyruqni odatdagidek ichki buyruqlar yoki PATH orqali qidiradi. So'z boshidagi teskari chiziq (\) esa faqat shu so'z uchun alias almashtirilishining oldini oladi.
Bitta aliasni o'chirish:
Joriy shell’dagi barcha aliaslarni ataylab tozalamoqchi bo'lmasangiz, unalias -a ni ishlatmang.
Shell o'zgaruvchilari
Shell o'zgaruvchisini yaratish:
Natija:
Qiymat berish sintaksisi qat’iy:
Bu qiymat berish. Lekin quyidagisi:
project nomli buyruq sifatida tushuniladi, = va demo esa uning argumentlari bo'lib qoladi.
O'zgaruvchi nomlarida katta-kichik harf farqlanadi. Odatda muhitga uzatiladigan o'zgaruvchilar katta harflar bilan, skript ichidagi mahalliy shell o'zgaruvchilari esa ko'pincha kichik harflar bilan yoziladi.
Muhitga export qilish
Export qilinmagan shell o'zgaruvchisi bola jarayonga o'tmaydi:
Natija:
Uni export qiling:
Natija:
Yaratish va export qilishni bitta qadamda bajarish:
O'zgaruvchilarni tekshirish:
Bu buyruqlar biroz boshqa-boshqa savollarga javob beradi:
printenv EDITORqiymatni jarayon muhitidan olib chiqaradi.echo "$EDITOR"Bash shell o'zgaruvchisini almashtirgandan keyingi qiymatni chiqaradi.declare -p EDITORfaqat Bash’da bor va o'zgaruvchining atributlarini, jumladan u export qilingan-qilinmaganini ko'rsatadi.
O'zgaruvchini joriy shell’dan o'chirish:
Bu buyruq allaqachon ishga tushib bo'lgan jarayonlarga ta’sir qilmaydi.
Muhitning meros bo'lib o'tishi
Yangi dastur ishga tushganda muhit ota jarayondan bola jarayonga nusxalanadi:
Bash with APP_MODE=staging exported
-> python app.py receives APP_MODE=staging
-> bash receives APP_MODE=staging
-> env prints that child's environment
Bola jarayon o'z nusxasini o'zgartirishi mumkin, lekin bu ota jarayonga ta’sir qilmaydi:
export APP_MODE='staging'
bash -c 'APP_MODE=testing; echo "child=$APP_MODE"'
echo "parent=$APP_MODE"
Natija:
O'zgaruvchini faqat bitta buyruq uchun berish:
Bu LC_ALL ni faqat shu sort jarayoni va uning bola jarayonlari uchun o'rnatadi. Buyruq tugagach, joriy shell’da bu qiymat bo'lmaydi.
Ko'p uchraydigan muhit o'zgaruvchilari
Ulardan bir nechtasini ko'rib chiqing:
Muhim o'zgaruvchilar:
HOME: foydalanuvchining uy katalogi.USERyokiLOGNAME: tizimga kirgan foydalanuvchi nomi (qaysi biri ishlatilishi dasturga bog'liq).SHELL: foydalanuvchi uchun sozlangan login shell. U hozir ishlab turgan shell’ni aniq ko'rsatmaydi.PATH: buyruqlar qidiriladigan kataloglar ro'yxati.LANGvaLC_*: til, saralash va formatlash uchun locale sozlamalari.TZ: ba’zi dasturlar o'z jarayoni uchun ishlatadigan vaqt zonasi.EDITORvaVISUAL: bu o'zgaruvchilarni hisobga oladigan dasturlar uchun afzal ko'rilgan matn muharriri.
Hozir ishlab turgan shell’ni alohida tekshiring:
EDITOR va VISUAL
Ba’zi vositalar muharrirni VISUAL yoki EDITOR qiymatiga qarab ochadi:
Hamma dasturlar ham bu o'zgaruvchilarni hisobga olavermaydi. Buni dasturning qo'llanma sahifasidagi ENVIRONMENT bo'limidan tekshiring.
TZ, LANG va takrorlanadigan natija
Vaqt natijalarini solishtiring:
Birinchi buyruq UTC vaqtini faqat o'sha jarayon uchun ishlatadi. Tizimning vaqt zonasi o'zgarmaydi.
Locale saralash tartibini va xabarlar tilini o'zgartirishi mumkin. Shu sabab baytma-bayt va har safar bir xil natija beradigan saralash kerak bo'lgan skriptlarda ko'pincha quyidagicha yoziladi:
PATH: buyruqlarni qidirish yo'li
PATH ni chiqarish:
Bu ikki nuqta (:) bilan ajratilgan kataloglar ro'yxati. Buyruq nomida / bo'lmasa, Bash bajariladigan faylni shu kataloglardan chapdan o'ngga qarab qidiradi.
Qaysi dastur ishga tushishini aniqlash:
Mavjud yo'lni yo'qotmasdan shaxsiy bin katalogini qo'shish:
Tekshirish:
Warning
export PATH="$HOME/.local/bin" deb yozib, PATH ni bilmasdan almashtirib yubormang. Bunda tizim kataloglari ro'yxatdan chiqib ketadi va oddiy buyruqlar ham ishlamay qolishi mumkin. PATH ga . ni yoki hamma yoza oladigan kataloglarni qo'shmang, ayniqsa root uchun.
Agar Bash buyruqlar joylashuvini eslab qolgan bo'lsa va siz PATH ni o'zgartirgan bo'lsangiz, bu xotirani (hash jadvalini) tozalang:
Sozlamalarni doimiy saqlash
Terminalda yozilgan aliaslar va o'zgaruvchilar shell yopilishi bilan yo'qoladi. Ularni saqlab qolish uchun to'g'ri ishga tushish (startup) fayliga yozing.
Debian va Ubuntu’dagi Bash uchun:
- Interaktiv, lekin login bo'lmagan shell’lar odatda
/etc/bash.bashrcva~/.bashrcni o'qiydi. - Interaktiv login shell’lar avval
/etc/profileni, keyin~/.bash_profile,~/.bash_loginva~/.profiledan birinchi o'qish mumkin bo'lganini o'qiydi. - Ubuntu’ning standart
~/.profilefayli Bash uchun~/.bashrcni chaqirishi mumkin, lekin buni taxmin qilmasdan, faylning o'zini tekshiring. - Nointeraktiv shell’lar, cron vazifalari va
systemdxizmatlari o'z-o'zidan sizning terminalingiz kabi ishlamaydi.
~/.bashrc ga aliasni xavfsiz qo'shish:
Quyidagi qatorni boshqa aliaslar yoniga qo'shing:
bash -n faylni bajarmasdan, faqat sintaksisini tekshiradi. Yangi shell’da sinab ko'ring:
O'zgargan faylni joriy shell’ga quyidagicha yuklashingiz mumkin:
Faqat o'zingiz ishongan fayllarni shu tarzda yuklang (source qiling). Bunda fayldagi shell kodi joriy shell’ingiz ichida bajariladi.
Xizmatlar ishlatadigan muhit o'zgaruvchilari uchun ~/.bashrc ga tayanmang. Buning uchun xizmat menejerining o'z usulidan foydalaning, masalan systemd unit faylidagi Environment= qatori yoki EnvironmentFile=. Bu mavzu keyingi darslarda ko'rib chiqiladi.
Xavfsizlik va production bo'yicha eslatmalar
- Muhit o'zgaruvchilarini jarayonning o'zi, ko'pincha esa shu foydalanuvchi yoki root ishga tushirgan diagnostika vositalari ham ko'ra oladi. Ularni maxfiy ma’lumotlar ombori deb hisoblamang.
LD_PRELOAD,LD_LIBRARY_PATH,PYTHONPATHva shunga o'xshash o'zgaruvchilar bilan ehtiyot bo'ling. Ular dastur qaysi kodni yuklashini o'zgartirib yuborishi mumkin.sudoodatda siyosatga ko'ra muhit o'zgaruvchilarini tozalaydi yoki filtrlaydi. Huquqni oshirganingizda shell muhitingiz o'zgarmasdan saqlanib qoladi deb o'ylamang.- Umumiy serverlarda aliaslarni kam va oddiy saqlang. Ish uslubingiz ko'plab shaxsiy aliaslarga bog'liq bo'lsa, toza tizimda xato qilib qo'yishingiz mumkin.
- Skriptlarda buyruqlarni to'liq yozing. Aliaslar asosan terminalda qo'lda ishlash uchun.
LD_PRELOAD nima uchun muhim?
LD_PRELOAD — Bash emas, dinamik bog'lovchi (dynamic linker) o'qiydigan muhit o'zgaruvchisi. Dinamik bog'langan dastur ishga tushganda bog'lovchi LD_PRELOAD da ko'rsatilgan har bir umumiy kutubxonani (shared library) dasturning odatdagi kutubxonalaridan oldin yuklaydi. Natijada shu kutubxonadagi funksiyalar dastur odatda chaqiradigan bir xil nomli funksiyalardan ustun bo'ladi. Bu qonuniy diagnostika usuli: profilerlar va libasan kabi xotira tekshiruvchilari tekshirilayotgan dasturni qayta kompilyatsiya qilmasdan unga shu yo'l bilan ulanadi.
Aynan shu mexanizm uni production uchun xavfli qiladi. LD_PRELOAD orqali ulangan zararli yoki buzilgan kutubxona libc’ning keng tarqalgan funksiyalarini — read, open, getuid, parol tekshiruvida ishlatiladigan funksiyalarni — almashtirib qo'yishi mumkin. Shunda dastur nimani ko'rishi yoki nima qilishi o'zgaradi, dasturning o'zi esa buni sezmaydi:
printf '%s\n' 'int getuid(void) { return 0; }' > /tmp/fake.c
gcc -shared -fPIC -o /tmp/fake.so /tmp/fake.c
LD_PRELOAD=/tmp/fake.so id -u
id -u odatda foydalanuvchining haqiqiy raqamli ID sini ko'rsatadi. Bu yerda esa root bo'lmagan foydalanuvchi uchun 0 chiqdi, chunki LD_PRELOAD dastur kim ishga tushirganini aniqlash uchun tayanadigan getuid chaqiruvini almashtirib qo'ydi. Hech qanday fayl ruxsati chetlab o'tilmadi va hech qanday ekspluatatsiya kerak bo'lmadi: dastur ishga tushishidan oldinroq uning libc chaqiruvlari jimgina boshqa joyga yo'naltirildi. Shu sababli sudo va huquqlarni hisobga oladigan boshqa vositalar biror narsani bajarishdan oldin LD_PRELOAD va shunga o'xshash o'zgaruvchilarni muhitdan olib tashlaydi. Meros bo'lib kelgan LD_PRELOAD yuqori huquq bilan birlashsa, diagnostika imkoniyati imtiyozli jarayonning tizimni qanday ko'rishini egallab olish vositasiga aylanadi. Yuqori huquq bilan ishlaydigan hech narsa uchun LD_PRELOAD yoki LD_LIBRARY_PATH ni o'rnatmang va ularni ishonchsiz muhitdan qabul qilmang. Xizmat muhitida sababi noma’lum LD_PRELOAD topilsa, uni g'alati sozlama deb emas, tekshirilishi kerak bo'lgan xavfsizlik hodisasi deb qabul qiling.
Amaliy vaziyat: skript terminalda ishlaydi, cron’da esa ishlamaydi
Muammo: texnik xizmat skripti SSH orqali qo'lda ishga tushirilganda muammosiz ishlaydi, lekin xuddi shu skript cron orqali rejalashtirilganda xato beradi yoki boshqacha ishlaydi.
Taxmin qilish o'rniga cron muhitini qayta hosil qilib ko'ring:
Cron bu qatorni /bin/sh orqali (bu sizning login Bash ingiz bo'lishi shart emas) interaktiv bo'lmagan va login bo'lmagan shell’da bajaradi. Shell va Bash qanday ishlaydi maqolasida aytilganidek, bunday shell ~/.bashrc ni o'qimaydi. Farqni ikkala muhitni faylga yozib, solishtirish orqali tasdiqlang:
O'z muhitini faylga yozadigan bir martalik cron vazifasini qo'shing, u ishga tushishini kuting, so'ng solishtiring:
* * * * * /usr/bin/env > /home/admin/env-cron.txt
diff /home/admin/env-interactive.txt /home/admin/env-cron.txt
Odatda natijada cron’dagi PATH ancha qisqa ekani ko'rinadi. Skriptingiz bilinmay tayangan aliaslar yoki ~/.bashrc da export qilingan o'zgaruvchilar esa umuman yo'q bo'ladi:
< PATH=/home/admin/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
---
> PATH=/usr/bin:/bin
< APP_MODE=staging
Xulosa: bu muammoni ~/.bashrc dagi sozlamalarni cron’ga ko'chirish bilan hal qilmang. Skriptning o'zini tuzating: u ishlatadigan har bir buyruq va fayl uchun to'liq yo'lni yozing, kerakli o'zgaruvchilarni skript boshida yoki crontab’ning o'zidagi muhit qatorlarida (jadval qatoridan yuqorida PATH=... va VAR=value) aniq belgilang. Cron vazifasidagi shell sizning terminalingiz o'qiydigan fayllarni o'qiydi deb hisoblamang. Solishtirib bo'lgach, bir martalik tekshiruv qatorini crontab’dan olib tashlang.
Amaliy vaziyat: qulay va xavfsiz ro'yxat buyrug'i
Muammo: o'z terminalingizda qulay ll buyrug'i bo'lishini xohlaysiz, lekin skriptlar yoki boshqa foydalanuvchilar unga bog'lanib qolishini istamaysiz.
Uni joriy shell uchun yarating:
Zaxira nusxa olib, uni ~/.bashrc ga doimiy yozing:
Yangi, toza interaktiv Bash oching:
Xulosa: alias faqat terminalda ishlash uchun qulaylik. Boshqa serverlar uchun hujjat, skript yoki runbook yozayotganda buyruqni to'liq yozing:
Keng tarqalgan xatolar
- Qiymat berishda
=atrofiga bo'sh joy qo'yish. - Aliaslar skriptlarda ham ishlaydi deb kutish.
- Bo'sh joyi bor qiymatlarni qo'shtirnoqqa olmaslik.
$SHELLni hozirgi jarayon qaysi shell ekanining isboti deb hisoblash.PATHga qo'shish o'rniga uni butunlay qayta yozib yuborish.- Oqibatlarini tushunmasdan maxfiy ma’lumotlarni muhit o'zgaruvchilarida saqlash.
~/.bashrcni zaxira nusxasiz va sintaksis tekshiruvisiz tahrirlash.
Mashqlar
lh='ls -lh'aliasini yarating, unitypebilan tekshiring, so'ngunaliasbilan o'chiring.- Qiymatida bo'sh joy bor shell o'zgaruvchisini yarating. Uni export qilmaguningizcha bola Bash jarayoni ko'ra olmasligini isbotlang.
dateni vaqtinchaTZ=UTCbilan ishga tushiring, so'ng ota shell’dagiTZo'zgarmaganini isbotlang.- Joriy shell’da
$HOME/.local/binniPATHga qo'shing va aslPATHni yo'qotmasdan, uning ro'yxatdagi o'rnini tekshiring.
Mashqni bajardim deyish uchun: biror sozlama faqat joriy buyruq qatoriga, joriy shell’ga, bola jarayonlarga yoki keyingi login sessiyalarga ta’sir qilishini tushuntirib bera olishingiz kerak.
Manbalar
- Bash qo'llanma sahifasi: https://man7.org/linux/man-pages/man1/bash.1.html
- GNU Bash Reference Manual: https://www.gnu.org/software/bash/manual/bash.html
environ(7)Linux qo'llanma sahifasi: https://man7.org/linux/man-pages/man7/environ.7.htmlexecve(2)Linux qo'llanma sahifasi: https://man7.org/linux/man-pages/man2/execve.2.html- GNU Coreutils
printenv: https://www.gnu.org/software/coreutils/manual/html_node/printenv-invocation.html ld.so(8)Linux qo'llanma sahifasi (LD_PRELOAD,LD_LIBRARY_PATH): https://man7.org/linux/man-pages/man8/ld.so.8.htmlcrontab(5)Linux qo'llanma sahifasi: https://man7.org/linux/man-pages/man5/crontab.5.html