Linux etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
Linux etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

22 Mart 2026 Pazar

CentOS 9da 4 Nodlu GlusterFS Kümesi Kurulumu


Merhaba. Bu yazıda hyperconverged mimariyle linux makinalar üzerinde bir depolama kümesi (storage cluster) oluşturacağım ama önce bu laf salatasına bir açıklık getireyim. Hyperconverged'den kastım, elimde bir disk kutusu (enclosure) yok. Bunun yerine, üzerinde atıl diskler olan birden fazla özdeş makinam var. Ben bu disk alanını yedekli bir biçimde birleştirip diğer makinalara sunacağım. Makinaların özdeş olması önemli, çünkü yedeklilik (redundancy) ve performans için dosyalar parçalara bölünerek makinalara dağıtılacak. Dolayısıyla sistemdeki en küçük disk dolarsa yazılan dosyalar tüm makinalara dağıtılamaz. Ayrıca işlemci ve bellek de eşit olmalı ki, bir makina yazmayı bitirdiğinde diğerlerini beklemek zorunda kalmasın.

Dağıtık (shared) dosya sistemi olarak GlusterFS kullanacağım, çünkü öncelikle ilk kurulumu görece basit. İleri seviye bir konfigürasyon çok karışık bir hal alabiliyor ama ben bu ayrıntılara en azından bu yazıda girmeyeceğim. Alternatif olarak Ceph veya Quobyte kullanabilirdim ama benim gözlemim Ceph, GlusterFS'ten çok daha karışık. Bir projede Quobyte ile çalıştım ve diğer ikisinin aksine kurulumu inanılmaz kolay, ancak GlusterFS, RHEL tarafından doğrudan destekleniyor(du). Buna geleceğim.

Normalde bu tür bir projede terabyte diskli sunucular kullanılır. Ben sadece yapılabilir olduğunu göstermek için 20 GB diskli dört makina kullanıp bunları %75 verimle, yani 20 GB * %75 * 4 = 60 GB'lık bir disk paylaştıracağım. %25'lik alan yedeklilik için kullanılacak. Bu kapasite, disklerin kapasitesiyle doğru ortantılı. Diğer yandan makina sayısı da önemli. Bu sistemi üç makinayla kursaydım, tavsiye edilen konfigürasyon RAID1 benzeri yapıda %33 verimle çalışıyor. Yani 20GB diskli üç makindan 20 GB kapasite alınabiliyor. Elbette küme RAID0 mantığıyla da kurulabilir ama bu durumda kümeden bir makina bile yeniden başlatılsa veri bozulması ve kaybı oluşur. Benim dört makina seçmemdeki neden, yedeklilikten ödün vermeden az sayıda makinayla yüksek verim sunabilmesi. Bu konfigürasyonda diskler RAID5 mantığında çalışıyor ve bir makina çökse bile sistem etkilenmiyor. Diğer yandan konfigürasyonun karışık bir hal alabileceğini yazmıştım. Dört makina, istenirse RAID10 mantığında, dosya parçalarının yarısı bir makinada diğer yarısı diğer makinada ve geri kalan iki makina da ilk iki makinayı aynalayacak (mirroring) şekilde de ayarlanabilir. Bu durumda aynı mirror group'ta olmamak koşuluyla, sistem iki makina arızasını kaldırabilir ancak depolama verimi %50 olur.

Diski ağda paylaştırmak için samba servisini kullanacağım. Eğer ağda yalnızca linux istemciler varsa NFS de bir seçenek. Samba'yı seçmemdeki bir neden, ctdb servisiyle high-availability sağlayabiliyor. Ctdb, samba'nın bir parçası ve NFS'i de destekliyor. Öte yandan ağda Windows istemciler varsa samba zaten alternatifsiz durumda. Ve disk erişimi Active Directory (AD) ile yönetilecekse samba'yla bunu halletmek daha kolay.

Dağıtım olarak CentOS9 kullanacağım, ama kullandığım GlusterFS komutlarını ve samba konfigürasyonunu Ubuntu'da da test ettim. Bu bakımdan dnf dışında yazı distro-agnostic olacak. Makinaları CentOS Cloud Image'dan oluşturacağım.

İlk olarak birden fazla makinaya kurulum yapacağımdan tmux'ta 4 farklı panel açtım, her panelde bir makinaya bağlandıktan sonra set syn komutunu verdim. Böylelikle komutlar tüm makinalarda çalıştırılacak.

tmux'ta dört panelde güncelleme

Ardından makinalara bağlanıp, gerekli paketleri yükledim. İlk satır hata analizi için gerekli araçlar. İkinci satırda GlusterFS paketlerini içeren repository ve üçüncü satırda bu repository'den glusterfs-server paketi yükleniyor. Sonraki satırlarda samba'yla ilgili paketleri yükleyip sistemi güncelledim. En sonda needs-restart ile makinaları yeniden başlattım.

dnf -y install tcpdump telnet wget epel-release
dnf -y install centos-release-gluster9
dnf -y install glusterfs-server

dnf -y install samba cifs-utils samba samba-common-tools samba-winbind ctdb --enablerepo=resilientstorage

dnf update
needs-restarting -r || reboot

GlusterFS için makinaların birbirlerine hostname'leriyle ulaşabilmeleri gerekiyor. Normalde bu DNS kayıtlarıyla yapılmalı. Ben küçük bir test ortamında çalıştığım için makinaların IP'lerini hosts dosyasına elle ekledim. Makinaları aşağıdaki gibi server01..04 olarak adlandırdım. İkinci komutla makinalara hostname atadım. Elbette bu komut her makinada ayrı ayrı girilmeli ve bash'in yeni hostname'i göstermesi isteniyorsa logout / login yapılmalı (Ubuntu için hostnamectl set-hostname server01).

cat >> /etc/hosts << EOF
172.18.186.101   server01
172.18.186.102   server02
172.18.186.103   server03
172.18.186.104   server04
EOF

nmcli gen hostname server01
chronyc sources

GlusterFS servisi zaman açısından hassas, makinalar arasında saat farkı bulunmamalı. Bu nedenle chrony'nin çalıştığını yukarıdaki komutla kontrol ettim. Bu arada Ubuntu'nun chronyd yerine kendi NTP istemcisi var. İstenirse chronyd yüklenebiliyor ve bu yapılırsa kendi NTP istemcisini sistemden otomatik kaldırıyor.

chronyc sources çıktısı

Bundan sonra sıra diskleri hazırlamaya geldi. Önce lsblk ile diskleri kontrol ettim. Benim diskim /dev/vdb. Kullanımda esnek olması için bir disk bölümü ve bu bölümde LVM'le bir de logical volume oluşturup onu kullandım.

fdisk /dev/vdb
# Burada bölümleme adımlarına değinmeyeceğim. Eski yazılardan nasıl yapılacağı bulunabilir.

pvcreate /dev/vdb1
vgcreate vg_gluster /dev/vdb1
lvcreate -l 100%FREE -n lv_brick vg_gluster
mkfs.xfs -f -i size=512 /dev/vg_gluster/lv_brick
mkdir -p /data/glusterfs/brick1
echo "/dev/vg_gluster/lv_brick  /data/glusterfs/brick1  xfs  defaults  1  2" >> /etc/fstab
systemctl daemon-reload
mount -a

Buraya kadar herşey yolundaysa son komut bir çıktı üretmemeli ve df -hP çıktısında yeni mount edilen bölüm listelenmeli. Bu noktada makinalar kuruluma hazır.

Aşağıdaki komutlarla shared_storage adında bir GlusterFS bölümü oluşturdum. systemctl komutu bütün makinalarda, geri kalan gluster komutları yanlızca birinci makinada çalıştırılacak.

systemctl enable --now glusterd

gluster peer probe server02
gluster peer probe server03
gluster peer probe server04
gluster volume create shared_storage disperse 4 redundancy 1 \
server01:/data/glusterfs/brick1/brick \
server02:/data/glusterfs/brick1/brick \
server03:/data/glusterfs/brick1/brick \
server04:/data/glusterfs/brick1/brick

gluster volume start shared_storage

gluster volume status shared_storage

gluster volume status shared_storage

Yukarıdaki görselde, komutu aynı anda bütün makinalardan girdiğimde, ilk iki makina, diğer makinalardaki komutun sonlanmasını bekliyor. Bu normal bir durum. Muhtemelen komut server03 ile server04'te bir kaç milisaniye farkla çalıştı. Normalde yalnız bir makinada çıktı vermesi gerekirdi.

Bu arada host firewall ile ilgili bir ayar yapmadım, çünkü benim makinalarımda firewalld çalışmıyor.

Bu noktada samba için ufak bir hileye başvuracağım. Normalde samba'nın glusterfs entegrasyonu vardı ve bu gayet performanslı çalışıyordu [1]. Ancak RedHat 2024 sonu itibariyle GlusterFS desteğini kaldırıp, kaynakları Ceph'e kaydırma kararı aldı [2][3]. Dolayısıyla bu entegrasyon dağıtımlardan çıkarıldı [5]. Başka bir deyişle artık samba-vhs-glusterfs paketi RedHat'lerde yok. Bu durum aşağıdaki gibi aşılabilir (bütün makinalarda çalıştırılacak). Fedora bu desteği sürdürüyor [4] ama ne kadar devam eder bilmiyorum.

mkdir -p /mnt/gluster_shared
echo "localhost:shared_storage  /mnt/gluster_shared  glusterfs  defaults,_netdev  0  0" >> /etc/fstab
systemctl daemon-reload
mount -a

Bu şekilde bütün makinalar GlusterFS diskini de kendi üzerine mount ettiler. Sambayı doğrudan GlusterFS ile konuşturamadığımdan, bu kaynağı normal bir dizin gibi samba ile paylaştırdım. Bunun dezavantajı dosya sistemi işlemlerinin kernel'a bir yerine iki kere girmek zorunda kalmasından [1] dolayı oluşan performans kaybı.

Şimdi ctdb'yi ayarlayıp diski ağdan paylaşabilirim, ama bunu yapmadan önce selinux'u Permissive moda almam gerek. Bir kaç kaynakta bazı boolean'larla oynayarak selinux'u kapatmadan ctdb cluster yapılabileceği yazıyor, ancak bende işe yaramadı.

sed -i -e "s/SELINUX=enforcing/SELINUX=permissive/" /etc/selinux/config
setenforce 0

/etc/ctdb/nodes dosyasında yanlızca node'ların IP'si girilmeli. /etc/ctdb/public_addresses dosyasında da floating IP adresi ve bu IP'nin atanacağı ağ kartını girmek gerek.

cat > /etc/ctdb/nodes << EOF
172.18.186.101
172.18.186.102
172.18.186.103
172.18.186.104
EOF

cat > /etc/ctdb/public_addresses << EOF
172.18.186.200/24    eth0
EOF

smb.conf dosyasının içeriği aşağıdaki gibi olmalı:

[global]
        netbios name = GLUSTER_CLUSTER
        workgroup = SAMBA
        #security = user
        clustering = yes

        passdb backend = tdbsam
        idmap config * : backend = tdb
        idmap config * : range = 1000000-1999999

        #printing = cups
        #printcap name = cups
        #load printers = yes
        #cups options = raw

[shared_storage]
    comment = GlusterFS
    path = /mnt/gluster_shared
    valid users = sambauser
    read only = no
    guest ok = yes
    create mask = 0664
    directory mask = 0775

Ve ctdb'yi aşağıdaki gibi ayarladım:

systemctl stop smb nmb
systemctl disable smb nmb
ctdb event script enable legacy 00.ctdb
ctdb event script enable legacy 10.interface
ctdb event script enable legacy 50.samba
systemctl enable --now ctdb

Aktifleştirilen scriptler, ctdb'nin floating IP'yi ve clustered samba'yı yönetebilmesi için gerekli. ctdb cluster'ın durumu ctdb status komutuyla görülebilir. Herşey doğru ayarlandıysa bu komutları çalıştırdıktan bir kaç saniye sonra bütün nodların OK olması lazım. Bu arada ctdb'ye birden fazla floating IP atamak da mümkün. Ben yalnızca bir tane IP verdim. IP'lerin durumu ctdb ip all komutuyla kontrol edilebilir.

ctdb status

Şimdi son adım, samba için bütün nodlarda bir kullanıcı oluşturmak:

groupadd -g 2000 sambagroup
useradd -u 2000 -g sambagroup -s /sbin/nologin sambauser
smbpasswd -a sambauser

sambauser kullanıcısının sistemdeki şifresi önemli değil. Samba kendi veri tabanını ayrı tutuyor.

Böylelikle depolama kümesi devreye alınmış oldu. Şimdi bunu mount edeceğim bir istemci lazım. Bunu hazırlamak çok daha kolay. Aynı ağda bulunan beşinci bir makinada şu komutları çalıştırdım:

dnf -y install centos-release-gluster9
dnf -y install glusterfs-fuse samba-client cifs-utils
mkdir -p /mnt/my_shared_storage

cat >> /etc/hosts << EOF
172.18.186.101   server01
172.18.186.102   server02
172.18.186.103   server03
172.18.186.104   server04
EOF

mount -t glusterfs 172.18.186.200:/shared_storage /mnt/my_shared_storage/
df -hP

İlk komutla glusterfs reposunu, sonra glusterfs'i mount etmek için gereken paketi ve samba istemcisini yükledim. Sunucuların listesinin olduğu hosts dosyasını bu makinada da oluşturdum. Her ne kadar istemci floating IP üzerinden mount ediyorsa da iç haberleşme için bu makinaların IP'lerini çözebiliyor olması gerek. DNS sunucunun olduğu bir ortamda bu adıma gerek yok. Son adımda shared_storage kaynağını glusterfs olarak mount ettim, df ile kontrol ettiğimde 60 GB'lik bir disk mount edilmiş oldu. Henüz samba olarak mount etmedim.

Samba olarak mount etmek için, önce aşağıdaki ilk komutla paylaşılan kaynakları görebilir ve ikinci komutla bu paylaşıma bağlanabilirim:

smbclient -L //172.18.186.200 -U sambauser
smbclient //172.18.186.200/shared_storage -U sambauser

Bu paylaşımı mount etmeden önce GlusterFS mount'unu kaldırıp sonra aynı paylaşımı bu kez samba olarak mount ettim:

umount /mnt/my_shared_storage
mount -t cifs //172.18.186.200/shared_storage /mnt/my_shared_storage -o username=sambauser

Ve kalıcı mount oluşturmak için /etc/fstab'e aşağıdaki satırı ekledim:

//10.0.100.231/shared_storage  /mnt/my_shared_storage  cifs  credentials=/etc/samba/user.cred,iocharset=utf8,_netdev 0 0

/etc/samba/user.cred dosyasında login bilgileri var.

cat >> /etc/samba/user.cred << EOF
username=sambauser
password=secret
domain=SAMBA
EOF

chmod go= /etc/samba/user.cred
chown root:root /etc/samba/user.cred
systemctl daemon-reload
mount -a
df -hP

Şimdilik yazıyı burada noktalıyorum, bu yazı yeterince uzun oldu. Bunun AD veya LDAP ile nasıl entegre edileceğini ileriki bir yazıda anlatmayı planlıyorum.


Kaynak:

[1]: https://lalatendu.org/2014/04/20/glusterfs-vfs-plugin-for-samba/
[2]: https://en.wikipedia.org/wiki/Gluster#cite_ref-10
[3]: https://www.reddit.com/r/kubernetes/comments/zojdl7/whats_the_story_behind_the_abandonment_with/
[4]: https://pkgs.org/search/?q=samba-vfs-glusterfs
[5]: https://www.samba.org/samba/docs/4.7/man-html/vfs_glusterfs.8.html

20 Şubat 2026 Cuma

Raspberry Pi4 ile Canon MF 4450 için Yazdırma Sunucusu Oluşturmak


Merhaba. Yazının başlığından anlaşılacağı gibi, ağ bağlantısı olmayan Canon MF4450 yazıcımı Raspberry Pi4 ile yerel ağdan nasıl paylaşıma açtığımı anlatacağım. Bunu yapmak zaten oldukça kolay. Ben asıl bunu yaparken hangi yollardan geçtiğimi, hangi zorluklarla karşılaştığımı açıklamak istedim. O yüzden konfigürasyondan önce tasarımı tartışmak istiyorum.

Not: Yazının geri kalanında Raspberry Pi yerine RPi kısaltmasını kullanacağım.


Öncelikli konu platform seçimi. Başlıkta da yazdığım gibi ben RPi4'te çalıştım, daha doğrusu çalışmak zorunda kaldım. Elimde RPi 1B de var ve RPi 1B, bu iş için aslında donanım olarak yeterli. Disk olarak, bu makinada başka birşey çalışmayacaksa 8 GB'lık bir SD kart (4 GB işletim sistemi olmak üzere) ve bir de RPi 1'lerde onboard WiFi olmadığı için bir WiFi dongle gerekiyor. Ben RPi 4'te başka servisler de çalıştırdığım için disk olarak 128 GB'lik bir kart kullanıyorum ama bu da önemli ölçüde boş. Son olarak RPi 4'ün WiFi kartı onboard, bunun için ekstra bir donanım gerekmiyor.

Diğer yandan RPi4'ü sadece bu iş için kullanmak açıkça kaynak israfı, ancak RPi1'le başıma şunlar geldi:


İşletim Sistemi Dağıtımı

Bu iş için ilk önce RPi 1B'i denedim. Bu, 32-bit bir cihaz. Raspberry Pi OS'un (eski Raspbian) 32-bit sürümü resmi sitesinden indirilebiliyor. Bu Debian tabanlı bir dağıtım. Ben bunun lite sürümünü denedim çünkü RPi 1'ler her ne kadar grafik arayüzü çalıştırabilse de çok yavaş. Bunun dışında, Alpine RPi, DietPi ve piCore'u da denedim ancak bunlardan yalnız DietPi'yi kısmen kullanışlı buldum. Debian tabanlı ve RPi OS'un özelleştirilmişi gibi bir izlenim verdi. Ancak DietPi konfigürasyon scripti daha ilk boot'ta, çalışan bir internet bağlantısı istiyor. Bu konuya ileride değineceğim.

RPi4 ise 64-bit. Bunun için RPi OS'un 64-bit sürümünü resmi sitesinden indirdim. Bunun yanında Manjaro ARM, Ubuntu ve Fedora IOT de indirdim ancak ilk ikisini kullanmaya çok zamanım olmadı. Fedora IOT'nin mantığı hem klasik Fedora'dan hem de diğer dağıtımlardan çok farklı. Konfigürasyon için ignition adında cloud-init benzeri ama JSON tabanlı bir script kullanıyor. RPi OS ise başlangıç scriptiyle ayarlanıyor.


Raspberry Pi 1'de WiFi Konfigürasyonu

RPi 1 için bende TP-Link AC600 WiFi dongle vardı ve fark ettim ki, RPi OS'ta ve DietPi'da bunun chipseti (Realtek rtl8821au) için uygun sürücü olmadığından, kart otomatik tanınmıyor. github'da bu chipset için geliştirilen bir sürücü var, fakat indirmek için yine internet gerekiyor. Dolayısıyla RPi'i en başta kabloyla bağlamak zorunda kaldım. DietPi'nin en başta internet olmadan konfigürasyon yapamadığını söylemiştim. Bu durum yumurta/tavuk problemine yol açıyor. Alternatif: Github reposunu indirip SD karta yaz.

Bir de TP-Link'in TL-WM725N modelini (rtl8188eu chipset) sipariş ettim. Bunun sürücüsü RPi OS'ta var ve otomatik tanınıyor. Bu arada github'dan indirdiğim sürücüyü de derledim. gcc, make ve bc paketlerinin yüklü olması gerekiyor ve basit bir install-driver.sh scriptiyle derlenip dkms ile yükleniyor, ancak RPi1'in hızı nedeniyle derleme yaklaşık 4-5 sa sürüyor. Bir de özellikle DietPi gibi küçük olması için optimize edilmiş bir dağıtıma yalnız 1-2 kere kullanacağım ekstra paketler kurmak çok hoşuma gitmedi.


Raspberry Pi 1'de Yazıcı Konfigürasyonu

RPi1'le yaşadığım ikinci sorun (WiFi'dan sonra) Canon MF4450'nin 32-bit ARM için resmi olarak bir sürücüsünün olmaması. Başka model yazıcısı olup RPi1'de sorunsuz çalıştırabilenler bu bölümü atlayabilir.

Yazıcının sürücüsünü Canon'un resmi sitesinden indirdim. Bu sayfaya göre Linux ARM destekleniyor. Dosyada (linux-UFRII-drv-v620-m17n-20.tar.gz) ARM64, x86 ve x84 gibi platformlar için .deb ve .rpm dosyaları var ama ARM32 yok. O nedenle Sources dizinindeki kaynak kodları derlemeye karar verdim. Ama bu yine, sadece derlerken kullanacağım bir yığın paket kurmak demek. Üstelik sonuç olumsuz (gidiş yolunu merak etmeyenler burayı atlayabilir). Sürücüyü derlemek için autoconf ve automake başta olmak üzere toplam 11 tane paket kurmak gerekiyor.

apt install autoconf automake libcups2-dev libglib2.0-dev libltdl-dev libtool-bin libglade2-0 libglade2-dev libgtk-3-dev libxml2 libxml2-dev

Bunları kurduktan sonra sırayla cnrdrvcups-common-6.20 ve cnrdrvcups-lb-6.20 dizinlerindeki allgen.sh scriptini çalıştırıp kodu derledim ve make install ile dosyaları kopyaladım. Bir de DietPi'de cnrdrvcups-lb-6.20'yi derlerken bir gösterici dönüştürme hatası alınıyor. O nedenle CFLAGS değişkenini -fpermissive olarak ayarlamak gerekiyor. Ben bunun için allgen.sh içindeki case yapısına aşağıdaki case'i ekledim:

    "armv6l")
        _machine_type="MACHINETYPE=armv6"
        _cflags="CFLAGS=-fpermissive"
    ;;

Bunları yaptıktan sonra, ne derlerken ne de CUPS'tan yazıcıyla ilgili bir hata aldım, ama lokalden gönderdiğim yazdırma istekleri dahi yazıcıya ulaşmadı. Sorunu henüz çözemedim ama denemediğim bir kaç şey var, çözebilirsem bu ayrı bir makale konusu olabilir. Özetle hem WiFi sorunu -çözülmüş bile olsa- hem de yazıcı sorunu nedeniyle RPi 1B ile zaman kaybetmeyip çalışır haldeki RPi 4'e yoğunlaşmaya karar verdim.


Kurulum Adımları

Yazının bu bölümünde "Raspberry Pi Print Server" makalesini referans aldım. RPi 4 kurulumunu uzun uzun anlatmayacağım. İmaj dosyasını SD karta aktarıp boot ettikten sonra, bir sihirbaz kullanıcı adı ve WiFi gibi ayrıntıları sorup sistemi hazırlıyor. Eğer SSH açık değilse

sudo systemctl enable --now ssh

komutuyla açılabilir. Ardından makalede sözü edilen paketleri yükledim:

sudo apt install cups printer-driver-gutenprint hplip samba cups-bsd

Açıkçası hplip ve printer-driver-gutenprint pek işime yaramadı. Yazıya göre Canon dahil birçok yazıcı sürücüsü içeriyormuş ama görünüşe göre MF4450 modeli yok. cups-bsd ise Canon sürücüsünün bağımlı olduğu bir paket.

CUPS bir web arayüzü üzerinden çalışıyor ve burada ayar yapabilmek için kullanıcının lpadmin grubunda veya root olması gerek. Aşağıdaki komutla kullanıcı kendini bu gruba ekleyip CUPS'a dışarıdan erişim izni veriyor:

sudo usermod -a -G lpadmin $USER
cupsctl --remote-any
sudo systemctl restart cups

Bu adımdan sonra ağdaki bir bilgisayardan http://<makinaIP>:631/ adresinden erişilebiliyor olmalı. Erişim yoksa host firewall çalışıyor olabilir. Bu durumda sudo ufw disable ile firewall'u kapatarak veya söz konusu port açılarak erişilebilir. Hala erişilmiyorsa o portta çalışan bir process olup olmadığı ve CUPS'ın çalışıp çalışmadığı kontrol edilmelidir.

Buraya kadar herşey tamamsa küçük bir parantez açıp yazıcı sürücüsünü kurmalıyım.


Raspberry Pi 4'de Yazıcı Konfigürasyonu

RPi 4'te yazıcıyı tanıtmak için, RPi 1 için kullandığım sürücü paketini kullandım. Yazıcıyı bağladıktan sonra ARM64/Debian dizinindeki .deb dosyayı aşağıdaki komutla kurdum.

sudo dpkg -i cnrdrvcups-ufr2-uk_6.20-1.20_arm64.deb

Burada dikkat edilmesi gereken bir ayrıntı var: Eğer bir pencere yöneticisi kuruluysa, kurulum sırasında masaüstünde yandaki gibi bir pencere açılıyor. Siz SSH üzerinden kuruyorsanız, kurulum durdu gibi geliyor. Halbuki program GUI üzerinden girdi bekliyor. Bu nedenle kurulum sırasında monitörü de bağlamak gerekli. Bağlı yazıcı otomatik tanınıyor. Sonraki adımda yazıcının modeli seçilerek kurulum tamamlanıyor.



RPi 1'de saatlerce ve farklı şekillerde derlediğim halde varamadığım noktaya, RPi 4'le ortalama on dakika gibi bir sürede geldim. Şimdi tekrar servis konfigürasyonuna geri dönüyorum.


En başta yüklediğim samba, yazıcıyı Windows makinalara paylaştırmak için gerekli. Benim cups.conf'ta bir değişiklik yapmam gerekmedi. Herhangi bir dizin paylaşmayacağım için, smb.conf'ta [homes] bölümünü kapattım (comment out). [printers] ve [print$] bölümlerinde, guest ok = yes olarak ayarladım. testparm -s ile hata var mı diye kontrol edip, systemctl reload smbd komutuyla yeni ayarları yükledim.

DietPi'de bu adımlar biraz farklı. Birincisi CUPS ve samba'nın dietpi-software programıyla yüklenmesi tavsiye ediliyor. İkincisi DietPi'nin özelleştirilmiş bir smb.conf'u var. Default [printers] ve [print$] bölümlerini smb.conf.example dosyasından kopyalamak gerekiyor.

CUPS ile sürücü birbirinden bağımsız. Sürücü yüklü olmasa bile CUPS, yazıcıyı bulup web arayüzünde gösteriyor ve sorunsuz şekilde ekleniyor. Bunun için ilk iş web arayüzünde üst frame'den Administration'ı seçtim. Bu adımda HTTP'den HTTPS'e yönlendirme yapıldığı için tarayıcıda sertifika uyarısı çıkıyor. Bunu geçip lpadmin'e eklediğim kullanıcıyla login oldum. "Find New Printers"a basınca yazıcıyı otomatik buldu. "Add This Printer"a basınca hangi adla ekleyeceğimi soran bir sayfa çıktı. Burada tek önemli konu "Share This Printer"ı seçmek. Sürücü yüklenmişse sonraki sayfada Canon'un model listesi çıkıyor. Bu adım sürücüyü yüklemeden, bağlı yazıcının PPD dosyasını yükleyerek geçilebilir. Canon MF4450 yazıcı için uygun dosya CNRCUPSMF4400ZK.ppd. Bunu, sürücü paketindeki herhangi bir .deb veya .rpm dosyadan makinama açabilirim. Fedora'da bu

rpm2cpio cnrdrvcups-ufr2-uk-6.20-1.20.aarch64.rpm | cpio -idmv

komutuyla yapılabilir. PPD dosyalar yazıcının özelliklerini içeren tanım dosyalarıdır. Platform ve dağıtımdan bağımsızdırlar. Sürücü seçme sayfası aşağıdaki görseldekine çok benzer, fakat ben yazıcıyı eklemiş bulunduğum için "Modify Printer" sayfasının görselini ekledim.


Yazıcıyı ekledikten sonra artık üst frame'in sağında Printers altında listeleniyor. (bu aşamada yazıcıyı silip farklı bir adla tekrar eklemem gerekti, bu nedenle bundan sonraki ekran görüntülerinde yazıcı adı farklı oldu).


Bu yazıcıya tıkladığımda yazıcı ve kuyruk ayarlarının yönetilebildiği sayfa açılıyor (yanda). Burada doğru PPD dosyayı yükleyip yüklemediğime bakacağım. Aynı PPD dosyanın Avrupa ve Amerika sürümünde varsayılan kağıt büyüklükleri farklı (A4 ve Letter). Yanlışlıkla Amerika sürümünü yükleyince yazdırma işi yazıcıya Letter olarak gidiyor ve yazdırmada bir uyarı çıkıyor. Ancak bu ekran görüntüsünden de görüleceği üzere burada doğru ayarlar seçili. Eğer bu ayarlarda Letter seçiliyse, 'Administration' menüsünden 'Set Default Options'ı seçip

çıkan sayfadan kağıt büyüklüğü A4 olarak değiştirilmelidir.


Son olarak ben bu arayüzde Maintenance -> Print Test Page ile bir test çıktısı aldım.


Eğer bu çıktı sorunsuz geliyorsa yazıcı kurulmuştur. İlk denememde sürücüleri kurmadan sadece PPD dosyayı girdiğimde, bu adımda çıktı gelmiyordu ve 'Show All Jobs' butonuna bastığımda rastertoufr2 ile ilgili bir hata veriyordu. Bu hata çıkıyorsa sürücü yüklen(e)memiştir. Normalde bu dosyanın /usr/lib/cups/filter/rastertoufr2 yolunda olması gerekir. Bu adımda artık sürücüyü yüklemekten kaçış yok. Yalnız bu dosyanın çağırılması gerektiği PPD dosyada belirtiliyor. Belki PPD dosyada bu satır değiştirilirerek birşeyler yapılabilir.

Ve son olarak bir ayar daha kaldı: Debian, uzun süre kablosuz ağ kartında bir aktivite görmediği zaman kartı kapatıyor. Bunu engellemek için

nmcli connection mod <SSID> 802-11-wireless.powersave 2

komutunu girmek gerek. Böylece yazıcı yerel ağa açılmış oldu.


Yazıcıyı Windows ve Linux İstemcilere Tanıtmak

Yazıcıyı ağ yazıcısı olarak yerel ağdaki bilgisayarlara tanıtmak gayet kolay. Üstelik itiraf edeyim Windows'ta Fedora'dan daha kolay. Muhtemelen diğer Linux dağıtımlarında da benzer şekildedir ama elimde Fedora olduğundan ben buna yoğunlaşacağım.


Fedora'da yazıcı eklemek için System Settings -> Printers'ı açtım, yukarıdaki '+ Add'e bastım ve ağ yazıcısı kısa sürede bulundu. Burada (aşağıda) 'Select Recommended Driver'a bastığım zaman IPP Everywhere seçiliyor.


Bunu seçerek devam ettim ve sonraki adımda yazıcının nasıl ekleneceğine dair bir ayar ekranı geldi. Burada hiçbir şeyi değiştirmeden devam ettim. Queue Name'in yerel makinaya özgü ve eşsiz (unique) bir ad olması gerek. Description ve Location alanları isteğe göre değiştirilebilir.

Benim sistemimde başka bir yazıcı bulunmadığı için 'Default printer' seçeneğinin bir önemi yok. Bunlar tamamsa 'Add'e basılarak yazıcı eklenir ve yazıcı listesinde bu yazıcının listeleniyor olması gerekir.


Yazıcının üzerine tıklayınca gelen formda 'Print Test Page'e basarak yazıcı test edilebilir.

Windows'ta (v10 ve v11) ayarlardan yazıcıları seçince veya başlat menüsünde Printers yazınca gelen formda, 'Add a printer or scanner' yanındaki 'Add device' butonuna basınca yazıcı otomatik listelendi. Listelenen yazıcının yanındaki 'Add device' butonuna basıldığı zaman, sisteme otomatik ekleniyor ancak bu adım 1-2 dakika kadar sürebiliyor. Muhtemelen bu sırada sürücüler internetten indiriliyor.


18 Aralık 2021 Cumartesi

Linux from Scratch ve LVM İçin initrd Oluşturmak


Merhaba. Uzun zamandır elektronikle ilgili yazmak istediysem de, maalesef yine olmadı. Bugünkü konum, beni iki hafta uğraştıran bir konfigürasyon. Daha doğrusu initrd oluşturmak. Peki neden böyle bir şeye ihtiyaç duydum?

Öncelikle LVM'den başlayayım. LVM'le ilk başlarda kötü deneyimlerim olsa da, 2014'ten beri o kadar alıştım ki, şu an bence LVM'siz linux kurulumu düşünülemez. Birden çok diske yayılmış bölümlerim yok ama bence en güzel özelliği diski taşıma ve yeniden boyutlandırma konusundaki esnekliği.

Konunun diğer tarafı Linux from Scratch (LFS) projesi. LFS, kullanıcılara linux çekirdeğini, bash kabuğunu ve linux'ta temel düzeyde çalışabilmek için gerekli araçları, sıfırdan yani kaynak kodlarından nasıl derleneceğini adım adım anlatan bir proje. Elbette çalışan bir derleyiciyle başlamak gerekiyor. gcc'yi cross compiler olarak derledikten sonra, temel araçlar bununla derleniyor ve minimal bir chroot (change root) ortamı oluşturuluyor. Son adımdaysa linux çekirdeği derleniyor ve grub ile boot edilebilir duruma getiriliyor. Bu projeden, Viktor Engelmann'ın videoları sayesinde haberim oldu. Ben burada onunkinden farklı bir yol izleyeceğim. Zaten ikimiz de LFS dökümantasyonundan, (LFS terminolojisiyle "kitap"tan) kısmen farklı bir yol izliyoruz ancak yapılacaklar kitabı temel alıyor. Benim izleyeceğim bir kaç adım (B)eyond LFS kitabından olacak.

Kitap, systemd ve initd sürümü olarak ikiye ayrılıyor ama ikisi arasında sekizinci bölümdeki paketlere kadar fark yok. Bu yazıda kitabın v11.0 sürümünü temel alıp ikisini de derleyeceğim. LFS'in sayfasında "Download" ve "Read Online" olmak üzere kitabın iki farklı sürümü var. Download bölümündeki .pdf dosya daha derli toplu olsa da, .html sürümü komutları kopyalayıp yapıştırmak için daha rahat. Bu arada projede zamanın çoğu paket derlemekle geçtiği için (tüm LFS'i derlemek benim makinamda 16 saat civarında sürdü, testler hariç), tek tek komutları tekrarlamak yerine yalnız kitaptan farklı yaptığım adımlara değineceğim.

Not: Bu yazıda verdiğim bağlantılar, yazıldığı tarih itibariyle kitabın son sürümüne bağlı. Dolayısıyla, v11'den daha güncel bir sürüm çıktığında, bazı bağlantılar farklı bölümleri açacaktır.


Sistem Gereksinimleri

Kitapta 10 GB'lik bir bölümün paketleri derlemek için yeterli olduğu, ama günlük kullanım için 30 GB'lik bir bölümün gerekeceği yazıyor. Çekirdeğin çok fazla özelliğini açıp (Fedora çekirdeğini) derlerken disk kullanımı 20 GB'yi geçtiği oldu.

Ben LFS için iki diskli bir sanal makina'nın (VM) birinci diskine işletim sistemi kurup, paketleri ikinci diskte derleyeceğim. Bunun avantajı, yanlışlıkla (chroot'ta olmadığımı unutup) kendi sistemimi bozma riskinin bulunmaması. Kod derlemek, yüksek disk performansı gerektiren bir iş. Bu nedenle, en iyisi SSD'de çalışmak. VM, zaten hostunun kendi disk performansına yakın bir performans verecektir. VM'in bir avantajı da, fiziksel diskte yeni bölüm ayıracak kadar boş yer yoksa bile izole bir ortam sağlayabilmesi.

Viktor Engelmann, videolarında paketleri USB belleğe indirip derliyor. Ben bunu mantıklı bulmuyorum. Dönen diskler bile USB belleklerden daha fazla performans sağlıyor. USB'de çalışmak bu iş için verimli değil. Eğer LFS, USB'den boot edilecekse, herşey diskte derlenip grub adımından önce USB belleğe kopyalanır ve önyükleyici en sonda USB'ye yazılabilir.

Projede disk dışında bir gereksinim bulunmuyor. Elbette hızlı bir işlemci, derleme süresini kısaltacaktır ama yavaş bir işlemcide de aynı sonucu almak mümkün.

Birinci diske kurulacak işletim sistemi konusunda da bir kısıtlama yok. Ben kendimi RedHat tabanlı sistemlerle rahat hissettiğim ve uzun zamandır CentOS 8 Stream'i denemek istediğim için bunu kullanacağım.


Sanal Makina Kurulumu ve Diskleri Oluşturmak

Yazıyı gereksiz uzatmamak için kurulumun detaylarına girmeyeceğim. Sanallaştırmayı hem VBox hem vmware'de denedim. Önceki yazıda, çekirdeği vmware için derlerken fazladan iki özelliğin aktifleştirilmesi gerektiğini anlattım, buna yeri geldiğinde tekrar değinirim. 2 GB RAM'li ve 20 GB diskli bir VM oluşturdum. Kurulumda temel olarak "Minimal Install" ve ek paket olarak "Development Tools"u seçtim (yanda). Tüm ayarlar aşağıdaki görseldeki gibi. Kurulumda LVM kendiliğinden oluşturuluyor, ben elle ayarlamadım. Benim asıl ilgilendiğim LFS'teki LVM yapısı, ve bunu elle oluşturacağım. Ama önce 40 GB'lık bir disk daha eklemeliyim. VBox'ta sanal makina çalışırken disk eklenemiyor (Sonradan gelen düzeltme: aslında eklenebiliyormuş). Vmware'de diski, VM çalışırken ekleyip echo "- - -" > /sys/class/scsi_host/host2/scan komutuyla tanıtmak veya makinayı yeniden başlatmak gerekiyor. Bende disk host2'ye bağlıydı (VBox için de aynı komut uygulanır).

CentOS'ta sshd çalışır olarak geliyor. Makinanın IP'sini bulup ssh ile bağlandım. Komutları kopyalayıp terminale yapıştırmak konsola elle girmekten daha kolay. VM, NAT'la bağlıysa "port forwarding"i ayarlamak gerekiyor. Buna da eski yazıların birinde değinmiştim.

Benim LVM şablonum, diskin başında 512 MB'lik bir /boot bölümü, kalanında LVM bölümü ve LVM içinde 4'er GB'lik /var, /home bölümleriyle 2'şer GB'lik /tmp ve swap, kalan alanda da kök dizin. Kök dizin harici bölümlerde toplam kullanım 60 MB'ı aşmıyor. Haliyle 12.5 GB'lik alan boş kalıyor. Yukarıda yazdığım gibi kök dizin kullanımı 16 GB'yi bulabilir. Bu yüzden 40 GB'lık görece büyük bir disk ekledim. Kurulum bittiğinde disk dosyasının net büyüklüğü 28.8 GB'dı.

Diski aşağıdaki komutla hızlıca bölümlendirdim:

echo -ne "n\np\n1\n\n+512M\nn\np\n2\n\n\nt\n2\n8E\np\nw\n" | sudo fdisk /dev/sdb

Sonuç, komutun çıktısından kontrol edilebilir:

Device     Boot   Start      End  Sectors  Size Id Type
/dev/sdb1          2048  1050623  1048576  512M 83 Linux
/dev/sdb2       1050624 83886079 82835456 39.5G 8e Linux LVM

Sonra sırayla LVM içindeki bölümleri oluşturdum:

sudo pvcreate /dev/sdb2
sudo vgcreate vg_lfs /dev/sdb2
sudo lvcreate -n lv_var  -L 4G vg_lfs
sudo lvcreate -n lv_home -L 4G vg_lfs
sudo lvcreate -n lv_swap -L 2G vg_lfs
sudo lvcreate -n lv_tmp  -L 2G vg_lfs
sudo lvcreate -n lv_root -l100%FREE vg_lfs
sudo lvscan

Son komutla hem yeni bölümleri hem de CentOS'un bölümlerini görmeliyim. Bölümler oluşturulduktan sonra formatlanmaları gerek:

sudo mkfs.ext4 /dev/sdb1
sudo mkfs.ext4 /dev/vg_lfs/lv_root
sudo mkfs.ext4 /dev/vg_lfs/lv_tmp
sudo mkfs.ext4 /dev/vg_lfs/lv_home
sudo mkfs.ext4 /dev/vg_lfs/lv_var
sudo mkswap    /dev/vg_lfs/lv_swap

LFS kitabı, kurulumda ext4 dosya sistemi kullanıldığını varsayıyor (bölüm 2.5).


LFS Çalışma Ortamını Oluşturalım

İlk olarak bölüm 2.2'deki betiği kaydedip çalıştırdığımda, yalnızca python3 ile makeinfo bulunamadı. Python'ı sudo dnf install python3 komutuyla yükledim. Diğer pakete sonra geleceğim.

export LFS=/mnt/lfs komutuyla LFS değişkenini oluşturup, bunu .bash_profile'a da ekledim (bölüm 2.6). Elbette ilgili dizini de oluşturdum. Diskleri mount etmem gerek (bölüm 2.7) ama dört bölümü elle mount etmemek için bir betik hazırladım:

#!/bin/bash

if [[ x$LFS == "x" ]]; then
    echo '$LFS' variable is empty.
    exit 1
fi

STEP=1
for PARTITION in "/" "var" "home" "tmp"; do
    if [[ $PARTITION == "/" ]]; then
        LVMNAME="root";
    else
        LVMNAME=$PARTITION;
    fi

    echo "[ $STEP / 5 ] Mounting $LVMNAME partition"
    if [ ! -d "$LFS/$PARTITION" ]; then
        sudo mkdir -pv "$LFS/$PARTITION";
        sudo chown $USER:$GROUPS "$LFS/$PARTITION";
    fi

    sudo mount "/dev/vg_lfs/lv_$LVMNAME" $LFS/$PARTITION
    sudo chown $USER:$GROUPS "$LFS/$PARTITION";

    STEP=$((STEP+1))
done

echo "[ 5 / 5 ] Activating swap.."
sudo swapon /dev/vg_lfs/lv_swap  2> /dev/null

Betiği tek bir kullanıcı çalıştıracaksa $USER ve $GROUPS yerine kullanıcı adı ve grubu yazılabilir. Bir de son adımda swap'i aktifleştirmeye bence gerek yok.


LFS Paketleri

Paket denildiğinde .rpm veya .deb dosyaları anlaşılmasın. Bizimkiler kaynak kod paketleri. Bunları indirmeden önce, eksik bir kaç paketi daha kurmak gerek. wget, vim-enhanced ve son olarak atladığım makeinfo. Bu, texinfo paketinde geliyor ama paketin bulunduğu "powertools" reposu aktif değil. Bu yüzden şöyle yaptım:

sudo dnf install --enablerepo="powertools" texinfo wget vim-enhanced

Sonra sources dizinini oluşturup (bölüm 3.1), wget listesiyle dosyaları buraya indirdim ve tabii ki md5'lerini kontrol ettim. İndirmede bazen sorun olursa, wget'e --no-check-certificate parametresini vermek gerekiyor.

Bölüm 4.2'deki komutları çalıştırmak için root'a geçtim ama LFS değişkenini root'ta tanımlamadığımdan önce bunu tanımladım, sonra komutları çalıştırdım. VM'de olduğum için lfs kullanıcısı (4.3) oluşturmayacağım. Dizinlerin sahipliğini kendi kullanıcıma aktadım. Verilen .bashrc'yi, lfs_env.sh adıyla ev dizinime (root değil) kaydettim ve source'la yükledim. VM'i reboot edersem bunu çalıştıracağım.

Beşinci ve altıncı bölümleri olduğu gibi uyguladım. 7.2'deki ve 7.3.2'ye kadar olan komutları çalıştırdım. Bundan sonraki komutlar chroot ortamına her girişte çalışacağı ve çıkışta da mount edilen kaynakların ters sırada umount edilmeleri gerektiği için, verilen komutlardan bir betik oluşturdum:

#!/bin/bash

if [[ x$LFS == "x" ]]; then
    echo '$LFS' variable is empty.
    exit 1
fi

mount -v --bind /dev $LFS/dev
mount -v --bind /dev/pts $LFS/dev/pts
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
mount -vt tmpfs tmpfs $LFS/run

if [ -h $LFS/dev/shm ]; then
  mkdir -pv $LFS/$(readlink $LFS/dev/shm)
fi

chroot "$LFS" /usr/bin/env -i HOME=/root  TERM="$TERM"  PS1='(lfs chroot) \u:\w\$ ' PATH=/bin:/usr/bin:/sbin:/usr/sbin /bin/bash --login +h

umount -v $LFS/run
umount -v $LFS/sys
umount -v $LFS/proc
umount -v $LFS/dev/pts
umount -v $LFS/dev

chroot'dan çıkarken özellikle /dev/pts unmount edilmediğinde, sanal makinada yeni bir terminal açılamıyor ve makinayı yeniden başlatmak gerekiyor.

chroot'a girip gerekli dizin ve dosyaları oluşturmaya devam ettim. Bu arada bölüm 7.6'da /etc/passwd ve /etc/group dosyaları, systemd ile sysVinit'in farklılaştıkları ilk nokta.

Betik, chroot'dan çıkışta kaynakları unmount ettiğinden, bölüm 7.14'teki umount'lara gerek kalmadı. Ayrıca kurulumu sanal makinada yaptığımdan yedeklemeyi de snapshot'la yapabilirim. Bu nedenle bu adımlara da gerek yok.

8.25'te shadow'u cracklib desteğiyle derlerken "undefined reference to `FascistCheck'" hatasını aldım. Aşağıdaki komutla bir kere daha konfigüre edip derlediğimde sorun olmadı:

LDFLAGS=-lcrack ./configure --sysconfdir=/etc --with-libcrack --with-group-name-max-length=32

8.26'daki "make -k check" adımı çok uzun sürüyor. Öyle ki testi yatmadan önce başlattım, sabah kalktığımda hala tamamlanmamıştı. Anladığım kadarıyla 350K'dan fazla test var ve testlerin bir kısmı stres testi. Ayrıca kitapta bazı testlerin başarısız olduğunun bilindiği yazılmış. Test sonuçlarına şuradan ulaşılabilir. Bendeki test sonuçları da hemen hemen bunlarla aynıydı. Bu bölümün sonunda basit bir derleme testi var. Belki sadece o testi yapmak yeterli olabilir ama kitap "make check" adımının kesinlikle atlanmamasını istiyor.

Bölüm 8.69'da artık systemd ve sysVinit paketleri farklılaşıyor.

Son olarak 8. bölümün sonunda lfs_enter_chroot.sh betiğinde bash'a verdiğim +h parametresini kaldırıp tekrar kaydettim.

Dokuzuncu bölüm initd/systemd ayarları. Yani bu bölüm iki kitapta tamamen farklı. Bu bölümde kitaptakileri birebir uyguladım. Türkçe klavye için initd'de /etc/sysconfig/console veya systemd'de /etc/vconsole.conf dosyasına KEYMAP=trq girdim, herhangi birşey girmeyince İngilizce klavye yükleniyor. /tmp için ayrı bir bölüm ayırdığımdan systemd kitabında 9.10.3'ü atladım.

Bölüm 10.2'de fstab ayarlanacağı için bu bölüm önemli. En başta oluşturduğum bölümleri burada fstab'a girmem gerek. /boot için ayırdığım bölüm ikinci diskte olduğundan şu anda aygıtın adı /dev/sdb1. Ama LFS'i boot etmek için birinci diski sanal makinadan ayırdığım zaman, bu bölüm /dev/sda1 olacak. Bu nedenle bu adlandırmayı kullanamam. Linux'ta her diskin eşsiz ve değişmez bir UUID'i bulunur. Bu değeri kullanmalıyım ki, /boot her zaman mount edilebilsin. Bunun için ls -la /dev/disk/by-uuid çıktısında sdb1'e linkli değeri bulurum veya:

lsblk -o NAME,MAJ:MIN,RM,SIZE,RO,TYPE,MOUNTPOINT,UUID

komutuyla diskleri UUID'leriyle birlikte listelerim. lsblk çıktısı daha ayrıntılı ama nedense chroot içinde UUID sütunu boş. Bu nedenle, komutu chroot'un dışında çalıştırdım ve değeri not alıp fstab'i oluşturdum:

/dev/mapper/vg_lfs-lv_root   /       ext4   defaults  1  1
/dev/mapper/vg_lfs-lv_var    /var    ext4   defaults  0  0
/dev/mapper/vg_lfs-lv_home   /home   ext4   defaults  0  0
/dev/mapper/vg_lfs-lv_tmp    /tmp    ext4   defaults  0  0
/dev/mapper/vg_lfs-lv_swap   swap    swap   pri=1     0  0
UUID=01234567-89ab-cdef-0123-456789abcdef /boot ext4 defaults 0 0

ve elbette initd sürümü için proc, sysfs, devpts vb. girdilerin de eklenmesi gerekiyor. Bu girdiler kitapta zaten olduğundan burada yer vermedim.


Linux Kernel'ini Derlemek

Bütün paketleri hazırladıktan sonra artık iş kerneli (çekirdeği) derlemeye kaldı. Her iki kitabın 10.3 bölümü çekirdeği derlemekle ilgili. Ben öncelikle make mrproper ve ardından make defconfig komutlarıyla çekirdeğin en standart özelliklerini seçtim. Bir önceki yazıda bunları yeterince detaylı açıklamıştım. Diğer özellikleri düzenlemek için make menuconfig'i kullanacağım.

make menuconfig metin arayüzü
systemd ayarları
initd sürümü için defconfig'de fazla değişikliğe gerek yok. uevent helper'ın kapalı ve devtmpfs desteğinin açık olması yeterli. Ama systemd sürümü için biraz daha fazla seçeneği değiştirmek gerekiyor (yanda).

Systemd'nin Errata'sında da belirtiliyor, yandaki CONFIG_SECCOMP'un yeri yanlış ama sorun değil, çünkü defconfig'de bu özellik zaten açık. Bu özellik yine de menuconfig içinde aratılabilir veya .config'den bakılabilir:

(lfs chroot) root:/sources/linux-5.13.12# grep -n SECCOMP  .config
687:CONFIG_HAVE_ARCH_SECCOMP=y
688:CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
689:CONFIG_SECCOMP=y
690:CONFIG_SECCOMP_FILTER=y
691:# CONFIG_SECCOMP_CACHE_DEBUG is not set

Bu arada, bu yalnız benim kişisel görüşüm ama kendi deneyimim (irc) ve posta listesi arşivine dayanarak LFS destek kanallarındakilerin biraz ters insanlar olduklarını düşündüğüm için, bu tür hataları kendime saklamayı tercih ediyorum.

Konuya döneyim. Hedefim LFS'i LVM desteğiyle kurmaktı. LFS, en temel linux kurulumunu içeriyor, örn. pencere yöneticisi yok. Temel kurulumdan sayılmayan LVM de, (B)eyond LFS adında ayrı bir projenin parçası. BLFS kitabının LVM bölümünde, LVM için açılması gereken diğer özelliklerin listesi verilmiş. Bunları açıp modüler olanları da çekirdeğe dahil edeceğim (kişisel tercih). Bu arada LVM için Gentoo dökümanlarının ne önerdiğine bakıp, BLFS'te olmayıp Gentoo'da önerilen bir kaç özelliği daha aktifleştirdim. Eksik özelliklerden ötürü kerneli tekrar derlemektense, bir kaç KB büyük bir kernelle boot etmeyi tercih ederim.

Son olarak vmware'le çalışan okurların, bir önceki yazının ana konusunu oluşturan "Fusion MPT device support"u da aktifleştirmesi gerek. Bu, özetle vmware'deki SCSI denetleyicinin sürücüsü ve bu olmadan, çekirdek sabit diski bulamayıp boot edemiyor. Bu özellik "Device Drivers" menüsü altında bulunabilir.

Tüm bu adımları tamamladıktan sonra, LFS bölüm 10.3.1'e dönüp kerneli make'le derledim ve ardından modülleri yükledim. Benim /boot bölümü /dev/sdb1'de olduğu için mount /dev/sdb1 /boot ile boot bölümünü mount edip; vmlinuz (kernel), System.map ve config dosyalarını kopyaladım.


Önyükleyici: GRUB

Kerneli derleyip /boot'a kopyaladıktan sonra sıra GRUB'u ayarlamaya geldi. Bu aşamada iki seçeneğim var: GRUB'u /dev/sdb'ye kurabilirim (aslında başta planım buydu) veya CentOS'un GRUB'ına (/dev/sda) ekleyebilirim. Birinci seçeneğin avantajı, diskin CentOS'tan bağımsız çalışacak biçimde ayarlanıyor olması. İkincinin avantajıysa kolay olması.

Önce birinci seçenek: grub-install /dev/sdb komutunu girdim. grub.cfg dosyası kitaptakinden biraz farklı olacak:

set default=0
set timeout=5

insmod ext2
set root=(hd0,1)

menuentry "GNU/Linux, Linux 5.13.12-lfs-11.0-systemd" {
    linux   /vmlinuz-5.13.12-lfs-11.0-systemd root=/dev/vg_lfs/lv_root ro
}

set root'la ayarlanan "grub root" sıfırıncı diskin ilk bölümü. Grub açısından LFS diski, henüz sıfırıncı değil ama CentOS'un kurulduğu diski çıkarınca öyle olacak. /boot bölümü ayrı olduğundan linux satırında /boot'a gerek yok. Çekirdeğe girilen root parametresiyse, root disk bölümünün aygıt yolu (device path). Bu arada yukarıda systemd için olan ayarlar var. initd için, menuentry ve linux satırlarında "-systemd" ifadesi olmaycak.

Bunu kaydettikten sonra chroot'tan çıkıp, sanal makinayı kapattım ve birinci diski sanal makinadan çıkarttım. Makinayı tekrar açtığımda, az önce oluşturduğum grub menüsünü gördüm ve bu girdiden boot ederken kernel panic aldım. Yeey!. Tamam, her ne kadar sevinilecek bir durum olmasa da, bu iki şeyi gösteriyor: (1) grub doğru şekilde ayarlanmış, (2) kernel dosyaları düzgün derlenmiş ve /boot'a kopyalanmış.

O halde neden kernel panic aldım. Call trace'de görüldüğü gibi mount_block_root fonksiyonunda, kök dizine mount edeceği (grub'da root= ile verilen) diski bulamamış. Neden? Çünkü LVM henüz aktif olamadı. Burada yapacak birşey olmadığından çıkardığım diski geri takıp CentOS'a döndüm.

Peki her defasında LFS'i açmak için diski sökmek ve sorun olduğunda CentOS'a geri dönmek için geri takmak zorunda mıyım? Hayır! CentOS'tayken /etc/grub.d/40_custom dosyasının sonuna şu satırları ekledim:

menuentry "GNU/Linux, Linux 5.13.12-lfs-11.0-systemd" {
  set root=(hd1,1)
  linux   /vmlinuz-5.13.12-lfs-11.0-systemd root=/dev/mapper/vg_lfs-lv_root ro
}

Bu, yukarıda andığım ikinci grub seçeneği ve aslında ilk konfigürasyonun aynısı, sadece set root, menuentry içinde. Örnek yine systemd için. initd için "-systemd" kısmı olmayacak. Sonra eklediğim satırı, CentOS'un grub.cfg'sine aktardım:

GRUB_DISABLE_OS_PROBER=true  grub2-mkconfig -o /boot/grub2/grub.cfg

OS prober diğer işletim sistemlerini otomatik bulup grub'a ekleyen güzel bir özellik ama bir bug yüzünden düzgün çalışmıyor. Şimdi, işletim sistemleri arasında geçiş yapmak kolaylaştığına göre kaldığım yerden devam edebilirim.


initramfs

BLFS kitabındaki LVM bölümünü (veya systemd LVM bölümünü) açtım. About LVM'in sondan ikinci paragrafında, kök dosya sisteminde LVM kullanabilmek için initramfs gerektiği yazıyor. initramfs, temel bazı programları ve konfigürasyonları içeren sıkıştırılmış sanal bir disk. Initial RAM Filesystem'in kısaltması. Bu dosya (varsa) önyükleyici tarafından kök dizine açılıyor. İçindeki programlar ve conf dosyaları sistemin açılmaya devam etmesi için gereken işleri yapıyor. Bir çok dağıtımla gelen "rescue kernel" da aslında kabuğu içeren basit bir initramfs.

BLFS'in kendi initramfs oluşturma betiği var. LVM desteğini initramfs'e eklemek için öncelikle lvm yüklü olmalı. Bunun için de;

1) Önce LVM'in önkoşulu olan libaio
2) which sadece LVM için değil, sorun bulmada da çok işe yarayan bir araç
3) mdadm. Testleri atlanabilir, zaten kitaptaki komutla çalışmıyorlar.*
4) initramfs'i sıkıştırmak için cpio
5) LVM. Bunun da testleri uzun sürüyor ve bazıları sorunlu. LVM'i kitaptaki --with-thin* ve --with-cache* parametreleri yanısıra --with-vdo=none ile konfigüre ettim. Kritik olmasa da systemd için LVM'de fazladan bir komut var.
6) ve initramfs betiği yüklü olmalı.

* Test etmedim ama sanıyorum mdadm olmadan da bu sistem çalışabilir.

initramfs betiği iki parçadan oluşuyor. Birinci parça betiğin kendisi ve ikinci parça init.in adında, initramfs'e init adıyla kopyalanacak olan dosya. LFS v10.1'de bu betik sorunluydu (bug). initramfs'te de mutlaka bulunması gereken coreutils ve util-linux'un bileşenlerini (ls, cp, mount, umount vb.), /bin yerine /usr/bin'de aradığı için hata verip sonlanıyordu. Betiğin /usr/lib'de aradığı ama aslında /lib'de olan dosyalarda da aynı sorun vardı. Çözüm olarak dosyaları /usr/bin ve /usr/lib'de olmaları gereken yere linklemiştim. Bu bug v11'de düzeltilmiş.

Betiğe kernel sürümünü parametre olarak girdiğim için, kernel modüllerini (.ko dosyaları) de initramfs'e ekleyerek dosyayı oluşturdu.

(lfs chroot) root:~# mkinitramfs 5.13.12
Creating initrd.img-5.13.12... done.

Dosyayı /boot'a kopyaladım (bölüm bağlı olmalı) ve chroot'tan çıkmadan önce /boot/grub/grub.cfg'yi aşağıdaki gibi değiştirdim:

menuentry "GNU/Linux, Linux 5.13.12-lfs-11.0-systemd" {
  linux /vmlinuz-5.13.12-lfs-11.0-systemd root=/dev/vg_lfs/lv_root ro
  initrd  /initrd.img-5.13.12
}

CentOS'un grub'unu kullandığım için aslında yukarıda yaptığım konfigürasyon yalnız CentOS diski söküldüğü zaman çalışacak. chroot'tan çıkıp, eklediğim satırı /etc/grub.d/40_custom dosyasına da ekleyip, tekrar şu komutu çalıştırdım:

GRUB_DISABLE_OS_PROBER=true  grub2-mkconfig -o /boot/grub2/grub.cfg

Makinayı yeniden başlattım. LFS'i seçtim ve sonuç:

ve systemd'li kurulum için aynı sonuç:

systemd'li makinada çalışmayan bazı servisler olsa genel olarak ikisi de sorunsuz açılıyor.

4 Aralık 2021 Cumartesi

Linux Kernel'ini Vmware için Derlemek


Merhaba. Bu yazıda linux kernel (çekirdek) derleme hakkında genel bilgiler verip, karşılaştığım bir sorunun çözümünü ele alacağım. Bu aslında sonraki yazının bir bölümü olacaktı, ama sorun o kadar uğraştırdı ki, ayrı bir yazıda ele almaya değeceğini düşündüm. Başlık zaten sonraki yazı hakkında ipucu verecektir.


Linux'ta Kernel Derlemek

Kernel derlemek, özel bir cihazla çalışmıyorsanız (örn. gömülü (embedded) sistem veya standart kernel'ın desteklemediği çok yeni bir donanımla) veya LFS gibi deneysel veya Gentoo gibi kernel'ın derlenmiş olarak gelmediği bir dağıtım kullanmadıkça, gündelik kullanımda yapılması gereken birşey değil. Öte yandan, öğrenmek veya sisteme en düşük seviyede hakim olmak için bence bilinmesi mutlak gerekli. Zaten bir kaç tane önkoşulu yerine getirip, temelleri bildikten sonra, herhangi bir kaynak kodu derlemekten daha kolay.

Ben bu yazıda kernel v5.13.12'yi derleyeceğim. İhtiyacım olan öncelikle kaynak kod. Bu arada kernel sürümünün önemli olduğu tek yer .config dosyası, buna da ileriki paragraflarda değineceğim. Tüm kernel'lar www.kernel.org/pub adresinde linux/kernel alt dizininden ulaşılabilir. Daha küçük olduğu için yukarıda .xz dosyanın bağlantısını verdim ama aynı dosyanın .gz sürümü de bulunabilir.

Bu dosyayı indirip açtım. Elbette bir dosyayı derlemek için make, gcc ve gcc-c++ gibi olması zorunlu programlar makinamda zaten yüklüydü. Eksik olan tek paket ncurses-devel'di. Bu aslında zorunlu değil, make menuconfig için gerekli ama menuconfig, kernel özelliklerini seçerken kolaylık sağlıyor. kernel'in bağımlılıkları bunlarla sınırlı değil, v5.13 sürümü için ayrıntılı liste kernel.org dökümantasyonunda var. Ama listedeki tüm paketlerin yüklü olması zorunlu değil, örn. PPP'yle ilgili birşey derlemeyecekseniz, pppd'ye gerek yok veya OpenSSL yalnız kernel modülleri imzalanacaksa gerekli.

Derlemeye geçmeden önce bazı ön bilgiler: make clean bilindiği gibi derlenen dosyaları silip kodu baştan derlemeye hazır hale getirir. linux'a özgü make mrproper ise .config dosyasını ve diğer ayarları da siler [1]. Bu yüzden ben de başlamadan önce bu komutla dizini temizledim ve sonra make defconfig ile en standart ayarları aktifleştirdim. Sözünü ettiğim bu ayarlar .config dosyasında tutuluyor, dolayısıyla defconfig aslında standart .config dosyası oluşturuyor. Bu ayarlar bir metin düzenleyiciyle görülebilir veya make menuconfig komutuyla, ncurses TUI kullanarak düzenlenebilir. .config dosyasında 4845 satır olduğundan tüm ayarları bu dosyadan elle yapmak hiç mantıklı değil.

.config dosyası her kernel sürümü için farklıdır, çünkü her minör sürümde bir kaç özellik eklenir veya çıkarılır. Haliyle, o sürüme uyumlu olmayan bir .config dosyası kullanarak derleyemem. Ama daha eski bir kernel'a ait .config dosyasını, yeni kernel'a make oldconfig komutuyla uyarlayabilirim. Bu komut, kullanıcıya yalnız .config'de olmayan (o kernel'a yeni eklenmiş) seçenekleri sorar. Tabi ki eski .config derken, v2.6 config'ini v5.13'e uyarlamak pek mantıklı iş değil.

make menuconfig metin arayüzü

make menuconfig komutunu çalıştırdım ve yukarıdaki menü çıktı. Ana menüdeki "--->" işaretli satırlar bir alt menüyü gösteriyor. Bu menüdeki tüm satırlar (eğer bir alt menüsü yoksa) .config'deki bir satıra karşılık geliyor. Kernel belgelerinde, açılması gereken özellikler yanında [*] ve açılmaması gerekenler yanında [ ] işaretiyle veriliyor. [M] ise özelliğin modüler olduğu anlamına geliyor, bunu daha sonra açıklayacağım. Örn. aşağıdaki görselde LFS'i systemd ile çalıştırmak için gereken kernel seçenekleri verilmiş:

LFS systemd kernel seçenekleri


Örneğin "Auditing Support", "Control Group support" ve "Configure standard kernel ..." gibi özellikler "General setup" altında; "open by fhandle syscalls" ise "Configure standard kernel ..."ın altında. Satır sonunda kareli parantez içinde verilen adlar, özelliğin .config içindeki maddesi (item). Bu arada, "Processor type and features" altında olması gereken "Enable seccomp ..."u bulamadım (kaynak hatalı). Bu özellik, Kernelconfig.io'ya göre v5.13'te "General architecture-dependent options" altında, ama eski sürümlerde mesela v5.9.9'da "Processor type and features" altında. Bu maddeler, menuconfig'deyken '/'a basıp, adlarıyla aratılabilir. Ancak ben menuconfig'den değil, .config dosyasından da bu ayarı değiştirebilirim (aşağıda). Bu arada özelliklerin genelde (her zaman değil) ilk harfi, aynı zamanda onun klavye kısa yolu, yani "Processor type..."a gidip "E" ye basarak, "E" ile başlayıp o an ekranda görünen seçenekler arasında gezebilirim.

$ grep -n SECCOMP .config
687:CONFIG_HAVE_ARCH_SECCOMP=y
688:CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
689:CONFIG_SECCOMP=y
690:CONFIG_SECCOMP_FILTER=y
691:# CONFIG_SECCOMP_CACHE_DEBUG is not set

Bu değer 689. satırda zaten açılmış. Gerekirse 'y'yi 'n' yapıp kapabilirim. Tüm bu özellikler .config dosyasında var. Sözünü ettiğim [M] içinse aşağıda bir örnek var:

BLFS: LVM için kernel seçenekleri


Bazı kernel seçeneklerinde bulunan M, özelliğin kernel modülü olarak derlenmesi anlamına geliyor. Bütün kernel fonksiyonları, /boot dizininde derlenmiş durumda bulunan vmlinuz-... adlı kernel dosyasında bulunmak zorunda değildir. Bu dosyayı olabildiğince küçük tutmak için, bazı fonksiyonlar modül olarak /usr/lib/modules altında tutulur, ve yalnız ihtiyaç olursa yüklenir. Bu sayede, örn. LVM diski olmayan bir makinada LVM modüllerinin veya ses kartı olmayan bir sanal makinada ses kartına ait modüllerin boşuna bellekte tutulması gerekmez.

Modül dosyaları .ko (kernel object) uzantılı dosyalardır. insmod veya modprobe ile yüklenir, lsmod'la listelenirler. Modüller, kernel'a sonradan eklenecek işlevlerin, kernel'ı tekrar derlemeye gerek kalmadan kullanılmasını sağlar [2]. Modüllere ait ayarlar /etc/modprobe.d/ dizinindeki .conf dosyalarında tutulur. Bu dosyalarla modüllere parametre girilebilir veya yüklenmesi engellenebilir. Kernel modülleri burada ele alabileceğimden çok daha geniş bir konu.

menuconfig yardımıyla veya elle istediğim seçenekleri ayarladıktan sonra make diyip yeni kernel'ı derledim. Tabii ki bu anında olmuyor. Benim bilgisayarımda standart seçeneklerle derlemek, yaklaşık 5dk sürüyor. Bazı seçenekler standartta modül olarak derlendiğinden, make'ten sonra make modules_install ile bu dosyaların o kernel'a karşılık gelen modül dizinine kopyalanması gerekiyor.

Derleme bittikten sonra, arch/x86/boot/bzImage (kernel) dosyası /boot altına vmlinuz-... adıyla kopyalanabilir ve grub yardımıyla açılabilir. Bu arada her dağıtım kernel'ı derlerken kullandığı .config dosyasını da /boot altına config-$(uname -r) adıyla kopyalar. Bu demektir ki, örn. kullandığım linux kernel'ının aynısını derlemek istersem, /boot'taki config dosyasını kernel dizinine .config adıyla kopyalayıp make edebilirim. Veya Fedora'nın v5.13.12 kernel'ını derlemek istersem, build sistemi koji'den kernel paketini aratır, x86_64 mimarisi için olan kernel-core paketini indiririm. Sonra rpm2cpio kernel-core-5.13.12-200.fc34.x86_64.rpm | cpio -idmv komutuyla açarım ve içinden çıkan lib/modules/5.13.12-200.fc34.x86_64/config dosyasını .config olarak linux-5.13.12 dizinine kopyalayıp, derlerim. Sonunda ortaya çıkan kernel Fedora'nın aynısı olacaktır (ek okuma: How to install a kernel from koji). Ancak Fedora gibi her makinada çalışması için üretilmiş bir kernel'da gerekli/gereksiz bir çok özelliğin açık olması, (örn. her ne kadar modüler de olsa Fibre Channel), derleme süresini aşırı arttırır. Öyle ki benim bilgisayarımda 5-6 saatte derlendi.

Bu kadar ön bilgiden sonra benim yaşadığım sorun ve çözümüne değinebilirim.


Vmware için Linux Kernel'ını Derlemek

Önce biri VBox'ta biri vmware'de iki makina kurdum. Bunlar ufak farklar dışında aynıydı. Yukarıda anlattığım gibi, standart config üzerine bir kaç özellik ekleyip kernel'ı derledim, /boot dizinine kopyaladım, initramfs'i ve bunları yükleyecek grub konfigürasyonunu oluşturdum. Buraya kadar herşey sorunsuz ilerledi.

Sonra sanal makinaları yeni kernel'la açtığımda VBox'taki çalışırken, vmware'deki çalışmayıp, initramfs'teki rescue shell'e düştü. Yandaki ekran görüntüsünden de görüleceği gibi, /dev altında sd* diskleri yok ve /dev/mapper boş. Bu olağandışı bir durum. Her iki makinada iki disk, ve disklerden birinde CentOS var. İkisini de CentOS'la tekrar açtım, çünkü sorunu tanılamaya yardımcı olacak lsblk, lspci gibi herhangi bir araç initramfs'te yok (Ubuntu Live da bu işi görecektir).

Aşağıdaki çıktıdan görüleceği gibi her iki makinadaki aygıtlara ve bunların kernel modüllerine lspci -k komutuyla baktım.

Vmware'de ata_piix, vmw_vmci, pcieport gibi genel geçer modüllerin yanısıra mptspi diye bir modül var, hem de SCSI denetleyicisi için. Alt taraftaki VBox çıktısındaysa ilginç herhangi bir sürücü yok. SATA controller olarak standart ahci kullanılıyor, mptspi bulunmuyor. Bu modülü biraz araştırdım. mptbase, mptscsih, mptspi sürücülerine ait konfigürasyon "Fusion MPT ScsiHost drivers for SPI" [3] olarak geçiyor, bu da kernelconfig.io'ya göre "Device Drivers/Fusion MPT device support" menüsü altında bulunuyor ve .config'de adı CONFIG_FUSION. Standart .config'de AHCI açık gelirken FUSION kapalı geliyor. Elbette bu seçenek CentOS'ta açık olduğundan onda bir sorun yaşanmıyor.

$ grep AHCI .config
CONFIG_SATA_AHCI=y
# CONFIG_SATA_AHCI_PLATFORM is not set
# CONFIG_SATA_ACARD_AHCI is not set

$ grep FUSION .config
# CONFIG_FUSION is not set

İşte sorunun kaynağı. Tekrar make menuconfig diyip, bu sürücüyü de seçtim. Makina sürekli vmware altında çalışacağından, modül olarak değil kernel'a dahil ederek bir daha derledim. Yeni kernel'i (arch/x86/boot/bzImage) /boot altına kopyalayıp makinayı yeniden başlattığımda makina düzgünce açıldı.




Kaynaklar:
[1]: Why both make clean and make mrproper are used?
[2]: https://en.wikipedia.org/wiki/Loadable_kernel_module
[3]: https://cateee.net/lkddb/web-lkddb/FUSION_SPI.html
 - : https://www.youtube.com/watch?v=WiZ05pnHZqM