Sprzęt, jądro i udev
Po tej lekcji: kursant w kilka minut spisuje, na jakim sprzęcie działa serwer, sprawdza i ładuje sterowniki jądra, zmienia parametry jądra w locie i na stałe oraz rozumie, kto nadaje nazwy urządzeniom w /dev.
Wstęp
Serwer w szafie. Nikt nie pamięta, kto go kupił. Naklejka z numerem seryjnym się odkleiła. Możesz wyłączyć go, odkręcić obudowę i czytać napisy na kościach pamięci z latarką w zębach. Albo zalogować się przez SSH i w dwie minuty mieć pełną kartotekę: procesor, pamięć, dyski, karty sieciowe, numer seryjny, wersję BIOS-u.
Dziś robimy przegląd maszynowni. Bez śrubokręta.
uname: dowód osobisty jądra
uname -a
uname -rLinux vm 6.8.0-48-generic #48-Ubuntu SMP PREEMPT_DYNAMIC Fri Sep 27 14:04:52 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
6.8.0-48-generic-a to wszystko naraz: system, nazwa komputera, wersja jądra, data budowy, architektura. Na co dzień najczęściej -r, czyli sama wersja jądra, bo o nią pytają instrukcje sterowników i zgłoszenia błędów. -m to architektura: x86_64 dla zwykłych komputerów, aarch64 dla ARM, na przykład Raspberry Pi albo Maców z procesorami Apple w maszynie wirtualnej.
[macOS] uname jest i na Macu, ale pokaże jądro Darwin. Reszta dzisiejszych narzędzi to już czysty Linux.
lscpu: kto stoi przy kuchence
lscpuArchitecture: x86_64
CPU(s): 2
Vendor ID: GenuineIntel
Model name: Intel(R) Xeon(R) Processor @ 2.10GHz
Thread(s) per core: 1
Core(s) per socket: 2
Socket(s): 1
Flags: fpu vme de pse tsc msr pae ... avx2 ... aes ...
Hypervisor vendor: KVM
Virtualization type: full
L1d cache: 96 KiB (2 instances)Czytamy jak skład kuchni. Socket to fizyczne gniazdo na płycie, czyli ile jest kuchni. Core to rdzeń, kuchenka. Thread to wątek: jeden kucharz może pilnować dwóch garnków naraz, jeśli procesor ma hyper-threading. CPU(s) to wynik mnożenia: tyle „procesorów” widzi system i tyle samo poda nproc.
Dwie linijki, które warto znać. Hypervisor vendor zdradza, że jesteśmy w maszynie wirtualnej i na czym, tu KVM. A Flags to lista umiejętności procesora. Jeśli instrukcja jakiegoś programu wymaga na przykład AVX2 albo AES, sprawdzisz to tak:
lscpu | grep -o -w -E 'avx2|aes' | sort -uRura, sito, sortowanie. Moduł pierwszy się przydaje.
lsblk: dyski jak drzewo
lsblk -o NAME,SIZE,TYPE,ROTA,RO,MOUNTPOINTS /dev/vdaNAME SIZE TYPE ROTA RO MOUNTPOINTS
vda 256G disk 1 0 /run/netns
/lsblk rysuje dyski, partycje i wolumeny jako drzewo: dysk, pod nim partycje, pod nimi LVM. -o wybiera kolumny. ROTA mówi, czy dysk się kręci, czyli 1 dla talerzowego, 0 dla SSD. Na maszynach wirtualnych to często kłamie, bo dysk wirtualny nie wie, co jest pod spodem. -f dokłada system plików i UUID, a -d pokazuje same dyski bez partycji. Nazwa dysku też coś mówi: sda to dysk SATA albo SCSI, nvme0n1 to NVMe, vda to dysk wirtualny virtio. Dyskom poświęcimy cały moduł, dziś wystarczy wiedzieć, gdzie je zobaczyć.
lspci i lsusb: co jest wpięte
Płyta główna ma dwie główne „ulice”, przy których mieszkają urządzenia: szynę PCI, czyli karty w środku obudowy, i USB, czyli to, co wpinasz z zewnątrz.
lspci00:00.0 Host bridge: Intel Corporation Device 0d57
00:02.0 Mass storage controller: Red Hat, Inc. Virtio 1.0 block device (rev 01)
00:08.0 Ethernet controller: Red Hat, Inc. Virtio 1.0 network device (rev 01)Kontroler dysków, karta sieciowa, wszystko od „Red Hat, Inc.”? Tak, bo wirtualne urządzenia virtio mają identyfikator producenta 1af4, zarejestrowany na Red Hata. Zobaczysz go przez lspci -nn. Na fizycznym serwerze zobaczysz tu Intela, Broadcoma, Mellanoxa i kartę graficzną. Najcenniejsza flaga to -k: pokazuje, jaki sterownik obsługuje urządzenie.
lspci -k -s 00:02.000:02.0 Mass storage controller: Red Hat, Inc. Virtio 1.0 block device (rev 01)
Subsystem: Red Hat, Inc. Virtio 1.0 block device
Kernel driver in use: virtio-pciNowa karta sieciowa nie działa? lspci -k i patrzysz, czy jest linijka „Kernel driver in use”. Nie ma? Problem jest w sterowniku, nie w kablu.
lsusb to samo dla USB, a lsusb -t rysuje drzewo portów. Na mojej maszynie wirtualnej nie wypisuje nic, bo nie ma w niej ani jednego portu USB. Na laptopie zobaczysz kamerkę, czytnik linii papilarnych i myszkę.
[RHEL] [Ubuntu] Polecenia są w pakietach o tych samych nazwach: pciutils i usbutils. Na minimalnej instalacji może ich nie być.
dmidecode: tabliczka znamionowa
Każdy komputer ma w firmware tabliczkę znamionową, standard SMBIOS, czyli DMI: producent, model, numer seryjny, wersja BIOS-u, ile jest slotów na pamięć i co w nich siedzi. Czyta ją dmidecode i potrzebuje do tego roota:
sudo dmidecode -t system
sudo dmidecode -t memory
sudo dmidecode -s system-serial-numberTo jest odpowiedź dla audytu z haka: model, numer seryjny i rodzaj pamięci, bez otwierania obudowy. Na serwerach z wypożyczalni i w chmurze numer seryjny bywa pusty albo jest identyfikatorem maszyny wirtualnej.
A na lekkiej mikromaszynie wirtualnej w chmurze bywa tak:
# dmidecode 3.5
Scanning /dev/mem for entry point.
Can't read memory from /dev/memTa maszyna po prostu nie ma tabliczki znamionowej. Lekkie maszyny wirtualne tak mają. To też jest informacja: jeśli dmidecode nic nie znajduje, a lscpu mówi „Hypervisor”, to wiesz, że nie szukasz fizycznego pudła w szafie.
Moduły jądra: wymienne narzędzia
Jądro nie ma w sobie na stałe sterowników do wszystkich urządzeń świata. Byłoby ogromne. Większość sterowników to moduły: osobne pliki, które jądro dołącza w biegu, kiedy są potrzebne. Jak wiertarka z wymiennymi końcówkami: wkrętak, wiertło, mieszadło do farby, zależnie od roboty.
Moduły leżą w /lib/modules/WERSJA_JĄDRA/. Dlatego po aktualizacji jądra nowy folder, a stare zostają dla starych jąder. Trzy komendy:
lsmod
modinfo e1000
sudo modprobe e1000
sudo modprobe -r e1000- lsmod — jakie końcówki są teraz włożone. Kolumna „Used by” mówi, kto z nich korzysta.
- modinfo — opis modułu: plik, autor, licencja, parametry i obsługiwane urządzenia.
- modprobe — ładuje moduł razem ze wszystkim, czego wymaga.
-rwyjmuje.
Na starożytnych forach spotkasz też insmod i rmmod. One nie znają zależności, więc jak przyjdzie Ci wybierać: zawsze modprobe.
A czasem, na przykład w kontenerze albo na lekkiej mikromaszynie w chmurze, lsmod odpowiada:
libkmod: ERROR ../libkmod/libkmod-module.c:1762 kmod_module_new_from_loaded: could not open /proc/modules: No such file or directory
Error: could not get list of modules: No such file or directoryTo nie awaria. To jądro zbudowane bez obsługi modułów: wszystko, czego potrzebuje, ma wkompilowane na stałe, więc pliku /proc/modules po prostu nie ma. Tak robią lekkie maszyny wirtualne do kontenerów. Na Twojej wirtualce z Ubuntu czy RHEL lsmod wypisze kilkadziesiąt modułów. Wniosek dla admina: ten sam błąd na prawdziwym serwerze znaczy coś zupełnie innego niż na mikromaszynie. Zawsze najpierw sprawdź, na czym stoisz.
Na stałe:
/etc/modules-load.d/*.conf— lista modułów do załadowania przy starcie, jeden w linijce./etc/modprobe.d/*.conf— opcje modułów i czarna lista: linijkablacklist nazwamówi „nie ładuj tego automatycznie”.
Po zmianach dotyczących sterowników potrzebnych przy starcie pamiętaj o walizce z lekcji 27, czyli przebudowie initramfs.
sysctl: pokrętła jądra
Jądro ma setki ustawień, które można zmieniać bez restartu. Wszystkie siedzą jako pliki w /proc/sys/. Pamiętasz /proc/sys/vm/swappiness? To było jedno z nich. sysctl to wygodny pilot do tych pokręteł, z kropkami zamiast ukośników:
sysctl vm.swappiness net.ipv4.ip_forward
sysctl -a | wc -lvm.swappiness = 60
net.ipv4.ip_forward = 0
904U mnie dziewięćset cztery pokrętła, u Ciebie liczba zależy od wersji jądra. net.ipv4.ip_forward = 0 znaczy, że ta maszyna nie przekazuje ruchu sieciowego dalej jak router. Włączysz to dopiero wtedy, gdy postawisz na niej kontenery albo VPN. Zmiana w locie:
sudo sysctl -w vm.swappiness=30vm.swappiness = 30I działa od razu, ale tylko do restartu. Na stałe wpisujesz do pliku w /etc/sysctl.d/, na przykład /etc/sysctl.d/99-moje.conf:
vm.swappiness = 20I wczytujesz bez restartu:
sudo sysctl -p /etc/sysctl.d/99-moje.confvm.swappiness = 20-p wczytuje jeden plik, a sudo sysctl --system wszystkie pliki konfiguracyjne w kolejności, w jakiej robi to system przy starcie. Pliki w /etc wygrywają z plikami o tej samej nazwie w /usr/lib. Ta sama zasada co w systemd. W lekcji o TuneD widziałeś, że profile robią dokładnie to: ustawiają sysctl za Ciebie. Jeśli używasz TuneD, sprawdź, czy profil nie nadpisuje Twoich wartości.
Uwaga: z sysctl można zrobić krzywdę. Zmiany w net.* na serwerze, do którego jesteś podłączony przez SSH, mogą Cię od niego odciąć. Eksperymentuj na maszynie wirtualnej i zapisz starą wartość, zanim ją zmienisz.
udev: recepcja, która nadaje identyfikatory
Wpinasz pendrive’a. Skąd bierze się /dev/sdb? I skąd /dev/disk/by-uuid/…?
Wyobraź sobie recepcję w biurowcu. Przychodzi gość, czyli urządzenie. Jądro go wykrywa i krzyczy do recepcji: „ktoś przyszedł!”. Recepcjonista, czyli udev, sprawdza w regulaminie, co z takim gościem zrobić: wypisuje mu identyfikator, czyli plik w /dev, dodaje mu kilka przydomków, czyli dowiązania w /dev/disk/by-id/ i /dev/disk/by-uuid/, ustawia uprawnienia i czasem dzwoni po kogoś, kto ma się nim zająć.
Co udev wie o urządzeniu:
udevadm info --query=property --name=/dev/vdaDEVPATH=/devices/pci0000:00/0000:00:02.0/virtio1/block/vda
DEVNAME=/dev/vda
DEVTYPE=disk
MAJOR=254
MINOR=0
SUBSYSTEM=blockA udevadm info -a -n /dev/vda wypisze wszystkie cechy urządzenia i jego „rodziców” w formacie gotowym do wklejenia w regułę. Reguły z pakietów leżą w /usr/lib/udev/rules.d/, Twoje w /etc/udev/rules.d/. Napiszmy własną: dysk systemowy ma dostać przydomek /dev/dysk-systemowy. Plik /etc/udev/rules.d/99-kurs.rules:
SUBSYSTEM=="block", KERNEL=="vda", SYMLINK+="dysk-systemowy"Podwójne równa się to „jeśli pasuje”. += to „dodaj”. Czytamy: jeśli to urządzenie blokowe o nazwie vda, dodaj mu dowiązanie. Sprawdzamy składnię i symulujemy:
sudo udevadm verify /etc/udev/rules.d/99-kurs.rules
sudo udevadm test /sys/class/block/vda 2>&1 | grep -i kurs1 udev rules files have been checked.
Success: 1
Fail: 0
vda: /etc/udev/rules.d/99-kurs.rules:1 Added SYMLINK 'dysk-systemowy'Na prawdziwym systemie po zmianie reguł mówisz recepcji, żeby przeczytała regulamin jeszcze raz, i odgrywasz wizytę gości od nowa:
sudo udevadm control --reload
sudo udevadm trigger--reload sam niczego nie zmienia w już podłączonych urządzeniach. Dopiero trigger albo ponowne wpięcie urządzenia.
Jak to działa pod spodem
Większość dzisiejszych narzędzi to tłumacze dwóch wirtualnych systemów plików, które jądro wystawia na zewnątrz. /proc to stare okienko: /proc/cpuinfo dla lscpu, /proc/modules dla lsmod, /proc/sys dla sysctl. /sys to nowe, uporządkowane drzewo wszystkich urządzeń: każde ma tam folder z plikami-cechami. lsblk czyta /sys/block, lspci czyta /sys/bus/pci, a udevadm info -a po prostu chodzi po tych folderach w górę.
Kiedy pojawia się nowe urządzenie, jądro tworzy jego folder w /sys i wysyła wiadomość „uevent”. Odbiera ją systemd-udevd, przechodzi przez wszystkie reguły w kolejności nazw plików, dlatego nazwy zaczynają się od numerów, i tworzy dowiązania w /dev. A jeśli urządzenie potrzebuje sterownika, którego jeszcze nie ma, udev woła modprobe z identyfikatorem urządzenia, a modprobe sam znajduje pasujący moduł. Tak działa „podłącz i działa”: jądro mówi, udev organizuje, modprobe dokłada końcówkę.
Ściąga flag
| Komenda | Flaga | Co robi |
|---|---|---|
| uname | -a / -r / -m | wszystko / wersja jądra / architektura |
| lscpu | (brak) | procesor, rdzenie, wątki, flagi |
| nproc | (brak) | liczba dostępnych procesorów |
| lsblk | -f / -d / -o KOLUMNY | systemy plików i UUID / same dyski / wybrane kolumny |
| lspci | -k / -nn / -v | sterownik / numery producenta / szczegóły |
| lsusb | -t / -v | drzewo portów / szczegóły |
| dmidecode | -t system / memory / bios | wybrana tabliczka znamionowa |
| dmidecode | -s system-serial-number | jedna wartość |
| lsmod | (brak) | załadowane moduły |
| modinfo | MODUŁ | opis i parametry modułu |
| modprobe | MODUŁ / -r MODUŁ | ładuje / wyjmuje moduł z zależnościami |
| sysctl | -a / -w KLUCZ=WARTOŚĆ | wszystkie / zmiana w locie |
| sysctl | -p PLIK / --system | wczytuje plik / wszystkie pliki |
| udevadm | info --name=/dev/X | właściwości urządzenia |
| udevadm | info -a -n /dev/X | cechy do reguł udev |
| udevadm | control --reload / trigger | przeładuj reguły / odegraj zdarzenia |
| udevadm | verify / test / monitor | składnia / symulacja / zdarzenia na żywo |
⚠ Typowy błąd
Zmieniasz parametr jądra, zapominając o sudo:
sysctl -w vm.swappiness=10
echo $?
cat /proc/sys/vm/swappinesssysctl: permission denied on key "vm.swappiness", ignoring
vm.swappiness = 10
0
60Przyjrzyj się temu dokładnie. sysctl mówi „permission denied, ignoruję”, a w następnej linijce dumnie wypisuje vm.swappiness = 10. Kod wyjścia zero, kciuk w górę. A prawdziwa wartość? Dalej 60. Nic się nie zmieniło. Jak urzędnik, który mówi „nie mogę tego przyjąć”, a potem i tak wbija pieczątkę „zatwierdzono” na Twojej kopii.
Skrypt, który sprawdza tylko kod wyjścia, uzna to za sukces. Dlatego po każdej zmianie pokrętła sprawdzasz wartość osobno: sysctl vm.swappiness albo cat /proc/sys/vm/swappiness. I używasz sudo.
Drugi klasyk to literówka w nazwie klucza: sysctl -w vm.swapines=10 kończy się komunikatem „cannot stat /proc/sys/vm/swapines: No such file or directory”. Ten przynajmniej jest uczciwy.
✎ Zadanie
Zbierz do pliku raport.txt (dopisując >>): nazwę komputera, wersję jądra, model procesora (z lscpu), liczbę rdzeni (nproc), pamięć (free -h) i listę dysków (lsblk).
Pokaż rozwiązanie
hostname >> raport.txt
uname -r >> raport.txt
lscpu | grep 'Model name' >> raport.txt
nproc >> raport.txt
free -h >> raport.txt
lsblk >> raport.txt
cat raport.txtvm
6.8.0-48-generic
Model name: Intel(R) Xeon(R) Processor @ 2.10GHz
2
total used free shared buff/cache available
Mem: 7.8Gi 654Mi 7.1Gi 15Mi 333Mi 7.2Gi
Swap: 0B 0B 0B
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
vda 254:0 0 256G 0 disk /
...Sześć komend, sześć razy podwójna strzałka, bo pojedyncza za każdym razem kasowałaby to, co już było. Jeśli w pliku masz tylko listę dysków, to wiesz, która strzałka była pojedyncza. grep przy lscpu wycina jedną linijkę z kilkudziesięciu, bo nikt nie chce czytać o flagach procesora przy porannej kawie.
Jedna uwaga: jeśli masz system po polsku, lscpu może mieć przetłumaczone nagłówki i grep 'Model name' nic nie znajdzie. Za chwilę pokażę, jak to obejść.
Co dalej
Te sześć komend wpisywanych ręcznie aż się prosi, żeby zapisać je raz i odpalać jednym poleceniem. I od tego zaczyna się następny moduł: w kolejnej lekcji piszemy pierwszy prawdziwy skrypt, z #!, chmod +x i wszystkim, co się dzieje, kiedy go uruchamiasz.