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

Paket Yönetimi: apt, Repository'ler, Güncellemeler ve Sunucuya .NET ile Node Kurmak

Mert Özen 14 Kas 2026 13 dk 3 görüntülenme
Paket Yönetimi: apt, Repository'ler, Güncellemeler ve Sunucuya .NET ile Node Kurmak

Ubuntu 24.04'te .NET'i Ubuntu'nun kendi feed'inden kurar, packages.microsoft.com'u bir apt pin dosyasıyla dışarıda tutarsın; apt-cache policy her paketin nereden ve hangi öncelikle geldiğini gösterir. apt'nin temelini, deb822 ve Signed-By'ı, backports PPA'sını, NodeSource'u script'siz kurmayı, apt-mark hold'u, unattended-upgrades'i ve gerçek bir upgrade'de needrestart'ın Bookstore.Api'yi yeniden başlattığını gösteriyoruz.

Sürüm notu: Bu yazıdaki komutlar Ubuntu Server 24.04.5 LTS (apt 2.8, needrestart 3.6, unattended-upgrades 2.9) çalıştıran bir test VM'inde; Ubuntu feed'inden ASP.NET Core runtime 10.0.15 ve NodeSource'tan Node.js 24.22 ile denenmiştir.

Önce Tahmin Et

Sitedeki serilerin ortak örnek uygulaması Bookstore'un (bir online kitapçı) sunucusunda 48 paket güncellenmeyi bekliyor. Bir SSH (uzak bağlantı protokolü) oturumundan, bir script içinde şunu çalıştırıyorsun:

sudo apt-get -y upgrade

Bookstore.Api'nin paketlerine dokunmadın, hatta onları hold'a aldın. Güncelleme sırasında uygulamaya bir şey olur mu? Cevap Güncellemeler bölümünde, gerçek bir upgrade'in çıktısında.

Bu yazıda sunucuya yazılım kurmayı ve güncel tutmayı görüyoruz: apt'nin temel komutları, bir paketin nereden ve hangi öncelikle geldiği, repository'ler, deb822 formatı ve signed-by key'ler, sunucuya .NET ve Node kurarken feed'leri karıştırmamak, otomatik güvenlik güncellemeleri ve kernel güncellemesinden sonra reboot. Windows'ta winget ya da Chocolatey kullandıysan mantık tanıdık gelecek; fark, Linux'ta sistemin neredeyse her parçasının bu paket yöneticisinden gelmesi.

apt'nin Temeli: update, upgrade, install, remove, purge

$ sudo apt update

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Hit:1 http://security.ubuntu.com/ubuntu noble-security InRelease
Hit:2 http://archive.ubuntu.com/ubuntu noble InRelease
Hit:3 http://archive.ubuntu.com/ubuntu noble-updates InRelease
Hit:4 http://archive.ubuntu.com/ubuntu noble-backports InRelease
Reading package lists...
Building dependency tree...
Reading state information...
48 packages can be upgraded. Run 'apt list --upgradable' to see them.
$ apt list --upgradable 2>/dev/null | head -n 4
Listing...
apt-utils/noble-updates,noble-security 2.8.4ubuntu0.1 amd64 [upgradable from: 2.8.3]
apt/noble-updates,noble-security 2.8.4ubuntu0.1 amd64 [upgradable from: 2.8.3]
bind9-dnsutils/noble-updates,noble-security 1:9.18.39-0ubuntu0.24.04.9 amd64 [upgradable from: 1:9.18.39-0ubuntu0.24.04.8]

update hiçbir paketi güncellemez; yalnızca repository'lerden paket listelerini indirir ve "hangi sürümler var" bilgisini tazeler. Paketleri güncelleyen upgrade. İkisi neredeyse her zaman art arda çalıştırılır. Çıktıdaki uyarı da önemli: apt insanlar için tasarlanmış, çıktısı sürümden sürüme değişebilir. Script'lerde ve otomasyonda apt-get ve apt-cache kullan; bu yazının geri kalanında script'ten çalıştırdığım komutlar bu yüzden apt-get.

apt-get upgrade güvenli tarafta kalır: yeni paket kurmaz, paket silmez. Bu yüzden kernel güncellemesi gibi yeni paket gerektiren güncellemeleri geride bırakır:

$ sudo apt-get upgrade -s | grep -A4 "kept back"
The following packages have been kept back:
  linux-headers-generic linux-headers-virtual linux-image-virtual
  linux-virtual
The following packages will be upgraded:
  apt apt-utils bind9-dnsutils bind9-host bind9-libs ca-certificates

-s (simulate) hiçbir şeyi değiştirmeden ne olacağını gösterir. "kept back" satırındaki kernel paketlerini almak için apt-get full-upgrade (eski adı dist-upgrade) gerekir; gerekirse yeni paket kurar, gerekirse paket kaldırır, bu yüzden çıktısını okumadan onaylama. Upgrade çıktısında bir de "deferred due to phasing" satırı gördüm: Ubuntu bazı güncellemeleri önce makinelerin bir kısmına dağıtıyor (phased update), sorun çıkmazsa herkese açıyor.

remove ile purge'ün farkını küçük bir FTP (dosya aktarım protokolü) sunucusu paketiyle gördüm:

$ sudo apt-get remove -y -qq vsftpd >/dev/null; dpkg -l vsftpd | tail -n 1; ls /etc/vsftpd.conf
rc  vsftpd         3.0.5-0ubuntu3.1 amd64        lightweight, efficient FTP server written for security
/etc/vsftpd.conf
$ sudo apt-get purge -y -qq vsftpd >/dev/null; dpkg -l vsftpd 2>&1 | tail -n 1; ls /etc/vsftpd.conf
dpkg-query: no packages found matching vsftpd
ls: cannot access '/etc/vsftpd.conf': No such file or directory

remove programı kaldırır ama /etc'deki configuration dosyalarını bırakır; dpkg -l'deki rc "removed, config files remain" demek. Paketi yeniden kurduğunda eski ayarlarınla gelir. purge config'i de siler. Bir servisi temizlemek istiyorsan purge, geçici kaldırıyorsan remove. apt autoremove ise artık hiçbir paketin ihtiyaç duymadığı bağımlılıkları kaldırır.

Bir Paket Nereden Gelir: apt-cache policy, dpkg -L ve dpkg -S

$ apt-cache policy aspnetcore-runtime-10.0
aspnetcore-runtime-10.0:
  Installed: 10.0.15-0ubuntu1~24.04.1
  Candidate: 10.0.15-0ubuntu1~24.04.1
  Version table:
 *** 10.0.15-0ubuntu1~24.04.1 500
        500 http://archive.ubuntu.com/ubuntu noble-updates/main amd64 Packages
        500 http://security.ubuntu.com/ubuntu noble-security/main amd64 Packages
        100 /var/lib/dpkg/status
$ dpkg -S /usr/bin/dotnet /usr/sbin/nginx
dotnet-host-10.0: /usr/bin/dotnet
nginx: /usr/sbin/nginx
$ dpkg -L aspnetcore-runtime-10.0 | head -n 6
/.
/usr
/usr/lib
/usr/lib/dotnet
/usr/lib/dotnet/shared
/usr/lib/dotnet/shared/Microsoft.AspNetCore.App

apt-cache policy bu yazının en önemli komutu. Installed kurulu sürümü, Candidate apt install yazınca kurulacak sürümü, version table ise her sürümün hangi repository'den ve hangi öncelikle (priority) geldiğini gösterir. *** kurulu olanı işaretler, 100 kurulu paketin kendi kaydı, 500 normal bir repository. apt aynı önceliktekiler arasında en yüksek sürümü seçer; öncelikleri değiştirmek için aşağıda göreceğimiz pin dosyaları var. dpkg -S bir dosyanın hangi paketten geldiğini, dpkg -L bir paketin hangi dosyaları kurduğunu söyler. "Bu dotnet nereden geldi" sorusunun cevabı tek satır.

Ne zaman ne kurulduğunun kaydı /var/log/apt/history.log'da tutulur; eskileri sıkıştırılıp döndürülür, önceki yazının zgrep'i burada da işe yarar: zgrep -h "^Commandline" /var/log/apt/history.log*.

Repository'ler: deb822, Signed-By ve Key'ler

$ cat /etc/apt/sources.list | grep -v "^$"
# Ubuntu sources have moved to the /etc/apt/sources.list.d/ubuntu.sources
# file, which uses the deb822 format. Use deb822-formatted .sources files
# to manage package sources in the /etc/apt/sources.list.d/ directory.
# See the sources.list(5) manual page for details.
$ cat /etc/apt/sources.list.d/ubuntu.sources | grep -v "^#" | grep -v "^$"
Types: deb
URIs: http://archive.ubuntu.com/ubuntu
Suites: noble noble-updates noble-backports
Components: main universe restricted multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
Types: deb
URIs: http://security.ubuntu.com/ubuntu
Suites: noble-security
Components: main universe restricted multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Ubuntu 24.04'te kaynaklar eski tek satırlık sources.list yerine deb822 formatındaki .sources dosyalarında. Her blok bir repository: adres, suite'ler (noble ilk yayın, noble-updates düzeltmeler, noble-security güvenlik güncellemeleri), bileşenler ve Signed-By. Son satır güvenlik açısından kritik: bu repository'den gelen paket listesi yalnızca bu key ile imzalanmışsa kabul edilir. Eski yöntemdeki apt-key add key'i bütün repository'lere güvenilir hâle getiriyordu; apt-key artık kullanılmıyor ve her üçüncü taraf repository kendi key dosyasına bağlanıyor.

Ne olduğunu görmek için bir repository'nin Signed-By'ını bilerek yanlış key'e çevirdim:

$ sudo apt-get update 2>&1 | grep -iE "nodesource|NO_PUBKEY|not signed" | head -n 4
Hit:5 https://deb.nodesource.com/node_24.x nodistro InRelease
Err:5 https://deb.nodesource.com/node_24.x nodistro InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 2F59B5F99B1BE0B4
W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: https://deb.nodesource.com/node_24.x nodistro InRelease: The

apt bu repository'nin listesini güncellemeyi reddetti ve eskisini kullanmaya devam etti. NO_PUBKEY gördüğünde çözüm doğru key dosyasını indirip Signed-By'a bağlamaktır; internette dolaşan "apt-key ile ekle" ya da "trusted=yes yaz" önerileri imza kontrolünü kapatır.

Sunucuya .NET Kurmak: Hangi Feed?

Bookstore.Api framework-dependent publish ediliyor (beşinci yazıdaki --self-contained false), yani sunucuda yalnızca runtime gerekiyor; SDK derleme makinesinde ve CI'da durur. ASP.NET Core runtime paketi .NET runtime'ını da getirir:

$ dotnet --list-runtimes
Microsoft.AspNetCore.App 10.0.15 [/usr/lib/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 10.0.15 [/usr/lib/dotnet/shared/Microsoft.NETCore.App]

Ubuntu'da .NET üç yerden gelebilir ve Microsoft'un kurulum sayfası Ubuntu 24.04 için dağılımı şöyle veriyor: .NET 10 ve 8 Ubuntu'nun kendi feed'inde, eski sürümler Canonical'ın "dotnet/backports" PPA'sında (Personal Package Archive; Launchpad'deki üçüncü taraf paket deposu), packages.microsoft.com'da ise 24.04 için .NET paketi yok. Bizim kurulumumuz ilk satıra uyuyor: runtime noble-updates ve noble-security'den geliyor. Ubuntu'nun SDK'sı her zaman 1xx feature band'inde (dotnet-sdk-10.0 10.0.115); daha yeni bir band gerekiyorsa SDK'yı CI'da kurarsın, sunucuda değil.

.NET 11 için backports PPA'sına baktım:

$ sudo add-apt-repository -y ppa:dotnet/backports 2>&1 | tail -n 2
More info: https://launchpad.net/~dotnet/+archive/ubuntu/backports
Adding repository.
$ apt-cache policy aspnetcore-runtime-9.0 aspnetcore-runtime-11.0 | head -n 12
aspnetcore-runtime-9.0:
  Installed: (none)
  Candidate: 9.0.23-0ubuntu1~24.04.1~ppa1
  Version table:
     9.0.23-0ubuntu1~24.04.1~ppa1 500
        500 https://ppa.launchpadcontent.net/dotnet/backports/ubuntu noble/main amd64 Packages
aspnetcore-runtime-11.0:
  Installed: (none)
  Candidate: 11.0.0-0ubuntu1~24.04.1~ppa1
  Version table:
     11.0.0-0ubuntu1~24.04.1~ppa1 500
        500 https://ppa.launchpadcontent.net/dotnet/backports/ubuntu noble/main amd64 Packages

Microsoft'un tablosu backports'ta yalnızca eski sürümleri gösterse de yazım anında (14 Kasım 2026) PPA'da aspnetcore-runtime-11.0 11.0.0 de vardı. Bu tür bilgiler hızlı değişir; tablodan değil apt-cache policy'den kontrol et. add-apt-repository 24.04'te deb822 formatında bir .sources dosyası oluşturuyor ve key'i dosyanın içine gömüyor. Bookstore .NET 10'da kalacağı için PPA'yı add-apt-repository --remove ile kaldırdım.

Asıl tehlike iki feed'in aynı paketi farklı biçimde sunması. Microsoft repository'si PowerShell ve SQL Server araçları için sık eklenir ve 22.04'ten yükseltilmiş sunucularda hâlâ kayıtlı olabilir. İçinde .NET olmasa bile isim çakışması tamamen bitmiş değil:

$ apt-cache policy '?name(dotnet.*)' | grep -B5 packages.microsoft.com
dotnet-apphost-pack-6.0:
  Installed: (none)
  Candidate: 6.0.30-1
  Version table:
     6.0.30-1 500
        500 https://packages.microsoft.com/ubuntu/24.04/prod noble/main amd64 Packages

İki feed'den karışık .NET paketleri kurulduğunda dotnet'in kendi klasörünü bulamadığı hatalar çıkar ("The folder [/usr/share/dotnet/host/fxr] does not exist" gibi); Microsoft'un "package mix ups" sayfası bunları listeliyor. Önerilen çözüm bir apt preferences dosyası. Repoya deploy/linux/apt/preferences.d/dotnet-microsoft olarak ekledik:

# /etc/apt/preferences.d/dotnet-microsoft
# .NET Ubuntu feed'inden gelir; packages.microsoft.com'dan asla alma
Package: dotnet* aspnet* netstandard*
Pin: origin "packages.microsoft.com"
Pin-Priority: -10
$ apt-cache policy '?name(dotnet.*)' | grep -B5 packages.microsoft.com
dotnet-apphost-pack-6.0:
  Installed: (none)
  Candidate: (none)
  Version table:
     6.0.30-1 -10
        500 https://packages.microsoft.com/ubuntu/24.04/prod noble/main amd64 Packages

Negatif öncelik "bu kaynaktan bu paketleri asla kurma" demek: aday artık (none). Dosya Microsoft repository'si yokken hiçbir şey yapmaz, birisi ileride eklediğinde sunucuyu korur.

Sunucuya Node Kurmak

Bookstore'un Angular arayüzü (bookstore-web) build edilip Nginx'ten statik dosya olarak sunuluyor, yani sunucuda Node gerekmiyor; build CI'da yapılıyor. Angular SSR (sunucu tarafında render) kullansaydın gerekirdi. Ubuntu'nun kendi paketi eski:

$ apt-cache policy nodejs
nodejs:
  Installed: (none)
  Candidate: 18.19.1+dfsg-6ubuntu5
  Version table:
     18.19.1+dfsg-6ubuntu5 500
        500 http://archive.ubuntu.com/ubuntu noble/universe amd64 Packages

Angular 22 için güncel bir LTS gerekiyor. Yaygın yol NodeSource repository'si. Kurulum sayfaları curl ... | sudo bash öneriyor; script'i okudum ve yaptığı şeyi elle, adım adım yaptım: key'i indir, deb822 dosyasını yaz.

$ curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/nodesource.gpg
$ cat /etc/apt/sources.list.d/nodesource.sources
Types: deb
URIs: https://deb.nodesource.com/node_24.x
Suites: nodistro
Components: main
Architectures: amd64
Signed-By: /usr/share/keyrings/nodesource.gpg
$ sudo apt-get install -y -qq nodejs >/dev/null 2>&1; node --version; apt-cache policy nodejs | head -n 3
v24.22.3
nodejs:
  Installed: 24.22.3-1nodesource1
  Candidate: 24.22.3-1nodesource1
$ sudo apt-mark hold nodejs
nodejs set on hold.

apt-cache policy artık iki kaynak gösteriyordu (NodeSource'un 24.x sürümleri ve Ubuntu'nun 18.19'u), ikisi de 500 öncelikli olduğu için yüksek sürüm seçildi. NodeSource'un kendi script'i buna ek olarak /etc/apt/preferences.d/nodejs dosyasıyla kendi kaynağına 600 öncelik veriyor; Ubuntu ileride daha yüksek numaralı bir sürüm yayınlarsa bile seçim değişmesin diye. apt-mark hold paketi bulunduğu sürümde dondurur: upgrade ona dokunmaz, apt-mark showhold dondurulanları listeler. Node'un major sürümü değiştiğinde uygulamanın da test edilmesi gerektiği için hold burada mantıklı. Denemeden sonra Node'u ve repository'yi sunucudan kaldırdım.

Güncellemeler: unattended-upgrades, needrestart ve Reboot

Tahminin cevabı. Bookstore'un .NET paketlerini hold'a alıp script'ten sudo apt-get -y upgrade çalıştırdım. Çıktının sonu:

Running kernel seems to be up-to-date.

Restarting services...
 /etc/needrestart/restart.d/systemd-manager
 systemctl restart bookstore-api.service cron.service multipathd.service nginx.service polkit.service ssh.service systemd-journald.service systemd-networkd.service systemd-resolved.service systemd-timesyncd.service systemd-udevd.service udisks2.service

Service restarts being deferred:
 systemctl restart ModemManager.service
 /etc/needrestart/restart.d/dbus.service
 systemctl restart getty@tty1.service
 systemctl restart serial-getty@ttyS0.service
 systemctl restart systemd-logind.service
 systemctl restart unattended-upgrades.service
$ journalctl -u bookstore-api --since "-20min" -o short-iso --no-pager | grep -E "Stopping|Stopped|started" | tail -n 4
2026-11-14T16:26:25+00:00 bookstore-dev bookstore-api[6062]: Bookstore.Api[0] Stopped cleanly
2026-11-14T16:26:25+00:00 bookstore-dev systemd[1]: Stopped bookstore-api.service - Bookstore API (ASP.NET Core on Kestrel).
2026-11-14T16:26:32+00:00 bookstore-dev bookstore-api[13906]: Microsoft.Hosting.Lifetime[0] Application started. Hosting environment: Production; Content root path: /opt/bookstore/releases/2026-11-14-6
2026-11-14T16:26:32+00:00 bookstore-dev bookstore-api[13906]: Bookstore.Api[0] Bookstore.Api started, PID 13906

Bookstore.Api'nin paketi güncellenmedi ama uygulama yeniden başlatıldı, 7 saniyelik bir kesintiyle. Sebep needrestart: güncellemeden sonra hangi çalışan process'lerin eski kütüphaneleri (burada güncellenen libc6) bellekte tuttuğunu bulur ve o service'leri yeniden başlatır. Terminal olmadan çalıştığında soru sormadan kendisi yapar; Nginx ve SSH de listede. Graceful shutdown (dördüncü yazı) sayesinde süren istekler tamamlandı, ama "sadece paket güncelledim" diye bir deploy penceresi dışında bunu yapmak beklenmedik bir kesinti demek. Belirli bir service'in otomatik restart edilmesini istemiyorsan needrestart'ın $nrconf{override_rc} ayarına /etc/needrestart/conf.d/ altında bir dosyayla ekleyebilirsin; o zaman restart'ı senin yapman gerekir.

Otomatik güvenlik güncellemeleri varsayılan olarak açık:

$ cat /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
$ systemctl list-timers "apt-daily*" "unattended*" --no-pager
NEXT                        LEFT LAST                        PASSED UNIT                    ACTIVATES
Sun 2026-11-15 00:37:40 UTC   8h Sat 2026-11-14 14:05:09 UTC      - apt-daily.timer         apt-daily.service
Sun 2026-11-15 06:32:57 UTC  14h Sat 2026-11-14 14:05:09 UTC      - apt-daily-upgrade.timer apt-daily-upgrade.service

2 timers listed.
Pass --all to see loaded but inactive timers, too.

Beşinci yazının timer'ları burada da: apt-daily listeleri günceller, apt-daily-upgrade unattended-upgrades'i çalıştırır. /etc/apt/apt.conf.d/50unattended-upgrades'teki Allowed-Origins varsayılan olarak noble ve noble-security'yi (bir de varsa ESM (Extended Security Maintenance; Ubuntu Pro'nun genişletilmiş güvenlik bakımı) kanallarını) içerir; noble yayından sonra değişmediği için pratikte her gün yalnızca güvenlik güncellemeleri kurulur ve ardından needrestart service'leri yeniden başlatır. Automatic-Reboot varsayılan olarak kapalı: kernel güncellense bile sunucu kendiliğinden yeniden başlamaz. Kurulan güncellemelerin log'u /var/log/unattended-upgrades/ altında.

Reboot gerekip gerekmediğini iki yerden anlarsın. full-upgrade ile yeni kernel'i kurduktan sonra:

$ cat /var/run/reboot-required.pkgs
libc6
linux-image-6.8.0-149-generic
linux-base
$ sudo needrestart -b -k
NEEDRESTART-VER: 3.6
NEEDRESTART-KCUR: 6.8.0-147-generic
NEEDRESTART-KEXP: 6.8.0-149-generic
NEEDRESTART-KSTA: 3
$ sudo reboot
...
$ uname -r
6.8.0-149-generic
$ ls /var/run/reboot-required 2>&1
ls: cannot access '/var/run/reboot-required': No such file or directory

/var/run/reboot-required dosyası varsa reboot gerekiyor, .pkgs hangi paketlerin istediğini söyler. needrestart'ın -b (batch) çıktısında KCUR çalışan kernel, KEXP beklenen kernel; KSTA: 3 "daha yeni bir kernel kurulu, reboot bekliyor" demek (reboot'tan sonra 1 oldu). Bu satırlar monitoring'e bağlanmaya uygun: SSH ile girildiğinde Ubuntu'nun karşılama mesajı da "System restart required" der, ama kimse giriş yapmazsa bilgi orada kalır.

Üretimde Dikkat

Güncellemeyi planla. Güvenlik güncellemelerini unattended-upgrades'e bırakmak doğru varsayılan; ama Bookstore'un bir service'inin günün ortasında yeniden başlayabileceğini bil ve health check'in bunu sorun olarak görmeyecek kadar toleranslı olsun. Kernel güncellemeleri için düzenli bir reboot penceresi belirle; birden çok sunucu varsa load balancer arkasında sırayla. Diğer güncellemeleri (Nginx'in, .NET runtime'ının minor sürümleri) önce bir test sunucusunda dene.

Sunucuyu elle değil tekrar üretilebilir şekilde kur. Repository dosyaları, pin'ler ve kurulu paket listesi bir script'te ya da configuration management aracında durmalı; bu yazıdaki komutları her yeni sunucuda hatırlamaya çalışmak bir gün bir adımı atlamak demek. Daha da iyisi uygulamayı container ile dağıtmak: o zaman runtime image'ın içinde gelir ve sunucuda yalnızca container runtime'ı güncellersin (ilerideki Docker serisi).

apt-mark hold'u kalıcı bir çözüm sanma. Hold'daki bir paket güvenlik güncellemesi de almaz. .NET runtime'ını hold'a aldıysan bunu bir yere yaz ve Microsoft'un aylık Patch Tuesday güncellemelerini takip et; denemeden sonra Bookstore'un paketlerini apt-mark unhold ile serbest bıraktım.

Sık Düşülen Tuzaklar

curl ... | sudo bash ile bilmediğin bir script çalıştırmak. Script'in ne yaptığını görmeden root yetkisi vermiş olursun; bağlantı yarıda koparsa script'in yarısı da çalışabilir. Önce dosyaya indir, oku, sonra çalıştır; ya da NodeSource örneğindeki gibi yaptığı iki üç adımı kendin yap.

PPA'larla sistemi karıştırmak. Her PPA, Ubuntu'nun test ettiği paketlerin yerine kendi sürümlerini koyabilir; birkaç PPA eklenmiş bir sunucuda bir paketin neden o sürümde olduğunu bulmak zorlaşır ve sürüm yükseltmesi (on üçüncü yazı) kırılır. Bir PPA eklemeden önce apt-cache policy ile hangi paketleri etkileyeceğine bak, işin bitince kaldır.

Script'te apt kullanmak ve soruya takılmak. apt-get -y kullan; bazı paketler kurulum sırasında soru sorar, otomasyonda DEBIAN_FRONTEND=noninteractive ile çalıştır. Aksi hâlde script, kimsenin göremediği bir soruda sonsuza kadar bekler.

update'i unutup install yapmak. Paket listesi eskiyse apt artık sunucuda bulunmayan bir sürümü indirmeye çalışır ve 404 alırsın. Kurulumdan önce her zaman apt-get update.

.NET'i iki feed'den kurmak. Bir sunucuda hem /usr/lib/dotnet hem /usr/share/dotnet varsa ve dotnet komutu garip hatalar veriyorsa, sebep çoğu zaman budur. apt-cache policy ile her .NET paketinin nereden geldiğine bak ve tek kaynağa dön.

Küçük Bir Deneme

★☆☆ Kendi sunucunda apt list --upgradable ile bekleyen güncellemeleri listele ve apt-get upgrade -s ile hangilerinin "kept back" kaldığını gör. /var/log/apt/history.log'da son beş işlemi bul.

★★☆ Bookstore.Api için needrestart'ın otomatik restart'ını kapatan bir dosyayı /etc/needrestart/conf.d/ altına yaz, bir kütüphane güncellemesinden sonra needrestart -b çıktısında service'in listelendiğini ama yeniden başlatılmadığını doğrula.

★★★ Temiz bir VM'de Microsoft repository'sini ekle, pin dosyası olmadan apt-cache policy '?name(dotnet.*)' ile hangi paketlerin iki kaynaktan da geldiğini listele, sonra pin dosyasını ekleyip farkı karşılaştır.

Sunucuya bir şey kurmayı ve güncel tutmayı gördük; kurduğumuz her şey de disk, bellek ve CPU tüketiyor. Bir sonraki yazıda kaynak sorunlarına bakıyoruz: df, du, free, vmstat, iostat, OOM (Out Of Memory; belleğin tükenmesi) killer ve gece yarısı "No space left on device" vakası.