IlmHamroh
JavaScript Full-stack/1-qism. Kompyuter, fayllar va terminal15/40-dars15 daqiqa
Mundarija (31)

Qator oxiri (CRLF/LF), inode va symlink

Qisqacha: Enter bosilganda faylga ko'rinmas belgi yoziladi. Windows ikkita belgi yozadi — CRLF (\r\n), Linux va macOS esa bitta — LF (\n). Windows'da yozilgan skript Linux serverda shu sababli ^M xatosi bilan to'xtaydi. Diskda fayl nomi faqat yorliq: faylning o'zi inode deb ataluvchi yozuvda saqlanadi. Hard link bitta faylga ikkinchi nom beradi, symlink esa boshqa faylning manzilini ko'rsatib turadi.

Bu darsda

  • Enter bosilganda faylga aynan qaysi baytlar yozilishini ko'rasiz.
  • /bin/bash^M: bad interpreter xatosini o'qiy olasiz va tuzata olasiz.
  • .gitattributes fayli qator oxiri muammosini butun jamoa uchun qanday hal qilishini tushunasiz.
  • Fayl deskriptori va inode nima ekanini oddiy so'zlar bilan tushuntira olasiz.
  • Hard link bilan symlink farqini aytib, qaysi biri qachon kerakligini bilasiz.

Oldin bilishingiz kerak: Matn kodlash: ASCII, Unicode va UTF-8, Fayl tizimi: papkalar daraxti va fayllar, Fayl ruxsatlari va foydalanuvchilar.

1. Nega bu kerak?

Jasur Windows noutbukida kichik skript yozdi. Skript — kompyuter ketma-ket bajaradigan buyruqlar yozilgan oddiy matn fayli. U skriptni Linux serverga yukladi va ishga tushirdi. Javob o'rniga shu chiqdi:

text
bash: ./skript.sh: /bin/bash^M: bad interpreter: No such file or directory

Jasur faylni ochib qaraydi — hamma narsa joyida. ^M degan belgini u yozmagan. Unda bu belgi qayerdan keldi?

Javob faylning ko'rinmas qismida. Har bir matn faylida ekranda ko'rinmaydigan belgilar bor. Windows va Linux ularni turlicha yozadi. Bu darsda ana shu ko'rinmas qismni ochamiz. Keyin fayl nomi, faylning o'zi va unga "havola" qanday bog'langanini ko'ramiz.

2. Enter bosilganda faylga nima yoziladi?

2.1 Ikki ko'rinmas belgi

Matn kodlash darsida har bir harf son bilan saqlanishini ko'rgan edik: A — 65, a — 97. Enter tugmasi ham xuddi shunday son yozadi. Faqat bu belgi ekranda harf bo'lib ko'rinmaydi — u "yangi qatorga o't" degan buyruq.

Bu belgilar yozuv mashinkasi davridan qolgan. Mashinkada qator tugaganda ikki ish qilinardi:

Belgi Kodi Inglizcha nomi Mashinkada nima qilardi
\r 13 Carriage Return (CR) Yozuv boshini qatorning chap chetiga qaytarardi
\n 10 Line Feed (LF) Qog'ozni bir qator yuqoriga surardi

\r va \n — ko'rinmas belgini matnda yozib ko'rsatish usuli. Teskari chiziq (\) "keyingi harf oddiy harf emas" degani. Faylning ichida \ va r degan ikki harf emas, bitta bayt — 13 soni turadi.

2.2 Uch tizim — uch xil odat

Kompyuterlar paydo bo'lganda har bir tizim o'z qarorini qabul qilgan:

Tizim Qator oxiri Baytlar Hajmi
Windows CRLF \r\n (13, 10) 2 bayt
Linux, macOS LF \n (10) 1 bayt
Eski Mac (2001-yilgacha) CR \r (13) 1 bayt

Eski Mac usuli bugun deyarli uchramaydi. Hozirgi hayotda ikkitasi qoldi: CRLF va LF.

Aniq misol. Faylga salom, Enter, dunyo, Enter yozdik:

Qayerda yozildi Faylning ichi Hajmi
Linux yoki macOS salom\ndunyo\n 12 bayt
Windows salom\r\ndunyo\r\n 14 bayt

Ekranda ikkala fayl bir xil ko'rinadi. Lekin ichida farq bor: Windows faylida har qator oxirida ortiqcha \r turibdi.

Tekshirib ko'ring: Windows'da 3 qatorli fayl yozildi, har qator oxirida Enter bosilgan. Xuddi shu matn Linux'da yozilsa, fayl necha bayt kichik bo'ladi?

Javob

3 bayt kichik. Windows har Enter uchun 2 bayt (\r\n), Linux esa 1 bayt (\n) yozadi. Har qatorda 1 bayt farq, 3 qatorda — 3 bayt.

3. Farq qachon muammoga aylanadi?

3.1 Jasurning xatosi

Linux skriptlarining birinchi qatori odatda shunday bo'ladi:

bash
#!/bin/bash

Bu qator Linux'ga "bu faylni /bin/bash dasturi bajarsin" deydi. bash — buyruqlarni tushunib bajaradigan dastur, uni Terminal, shell va prompt darsida batafsil ko'ramiz.

Jasur skriptni Windows'da yozgan edi. Shuning uchun birinchi qator oxirida \r qolgan. Linux esa faqat \n ni qator oxiri deb biladi. U \r ni ham dastur nomining bir qismi deb o'qiydi va /bin/bash\r degan dasturni qidiradi. Bunday dastur yo'q — xato chiqadi.

Xato matnini bo'laklab tarjima qilamiz:

  • bad interpreter — "yomon bajaruvchi": ko'rsatilgan dasturni ishga tushirib bo'lmadi.
  • /bin/bash^M — qidirilgan nom. ^M — terminal \r ni shunday ko'rsatadi. M alifboda 13-harf, \r ning kodi ham 13.
  • No such file or directory — "bunday fayl yoki papka yo'q".

Demak, xato "bash topilmadi" demayapti. U "bash + ko'rinmas belgi" degan nom topilmadi, deyapti. Qoida: xatoda ^M ko'rsangiz — faylda Windows qator oxiri qolgan.

3.2 Xuddi shu sababli chiqadigan boshqa xatolar

Skriptni bash skript.sh deb ishga tushirsangiz, birinchi qator o'qilmaydi. Lekin \r boshqa joyda "otadi":

text
skript.sh: line 3: $'\r': command not found

Bu "\r degan buyruq topilmadi" degani: bo'sh qatorda faqat \r qolgan va Linux uni buyruq deb o'ylagan.

Yana bir holat — jamoada ishlash. Ali Windows'da, Malika macOS'da ishlaydi. Ali bitta so'zni tuzatib saqlasa, tahrirlovchi dastur butun faylni CRLF bilan qayta yozishi mumkin. Malika o'zgarishlar ro'yxatida bitta so'z emas, hamma qatorlar o'zgarganini ko'radi.

Maslahat: Windows'dagi Git Bash (Git dasturi bilan keladigan terminal) CRLF'li skriptni ko'pincha kechiradi va ishga tushiradi. Biz buni sinab ko'rdik. Shuning uchun xato o'z kompyuteringizda emas, serverda birinchi marta chiqadi.

Tekshirib ko'ring: Nega xato matnida ^M so'zi turibdi, ^R emas?

Javob

Terminal ko'rinmas belgilarni ^ va harf bilan ko'rsatadi. Harf belgining kodiga qarab tanlanadi: kodi 13 bo'lgan belgi alifbodagi 13-harf — M bilan yoziladi. \r ning kodi 13, shuning uchun ^M.

4. Qanday aniqlash va tuzatish mumkin?

4.1 Tahrirlovchida

VS Code (kod yozish dasturi, uni VS Code darsida o'rnatamiz) oynaning pastki o'ng burchagida CRLF yoki LF deb yozib turadi. Shu yozuvni bosing va LF ni tanlang, keyin faylni saqlang. Fayldagi barcha qator oxirlari \n ga aylanadi.

4.2 Terminalda

Terminal buyruqlarini keyingi darslarda o'rganamiz. Hozir faqat natijaga qarang — bu buyruqlarni biz Windows'dagi Git Bash'da ishga tushirdik:

bash
file skript.sh
text
skript.sh: Bourne-Again shell script, ASCII text executable,
with CRLF line terminators

file buyrug'i fayl turini aytadi. Oxiridagi with CRLF line terminators — "qator oxirlari CRLF". Tuzatish uchun dos2unix dasturi bor:

bash
dos2unix skript.sh
text
dos2unix: converting file skript.sh to Unix format...

Endi file skript.sh yana ishga tushirilsa, with CRLF qismi yo'qoladi. dos2unix Git Bash'da tayyor turadi. Ubuntu serverda esa uni avval o'rnatish kerak (sudo apt install dos2unix) — dastur o'rnatishni keyingi darsda o'rganamiz.

4.3 Git bilan — butun jamoa uchun

Har kim faylni qo'lda tuzatib yurishi ishonchsiz. Kimdir unutadi. Shuning uchun loyihaga bir marta qoida yoziladi.

Git — kodning har bir o'zgarishini saqlaydigan dastur. Uni Git qismida to'liq o'rganamiz, hozir bilish shart emas. Loyiha papkasida .gitattributes nomli fayl ochiladi va unga shunday yoziladi:

text
* text=auto eol=lf
*.bat text eol=crlf
*.png binary

Har qatorni o'qiymiz:

  • * text=auto eol=lf — hamma fayl (*): matn ekanini Git o'zi aniqlasin (text=auto), matn fayllarida qator oxiri LF bo'lsin (eol=lf).
  • *.bat text eol=crlf — .bat fayllar faqat Windows'da ishlaydi, ular uchun CRLF qoldiramiz.
  • *.png binary — rasm matn emas, uning ichidagi baytlarga tegmaslik kerak.

Windows'ga Git o'rnatilganda u o'zi ham qator oxirlarini almashtirib turadi (core.autocrlf sozlamasi). Lekin bu sozlama har kimning kompyuterida har xil bo'ladi. .gitattributes esa loyiha bilan birga yuradi va hammaga bir xil ishlaydi. Batafsil — .gitattributes darsida.

Tekshirib ko'ring: Nega *.png qatoriga binary yozildi? Unga ham eol=lf qo'llansa nima bo'lardi?

Javob

Rasm faylidagi baytlar tasodifan 13 va 10 bo'lishi mumkin, lekin ular qator oxiri emas — rasmning bir bo'lagi. Git ularni almashtirsa, rasm buziladi. binary Git'ga "bu faylning ichiga tegma" deydi.

5. Fayl deskriptori: ochiq faylning raqami

Endi fayllarning ikkinchi ko'rinmas tomoniga o'tamiz: dastur faylni qanday ushlab turadi?

Teatrdagi kiyim ilgichni eslang. Paltoingizni topshirasiz, sizga raqamli jeton berishadi. Keyin paltoni "qora palto, cho'ntagida kalit" deb emas, jeton raqami bilan qaytarib olasiz.

Operatsion tizim ham shunday ishlaydi. Dastur faylni ochganda tizim unga kichik butun son beradi. Bu son fayl deskriptori (file descriptor) deb ataladi. Dastur keyin faylni nomi bilan emas, shu raqam bilan o'qiydi va yozadi.

Har bir dastur (jarayon) ishga tushishi bilan uch raqam tayyor turadi:

Raqam Nomi Nima
0 stdin Kirish: odatda klaviatura
1 stdout Oddiy natija: odatda ekran
2 stderr Xato xabarlari: odatda ekran

Dastur yangi fayl ochsa, u keyingi bo'sh raqamni oladi: 3, 4 va keyingilari. Bu uch raqam bilan terminalda ajoyib ishlar qilinadi — Oqimlar, pipe va yo'naltirish darsida.

Maslahat: Tizim bitta dasturga cheksiz raqam bermaydi. Dastur fayllarni ochib, yopishni unutsa, raqamlar tugaydi va Too many open files ("ochiq fayllar juda ko'p") xatosi chiqadi. Bu xato serverlarda uchraydi — endi uning ma'nosini bilasiz.

Tekshirib ko'ring: Dastur ishga tushdi va birinchi marta bitta fayl ochdi. Tizim bu faylga qaysi raqamni beradi?

Javob

3. 0, 1 va 2 har bir dasturda oldindan band — ular kirish, natija va xatolar uchun. Birinchi ochilgan fayl keyingi bo'sh raqamni oladi.

6. Inode: faylning haqiqiy "pasporti"

6.1 Nom — faqat yorliq

Kutubxonani tasavvur qiling. Kitob javonda turadi. Kirishdagi katalogda esa kartochkalar: "Alpomish — 1234-javon". Kartochka kitobning o'zi emas, faqat kitobga yo'l ko'rsatadi.

Linux fayl tizimi ham shunday tuzilgan. Faylning barcha ma'lumoti maxsus yozuvda saqlanadi. Bu yozuv inode (inglizcha "index node" — ko'rsatkich yozuvi) deb ataladi. Har bir inode'ning o'z raqami bor.

Inode ichida:

  • fayl hajmi;
  • fayl diskning qaysi bo'laklarida yotgani;
  • egasi va ruxsatlari (rwx);
  • o'zgartirilgan vaqti;
  • shu faylga nechta nom bog'langani.

Qiziq tomoni: fayl nomi inode ichida yo'q. Nom papkada yoziladi. Papka aslida kichik ro'yxat: "hisobot.txt → 1234-inode", "rasm.png → 1235-inode".

6.2 Inode raqamini ko'rish

Terminalda ls -i buyrug'i fayl nomi yonida inode raqamini ko'rsatadi (ls ni Terminalda harakatlanish darsida o'rganamiz). Linux'da natija taxminan shunday:

text
1234 hisobot.txt
1235 rasm.png

Windows'ning NTFS fayl tizimida ham shunga o'xshash "fayl raqami" bor. Git Bash'da ls -i uni ko'rsatadi, faqat raqam juda uzun bo'ladi (masalan, 8444249302316789).

Tekshirib ko'ring: Faylning nomini o'zgartirsangiz, inode raqami o'zgaradimi?

Javob

O'zgarmaydi. Nom inode ichida emas, papkadagi ro'yxatda saqlanadi. Nomni o'zgartirish — faqat ro'yxatdagi yozuvni almashtirish. Faylning o'zi va uning inode'i joyida qoladi.

Inode'ni tushundingiz — endi "havolalar" qiyin emas. Ikki turi bor.

flowchart LR
  A["asl.txt (nom)"] --> I["Inode 1234"]
  B["ikkinchi.txt (hard link)"] --> I
  I --> D[("Diskdagi ma'lumot")]
  S["yorliq.txt (symlink)"] -. "yo'lni saqlaydi" .-> A

Hard link (qattiq havola) — mavjud inode'ga papkada yana bitta nom yozish. Kutubxona misolida: bitta kitobga ikkinchi kartochka ochish.

Linux'da (va Git Bash'da) hard link ln buyrug'i bilan yaratiladi:

bash
ln asl.txt ikkinchi.txt
ls -li asl.txt ikkinchi.txt

Windows'dagi Git Bash'da ishga tushirganimizda chiqqan natija (qisqartirilgan):

text
8444249302316789 -rw-r--r-- 2 ... asl.txt
8444249302316789 -rw-r--r-- 2 ... ikkinchi.txt

Ikkala nomning inode raqami bir xil. Ruxsatlardan keyingi 2 — "bu faylga 2 ta nom bog'langan".

Ikkala nom teng huquqli. Qaysi biri orqali o'zgartirsangiz ham, bitta fayl o'zgaradi. asl.txt ni o'chirsangiz, fayl yo'qolmaydi: ikkinchi.txt orqali ochilaveradi. Fayl diskdan faqat oxirgi nom o'chirilganda yo'qoladi.

Hard link'ning ikki cheklovi bor: papkaga qo'yib bo'lmaydi va boshqa diskdagi faylga qo'yib bo'lmaydi.

Symlink (symbolic link, ramziy havola) — ichida boshqa faylning yo'li yozilgan kichik fayl. Kutubxona misolida: "bu kitob 1234-javonda" degan qog'ozcha.

bash
ln -s asl.txt yorliq.txt
ls -l yorliq.txt

Linux'da natija oxirida strelka ko'rinadi:

text
lrwxrwxrwx 1 ... yorliq.txt -> asl.txt

Boshidagi l harfi — "link". -> asl.txt — symlink qaysi faylni ko'rsatayotgani.

Symlink boshqa diskka ham, papkaga ham ko'rsata oladi. Lekin u faqat yo'lni eslab qoladi. Asl fayl o'chirilsa yoki boshqa joyga ko'chirilsa, symlink "hech narsaga" ko'rsatib qoladi. Buni singan symlink (broken symlink) deyiladi.

7.3 Uchalasi yonma-yon

Hard link Symlink Windows yorlig'i (.lnk)
Nima saqlaydi Inode'ga nom Faylning yo'li Faylning yo'li
Asl fayl o'chirilsa Fayl yashayveradi Singan havola Singan yorliq
Papkaga Yo'q Ha Ha
Dasturlar tushunadimi Ha Ha Faqat Explorer

Windows'dagi ish stoli yorlig'i symlink'ga o'xshaydi, lekin u oddiy fayl. Uni faqat Explorer ochadi. Boshqa dasturlar esa symlink'ni oddiy fayl kabi ochaveradi.

Diqqat: Windows'da ikki nozik joy bor. Birinchisi: Git Bash'da ln -s sukut bo'yicha haqiqiy symlink emas, faylning nusxasini yaratadi — biz buni sinab ko'rdik. Ikkinchisi: Windows'da haqiqiy symlink yaratish uchun Administrator huquqi yoki "Developer Mode" (dasturchi rejimi) kerak. Linux va macOS'da bunday cheklov yo'q.

Tekshirib ko'ring: asl.txt fayliga bitta hard link (ikkinchi.txt) va bitta symlink (yorliq.txt) qo'yildi. Keyin asl.txt o'chirildi. Qaysi nom orqali matnni hali ham o'qish mumkin?

Javob

Faqat ikkinchi.txt orqali. U inode'ga to'g'ridan-to'g'ri bog'langan, inode esa hali bitta nom borligi uchun yashayapti. yorliq.txt esa asl.txt degan nomni qidiradi — u endi yo'q, shuning uchun symlink singan.

8. Ko'p uchraydigan xatolar

8.1 bad interpreter va $'\r': command not found

text
bash: ./skript.sh: /bin/bash^M: bad interpreter: No such file or directory

Sababi: skript Windows'da CRLF bilan saqlangan. Tuzatish: VS Code'da pastki o'ng burchakdagi CRLF ni LF ga almashtiring yoki dos2unix skript.sh ni ishga tushiring. Qayta takrorlanmasligi uchun loyihaga .gitattributes qo'shing.

text
cat: yorliq.txt: No such file or directory

"Bunday fayl yo'q" — lekin papkada yorliq.txt ko'rinib turibdi. Sababi: symlink singan, u ko'rsatayotgan asl fayl o'chirilgan yoki ko'chirilgan. Xato symlink'ning o'zi haqida emas, u ko'rsatayotgan manzil haqida. Tuzatish: ls -l yorliq.txt bilan strelkadan keyingi yo'lni tekshiring va asl faylni qaytaring yoki symlink'ni qayta yarating.

Malika ikkinchi.txt ni zaxira nusxa deb o'yladi va asl.txt ni bemalol tahrirladi. Keyin qarasa, "zaxira" ham o'zgarib qolgan. Sababi: hard link — nusxa emas, o'sha faylning ikkinchi nomi. Zaxira kerak bo'lsa, faylni nusxalash kerak (cp buyrug'i — Fayl va papkalar bilan ishlash darsida).

Siz ln -s qildingiz, asl faylni o'zgartirdingiz, lekin "havola" eski matnni ko'rsatyapti. Sababi: Git Bash sukut bo'yicha nusxa yaratgan. Haqiqiy symlink bilan ishlashni Linux'da yoki WSL2 ichida mashq qiling.

9. Mashqlar

1-mashq (oson): Baytlarni sanang

ha so'zi yozilib, Enter bosildi. Keyin yo'q yozilib, yana Enter bosildi. Fayl Linux'da necha bayt bo'ladi? Windows'da-chi? Ishora: ha va yo'q dagi har bir harf va apostrof — 1 baytdan (ular ASCII belgilar, Matn kodlash darsidan).

Linux'da: [:8] bayt. Windows'da: [:10] bayt.

Yechim

Harflar: ha — 2 bayt, yo'q — 4 bayt, jami 6 bayt. Linux har Enter uchun 1 bayt qo'shadi: 6 + 2 = 8 bayt. Windows har Enter uchun 2 bayt qo'shadi: 6 + 4 = 10 bayt.

2-mashq (o'rta): .gitattributes yozing

Loyihangizda uch xil fayl bor: deploy.sh (Linux serverda ishlaydigan skript), ishga-tushir.bat (faqat Windows'da ishlaydigan fayl) va logo.jpg (rasm). .gitattributes faylini yozing: skript LF bilan, .bat CRLF bilan saqlansin, rasmga tegilmasin. Ishora: "Git bilan — butun jamoa uchun" bo'limidagi uch qatorli namunaga qarang, faqat rasm kengaytmasini almashtiring.

Yechim
text
* text=auto eol=lf
*.bat text eol=crlf
*.jpg binary

Birinchi qator barcha matn fayllarini, jumladan deploy.sh ni LF qiladi. Ikkinchisi .bat uchun istisno. Uchinchisi .jpg rasmni "matn emas" deb belgilaydi, shuning uchun Git uning baytlariga tegmaydi.

3-mashq (qiyin): Nima qoladi?

Linux'da shu buyruqlar ketma-ket bajarildi:

bash
ln narxlar.txt narxlar-2.txt
ln -s narxlar.txt narxlar-yorliq.txt

Keyin narxlar.txt o'chirildi. So'ng yangi narxlar.txt yaratilib, ichiga yangi narxlar deb yozildi. Endi narxlar-2.txt va narxlar-yorliq.txt ochilsa, har birida qaysi matn chiqadi — eskisimi, yangisimi?

Yechim
  • narxlar-2.txt — eski matn. Bu hard link: u eski faylning inode'iga bog'langan. Eski narxlar.txt nomi o'chganda ham inode yashab qoldi.
  • narxlar-yorliq.txt — yangi matn. Symlink faqat narxlar.txt degan nomni eslaydi. Shu nom bilan yangi fayl paydo bo'ldi — symlink endi unga ko'rsatadi.

Bu mashq asosiy farqni ko'rsatadi: hard link faylning o'ziga, symlink esa nomiga bog'lanadi.

10. Real ishda

  • Deploy skriptlari. Windows'da ishlaydigan dasturchi serverga skript yuborishdan oldin qator oxirini tekshiradi. Deyarli har bir jiddiy loyihada .gitattributes bor.
  • Veb-server sozlamalari. Ubuntu serverlarda Nginx (saytni internetga beradigan dastur, keyinroq o'rganamiz) sozlamalari sites-enabled papkasida symlink sifatida yoqiladi. Symlink'ni o'chirsangiz, sayt o'chadi, lekin asl sozlama fayli joyida qoladi.
  • Dastur versiyalari. python3 yoki node buyrug'i ko'pincha aniq versiyaga ko'rsatadigan symlink bo'ladi. Versiyani almashtirish — symlink'ni boshqa faylga yo'naltirish.
  • Serverdagi xatolar. Too many open files va No space left on device (bo'sh inode tugashi ham shunday xato beradi) — tajribali dasturchi bu xabarlarni fayl deskriptori va inode bilan bog'laydi.
  • Intervyu. "Hard link va symlink farqi nima?" — Linux va backend intervyularida tez-tez beriladigan savol.

Xulosa

  • Qator oxiri — ko'rinmas belgi: Windows \r\n (CRLF), Linux va macOS \n (LF) yozadi.
  • Xatoda ^M ko'rsangiz — faylda \r qolgan. VS Code'da LF ni tanlang yoki dos2unix ishlating.
  • .gitattributes (* text=auto eol=lf) qator oxirini butun jamoa uchun bir xil qiladi.
  • Fayl deskriptori — dastur ochgan faylga tizim bergan raqam; 0, 1, 2 doim band.
  • Inode — faylning haqiqiy yozuvi; nom esa papkadagi yorliq.
  • Hard link — o'sha inode'ga ikkinchi nom; symlink — boshqa faylning yo'li yozilgan kichik fayl.

Keyingi dars: Dastur o'rnatish va paket menejerlari (OS darajasida) — dasturlarni saytma-sayt qidirmasdan, bitta buyruq bilan o'rnatishni o'rganamiz.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Qator oxiri (CRLF/LF), inode va symlink — IlmHamroh