Mert Özen Her Satırda Daha İleri
DevOps Linux ve Shell (geliştirici için) — #13

Ubuntu 24.04'ten 26.04'e ve Eski Sunucuları Okumak: sudo-rs, Rust Coreutils, nftables, SysV'den systemd'ye

Mert Özen 14 Kas 2026 14 dk 4 görüntülenme
Ubuntu 24.04'ten 26.04'e ve Eski Sunucuları Okumak: sudo-rs, Rust Coreutils, nftables, SysV'den systemd'ye

Ubuntu 26.04'te komut adları aynı kalsa da sudo-rs ve Rust coreutils davranışı değiştirebilir: denediğim uutils 0.10.0'da ln -sfn artık atomik değil ve sudo'nun hata mesajı farklı, bu yüzden script'lerini yükseltmeden önce yeni sürümde çalıştır. OpenSSH 10'un post-quantum key exchange'ini, SysV script'lerini, ifconfig ve iptables'ın karşılıklarını, RHEL farklarını ve yerinde yükseltme ile yeni sunucuya taşıma seçimini gerçek çıktılarla anlatıyoruz.

Sürüm notu: Bu yazıdaki komutlar Ubuntu Server 24.04.5 LTS (kernel 6.8, systemd 255, sudo 1.9.15p5, coreutils 9.4, OpenSSH 9.6p1) çalıştıran bir test VM'inde, Ubuntu 26.04.1 LTS'in resmi container image'ında (sudo-rs 0.2.13, uutils coreutils 0.10.0, klasik coreutils 9.7, OpenSSH 10.2p1) ve Rocky Linux 9.8 container image'ında denenmiştir. 26.04'ün kernel ve systemd ile ilgili maddeleri container'da denenemediği için Ubuntu'nun resmi sürüm notlarından alınmıştır.

Önce Tahmin Et

İkinci yazıda sitedeki serilerin ortak örnek uygulaması Bookstore'un (bir online kitapçı) release'lerini current symlink'iyle değiştirmiştik ve strace ile ln -sfn'in bu işi atomik yaptığını görmüştük: yeni link geçici bir adla oluşturuluyor, sonra tek bir rename ile eskisinin yerine geçiyor. Aradaki hiçbir anda current yok değil. Şimdi yeni sunucuyu Ubuntu 26.04 ile kuruyorsun ve deploy script'in hiç değişmiyor:

$ ln -sfn /opt/bookstore/releases/2026-11-14-7 /opt/bookstore/current

Komut aynı, çıktı aynı, sonuçta link yeni release'i gösteriyor. Değişim hâlâ atomik mi? Cevap Rust coreutils bölümünde.

Serinin son yazısı iki yöne bakıyor. İleriye: Nisan 2026'da çıkan Ubuntu 26.04 LTS'te bir geliştiricinin sunucusunu etkileyen değişiklikler (sudo-rs, Rust ile yazılmış coreutils, OpenSSH 10 ile post-quantum key exchange; SSH (uzak bağlantı protokolü) tarafında) ve 24.04'ten geçiş stratejisi. Geriye: hâlâ çalışan eski sunuculardaki SysV init script'leri, ifconfig ve netstat, iptables ve RHEL (Red Hat'in kurumsal Linux dağıtımı) ailesinin farkları.

Ubuntu 26.04 LTS'te Ne Değişti?

Ubuntu 26.04 LTS (kod adı Resolute Raccoon) 23 Nisan 2026'da yayımlandı ve Nisan 2031'e kadar standart destek alıyor. 24.04'ten gelenler için hazırlanan resmi özetten bu serinin konularına dokunan maddeler:

  • Kernel 6.8'den 7.0'a, systemd 255'ten 259'a. 26.04, SysV service script'lerinin systemd tarafından desteklendiği son sürüm; cgroup v1 desteği kaldırıldı.
  • sudo komutunun arkasında artık Rust ile yazılmış sudo-rs var; eski sudo sudo.ws adıyla duruyor.
  • Temel komutlar (ls, cat, date…) uutils'in Rust coreutils'inden geliyor; cp, mv ve rm şimdilik GNU (Linux'taki temel araçları geliştiren özgür yazılım projesi) sürümünde kaldı.
  • OpenSSH 9.6'dan 10.2'ye: varsayılan key exchange post-quantum mlkem768x25519-sha256, DSA (eski bir imza algoritması) desteği tamamen kalktı.
  • APT (Ubuntu'nun paket yönetim altyapısı) 2.7'den 3.1'e ve apt-key kaldırıldı (dokuzuncu yazıdaki uyarı artık hata); yeni kurulumlarda zaman senkronizasyonu systemd-timesyncd yerine chrony ile.

Bu yazıdaki 26.04 denemelerini Ubuntu'nun resmi ubuntu:26.04 container image'ında yaptım. Container kendi kernel'ini ve systemd'sini çalıştırmaz; bu yüzden kernel 7.0 ve systemd 259 maddelerini doğrudan denemedim, sürüm notlarından aktarıyorum. sudo, coreutils ve OpenSSH ise container'da bire bir aynı paketler.

sudo-rs: Aynı sudoers, Farklı Mesajlar

$ cat /etc/os-release | head -n 1
PRETTY_NAME="Ubuntu 26.04.1 LTS"
$ sudo --version | head -n 1; ls --version | head -n 1; cp --version | head -n 1; ssh -V
sudo-rs 0.2.13-0ubuntu1.2
ls (uutils coreutils) 0.10.0
cp (GNU coreutils) 9.7
OpenSSH_10.2p1 Ubuntu-2ubuntu3.8, OpenSSL 3.5.5 27 Jan 2026
$ readlink -f /usr/bin/ls /usr/bin/cp /usr/bin/sudo
/usr/lib/cargo/bin/coreutils/ls
/usr/bin/gnucp
/usr/lib/cargo/bin/sudo
$ update-alternatives --display sudo | grep priority
/usr/bin/sudo.ws - priority 40
/usr/lib/cargo/bin/sudo - priority 50

sudo bir alternatives link'i (dokuzuncu yazıdaki update-alternatives mekanizması): sudo-rs 50, eski sudo 40 önceliğiyle kayıtlı ve yüksek olan kazanıyor. Üçüncü ve on ikinci yazıda yazdığımız sudoers dosyasını, değiştirmeden, 26.04'te denedim (container'da root olarak çalıştığım için yönetim komutlarında sudo yok):

$ visudo -cf /tmp/bookstore-deploy
/tmp/bookstore-deploy: parsed OK
$ sudo -l -U deploy
User deploy may run the following commands on bookstore-next:
    (root) NOPASSWD: /usr/bin/systemctl restart bookstore-api, /usr/bin/systemctl status bookstore-api, /usr/bin/systemctl reset-failed bookstore-api
$ sudo -u deploy sudo -n cat /etc/bookstore/secrets.env; echo "exit=$?"
sudo: I'm sorry deploy. I'm afraid I can't do that
exit=1
$ visudo -cf /tmp/bad; echo "exit=$?"
/tmp/bad:1:28: syntax error: expecting ':' but found '/'
deploy ALL=(root) NOPASSWD /usr/bin/systemctl restart bookstore-api
                           ^
visudo: invalid sudoers file
exit=1

Kurallar aynı çalışıyor: visudo (artık visudo-rs) dosyayı kabul etti, izin verilen komutlar aynı, izin verilmeyen komut reddedildi. Değişen mesajlar. Aynı container'da alternatives'i geçici olarak eski sudo'ya çevirip aynı komutu çalıştırınca mesaj üçüncü yazıdaki gibi sudo: a password is required oldu. sudo-rs ise reddi açıkça söylüyor. Exit code ikisinde de 1. Hatalı satırda da visudo-rs, hatayı GNU'nun gösterdiği satır sonu yerine iki noktanın eksik olduğu karaktere işaret ediyor.

Pratik sonuç: sudo'nun çıktısını grep ile okuyan bir script ya da monitoring kuralı ("a password is required" görürsen şunu yap) 26.04'te sessizce çalışmaz. Script'lerde mesaja değil exit code'a bak. sudo-rs sudoers'ın ve sudo'nun yalnızca bir kısmını destekliyor ve projenin README'si bunun bir kısmının bilinçli olduğunu yazıyor: örneğin sudo -E (environment'ı korumak) yok, logfile ayarı desteklenmiyor (log her zaman syslog'a gidiyor) ve komut kurallarında wildcard yalnızca son argümanda çalışıyor. Script'lerinde sudo -E varsa ya da karmaşık bir sudoers dosyan varsa yükseltmeden önce visudo -c ile 26.04'te kontrol et. Gerekirse eski sudo'ya dönmek tek komut:

$ update-alternatives --set sudo /usr/bin/sudo.ws
update-alternatives: using /usr/bin/sudo.ws to provide /usr/bin/sudo (sudo) in manual mode
...
$ sudo --version | head -n 1
Sudo version 1.9.17p2
$ update-alternatives --auto sudo
update-alternatives: using /usr/lib/cargo/bin/sudo to provide /usr/bin/sudo (sudo) in auto mode
...
$ sudo --version | head -n 1
sudo-rs 0.2.13-0ubuntu1.2

Rust Coreutils: Komutlar Aynı, Davranış Her Zaman Değil

Tahminin cevabı. Aynı ln -sfn'i 26.04'te strace ile izledim, sonra aynı işi image'ın içinde duran GNU sürümüyle (gnuln) yaptım:

$ readlink -f /usr/bin/ln /usr/bin/mv
/usr/lib/cargo/bin/coreutils/ln
/usr/bin/gnumv
$ cd /opt/bookstore
$ strace -e trace=symlink,symlinkat,unlink,unlinkat,rename,renameat,renameat2 ln -sfn /opt/bookstore/releases/2026-11-14-7 current
unlinkat(AT_FDCWD, "current", 0)        = 0
symlinkat("/opt/bookstore/releases/2026-11-14-7", AT_FDCWD, "current") = 0
$ strace -e trace=symlink,symlinkat,unlink,unlinkat,rename,renameat,renameat2 gnuln -sfn /opt/bookstore/releases/2026-11-14-6 current
symlinkat("/opt/bookstore/releases/2026-11-14-6", AT_FDCWD, "current") = -1 EEXIST (File exists)
symlinkat("/opt/bookstore/releases/2026-11-14-6", AT_FDCWD, "CuNNzgVW") = 0
renameat(AT_FDCWD, "CuNNzgVW", AT_FDCWD, "current") = 0

Hayır, atomik değil. uutils 0.10.0'daki ln önce eski link'i siliyor (unlinkat), sonra yenisini oluşturuyor (symlinkat). İki system call arasındaki kısa sürede current yok; o anda başlayan bir systemctl restart ya da Nginx'in o yoldan okuduğu bir dosya "No such file or directory" alır. GNU ln ise ikinci yazıdaki gibi geçici bir adla oluşturup renameat ile değiştiriyor. Bu bir saniyeden çok daha kısa bir pencere ve çoğu deploy'da kimse fark etmez; ama tam da "bazen, açıklanamayan şekilde" görülen türden bir hata. Komut adı, seçenekler ve sonuç aynı olduğu için bunu yalnızca system call seviyesinde görebilirsin.

Çözüm script'i hangi coreutils'in çalıştırdığına bağlı olmaktan çıkarmak. Atomikliği ln'e değil, tanımı gereği atomik olan rename'e bırak: link'i geçici bir adla oluştur, mv -T ile yerine taşı. mv 26.04'te hâlâ GNU ve -T hedefi bir klasör gibi değil dosya gibi ele alıyor:

$ strace -e trace=symlinkat,unlinkat,renameat,renameat2,rename bash -c "ln -s /opt/bookstore/releases/2026-11-14-7 current.tmp && mv -T current.tmp current"
renameat2(AT_FDCWD, "current.tmp", AT_FDCWD, "current", RENAME_NOREPLACE) = -1 EEXIST (File exists)
renameat(AT_FDCWD, "current.tmp", AT_FDCWD, "current") = 0
$ readlink current
/opt/bookstore/releases/2026-11-14-7

Başka farklar da var. Gündelik kullandığım 25 komutu (sort, cut, date, stat, du, numfmt, sha256sum, uniq…) iki sürümle çalıştırıp çıktıları karşılaştırdım; çoğu bire bir aynıydı, ikisi farklıydı:

$ mkdir /tmp; gnumkdir /tmp
mkdir: /tmp: File exists
gnumkdir: cannot create directory '/tmp': File exists
$ ls -l --block-size=K books.csv; gnuls -l --block-size=K books.csv
-rw-r--r-- 1 root root 1 Nov  1 10:00 books.csv
-rw-r--r-- 1 root root 1K Nov  1 10:00 books.csv
$ ls /usr/bin/gnu* | wc -l
104

Hata mesajının metni değişmiş ve --block-size=K ile birim eki kaybolmuş. İkisi de mesajı ya da çıktıyı metin olarak işleyen bir script'i bozabilir. 26.04 GNU sürümlerini gnu önekiyle (104 komut) yanında tutuyor; bir script'te belirli bir komutun GNU davranışına ihtiyacın varsa onu açıkça çağırabilirsin. Bütün sistemi GNU'ya döndürmenin yolu sürüm notlarında:

$ apt-get install -y coreutils-from-gnu coreutils-from-uutils- --allow-remove-essential
...
dpkg: warning: overriding problem because --force enabled:
dpkg: warning: this is a protected package; it should not be removed
...
$ ls --version | head -n 1; readlink -f /usr/bin/ln
ls (GNU coreutils) 9.7
/usr/bin/gnuln

Komutun sonundaki -, apt'ye o paketi kaldırmasını söylüyor; --allow-remove-essential gerekiyor, çünkü coreutils "essential" işaretli. Dönüşten sonra ln -sfn yine renameat kullandı. Hangisini seçersen seç, kararı yükseltmeden önce ver ve deploy ile yedek script'lerini 26.04'te bir kez çalıştır. Bash Scripting serisinin script'i test etme yazısı bu tür taşınabilirlik testlerini anlatıyor.

OpenSSH 10: Post-Quantum Key Exchange

SSH bağlantısının başında iki taraf bir key exchange ile oturum anahtarını belirler. Bugün kaydedilen trafiğin ileride yeterince güçlü bir kuantum bilgisayarla çözülmesi riskine ("store now, decrypt later") karşı OpenSSH klasik algoritmayı post-quantum bir algoritmayla birleştiren hibrit yöntemlere geçti. Teorisi Networking ve HTTP serisinin TLS (HTTPS'in şifreleme protokolü) 1.3 handshake'i yazısında. 26.04'teki 10.2 istemcisiyle 24.04'teki Bookstore sunucusuna bağlandım:

ada@bookstore-next:~$ ssh -v bookstore-dev true 2>&1 | grep -E "kex: algorithm|Remote protocol|Local version"
debug1: Local version string SSH-2.0-OpenSSH_10.2p1 Ubuntu-2ubuntu3.8
debug1: Remote protocol version 2.0, remote software version OpenSSH_9.6p1 Ubuntu-3ubuntu13.20
debug1: kex: algorithm: sntrup761x25519-sha512@openssh.com
ada@bookstore-next:~$ ssh -G bookstore-dev | grep -E "^kexalgorithms" | cut -c1-120
kexalgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve255

İstemcinin ilk tercihi mlkem768x25519-sha256, ama 9.6 onu bilmiyor; iki taraf ikinci sıradaki sntrup761x25519-sha512'de anlaştı. O da post-quantum hibrit bir algoritma ve OpenSSH 9.0'dan beri varsayılan. Yani 24.04 sunucuların 26.04 istemcilerle sorunsuz ve yine post-quantum korumayla konuşuyor. Asıl fark daha eski sunucularda. Bunu taklit etmek için 26.04 container'ında yalnızca klasik curve25519-sha256'yı kabul eden bir sshd başlattım:

ada@bookstore-next:~$ ssh -o StrictHostKeyChecking=accept-new -p 2222 localhost "echo connected"
Warning: Permanently added '[localhost]:2222' (ED25519) to the list of known hosts.
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
connected

Bağlantı kuruluyor ama 10.1'den beri istemci her seferinde uyarıyor. Ubuntu 20.04'teki OpenSSH 8.2 gibi post-quantum algoritma bilmeyen eski bir sunucuya bağlanan her 26.04 makinesi bunu görecek. Uyarı ssh_config'teki WarnWeakCrypto ile kapatılabiliyor, ama doğru cevap sunucuyu güncellemek. Bu uyarı stderr'e yazılıyor; stderr'i hata çıktısı sayan bir CI adımı varsa onu da kontrol et. DSA key'ler de 10.x'te tamamen kalktı: hâlâ id_dsa kullanan bir CI ya da eski bir cihaz varsa yükseltmeden önce ed25519'a geç (birinci yazı).

Eski Sunucuları Okumak: SysV, ifconfig ve iptables

Devraldığın eski bir sunucuda service'ler /etc/init.d/ altındaki shell script'leriyle yönetiliyor olabilir (SysV init, systemd'den önceki init sistemi). 24.04'te bu klasör hâlâ var ve systemd bu script'leri unit'e çeviriyor. Eski tarz bir Bookstore script'i koydum:

$ ls /etc/init.d/ | paste -sd" "
apparmor apport console-setup.sh cron cryptdisks cryptdisks-early dbus fail2ban grub-common iscsid keyboard-setup.sh kmod nginx open-iscsi open-vm-tools plymouth plymouth-log procps rsync screen-cleanup ssh sysstat ubuntu-fan ufw unattended-upgrades uuidd
$ sudo install -m 755 /tmp/bookstore-legacy /etc/init.d/bookstore-legacy && sudo systemctl daemon-reload
$ systemctl status bookstore-legacy --no-pager | head -n 4
○ bookstore-legacy.service - LSB: Bookstore API (old init.d script)
     Loaded: loaded (/etc/init.d/bookstore-legacy; generated)
     Active: inactive (dead)
       Docs: man:systemd-sysv-generator(8)
$ systemctl cat bookstore-legacy --no-pager | head -n 14
# /run/systemd/generator.late/bookstore-legacy.service
# Automatically generated by systemd-sysv-generator

[Unit]
Documentation=man:systemd-sysv-generator(8)
SourcePath=/etc/init.d/bookstore-legacy
Description=LSB: Bookstore API (old init.d script)
After=network-online.target
After=remote-fs.target
Wants=network-online.target

[Service]
Type=forking
Restart=no
$ service nginx status --no-pager | head -n 3
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
    Drop-In: /etc/systemd/system/nginx.service.d

/etc/init.d/'deki dosyaların çoğu paketlerin geriye uyumluluk için bıraktığı script'ler; nginx, ssh ve cron'un asıl unit'leri /usr/lib/systemd/system/ altında. systemd-sysv-generator script'in başındaki LSB (Linux Standard Base; init script'leri için standart başlık biçimi) başlığını okuyup bağımlılıkları After='a çeviriyor ve Restart=no veriyor: script'le çalışan bir service çökerse kimse onu kaldırmaz. service komutu da hâlâ var, ama arkasında systemctl çalışıyor. Sürüm notlarına göre 26.04 bu çevirinin destekleneceği son sürüm; böyle bir script'i beşinci yazıdaki gibi gerçek bir unit'e taşımanın zamanı yükseltmeden önce.

Eski sunucuda alışkanlıkla yazılan network komutları 24.04'te yok:

$ ifconfig
Command 'ifconfig' not found, but can be installed with:
sudo apt install net-tools
$ netstat -tlnp
Command 'netstat' not found, but can be installed with:
sudo apt install net-tools
$ ls /var/log/messages
ls: cannot access '/var/log/messages': No such file or directory
$ update-alternatives --display iptables | head -n 3
iptables - auto mode
  link best version is /usr/sbin/iptables-nft
  link currently points to /usr/sbin/iptables-nft

Eski komutların karşılıkları:

Eski sunucudaBugünBu seride
ifconfig, route -nip a, ip rsekizinci yazı
netstat -tlnpss -tlnpbirinci ve sekizinci yazı
service x start, /etc/init.d/xsystemctl start xbeşinci yazı
chkconfig, update-rc.dsystemctl enable xbeşinci yazı
/var/log/messages (RHEL), /var/log/syslogjournalctlaltıncı yazı
iptables -Lnft list ruleset, ufw ya da firewalldon birinci yazı

iptables için durum biraz farklı: komut hâlâ var ve çalışıyor, ama 24.04'te arkasında iptables-nft var, yani kurallarını nftables'a yazıyor. On birinci yazıda ufw'nin kurallarını nft ile okuduk ve "iptables-nft tarafından yönetiliyor, dokunma" uyarısını gördük. Eski bir sunucuda iptables -V çıktısında (legacy) görüyorsan kurallar eski altyapıda; iki altyapıyı aynı makinede karıştırmak hangi kuralın geçerli olduğunu belirsizleştirir. Kuralları bir dosyadan geri yükleyen eski bir script (iptables-restore) varsa, ufw'ye ya da doğrudan nftables'a taşımak yükseltme planının parçası olmalı.

RHEL Ailesi İçin Kısa Harita

Seri Ubuntu üzerinde ilerledi, ama kurumsal ortamda RHEL ve onunla uyumlu Rocky Linux ya da AlmaLinux sık karşına çıkar. Komutların çoğu aynı (systemctl, journalctl, ss, ip, coreutils); farklı olanlar paket yönetimi, firewall ve güvenlik katmanı. Rocky Linux 9 container'ında:

$ cat /etc/redhat-release
Rocky Linux release 9.8 (Blue Onyx)
$ rpm -qf /usr/bin/ls
coreutils-single-8.32-40.el9.x86_64
$ dnf -q info nginx | grep -E "^(Name|Version|Repository)"
Name         : nginx
Version      : 1.20.1
Repository   : appstream

apt'nin karşılığı dnf, dpkg -S'nin karşılığı rpm -qf. Aynı yıllarda yayımlanan iki dağıtımda bile sürümler farklı: Ubuntu 24.04'te Nginx 1.24, Rocky 9'un varsayılan deposunda 1.20.1. Container'da çalıştırmadığım, dokümandan bilinen iki fark daha var. Firewall ufw değil firewalld (firewall-cmd), arkasında yine nftables. Güvenlik katmanı AppArmor değil SELinux (Security-Enhanced Linux; dosya ve process'lere etiket bazlı erişim kuralı uygulayan kernel modülü) ve varsayılan olarak enforcing modda. Bookstore'u RHEL'e taşırken en sık görülen sorun budur: dosya izinleri doğru olduğu hâlde Nginx'in 5000'deki uygulamaya bağlanamaması. Sebebi getenforce ve audit log'unda (ausearch -m avc) aranır; çözüm SELinux'u kapatmak değil, doğru boolean'ı açmaktır (Nginx'in network bağlantısı için httpd_can_network_connect).

Yükseltme: do-release-upgrade mı, Yeni Sunucu mu?

Bookstore sunucusu yeni sürümü zaten görüyor:

$ do-release-upgrade -c
Checking for a new Ubuntu release
New release '26.04.1 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
$ grep ^Prompt /etc/update-manager/release-upgrades
Prompt=lts

Prompt=lts yalnızca LTS'ten LTS'e yükseltme teklif edilmesi demek. Ubuntu LTS'ten LTS'e yükseltmeyi ilk point release'e (burada 26.04.1) kadar açmıyor; ilk aylardaki hatalar o sürede düzeltiliyor. İki yol var:

Yerinde yükseltme (do-release-upgrade): sunucunun adresi, verisi ve elle yapılmış her ayarı yerinde kalır. Ama yükseltme sırasında servis kesilir, yarıda kalırsa sunucu iki sürüm arasında kalabilir ve geri dönüş için tam bir snapshot ya da yedek gerekir. Bu seride sunucuyu bu yolla yükseltmedim; komutun çıktısını yalnızca kontrol modunda (-c) gösteriyorum.

Yeni sunucuya taşıma: 26.04 ile yeni bir VM kur, repodaki dosyalarla (unit'ler, sudoers, sshd drop-in'i, Fail2ban, Nginx config'i) hazırla, Bookstore'u deploy et, test et ve trafiği load balancer'da ya da DNS'te yeni sunucuya çevir. Eski sunucu geri dönüş yolu olarak birkaç gün kalır. Bu, immutable altyapı (sunucuyu değiştirmek yerine yenisini kurmak) yaklaşımı: bu seride her ayarı repoya koymamızın sebebi tam olarak bu yükseltmeyi mümkün kılmak. Elle yapılıp repoya girmemiş her değişiklik yeni sunucuda eksik çıkar ve bunu taşıma sırasında öğrenirsin. Sunucuyu kodla kurmak ilerideki Infrastructure as Code: Terraform serisinin konusu.

Bookstore gibi tek bir uygulama ve az sayıda sunucu için ikinci yol daha güvenli ve test edilebilir. Yerinde yükseltme, taşıması zor durumlu bir sunucu (büyük yerel veri, lisanslı yazılım, belgelenmemiş eski ayarlar) için kalır; o zaman da önce sunucunun bir kopyasında dene.

Üretimde Dikkat

Yükseltmeden önce 26.04'te script'lerini çalıştır. Bu yazıdaki iki bulgu (atomik olmayan ln -sfn ve değişen sudo mesajı) hiçbir hata vermeden davranış değiştiriyor; bunları ancak deploy, yedek ve bakım script'lerini yeni sürümde gerçekten çalıştırarak, gerekirse strace ile bakarak bulursun.

Eski bir sunucuyu devraldığında önce envanter çıkar: /etc/init.d/'deki ve paketlere ait olmayan script'ler, cron job'ları, iptables kuralları, /etc'de elle değiştirilmiş dosyalar (dpkg --verify paket dosyalarındaki değişiklikleri gösterir). Bunlar yeni sunucuya taşınması gereken, ama kimsenin hatırlamadığı ayarlar.

Sık Düşülen Tuzaklar

Komut adı aynı diye davranışın da aynı olduğunu varsaymak. 26.04'te ls, ln ve sudo başka bir codebase'den geliyor; seçenekler büyük ölçüde aynı, edge case'lerdeki davranış değil. Kritik adımlarda (atomik değişim, hata kontrolü) ya GNU sürümünü açıkça çağır ya da davranışı garanti eden bir yöntem kullan (mv -T gibi).

Script'te hata mesajını grep'lemek. Mesajlar sürümden sürüme değişir; exit code daha kararlı bir sözleşme. sudo-rs ve uutils örnekleri bunun canlı kanıtı.

LTS çıkar çıkmaz yerinde yükseltmek. İlk point release'i bekle, önce bir kopyada ya da yeni bir sunucuda dene.

Küçük Bir Deneme

★☆☆ docker run --rm -it ubuntu:26.04 ile bir container aç ve readlink -f ile /usr/bin altındaki ls, cp, mv, rm, date ve sudo'nun nereden geldiğini listele. Hangileri GNU, hangileri Rust?

★★☆ Kendi deploy script'ini 26.04 container'ında strace -f -e trace=unlinkat,symlinkat,renameat ile çalıştır. Symlink değişimi hangi system call'larla yapılıyor? mv -T yöntemine geçince ne değişiyor?

★★★ Bu seride kurduğun Bookstore sunucusunu yeni bir 26.04 VM'inde yalnızca repodaki dosyalarla yeniden kur. Elle yapmak zorunda kaldığın her adımı not et; o listedeki her madde repoya girmesi gereken bir şey.

Seriyi burada bitiriyoruz. SSH ile bağlanmaktan başlayıp file system'i, permission'ları, process'leri, systemd'yi, log okumayı, network'ü, paketleri, kaynakları, sertleştirmeyi ve sorun gidermeyi bir Bookstore sunucusu üzerinde gördük ve sürümler değiştiğinde nelere bakacağımızı konuştuk. Burada öğrendiklerini script'e dökmek Bash Scripting serisinde, aynı uygulamayı container ile çalıştırmak Docker serisinde devam ediyor.