Tarkibga o'tish

Hard va symbolic link’lar

Linux’da faylning nomi ma’lumotning o'zi emas. Katalog yozuvi nomni inode bilan bog'laydi, inode esa faylning metama’lumotlarini saqlaydi va uning ma’lumot bloklariga ishora qiladi. Nom va ma’lumot alohida bo'lgani uchun bitta inode bir nechta nomga ega bo'lishi yoki bitta nom butunlay boshqa joyga ishora qilishi mumkin. Birinchi holat hard link, ikkinchisi symbolic link (qisqacha symlink) deyiladi.

Bu mavzuni tushunish Disk va fayl tizimi asoslari maqolasida tanishtirilgan inode modeliga bog'liq. Yo'llar qanday aniqlanishini eslash kerak bo'lsa, shu modulning keyingi qismidagi Yo'llar va fayl turlari maqolasi buni chuqurroq yoritadi. Misollarda Ubuntu Server LTS’dagi GNU Coreutils’ning ln buyrug'i ishlatiladi. Quyida hard link va symbolic link o'rtasidagi ichki farqni ko'ramiz; ikkalasini ln, stat, readlink va find bilan yaratib, tekshiramiz; nisbiy symlink maqsadi aslida qayerdan boshlab aniqlanishini bilib olamiz; nom o'chirilgandan keyin ma’lumot qachon saqlanib qolishini tushunamiz. Oxirida buzilgan link, turli fayl tizimlari orasidagi holat va noto'g'ri reliz ko'rsatkichini tashxislaymiz, shuningdek link’lar zaxira nusxa olish va production’da versiya almashtirish paytida qanday xavf tug'dirishini baholaymiz.

Katalogdagi nom, inode va ma’lumot

Oddiy faylning soddalashtirilgan ko'rinishi:

name in a directory ──> inode ──> data blocks

Inode faylning turi, egasi, ruxsatlari, vaqt tamg'alari, havolalar soni va ma’lumot bloklariga ko'rsatkichlarni saqlaydi. Fayl nomi odatda inode ichida umuman saqlanmaydi — u katalog yozuvida turadi. Shuning uchun ikkita katalog yozuvi bitta inode’ga ishora qilishi mumkin.

report.txt ─┐
            ├──> inode 10542 ──> data
copy.txt ───┘

Bular ikkita hard link. Texnik jihatdan ulardan birini "asl", ikkinchisini "nusxa" deb bo'lmaydi: ikkalasi ham bitta faylning teng huquqli nomlari.

Hard link’lar

ln sukut bo'yicha hard link yaratadi:

ln <existing-file> <new-name>

Masalan:

printf 'version=1\n' > settings.conf
ln settings.conf settings.backup

Natijani tekshirish:

ls -li settings.conf settings.backup
stat -c 'inode=%i link=%h name=%n' settings.conf settings.backup

Namunaviy natija:

10542 -rw-r--r-- 2 user user 10 Jul 29 11:00 settings.backup
10542 -rw-r--r-- 2 user user 10 Jul 29 11:00 settings.conf
inode=10542 link=2 name=settings.conf
inode=10542 link=2 name=settings.backup

Ikkala nomning inode raqami bir xil, havolalar soni esa 2. Bir nom orqali mazmunni o'zgartirsangiz, bu ikkinchi nom orqali darhol ko'rinadi:

printf 'mode=production\n' >> settings.backup
tail -n 2 settings.conf

Bu nusxa emas. Diskda ikkita mustaqil ma’lumot bloklari to'plami yo'q.

Nom o'chirilganda nima bo'ladi?

rm odatda ma’lumot bloklarini to'g'ridan-to'g'ri "o'chirmaydi": u katalogdagi nomni inode’dan uzib qo'yadi. Inode’ning havolalar soni bittaga kamayadi. Oxirgi hard link o'chirilgach va faylni hech bir jarayon ochiq ushlab turmagan bo'lsa, kernel uning joyini qayta ishlatishi mumkin.

rm -- settings.conf
cat settings.backup
stat -c 'inode=%i link=%h name=%n' settings.backup

settings.backup ishlashda davom etadi, havolalar soni esa 1 ga tushadi. Ishlab turgan jarayon log faylni ochiq ushlab turgan bo'lsa, u o'chirilgandan keyin disk joyi darhol bo'shamasligi ham aynan shu xususiyat bilan tushuntiriladi. Bu holatni keyinroq lsof +L1 bilan tekshirishingiz mumkin.

Hard link’ning cheklovlari

Hard link:

  • faqat mavjud inode’ga yaratiladi;
  • fayl tizimi chegarasidan o'ta olmaydi;
  • odatda oddiy foydalanuvchi tomonidan katalogga ishora qiladigan qilib yaratilmaydi;
  • maqsadi ko'chirilganda "buzilmaydi", chunki u yo'l satriga emas, inode’ga bog'langan.

Turli fayl tizimlari o'rtasida hard link yaratishga urinish Invalid cross-device link xatosini (EXDEV) beradi. Ikki yo'l bitta diskda turgandek ko'rinsa ham, alohida mount qilingan fayl tizimlariga tegishli bo'lishi mumkin:

findmnt -T <existing-file>
findmnt -T <new-link-directory>

Agar ikkala natijadagi fayl tizimi yoki qurilma identifikatori farq qilsa, u yerda hard link yaratib bo'lmaydi — buning o'rniga symbolic link yoki haqiqiy nusxa kerak.

Symbolic link’lar

Symbolic link — o'z maqsadini matn satri sifatida saqlaydigan alohida fayl turi:

current ──> "releases/v2" ──> releases/v2

U ln -s bilan yaratiladi:

ln -s <target-path> <link-name>

Masalan:

ln -s settings.backup settings.current

Natijani tekshirish:

ls -li settings.current settings.backup
readlink settings.current
readlink -f settings.current
stat -c 'inode=%i type=%F name=%n' settings.current
stat -Lc 'inode=%i type=%F name=%n' settings.current

readlink link ichida saqlangan matnni aynan o'zicha chiqaradi; readlink -f esa to'liq aniqlangan kanonik yo'lni chiqaradi. GNU stat odatda link’ning o'zi haqida ma’lumot beradi, -L bilan esa uning maqsadi ortidan boradi. Natijadagi ikki inode raqami har xil bo'ladi.

Nisbiy maqsad qayerdan boshlab aniqlanadi?

Eng muhim qoida: symbolic link ichida saqlangan nisbiy yo'l terminalning joriy ish katalogiga nisbatan emas, link’ning o'zi turgan katalogga nisbatan aniqlanadi.

Quyidagi tuzilmani olaylik:

/srv/demo/
├── current -> releases/v2
└── releases/
    └── v2/
        └── app.conf

/srv/demo/current link’i releases/v2 satrini saqlaydi. Kernel uni /srv/demo ga nisbatan aniqlaydi va natijada /srv/demo/releases/v2 ga yetib boradi.

ln -s releases/v2 /srv/demo/current

Bu buyruqni qaysi katalogdan ishga tushirganingiz keyinchalik maqsad qanday aniqlanishiga ta’sir qilmaydi. Lekin link yaratish paytida yo'lni noto'g'ri yozib qo'yish oson. GNU ln maqsaddan link’ning o'z joyigacha bo'lgan to'g'ri nisbiy yo'lni avtomatik hisoblash uchun -r opsiyasini taklif qiladi:

ln -sr /srv/demo/releases/v2 /srv/demo/current

-r — GNU Coreutils kengaytmasi, u har qanday POSIX muhitida mavjud emas.

/srv/demo/releases/v2 kabi absolyut link tizimdagi qat’iy nuqtadan boshlanadi. Link turgan katalog ko'chirilsa ham, u o'sha joyga ishora qilishda davom etadi, lekin butun katalog daraxti boshqa ildiz, chroot, konteyner yoki serverga ko'chirilsa, buzilishi mumkin.

Nisbiy link birgalikda bitta butun sifatida ko'chiriladigan katalog daraxtlari uchun qulay. Lekin link’ning o'zi boshqa joyga ko'chirilsa, maqsadining ma’nosi o'zgaradi. Tanlovni sizda haqiqatan mavjud deploy tuzilmasiga qarab qiling.

Agar maqsad mavjud bo'lmasa, natija osilib qolgan (buzilgan) link bo'ladi. Uni yaratishga ruxsat beriladi:

ln -s does-not-exist broken
ls -l broken
readlink broken
realpath -e broken

ls va readlink link’ning o'zini ko'radi; realpath -e esa maqsadni aniqlab bo'lmagani uchun xato beradi. test -L link’ning o'zi mavjudligini, test -e esa uning maqsadi aniqlanishini tekshiradi:

test -L broken && printf 'the link exists\n'
test -e broken || printf 'but the target does not exist\n'
Xususiyat Hard link Symbolic link
Nimaga bog'lanadi Bitta fayl tizimidagi inode’ga Maqsad yo'lini saqlaydigan satrga
O'z inode’i bormi? Yo'q, maqsadning inode’ini ulashadi Ha
Fayl tizimlari chegarasidan o'ta oladimi? Yo'q Ha
Katalogga ishora qila oladimi? Odatda yo'q Ha
Mavjud bo'lmagan maqsadga ishora qila oladimi? Yo'q Ha
Maqsad nomi o'chirilsa Boshqa hard link ishlashda davom etadi Link buziladi
ls -l ko'rsatadigan tur Maqsadning o'z turi l

"O'z inode’i bormi?" qatori symbolic link’ning o'zini tavsiflaydi. Ko'p dasturlar link ortidan avtomatik borib, uning maqsadi ustida ishlaydi; rm link kabi ba’zi amallar esa link’ning o'ziga ta’sir qiladi.

Xavfsiz laboratoriya

Bu laboratoriya faqat mktemp yaratgan katalog ichida ishlaydi. Quyida ko'rsatilgan $lab o'zgaruvchisini qayta o'rnatmasdan boshqa terminal sessiyasida ishlatmang.

Boshlang'ich holat

lab=$(mktemp -d)
printf 'Lab: %s\n' "$lab"
printf 'alpha\n' > "$lab/original.txt"

Ikkala turdagi link’ni yaratish

ln "$lab/original.txt" "$lab/hard.txt"
ln -s original.txt "$lab/symlink.txt"

Natijani tekshirish:

ls -li "$lab"
stat -c 'dev=%d inode=%i link=%h type=%F name=%n' "$lab/original.txt" "$lab/hard.txt"
readlink "$lab/symlink.txt"

original.txt va hard.txt da dev, inode va havolalar soni bir xil chiqishi kerak. symlink.txt ning inode’i boshqa va u original.txt satrini saqlaydi.

Mazmun va nom bir-biridan mustaqil

printf 'beta\n' >> "$lab/hard.txt"
cat "$lab/original.txt"
cat "$lab/symlink.txt"

Ikkala buyruq ham alpha va beta ni chiqaradi. Endi asl nomni interaktiv rejimda o'chiring:

rm -i -- "$lab/original.txt"

Tasdiqlagandan keyin:

cat "$lab/hard.txt"
readlink "$lab/symlink.txt"
test -L "$lab/symlink.txt" && printf 'the symlink still exists\n'
test ! -e "$lab/symlink.txt" && printf 'but its target is gone\n'

Hard link mazmunni hali ham ochadi; symbolic link esa mavjud, lekin endi maqsadini topa olmaydi.

Faylga tegishli barcha hard link’larni topish

find "$lab" -xdev -samefile "$lab/hard.txt" -printf '%i %p\n'

-samefile berilgan fayl bilan bir xil inode’ga bog'langan barcha nomlarni topadi. -xdev boshqa fayl tizimiga o'tishning oldini oladi. Bu mantiqli, chunki inode raqamlari faqat o'z fayl tizimi ichida yagona bo'ladi.

Tozalash

printf 'directory to remove: %q\n' "$lab"
find "$lab" -maxdepth 1 -ls
rm -rI -- "$lab"
test ! -e "$lab" && printf 'cleaned up\n'

Warning

Agar rm ga berilgan yo'l symbolic link’ning o'zi bo'lsa, rm odatda maqsadni emas, link’ni o'chiradi. Lekin rekursiv vositalar va oxiridagi / kabi sintaksis tafsilotlari maqsad ortidan borishga sabab bo'lishi mumkin. Production’da symbolic link ustida rekursiv amalni uning maqsadini avval readlink, realpath va stat bilan tekshirmasdan bajarmang.

Amaliy vaziyat: buzilgan reliz ko'rsatkichi

Deploy jarayoni /srv/myapp/current ni faol relizga yo'naltiradi. Xizmat qayta ishga tushgandan keyin o'z konfiguratsiyasini topa olmayapti.

Tekshiruv

Avval hech narsani o'zgartirmasdan link’ni tahlil qiling.

namei -l yo'lning har bir qismini alohida ko'rsatadi, shunda aniqlash aynan qayerda uzilishini ko'rish mumkin bo'ladi. readlink -f va namei ning yo'l diagnostikasi o'rtasidagi farq shu modulning keyingi qismidagi Yo'llar va fayl turlari maqolasida chuqurroq yoritilgan.

ls -ld /srv/myapp/current
readlink /srv/myapp/current
readlink -f /srv/myapp/current
namei -l /srv/myapp/current/config/app.ini
findmnt -T /srv/myapp/current

Masalan, readlink releases/v3 ni chiqarsa-yu, readlink -f hech narsa chiqarmasa, demak /srv/myapp/releases/v3 yo mavjud emas, yo yo'lning biror qismi aniqlanmayapti. namei aynan qaysi qism buzilganini ko'rsatadi.

Xavfsiz almashtirish

Production’dagi mavjud current link’ini majburan ustidan yozishdan oldin yangi reliz va rollback maqsadini qayd eting:

readlink /srv/myapp/current
test -d /srv/myapp/releases/v2
namei -l /srv/myapp/releases/v2

Quyidagi haqiqiy o'zgarish faqat ruxsatlari va zaxira siyosati tekshirilgan test VM’da yoki tasdiqlangan deploy jarayonining bir qismi sifatida bajarilishi kerak:

cd /srv/myapp
ln -s releases/v2 current.new
readlink -f current.new
mv -T current.new current

current.new xuddi shu katalogda yaratilgani uchun yakuniy qayta nomlash bitta fayl tizimi ichida atomar bo'ladi: kuzatayotgan jarayon yo eski nomni, yo yangisini ko'radi, ular orasida bo'shliq bo'lmaydi. Bu jarayon allaqachon ochib qo'ygan fayl deskriptorlarini yoki allaqachon ishga tushgan jarayonning konfiguratsiyasini avtomatik yangilamaydi.

Rollback:

cd /srv/myapp
ln -s releases/<previous-version> current.rollback
readlink -f current.rollback
mv -T current.rollback current

<previous-version> ni tekshiruv bosqichida qayd etgan qiymatingiz bilan almashtiring. sudo faqat buyruqni bajarayotgan hisobda /srv/myapp ga yozish huquqi bo'lmasa va deploy siyosati uni ishlatishga ruxsat bersa kerak bo'ladi; u noto'g'ri maqsadni xavfsiz qilib qo'ymaydi.

Danger

ln -sfn ni ko'r-ko'rona ishlatish mavjud yo'lni jimgina almashtirib yuborishi mumkin. Maqsad katalogmi, oddiy faylmi yoki boshqa symbolic link’mi — buni stat, readlink va namei bilan tekshiring. Muhim bo'lgan har qanday deploy uchun reliz katalogining zaxira nusxasini yoki VM snapshot oling va rollback uchun eski link qiymatini qayd eting.

Zaxira nusxa, nusxalash va xavfsizlik

Arxiv link’ni saqlaydimi yoki maqsadnimi?

Zaxira nusxa vositangizning link’lar bo'yicha siyosatini tekshiring. Masalan, GNU cp -a odatda symbolic link’ni symbolic link sifatida saqlaydi, cp -L esa uning maqsadi ortidan boradi. Hard link’lar zaxira formati va ishlatilgan opsiyalarga qarab yo bitta umumiy inode sifatida, yo alohida nusxalar sifatida tiklanishi mumkin.

Tiklagandan keyin faqat fayllar sonini emas, ko'proq narsani tekshiring:

find <restored-directory> -type l -ls
stat -c '%d:%i %h %n' <important-file-1> <important-file-2>

Hamma yoza oladigan katalogda boshqa foydalanuvchi link’ni almashtirib, yuqoriroq huquqli jarayonni kutilmagan maqsadga yo'naltirishi mumkin. Dasturlash darajasida bu muammoni lstat, openat2 cheklovlari yoki O_NOFOLLOW kabi vositalar hal qiladi. Administrator sifatida esa:

  • xavfsiz vaqtinchalik fayl uchun mktemp dan foydalaning;
  • hujumchi o'zgartira oladigan katalogda maqsadni tekshirish va uni ishlatish o'rtasida vaqt oralig'i qoldirmang;
  • rekursiv nusxalash vositasiga tayanishdan oldin uning -H, -L, -P qoidalarini tekshiring;
  • symlink egasi va katalogning sticky bit siyosatini e’tiborsiz qoldirmang.

Keng tarqalgan xatolar

  • Hard link’ni nusxa deb hisoblash.
  • Bir nechta hard link orasidan "aslini" topishga urinish — bunday farq yo'q.
  • Nisbiy symlink maqsadini link’ning o'z katalogiga emas, joriy ish katalogiga nisbatan aniqlash.
  • Osilib qolgan symlink uchun test -e natijasini link’ning o'zi mavjud emasligining isboti deb hisoblash — test -e aniqlangan maqsadni tekshiradi; link’ning o'zi uchun test -L dan foydalaning.
  • Inode raqamini faqat o'z fayl tizimi ichida yagona bo'lgan identifikator emas, global noyob identifikator deb hisoblash.

Mashqlar

  1. Vaqtinchalik katalogda bitta fayl va unga ikkita hard link yarating. Har bir qadamdan keyin havolalar sonini stat -c '%i %h %n' bilan qayd eting.
  2. Ikkita symbolic link yarating: birining maqsadi absolyut, ikkinchisiniki nisbiy bo'lsin. Katalog daraxtini boshqa vaqtinchalik joyga ko'chiring va qaysi link hali ham ishlashini va nima uchunligini aniqlang.
  3. Osilib qolgan symlink yarating. ls -l, test -L, test -e, readlink va realpath -e natijalarini solishtiring.
  4. Ikkita alohida fayl tizimi bor test VM’da turli fayl tizimlari orasida hard link yaratishga urinishdan oldin farqni findmnt -T va stat -c '%d' bilan isbotlang. Kutilgan xato nomini qayd eting; buni production’da sinab ko'rmang.
  5. Test deploy daraxtida current symlink’ini vaqtinchalik nom va mv -T yordamida almashtiring. Qayd etilgan maqsad yordamida oldingi qiymatga rollback qiling.

Mashqni bajardim deyish uchun: hard link’lar uchun qurilma va inode qiymatlari bir xil ekanini, symbolic link’lar uchun esa saqlangan maqsad satrini ham, to'liq aniqlangan yo'lni ham ko'rsata olishingiz kerak.

Manbalar

  • GNU Coreutils qo'llanmasi: ln invocation: https://www.gnu.org/software/coreutils/manual/html_node/ln-invocation.html
  • Linux man-pages: link(2): https://man7.org/linux/man-pages/man2/link.2.html
  • Linux man-pages: symlink(7): https://man7.org/linux/man-pages/man7/symlink.7.html
  • Linux man-pages: path_resolution(7): https://man7.org/linux/man-pages/man7/path_resolution.7.html
  • GNU Coreutils qo'llanmasi: cp invocation va symbolic link’lar: https://www.gnu.org/software/coreutils/manual/html_node/cp-invocation.html
  • Linux man-pages: openat2(2): https://man7.org/linux/man-pages/man2/openat2.2.html