Kategori: Uncategorized

  • Linux Sistem Yönetimi | LKD #9

    SSH (secure shell) farklı bir bilgisayardan hedef sunucunun terminalini doğrudan kullanmamızı sağlayan uzaktan erişim yöntemidir.

    SSH bağlantısı kurmak için Windows’ta,

    • Putty
    • Mobaxterm araçlarını kullanabiliriz.

    SSH bağlantıları Linux’ta openssh üzerinden yürütülür. Doğrudan indireceğimiz paket adını bilmiyorsak, apt search komutuyla arayabiliriz.

    bash
    mehmet@debian ~$ apt search openssh-server

    Yalnızca IP adresini yazarsak karşı bilgisayara bulunduğumuz kullanıcı adıyla bağlanmayı deneriz.

    Farklı bir kullanıcıyla bağlanmak istiyorsak kullanıcı adını IP adresinin önünde belirtmemiz gerekir.

    bash
    mehmet@debian ~$ ssh kullanici_adi@ip_adresi

    SSH Sunucu Anahtarı

    Bir SSH sunucusuna ilk kez bağlanırken sunucunun kimliğine güvenip güvenmediğimiz sorulur. Bağlantıyı kabul ettiğimizde sunucunun anahtarı kullanıcının ~/.ssh/known_hosts dosyasına kaydedilir.

    Bundan sonraki bağlantılarda sunucunun gönderdiği anahtar, daha önce kaydedilen anahtarla karşılaştırılır.

    Sunucunun anahtarı değişirse SSH bize kimlik uyarısı verir. Bu durum sunucunun yeniden kurulmasından, IP adresinin başka bir sunucuya verilmesinden veya sunucu taşınırken SSH host anahtarlarının aktarılmamasından kaynaklanabilir.

    Aynı uyarı ortadaki adam (man in the middle) saldırısında da görülebileceğinden, değişikliğin nedenini bilmeden bağlantıya devam etmemeliyiz.

    Eski anahtarın gerçekten geçersiz olduğundan eminsek kaydı aşağıdaki şekilde silebiliriz.

    bash
    mehmet@debian ~$ ssh-keygen -R ip_adresi

    -v parametresiyle bağlantı sırasında gerçekleşen işlemleri daha ayrıntılı görebiliriz. Bağlantının neden kurulamadığını araştırırken işimize yarayabilir.

    bash
    mehmet@debian ~$ ssh -v kullanici_adi@ip_adresi

    Sunucu tarafındaki SSH servisinin loglarını ise journalctl üzerinden inceleyebiliriz.

    bash
    mehmet@debian ~$ journalctl -u ssh

    /etc/ssh/ssh_config istemci ayarlarını, /etc/ssh/sshd_config ise SSH sunucusunun ayarlarını tutar.

    Yapılandırma dosyasında bazı ayarlar yorum satırında görünmesine rağmen OpenSSH kendi varsayılan değerini kullanmaya devam eder. Varsayılan değer bizim için uygunsa başındaki # işaretini kaldırmamız gerekmez.

    Debian ve Ubuntu sistemlerinde root kullanıcısının parolayla SSH girişi varsayılan olarak kapalıdır. Root kullanıcı adı herkes tarafından bilindiği için doğrudan parola denemelerinin önüne geçilmiş olur. Anahtar kullanımına izin verilip verilmemesi ise PermitRootLogin ayarına bağlıdır.

    SSH sunucusunun ayar dosyasında yaptığımız değişikliğin uygulanması için servisi yeniden yüklememiz gerekir.

    bash
    mehmet@debian ~$ sudo systemctl reload ssh

    Public ve Private Key

    SSH bağlantısında parolanın yerine anahtar çifti kullanabiliriz. Private key bağlandığımız bilgisayarda kalır (localde yani) ve kimseyle paylaşılmaz. Public key ise bağlanacağımız kullanıcı hesabına kopyalanır.

    Anahtar çiftini aşağıdaki komutla oluşturabiliriz.

    bash
    mehmet@debian ~$ ssh-keygen -t ed25519

    Not: Herhangi bir parametre vermeden doğrudan ssh-keygen yazdığımızda da ed25519 ile yeni key üretilir.

    Public key hangi kullanıcı hesabına eklenirse o hesaba giriş yapmak için kullanılabilir. Aynı anahtar birden fazla sunucuya veya kullanıcı hesabına da eklenebilir.

    Anahtarımızı karşı bilgisayardaki kullanıcıya ssh-copy-id ile kopyalayabiliriz.

    bash
    mehmet@debian ~$ ssh-copy-id mehmet@192.168.57.11

    Birden fazla anahtarımız varsa göndereceğimiz public key dosyasını -i ile belirtebiliriz.

    bash
    mehmet@debian ~$ ssh-copy-id -i ~/.ssh/id_ed25519.pub mehmet@192.168.57.11

    Anahtar ile girişin çalıştığını kontrol ettikten sonra sunucu tarafındaki sshd_config dosyasında parolayla girişi kapatabiliriz.

    Bunun için sshd_config dosyasında ve sshd_config.d dizinlerinde Password Authentication satırlarını no’ya çevirmemiz yeterlidir.

    Değişikliğin geçerli olması için SSH servisini yeniden yüklememiz gerekir.

    scp

    scp, SSH bağlantısı üzerinden iki bilgisayar arasında dosya kopyalamamızı sağlar.

    bash
    mehmet@debian ~$ scp deneme.txt mehmet@192.168.57.11:/home/mehmet/

    Uzak bilgisayardaki bir dosyayı kendi bilgisayarımıza da kopyalayabiliriz.

    bash
    mehmet@debian ~$ scp mehmet@192.168.57.11:/home/mehmet/deneme.txt .

    SFTP

    SFTP, SSH üzerinden dosya aktarımı yapmamızı sağlar. Ayrı bir SFTP portu açmamıza gerek yoktur, SSH bağlantısı için kullandığımız port yeterlidir.

    bash
    mehmet@debian ~$ sftp mehmet@192.168.57.11

    SFTP içerisinde pwd ve ls komutları karşı bilgisayarda çalışır. lpwd ve lls komutları ise kendi bilgisayarımızdaki dizinleri gösterir.

    put ile karşı bilgisayara dosya gönderir, get ile karşı bilgisayardan dosya alırız.

    rsync

    rsync, iki konum arasındaki dosyaları senkronize etmek için kullanılır. SSH üzerinden çalıştırıldığında dosyalar şifreli bağlantı üzerinden aktarılır.

    bash
    mehmet@debian ~$ rsync -av belgeler/ mehmet@192.168.57.11:/home/mehmet/belgeler/

    Burada -a parametresiyle dosyalar arasında hiyerarşiyi koruyup izinleriyle birlikte aldık, -v ile terminale hangi dosyaları aldığımızı yazmasını söyledik.

    Rsync kendi daemon servisi üzerinden de çalışabilir. Bu yöntemde varsayılan olarak TCP 873 numaralı port kullanılır. Genellikle herkese açık bir dosya kaynağı sunulacaksa bu yöntem tercih edilebilir.

    SSHFS

    SSHFS, karşı bilgisayardaki bir dizini kendi sistemimizdeki normal bir dizin gibi bağlamamızı sağlar. Dosya aktarımı SSH üzerinden yapılır.

    bash
    mehmet@debian ~$ mkdir uzak-dizin
    mehmet@debian ~$ sshfs mehmet@192.168.57.11:/home/mehmet uzak-dizin

    Bağladığımız dizini findmnt, mount veya df -h komutlarıyla görebiliriz.

    İşimiz bittiğinde bağlantıyı kaldırabiliriz.

    bash
    mehmet@debian ~$ fusermount3 -u uzak-dizin

    SSH bağlantısını etkileşimli bir terminal açmadan, karşı bilgisayarda tek bir komut çalıştırmak için de kullanabiliriz. Komut tamamlandıktan sonra bağlantı kapanır ve kendi terminalimize geri döneriz.

    bash
    mehmet@debian ~$ ssh mehmet@192.168.57.11 ls

    SSH kullanarak yapabileceğimiz farklı işlemler de bulunur. Örnek olarak,

    SSH Agent Forwarding

    Agent forwarding, kendi bilgisayarımızdaki SSH anahtarını başka bir makineye kopyalamadan o makine üzerinden üçüncü bir sunucuya bağlanmamızı sağlar.

    Örneğin A makinesinden B makinesine bağlanabiliyoruz. B makinesi de C makinesine fiziksel yöntemlerle ya da ssh ile bağlanabiliyor ancak A makinesi C makinesine ssh ile bağlanamıyor. Bu durumda B üzerinden C makinesine bağlanmak istediğimizde, kimlik doğrulama isteği B üzerinden A makinesindeki SSH agent’a iletilir. Private key B makinesine kopyalanmaz.

    SSH Ters Tünelleme

    Ters tünelleme, doğrudan dışarıdan erişilemeyen bir makinedeki servisi SSH sunucusu üzerinden erişilebilir hale getirmemizi sağlar.

    Kendi makinemizdeki bir port, uzak sunucudaki bir porta yönlendirilir. Uzak sunucunun ilgili portuna gelen istekler, kurulan tünel üzerinden bizim makinemize iletilir. Bu şekilde, normalde dışarıdan erişilemeyen kendi makinemize, uzak sunucu üzerinden dışarıdan erişilebilir hale geliriz.

    SSH Tünelleme

    SSH tünelleme ile kendi bilgisayarımızdaki bir portu, SSH sunucusunun ulaşabildiği başka bir servise aktarabiliriz. Makinelerin aynı ağda bulunması gerekmez ancak aralarında gerekli bağlantının kurulabiliyor olması gerekir.

    Kendi bilgisayarımızdaki 8080 portuna gelen bağlantılar, SSH sunucusu üzerinden hedef sunucunun 80 numaralı portuna iletilir.

    SSH SOCKS Proxy

    SSH SOCKS Proxy, belirlediğimiz bir uygulamanın ağ trafiğini SSH sunucusu üzerinden göndermemizi sağlar. Örneğin tarayıcımızı bu proxy’yi kullanacak şekilde ayarlarsak, ziyaret ettiğimiz sitelere doğrudan kendi bilgisayarımızdan değil SSH sunucusu üzerinden ulaşırız.

    SSH ile X11 Aktarımı

    X11 aktarımı, uzak bilgisayarda çalışan grafik arayüzlü bir uygulamanın penceresini kendi ekranımızda göstermemizi sağlar. Bu işlem uzak masaüstü bağlantısı değildir, yalnızca çalıştırdığımız uygulamanın penceresi aktarılır.


    Başta Doruk ve Onur hocalarım olmak üzere kampta emeği geçen herkese teşekkür ederim.


  • Linux Sistem Yönetimi | LKD #8

    İnternet üzerinde bir sunucuya ulaşabilmek için IP adresi kullanılır. Ancak ziyaret ettiğimiz her sitenin IP adresini ezberlemek kullanışlı bir yöntem değildir. DNS, yazdığımız alan adının hangi IP adresine karşılık geldiğini bulmamızı sağlar.

    Alan adı çözümlemesi çalışmadığında internet bağlantımız devam ediyor olsa bile alan adlarını kullanarak servislere ulaşamayabiliriz. IP adresini bildiğimiz bir hedefe erişebilmemiz, DNS çözümlemesinin de çalıştığı anlamına gelmez.

    DNS Hiyerarşisi

    DNS tek bir sunucudan oluşmaz. Alan adları hiyerarşik bir yapı içerisinde root DNS sunucuları, üst seviye alan adı sunucuları ve alan adının kayıtlarını tutan yetkili DNS sunucuları üzerinden çözümlenir.

    Bilgisayarımız genellikle bu sunucuların tamamına kendisi tek tek gitmez. Sorguyu kullandığı recursive DNS sunucusuna gönderir. Recursive DNS sunucusu cevap önbelleğinde bulunuyorsa doğrudan geri döner. Bulunmuyorsa root sunucudan başlayarak hangi DNS sunucusuna gitmesi gerektiğini öğrenir.

    Root sunucu alan adının IP adresini doğrudan vermek zorunda değildir. Öncelikle ilgili üst seviye alan adından sorumlu DNS sunucusunu gösterir. Örneğin .tr ile biten bir alan adı için .tr sunucularına yönlendirme yapılır. Buradan da alan adının kayıtlarını tutan yetkili DNS sunucusuna ulaşılır.

    Bulunan cevap recursive DNS sunucusunun önbelleğine alınabilir. Aynı kayıt tekrar sorulduğunda bütün sorgu adımlarının yeniden uygulanması gerekmez. Böylece hem daha hızlı cevap alınır hem de diğer DNS sunucularına giden sorgu sayısı azalır.

    TTL

    DNS sunucusunun döndürdüğü kayıtlar önbellekte sonsuza kadar tutulmaz. Kayıtla birlikte verilen TTL değeri, cevabın kaç saniye boyunca önbellekte geçerli kabul edilebileceğini belirtir.

    DNS kaydına kısa bir TTL verilirse yapılan değişiklikler önbelleklerin süresi dolduktan sonra daha hızlı fark edilir. Ancak kayıt daha sık sorgulanacağı için DNS sunucularına giden sorgu sayısı artabilir.

    Uzun bir TTL kullanıldığında kayıt daha uzun süre önbellekten cevaplanabilir. Bu durum sorgu sayısını azaltır ancak IP adresinde yapılan bir değişikliğin kullanıcılara ulaşmasını geciktirebilir.

    TTL değerini değiştirmek DNS kaydını değiştirmemizi engellemez. Fakat eski kayıt daha önce uzun bir TTL değeriyle önbelleğe alınmışsa o önbellekteki sürenin dolmasını beklememiz gerekebilir. Sonradan TTL değerini düşürmemiz, daha önce alınmış kayıtların kalan süresini geriye dönük olarak değiştirmez.

    Bu nedenle bir siteyi başka bir IP adresine taşıyacağımızı önceden biliyorsak TTL değerini taşıma işleminden önce düşürebiliriz. Eski TTL süresi dolduktan sonra IP adresini değiştirdiğimizde yeni kayıt daha kısa sürede yayılabilir.

    Not: DNS kayıtlarında bulunan TTL ile IP paketlerinde bulunan TTL aynı şey değildir. DNS TTL değeri kaydın önbellekte tutulacağı süreyi, IP paketindeki TTL ise paketin geçebileceği router sayısını sınırlar.

    Linux’ta bir ismin hangi adrese karşılık geldiğini bulmak için yalnızca DNS kullanılmak zorunda değildir. Sistem yerel dosyalara veya yapılandırmada belirtilen başka kaynaklara da bakabilir.

    /etc/hosts

    /etc/hosts, IP adresleriyle isimleri yerel olarak eşleştirebildiğimiz dosyadır. Buraya yazdığımız eşleştirme yalnızca düzenlemeyi yaptığımız bilgisayarda geçerli olur. DNS sunucusundaki kaydı değiştirmez.

    Bu dosyanın en yaygın kullanım alanlarından biri, bir siteyi başka bir IP adresine taşımadan önce yeni sunucuyu test etmektir. Alan adını yalnızca kendi bilgisayarımızda yeni IP adresiyle eşleştirerek DNS kaydını değiştirmeden siteyi kontrol edebiliriz.

    /etc/hosts belirli alan adlarını farklı bir adrese yönlendirmek veya bir uygulamanın istenmeyen bir adrese ulaşmasını basit şekilde engellemek için de kullanılabilir.

    /etc/hosts dosyasının içeriği

    /etc/nsswitch.conf

    Bir isim çözümlenirken bilgisayarın hangi kaynaklara ve hangi sırayla bakacağını /etc/nsswitch.conf dosyasından görebiliriz.

    Örneğin, dosyadaki hosts: satırında files dns yazıyorsa sistem önce yerel dosyalara, ardından DNS’e bakar. Buradaki sıra değiştirilebilir. Bu nedenle Linux’un her durumda önce /etc/hosts dosyasına bakacağı şeklinde sabit bir kural yoktur; hangi kaynağın önce kullanılacağını bu satır belirler.

    Not: files ifadesinin baktığı dosya, sorgulanan bilgi türüne göre değişir. hosts için /etc/hosts, passwd için /etc/passwd kullanılır.

    /etc/resolv.conf

    DNS sorgularının hangi DNS sunucusuna göndereceğini /etc/resolv.conf dosyasından görebiliriz. Dosyadaki nameserver satırlarında kullanılacak DNS sunucularının adresleri bulunur.

    whois

    whois, bir IP adresinin hangi alan adına karşılık geldiğini bulmak için değil, IP bloğunun kime tahsis edildiğini öğrenmek için kullanılır.

    Bir IP adresini sorguladığımızda adres bloğının hangi kuruma tahsis edildiği, ilgili ağ aralığı ve iletişim bilgileri gibi sonuçlar görebiliriz. Alan adı sorgularında ise kayıt kuruluşu ve kayıt tarihleri gibi bilgiler dönebilir.

    WHOIS ayrı bir protokoldür ve klasik kullanımında TCP 43 numaralı port üzerinden çalışır. Ağdaki bir güvenlik duvarı bu bağlantıya izin vermiyorsa sorgu sonuçlanmayabilir.

    host ve Ters DNS Sorgusu

    host komutuyla bir alan adının IP adresini sorgulayabileceğimiz gibi bir IP adresi için ters DNS sorgusu da yapabiliriz. IP adresinden isim sorgulandığında ilgili PTR kaydı aranır.

    Bir IP adresi için PTR kaydı bulunması, dönen alan adının tekrar sorgulandığında aynı IP adresine karşılık geleceğini garanti etmez. İleri yönlü kaydı alan adını yöneten taraf, ters yönlü kaydı ise IP bloğunu yöneten taraf oluşturabilir. Bu iki kayıt birbirinden bağımsızdır.

    DNS Kayıtları

    DNS yalnızca alan adının IP adresini tutmaz. Farklı amaçlar için farklı kayıt türleri kullanılır.

    • A: Bir alan adını IPv4 adresiyle eşleştirir.
    • MX: Alan adına gelen e-postaların hangi posta sunucularına gönderileceğini belirtir.
    • CNAME: Bir alan adını başka bir alan adına takma ad olarak yönlendirir.
    • TXT: Alan adıyla ilgili metin biçimindeki bilgileri tutar.

    dig

    dig, DNS sunucularına sorgu göndermek ve dönen cevabın ayrıntılarını incelemek için kullanılır. Çıktıda sorgulanan kayıt türünü, alınan cevabı, TTL değeri gibi değerleri görebiliriz.

    hostname

    Bilgisayarın sistem içerisindeki adını /etc/hostname dosyasından görebiliriz. Bu dosyadaki değeri değiştirerek bilgisayarın hostname bilgisini değiştirebiliriz.

    Bunu doğrudan hostnamectl aracı ile,

    bash
    mehmet@debian ~$ sudo hostnamectl set-hostname yeni-isim

    ya da doğrudan /etc/hostname dosyasındaki değeri değiştirerek yapabiliriz. Ardından oturumumuzu yenileyerek hostname’in değiştiğini görebiliriz.

    Yalnız her ikisinde de /etc/hosts dosyasındaki değerin değişmediğini fark ettim. İsim çözümlemeye çalışan uygulamaların sorun yaşayabileceği bir durum oluşabileceğini düşünüyorum ancak net bir örnek bulamadım.

    Günün geri kalanında LAMP (apache – php – mariadb – wordpress) kurulumu yaptık. Bu kısmı daha öncesinde katılmış olduğum web servisi eğitimlerinde de tekrar ettiğimizden yazmadım, bağlantıya tıklayarak notlara ulaşabilirsiniz.

    Not: İlgili bağlantıda kurulumlar tek bir makine üzerine yapılıyor, biz sınıfta iki farklı makine üzerinden kurulum yaptık. Bir tarafa mariadb, diğer tarafa web server kurduk. Ekstra olarak,

    Veritabanı sunucusuna diğer makineden bağlanabilmek için /etc/my.cnf.d/mariadb-server.cnf dosyasındaki bind-address değerini 0.0.0.0 olarak düzenliyoruz. Böylece MariaDB yalnızca 127.0.0.1 üzerinde değil, sistemdeki bütün IPv4 arayüzlerinde bağlantı dinleyebiliyor. Bağlantının kurulabilmesi için güvenlik duvarının ve MariaDB kullanıcı yetkilerinin de buna izin vermesi gerekir.

    Ardından wp-config.php dosyasındaki DB_HOST bölümüne MariaDB sunucusunun IP adresini yazıyoruz. Böylece WordPress, diğer makinede çalışan veritabanı sunucusuna bağlanabiliyor.

    Devamını okumak için…


  • Linux Sistem Yönetimi | LKD #7

    Bilgisayarımız bir ağa bağlanırken ağ arayüzlerini kullanır. Bir bilgisayarda Ethernet, kablosuz ağ veya sanal ağ kartı gibi birden fazla arayüz bulunabilir.

    Ağa bağlandığımızda sistemimiz dhcp isteği gönderebilir. Ağda bir dhcp sunucusu varsa IP adresi, ağ maskesi, varsayılan ağ geçidi ve dns gibi ayarları bilgisayarımıza iletir. Böylece bu bilgileri elle tanımlamadan dhcp’nin gönderdiği ayarları uygulayarak bağlanabiliriz.

    MAC adresi, aynı yerel ağdaki ağ kartlarının birbirlerini tanıyabilmesi için kullanılır. IP adresi ise farklı ağlar arasında yönlendirme yapabilmemizi sağlar.

    TCP başlığında MAC adresi bulunmaz. Çünkü TCP, taşıma katmanında çalışır. MAC adresi Ethernet çerçevesinde, IP adresi IP başlığında, port bilgileri ise TCP veya UDP başlığında yer alır. Bu nedenle yerel ağınızın dışındaki biriyle haberleştiğinizde karşı taraf sizin MAC adresinizi doğrudan göremez. Ancak günümüzde birçok uygulama, paket başlıklarından bağımsız olarak kullanıcıdan izin alıp MAC adresini normal bir veri gibi çekebilir.

    TCP başlıkları (MAC alanı bulunmuyor)

    Broadcast

    Broadcast, aynı yerel ağdaki bütün cihazlara paket gönderebilmemizi sağlar. Gönderilen broadcast trafiği aynı ağdaki (genel olarak) cihazlara ulaşabilir.

    Bir paketin ağdaki başka cihazlar tarafından görülebilmesi, içeriğinin okunabileceği anlamına gelmez. Haberleşmede şifreleme kullanılıyorsa trafik görülse bile içerisindeki veriler doğrudan okunamayabilir.

    Default Gateway ve Router

    Bilgisayarımız kendi ağı dışında bulunan bir hedefe gitmek istediğinde paketi varsayılan ağ geçidine gönderir. Default gateway çoğunlukla yerel ağımızı başka ağlara bağlayan router’ın IP adresidir.

    Router’lar paketleri nereye göndereceklerine routing table üzerinden karar verirler. Yönlendirme tablosunda hedef ağlar ve bu ağlara ulaşmak için kullanılacak yollar bulunur.

    Kullandığımız bilgisayarlar da bazı durumlarda router gibi çalışabilir. Örneğin ana bilgisayarımız, sanal makinelerin internete çıkabilmesi için onların trafiğini başka bir ağ arayüzüne yönlendirebilir.

    Yönlendirme Tablosu

    ip route komutuyla bilgisayarımızın yönlendirme tablosunu görebiliriz. Çıktıda doğrudan bağlı ağlar, default route, kullanılacak ağ arayüzü ve bazı satırlarda kaynak IP adresi bulunur.

    default via ile başlayan satır, yönlendirme tablosunda daha özel bir rota bulunmadığında paketin hangi ağ geçidine gönderileceğini belirtir.

    dev, trafiğin hangi ağ arayüzünden çıkacağını gösterir.

    src, bu rota kullanılırken tercih edilecek kaynak IP adresini gösterir. Her rota satırında src bulunması zorunlu değildir.

    Yönlendirme tablosunda hedefe uygun özel bir rota bulunmuyorsa sistem default route’u kullanır. Default route da bulunmuyorsa hedefe ulaşılamadığına dair bir hata alabiliriz.

    Not: No route to host hatası yalnızca yönlendirme tablosunda rota bulunmadığı için oluşmaz, güvenlik duvarı veya hedefe yerel ağ üzerinden ulaşılamaması gibi durumlarda da görülebilir.

    Loopback

    127.0.0.0/8 IPv4 loopback bloğudur. En sık kullandığımız loopback adresi 127.0.0.1 adresidir.

    Loopback arayüzü, bilgisayarın ağ trafiğini fiziksel ağ kartına göndermeden kendi üzerine yönlendirebilmesini sağlar.

    Loopback arayüzüne tanımlanan adresler de birer ağ ayarıdır. Bu ayarlar değiştirilebilir ancak birçok program 127.0.0.1 adresinin loopback olarak kullanılacağını varsaydığı için gereksiz yere değiştirilmemelidir.

    ip ve ifconfig

    Eskiden ağ arayüzlerini görüntülemek ve yapılandırmak için ifconfig yaygın olarak kullanılıyordu. Artık tarih oldu. Günümüzde bunun yerine çoğunlukla ip komutu kullanılır.

    ip a çıktısı

    CIDR ve Bir Arayüze Birden Fazla IP Verilmesi

    IP adresleri eskiden sınıflı adresleme adı verilen bir yöntem kullanıyordu. Yöntem IP adreslerini 5 ana sınıfıa bölüyor ve birçok adresin boşa harcanmasına sebep oluyordu. Bundan ötürü zamanla bu fikir terk edildi ve CIDR denen yeni gösterime geçildi.

    IP adreslerinin sonunda gördüğümüz /24, /16 veya benzeri ifadeler CIDR gösterimidir. Buradaki sayı, adresin kaç bitinin ağ kısmını oluşturduğunu belirtir.

    Bir ağ arayüzünde yalnızca bir IP adresi bulunmak zorunda değildir. Aynı arayüze birden fazla IPv4 veya IPv6 adresi tanımlanabilir.

    enp0s8 kartında 3 farklı ip adresi tanımlanmış

    VirtualBox Ağ Modları

    Sanal makinelerin birbirleriyle, ana makineyle ve internetle nasıl haberleşeceğini VirtualBox içerisindeki ağ modları belirler. Ağ ayarları yapmak için sanal makine ayarlarına girip network sekmesine geçmeniz gerekir.

    • NAT: Sanal makine, VirtualBox’ın adres çevirisini kullanarak ana makine üzerinden internete çıkar. Cihazlara yönlendirilebilir public IP verilebilen ağlarda NAT zorunlu değildir.
    • Bridged Adapter: Sanal makine, fiziksel ağa ayrı bir cihaz gibi bağlanır. DHCP’den IP alabilir ve aynı ağdaki cihazlarla haberleşebilir.
    • Internal Network: Yalnızca aynı isimdeki iç ağa bağlı sanal makineler haberleşebilir. Ana makine ve internet bu ağa dahil değildir.
    • Host-only Adapter: Ana makine ile sanal makineler arasında özel bir ağ kurar. Ana makine ve aynı host-only ağa bağlı sanal makineler birbiriyle haberleşebilir.

    Özgür yazılım kampında hemen hemen sistem temelli birçok eğitimin temel gereksinimi olan sanal makinelerin birbirleriyle ve ana makine ile haberleşmesi için bir yapılandırma yapalım.

    İlk olarak virtualbox’ta sol sekmede yer alan ağ simgesine gidelim. Burada sanal ağ kartları oluşturabiliyoruz. Oluştur seçeneğine tıklayıp oluşturalım.

    vboxnet2 adında bir sanal ağ kartı oluşturdum. Ağı 192.168.58.0/24 . Bir sonraki adımda haberleştireceğimiz sanal makinelerin ağ ayarlarını yapacağız.

    Bunun için ilk önce haberleştireceğimiz sanal makineleri shutdown edelim. Ardından sağ tık ile sanal makine ayarlarına gidelim, network ayarlarına gelelim.

    İlk ağ kartını NAT, ikinci ağ kartını “host-only adapter” olarak değiştirelim.

    İkinci ağ kartını vboxnet2 ağ kartına geçirelim. Bunu da “Ad” kısmından yapıyoruz.

    haberleştireceğimiz diğer sanal makinelerde de aynı ayarları tekrar edelim.

    Ardından iki sanal makineyi de başlatıp ağ arayüzlerini görmek için,

    bash
    mehmet@debian ~$ ip -br address

    komutunu yazalım. Burada enp0s8 ağ kartını gördükten sonra ilk önce sanal ağ kartını ayağa kaldıralım.

    Ancak öncesinde iki dağıtım arasında farklı olarak gördüğüm bir özelliği paylaşmak istiyorum. Debian’da ağ kartı eklendiğinde down durumda başlarken, rocky’de bir şey yapmama gerek kalmadan up oldu. Devam edelim.

    bash
    mehmet@debian ~$ sudo ip link set enp0s8 up

    Ağ arayüzünü ayağa kaldırdıktan sonra bir ip atayalım.

    bash
    mehmet@debian ~$ sudo ip addr add 192.168.58.11/24 dev enp0s8

    Rocky’e geçelim.

    bash
    mehmet@rocky ~$ sudo ip addr add 192.168.58.12/24 dev enp0s8

    Artık sanal makineleri ana makineyle ve birbirleriyle haberleştirebiliyoruz. Ancak şimdi sistemi yeniden başlattıktan sonra da devam edebilmesi için gerekli ayarlamaları yapalım.

    İlk olarak Rocky de network manager ayarlamalarını yapacağız. Mevcut durumu incelemek için

    bash
    mehmet@rocky ~$ nmcli connection show

    komutunu giriyorum. Çıktı da

    enp0s8 kartı mevcut durumda açılışta gelecek yeni ağ ayarını uyguluyor. Biz açılışta daima aynı ip’yi alması için düzenlemelere başlayalım.

    bash
    mehmet@rocky ~$ nmcli connection modify enp0s8 ipv4.method manual ipv4.addresses 192.168.58.12/24 ipv4.gateway "" ipv4.dns "" ipv4.never-default yes connection.autoconnect yes

    Bu komutta,

    • nmcli connection modify enp0s8: enp0s8 bağlantı profilini değiştirir.
    • ipv4.method manual: IP adresinin DHCP’den değil, elle verileceğini belirtir.
    • ipv4.addresses 192.168.58.12/24: Kalıcı IP adresini ve ağ maskesini tanımlar.
    • ipv4.gateway : Bu bağlantıya ağ geçidi verilmez. İnternete NAT kartı olan enp0s3 üzerinden çıkacağız.
    • ipv4.dns : Host-only bağlantıya DNS sunucusu verilmez.
    • ipv4.never-default yes: enp0s8 bağlantısının varsayılan internet yolu olmasını engeller.
    • connection.autoconnect yes: Sistem açıldığında bu bağlantının otomatik etkinleştirilmesini sağlar.

    Kısacası enp0s8 kartına kalıcı olarak 192.168.58.12/24 adresini verir, fakat internet trafiğini NAT kartına bırakır.

    Ardından yeni ayarlarla bağlantı yeniden etkinleştirmek için

    bash
    mehmet@rocky ~$ nmcli connection up enp0s8

    tekrar network manager’ın durumuna baktığımızda

    başarıyla rocky tarafında işlemi tamamladığımızı görüyoruz. Şimdi diğer makine içinde bu işlemleri yapalım.

    Ubuntu’da, Rocky’den farklı olarak ağ ayarlarını doğrudan NetworkManager üzerinden değil, Netplan yapılandırma dosyası üzerinden yapıyoruz. Çünkü Ubuntu ağ yapılandırmasında varsayılan olarak Netplan’i, Rocky Linux ise doğrudan NetworkManager’ı kullanır.

    Mevcut konfigürasyon dosyalarını inceleyerek başlayalım.

    bash
    mehmet@debian ~$ ls -l /etc/netplan/

    -rw——- 1 root root 303 Sep  2 07:55 00-installer-config.yaml


    Mevcut dosya içeriğine ek olarak enp0s8’e statik ip ataması yapalım.

    Burada enp0s3 kartını Nat için, yani internete çıkabilmek için, enp0s8 kartını diğer sanal makine ve ana makine ile bağlantı kurabilmek için yapılandırdık.

    Dosyada bir yazım hatası yapıp yapmadığımızı kontrol etmek için

    bash
    mehmet@debian ~$ sudo netplan generate

    herhangi bir çıktı almıyoruz, yapmamışız. Ayarları uygulayabiliriz.

    bash
    mehmet@debian ~$ sudo netplan try

    Burada enter bastıktan sonra başarıyla yapılandırmayı tamamladık.

    Makineler arasında ve anamakineye doğrudan ping atmayı denediğimde başarıyla çalışıyor. İki makineden de internete çıkabiliyorum. Statik ip alıp almadığını kontrol etmek için bilgisayarımı farklı bir ağa bağladım, ardından sanal makineleri yeniden başlattım. Yine aynı ip’ler üzerinden iletişim kurabilmeye devam edebildim. Yani bu işlemi de başarıyla tamamlamış olduk.

    IPv4 ve IPv6

    IPv4 adresleri 32 bit uzunluğundadır. İnternete bağlanan cihazların sayısı arttığı için kullanılabilecek IPv4 adresleri yetersiz kalmaya başlamıştır. Bunun üzerine IPv6 peydah olur.

    IPv6 adresleri 128 bit uzunluğundadır ve IPv4’e göre çok daha geniş bir adres alanı sağlar.

    TCP ve UDP

    TCP bağlantı kurarak çalışan ve verilerin sıralı, eksiksiz ulaştırılmasını kontrol eden bir taşıma protokolüdür. Paket kaybolursa yeniden gönderilmesini sağlayabilir. Bu kontroller nedeniyle UDP’ye göre daha fazla işlem yapar.

    UDP bağlantı kurmadan datagram (tcp de segment udp de datagram denir) gönderir. Paketin ulaşıp ulaşmadığını, sırasını veya tekrar gönderilmesini kendi başına garanti etmez. Bu nedenle gecikmenin düşük tutulmasının önemli olduğu bazı uygulamalarda tercih edilebilir.

    Not: TCP’nin güvenilir olması, veriyi şifrelediği veya güvenli hâle getirdiği anlamına gelmez. UDP de doğrudan “güvensiz” bir protokol değildir. Buradaki fark güvenlikten ziyade teslimat ve bağlantı kontrolüdür.

    UDP kullanılacaksa uygulama paket kaybını tolere edebilmeli veya ihtiyaç duyduğu kontrolü kendisi sağlamalıdır.

    Video aktarımı hem TCP hem UDP üzerinden yapılabilir. Canlı bir videoda kaybolan tek bir kareyi yeniden istemek, bu sırada yeni karelerin de gecikmesine neden olabilir. Bu yüzden bazı gerçek zamanlı yayınlarda eski paketi tekrar beklemek yerine akışa devam etmek yani UDP kullanmak tercih edilir

    DNS de ihtiyaca göre hem UDP hem TCP kullanabilir.

    Port

    Bir IP adresi üzerinde birden fazla servis çalışabilir. Port numaraları, gelen verinin aynı IP adresindeki hangi uygulamaya veya servise teslim edileceğini belirler.

    Örneğin tek bir sunucuda web servisi, SSH servisi ve başka uygulamalar farklı portları dinleyebilir. Böylece aynı IP adresi üzerinden birden fazla ağ hizmeti sunulabilir.

    Netmask ve Subnetting

    Netmask veya CIDR prefix değeri, IP adresinin ağ ve cihaz kısımlarını birbirinden ayırır. Başka bir ifadeyle ağın hangi adres aralığını kapsadığını belirler.

    Subnetting, büyük bir IP ağını daha küçük ağlara bölmemizi sağlar. Böylece farklı cihaz grupları ayrı ağlarda tutulabilir.

    Klasik IPv4 subnetlerinde ağ adresi ve broadcast adresi cihazlara verilmez. Bu nedenle subnet hesabında iki adres cihazlara dağıtılamaz. Toplam adres sayısından 2’yi çıkartarak kullanılabilir IP adres sayısını öğrenebiliriz.

    192.168.1
    Ağ kısmı
    25
    Cihaz kısmı

    /24 → 256 toplam adres → 254 kullanılabilir adres

    Firewall

    Firewall, ağ trafiğini belirlenen kurallara göre kabul eder veya engeller. Kaynak ve hedef IP adresi, protokol ve port gibi bilgilere bakarak hangi trafiğin geçebileceğine karar verebilir.

    OSI Modeli

    OSI modeli, ağ haberleşmesini farklı katmanlara ayırarak incelememizi sağlar. Fiziksel bağlantıdan uygulamaya kadar yapılan işlemler yedi katman altında ele alınır.

    Bu model sayesinde MAC adresi, IP adresi, TCP, UDP ve uygulama protokolleri gibi yapıların ağ haberleşmesinin hangi bölümünde görev yaptığını daha kolay ayırabiliriz.

    traceroute

    traceroute, hedefe giderken paketin geçtiği router’ları adım adım görmemizi sağlar.

    Çıktı da yıldız görünmesi, ilgili denemeye zaman aşımı süresi içerisinde cevap gelmediğini gösterir. Bunun nedeni router’ın cevap vermemesi, ICMP mesajlarının güvenlik duvarı tarafından engellenmesi veya ağdaki başka bir filtre olabilir.

    Yıldız görülen bir adım, paketin kesin olarak orada durduğu anlamına gelmez. Sonraki adımlar görünüyorsa trafik o router üzerinden veya o noktadan geçmeye devam etmiş ancak ilgili cihaz traceroute denemesine cevap vermemiş olabilir.

    Public ve Private IP Çakışması

    Bir public IP bloğunu private ağımızda gelişigüzel kullanırsak yönlendirme karışıklığı yaşayabiliriz. Sistem bu adresin yerel ağda mı yoksa internet üzerinde mi bulunduğuna yönlendirme tablosuna göre karar verir.

    Yerel ağdaki rota daha özel olduğu için aynı public adrese internet üzerinden ulaşmak istediğimizde paket yanlışlıkla yerel ağa gönderilebilir. Bu nedenle private ağlarda private kullanım için ayrılmış adres bloklarını tercih ederiz.

    ping, TTL ve Traceroute İlişkisi

    TTL, bir IP paketinin kaç router geçebileceğini sınırlar. Paket her router’dan geçtiğinde TTL değeri bir azaltılır. Değer sıfıra düştüğünde router paketi düşürür ve çoğunlukla ICMP Time Exceeded mesajı gönderir.

    ping tarafından gönderilen paketlerin başlangıç TTL değeri işletim sistemine göre değişebilir. Ping çıktısında gördüğümüz TTL ise cevap paketinin bize ulaştığı andaki kalan değerdir.

    Traceroute bu mekanizmadan yararlanır. İlk denemede düşük bir TTL değeri kullanır. TTL ilk router’da bittiğinde o router cevap verir. Sonraki denemelerde TTL kademeli olarak artırılır ve böylece yol üzerindeki router’lar ortaya çıkarılır.

    ICMP

    Ping, hata bildirimleri ve traceroute sırasında alınan bazı cevaplar ICMP üzerinden taşınır.

    ICMP, TCP veya UDP değildir. Ayrı bir protokoldür. Bu nedenle TCP ve UDP servislerinde olduğu gibi port numarası kullanmaz.

    Kimi zaman güvenlik sıkılaştırılması yapılırken ICMP’nin gelişi sistemlerce kısıtlanabilir, yani ping yanıtı alınmaması bağlantının kesin olarak çalışmadığını göstermez

    ss

    ss komutuyla kendi bilgisayarımızdaki dinleme durumunda olan TCP ve UDP soketlerini görebiliriz.

    bash
    mehmet@debian ~$ ss -tuln
    • t: TCP
    • u: UDP
    • l: Yalnızca dinleyen soketler
    • n: Port isimleri yerine port numaraları

    netstat eskiden bu iş için yaygın olarak kullanılıyordu. Günümüzde çoğunlukla ss tercih edilir. Netstat tamamen yok olmuş değildir ancak eski kabul edilir ve bazı sistemlerde varsayılan olarak bulunmaz.

    Netcat

    Netcat ile belirli bir port üzerinde dinleme başlatabiliriz. Notlarda nc -lvp 4444 kullanarak 4444 numaralı portu dinleyen bir örnek oluşturduk.

    nmap

    Nmap, ağdaki cihazları ve bu cihazlarda erişilebilir durumda olan portları incelemek için kullanılabilir. Tek bir araç içerisinde farklı tarama yöntemleri ve seçenekler bulunur.

    Telnet

    Telnet, uzak bir sisteme düz metin üzerinden bağlantı kurulmasını sağlayan bir protokoldür. Haberleşme şifrelenmediği için uzaktan yönetim amacıyla yerini büyük ölçüde SSH’ye bırakmıştır.

    Telnet istemcisi günümüzde bir hedefteki TCP portuna bağlantı kurulup kurulamadığını kontrol etmek için de kullanılabilir. Ancak bir porta Telnet ile bağlanamamak her zaman o porta hiç kimsenin bağlanamayacağı anlamına gelmez. Güvenlik duvarı kuralları, kaynak IP adresi veya servisin yalnızca belirli arayüzleri dinlemesi sonucu değiştirebilir.

    Tcpdump

    Tcpdump, bir ağ arayüzünden geçen paketleri yakalamamızı ve incelememizi sağlar. Yalnızca TCP paketlerini değil, UDP ve ICMP gibi farklı protokollere ait paketleri de filtreleyebilir.

    Belirli bir TCP portundaki gelen ve giden trafiği filtreleyerek kaydedebiliriz.

    Tcpdump ile UDP trafiğini filtreleyerek paketleri yakalayacağız.

    Bunu iki ayrı sanal makineden yürüteceğim. Yazının önceki kısımlarında statik ip ataması yaptığım rocky ve ubuntu benimle olacak. Öncelikle ubuntu’da,

    bash
    mehmet@debian ~$ sudo tcpdump -i enp0s8 -nn udp

    tcpdump’ı enp0s8’deki udp paketlerini filtreleyecek şekilde ayarladık

    Ardından,

    bash
    mehmet@rocky ~$ echo "UDP test paketi" | nc -u -w 1 192.168.58.11 5555

    rocky’den ubuntu’ya bir udp paketi yolladık.

    başarıyla tcpdump aracıyla udp paketlerini de filtreyebilmiş olduk.

    Devamını okumak için…


  • Linux Sistem Yönetimi | LKD #6

    Süreç Yönetimi

    Sistemde çalışan programların her biri birer süreç oluşturur. Süreçleri görüntülemek için ps aux veya top gibi araçları kullanabiliriz.

    ps aux çıktısı
    AlanAnlamı
    USERSüreci çalıştıran kullanıcı
    PIDSürecin kimlik numarası
    %CPUSürecin işlemci kullanım oranı
    %MEMSürecin RAM kullanım oranı
    VSZSürecin toplam sanal bellek alanı
    RSSSürecin fiziksel RAM üzerinde kapladığı alan
    TTYSürecin bağlı olduğu terminal. ? herhangi bir terminale bağlı olmadığını gösterir
    STATSürecin durumu ve ek özellikleri
    STARTSürecin başlatıldığı zaman
    TIMESürecin kullandığı toplam işlemci süresi
    COMMANDÇalıştırılan komut ve parametreleri

    ps aux, komutu çalıştırdığımız andaki süreçleri listeler. top ise bu listeyi belirli aralıklarla yenileyerek işlemci ve bellek kullanımını anlık olarak takip etmemizi sağlar.

    top çıktısı

    ps veya top çıktısında isimleri köşeli parantez içerisinde görünen süreçler genellikle kernel space’de çalışan süreçlerdir. Köşeli parantez bulunmayanlar ise user space’de çalışan normal süreçlerdir.

    Not: cpu ve memory alanlarında 0.0 durumu, ondalığın daha gerisinde bir güç harcandığını belirtir.

    Nice Değeri

    Nice değeri, bir sürecin diğer süreçlere göre işlemciyi kullanma önceliğini etkiler. Linux’ta nice değeri -20 ile 19 arasındadır.

    Nice değeri küçüldükçe süreç daha öncelikli, büyüdükçe daha az öncelikli hale gelir. Yani nice değeri 10 olan bir süreç, nice değeri 0 olan bir sürece göre işlemci sırasında daha geri planda kalabilir.

    Yeni bir programı belirli bir nice değeriyle başlatmak için nice, çalışmakta olan bir sürecin nice değerini değiştirmek için renice komutunu kullanabiliriz.

    bash
    mehmet@debian ~$ nice -n NICE_DEĞERİ PROGRAM PARAMETRELER
    bash
    mehmet@debian ~$ renice -n YENİ_NICE_DEĞERİ -p Process_ID

    Normal bir kullanıcı kendi sürecini daha az öncelikli hale getirebilir. Ancak nice değerini düşürerek sürece daha yüksek öncelik vermek istediğinde yetki hatası alabilir. Ben de negatif bir nice değeri vermeye çalıştığımda permission denied hatası aldım.

    top ve ps çıktısındaki NI alanı nice değerini gösterir. PRI veya PR alanı ise çekirdeğin süreç için kullandığı öncelik bilgisidir. Nice değeri kullanıcı tarafından değiştirilebilirken süreçlerin çalıştırılma sırasına son kararı çekirdek verir.

    İşlemci Kullanımı ve Load Average

    Bir sürecin işlemci kullanımı %100 değerini geçebilir. Çok çekirdekli bir sistemde %100, yaklaşık olarak bir çekirdeğin tamamen kullanılması anlamına gelir. Örneğin %250 işlemci kullanan bir süreç, yaklaşık iki buçuk çekirdek kadar işlemci zamanı kullanıyor olabilir.

    Sistemde kaç işlemci ve çekirdek bulunduğunu lscpu komutuyla görebiliriz. İşlemciyle ilgili bilgilere /proc/cpuinfo dosyasından da ulaşabiliriz.

    lscpu çıktısı

    Bunun haricinde sistemimizin ne kadar süredir açık olduğunu bilgisini de içeren bir komut olan uptime’ı deneyelim,

    çıktısında bulunan üç load average değeri sırasıyla son 1, 5 ve 15 dakikadaki ortalama sistem yükünü gösterir. 1 user kısmıysa sistemimizde şu anda kaç oturum olduğunu gösterir.

    Sistemimizde şu anda kimlerin olduğunu görebileceğimiz bir diğer komut ise,

    w komutunun çıktısı

    w veya who komutudur. Bu çıktı da IDLE oturumun ne kadar süredir boşta olduğunu, JCPU terminale bağlı süreçlerin toplam işlemci süresini, PCPU o anda çalışan sürecin işlemci süresini, WHAT ise çalışan süreç veya komutu gösterir.

    Eğer buradaki değerler sistemdeki çekirdek sayımızı geçtiyse sistemimiz çok yoğun yük altında demektir.

    USB ve PCI Aygıtları

    lsusb komutuyla sisteme bağlı USB aygıtlarını listeleyebiliriz. -v seçeneğini kullandığımızda aygıtların üreticisi, kimliği ve özellikleri gibi daha ayrıntılı bilgiler gösterir.

    lspci ise sistemin PCI veri yollarında gördüğü aygıtları listeler. Ekran kartı, ağ kartı, depolama ve USB denetleyicileri bu çıktıda görülebilir. Bu aygıtlar anakarta takılan ayrı kartlar olabileceği gibi anakart üzerinde yerleşik olarak da bulunabilir. PCI, bu bileşenlerin sistemle haberleşmesini sağlayan bağlantı yapılarıdır.

    Bellek Kullanımı

    free komutuyla sistemdeki fiziksel bellek ve swap kullanımı hakkında bilgi alabiliriz. -m seçeneği değerleri Mb cinsinden gösterir. Değerlerin boyutuna göre Mb veya Gb biçiminde daha okunabilir (insani) bir çıktı almak için -h seçeneğini kullanabiliriz. Detaylı bilgi almak için -v parametresini de kullanabiliriz.

    Burada kullanılabilir bellek alanı için yalnızca free sütununa bakmak doğru değildir. Kullanılmayan belleğin bir kısmını önbellek olarak değerlendirir. Yeni bir uygulamanın kullanabileceği yaklaşık alanı görmek için available sütunu daha faydalıdır.

    kill

    kill komutu yalnızca süreçleri zorla kapatmak için kullanılmaz. Asıl görevi süreçlere sinyal göndermektir.

    Herhangi bir sinyal belirtmeden kill kullandığımızda sürece varsayılan olarak 15 numaralı SIGTERM sinyali gönderilir. Bu sinyal sürece kapanmadan önce elindeki işleri tamamlayabilmesi için fırsat verir.

    9 numaralı SIGKILL sinyali ise süreci doğrudan sonlandırır. Süreç bu sinyali yakalayamaz ve kapanma işlemini düzenli biçimde tamamlayamaz. Bu nedenle bir yazma işlemi veya başka bir operasyon yarıda kalabilir.

    1 numaralı SIGHUP sinyali birçok daemon tarafından yapılandırma dosyasını yeniden okumak için kullanılır. Ancak bunun nasıl yorumlanacağı programa bağlıdır.

    Not: kill -l çıktısında 32 ve 33 numaralarının görünmemesinin sebebi çekirdek için ayrılmış olmalarıdır.

    Zombi Süreçler

    Süreçler kendi aralarında ata ve çocuk ilişkisi kurarlar. Bir çocuk süreç sona erdiğinde ata sürecin onun çıkış bilgisini alması gerekir.

    Ata süreç bu bilgiyi almazsa çocuk süreç, çalışması bitmiş olmasına rağmen süreç tablosunda zombi olarak kalır. ps çıktısında zombi süreçler Z durumuyla görülebilir.

    Zombi süreç zaten çalışmasını tamamladığı için doğrudan öldürülemez. Sorunun çözülmesi için ata sürecin çocuk sürecin çıkış bilgisini toplaması gerekir. Gerekli olduğunda hatalı ata süreç yeniden başlatılabilir veya sonlandırılabilir.

    Çocuk değil de ata süreç sonlandırıldığında geride kalan çocuk süreçler PID 1 tarafından sahiplenilebilir.

    Servisler

    Servis ile süreç tamamen birbirinden ayrı yapılar değildir. Bir servis çalıştığında arka planda bir veya daha fazla süreç oluşturabilir. Bir servis çalışırken arka planda bir veya birden fazla süreç oluşturabilir.

    Servisleri systemctl komutuyla yönetebiliriz. Bir servisi başlatmak, durdurmak veya durumunu görüntülemek için start, stop ve status işlemlerini kullanabiliriz.

    systemctl status ssh çıktısı

    Servis adını bilmiyorsak servisleri listeleyebilir veya ilgili programın adını servis listesinde arayabiliriz. Aramak için,

    bash
    mehmet@debian ~$ systemctl list-unit-files --type=service

    Buradaki STATE servisin açılışta otomatik başlatılacak şekilde ayarlanıp ayarlanmadığını, PRESET ise dağıtımın servis için belirlediği varsayılan ayarı gösterir.

    Paketlerle gelen servis dosyaları /usr/lib/systemd/system/, kendi oluşturduğumuz servisler ve yaptığımız özel ayarlar ise /etc/systemd/system/ altında bulunur. /usr/lib altındaki dosyaları doğrudan değiştirmeyiz; çünkü paket güncellemelerinde yaptığımız değişiklikler kaybolabilir.

    Paket tarafından getirilen servis dosyasını doğrudan değiştirmek yerine systemctl edit kullanarak ek bir ayar dosyası oluşturabiliriz. Böylece paket güncellendiğinde yaptığımız değişikliğin üzerine yazılması engellenmiş olur.

    bash
    mehmet@debian ~$ sudo systemctl edit ssh

    komutu girdiğimizde önceki ayarları yorum satırına alarak gelmiş olan bir dosya açılır. Burada değişikliklerimizi yaptıktan sonra …/ssh.service.d/override.conf dosyası oluşturulur.

    Bir servis dosyası 3 ana bölümden oluşur.

    Unit, service ve install.

    Unit bölümünde servisin açıklaması ve diğer unit’lerle ilişkisi bulunur.

    Description, servisin kısa açıklamasıdır.

    Documentation, servisle ilgili bakılabilecek belgeleri gösterir.

    target, sistem açılırken ulaşılan belirli bir aşamayı ifade eder. After=network.target yazarak SSH servisinin ağla ilgili temel işlemlerden sonra başlatılmasını isteriz. Buradaki network.target bir servis değil, başlatma sırasını belirlememize yardımcı olan bir hedeftir.

    ConditionPathExists, belirtilen dosya koşuluna göre servisin çalıştırılıp çalıştırılmayacağını belirleyebilir. Örneğin yukarıdaki servis dosyasında, /etc/ssh/sshd_not_to_be_run dosyası yoksa servis başlatılacak.

    EnvironmentFile, servisin değişken okuyacağı dosyayı gösterir. Dosya yolunun önündeki – işareti, dosya bulunmazsa bunun hata olarak kabul edilmemesini sağlar.

    ExecStartPre, ana servis başlamadan önce çalıştırılacak kontrolü belirtir. (sshd -t)

    ExecStart, servisi başlatacak asıl komuttur.

    ExecReload, servis yeniden yüklendiğinde çalıştırılacak komutu belirtir. (kill -l çıktısındaki 1 numaralı SIGHUP)

    Restart=on-failure, servis bir hata nedeniyle kapanırsa yeniden başlatılmasını sağlar.

    Type=notify, servis hazır olduğunda systemd’ye bildirim göndereceğini belirtir.

    RuntimeDirectory, servis çalışırken ihtiyaç duyulan geçi duyulan geçici dizinin oluşturulmasını sağlar.

    RuntimeDirectoryMode=0755, SSH için oluşturulan /run/sshd dizininin izinlerini belirler. Buradaki mode, dosya veya dizine verilecek izin anlamına gelir.

    WantedBy=multi-user.target, servis etkinleştirildiğinde multi-user.target altında çalışacak unit’lerden biri hâline gelmesini sağlar.

    Alias=sshd.service, servisinin sshd.service adıyla da kullanılabilmesini sağlar. Buradaki Alias, servise verilen takma ad anlamına gelir.

    Not: Target birimleri, sistemin ulaşması gereken durumu belirtir. Kendileri çalışan bir program değildir.

    systemctl start, servisi o anda başlatır. systemctl enable ise servisin sistem açılışında otomatik olarak başlatılabilmesi için gerekli bağlantıları oluşturur. Sistem başlarken başlayacak servisler o sembolik bağlar aracılığıyla anlaşılır ve başlatılır.

    SysV init ve systemd

    Systemd öncesinde SysV init sistemi yaygın olarak kullanılıyordu. Servis betikleri /etc/init.d altında bulunuyor ve belirli bir sıraya göre çalıştırılıyordu.

    Systemd ise birbirinden bağımsız servisleri paralel olarak başlatabilir. Bir servisin diğerinden önce veya sonra başlaması gerekiyorsa unit dosyalarında bağımlılık ve sıralama ilişkileri tanımlanır.

    Bu nokta da bize verilen ödevi yapmak istiyorum. Sistem açıldığında otomatik olarak çalışan bir servis dosyası hazırlayacağız. Servis her çalıştığında /tmp altında bulunan bir dosyaya “ben açıldım” ifadesiyle birlikte o anki tarihi yazacak.

    İlk önce servis dosyamın tanımını /etc/systemd/system altında deneme.service adıyla yapıyorum.

    bash
    mehmet@debian ~$ sudo nano /etc/systemd/system/deneme.service

    Dosyamda unit, service ve İnstall alanları için gerekli kısımları giriyorum. Görüldüğü üzere bir servis tanımında bütün alanların girilmesi gerekliliği yok, bu servisten servise ve gereksinimlere göre değişiyor.

    şeklinde dosyamı hazırlayıp kaydedip çıkıyorum. Ardından değişikliklerin geçerli olması için,

    bash
    mehmet@debian ~$ sudo systemctl daemon-reload

    daemon’a dosyayı yeniden okutuyorum.

    Açılışta başlaması için,

    bash
    mehmet@debian ~$ sudo systemctl enable deneme.service

    komutunu giriyorum ve sembolik link oluşuyor. Status ile durumunu kontrol ediyorum.

    ardından makinemi reboot edip kontrol ediyorum.

    başarıyla görevi tamamladık (her açılışta >> dememize rağmen önceki kaydın silinmesinin nedeni dosyayı /tmp’de oluşturuyor olmamız.

    Loglama

    Sistemdeki log dosyalarının önemli bir bölümü /var/log altında bulunur. Servislerin ve uygulamaların oluşturduğu hata, uyarı ve bilgilendirme kayıtlarını burada görebiliriz.

    Uygulamalar loglarını farklı yöntemlerle oluşturabilirler.

    • Bir uygulama kendi log dosyasını açıp kayıtlarını doğrudan bu dosyaya yazabilir.
    • Uygulama mesajını syslog sistemine gönderebilir ve rsyslog bu mesajı belirlenen dosyaya yazabilir.
    • Systemd ile gelen journald servisi de servislerden ve uygulamalardan gelen kayıtları toplayabilir.

    Rsyslog’un ana yapılandırma dosyası /etc/rsyslog.conf, ek yapılandırmaların bulunduğu dizin ise /etc/rsyslog.d şeklindedir. Hangi log mesajının hangi dosyaya yazılacağı bu dosyalardaki kurallarla belirlenebilir.

    Rsyslog her sistemde varsayılan olarak kurulu olmak zorunda değildir. Benim kullandığım minimized Ubuntu Server kurulumlarında rsyslog varsayılan olarak bulunmuyordu. Rocky Linux’ta ise kurulu olarak geldi.

    Örnek olarak bir rsyslog kuralı oluşturup belirlediğimiz log mesajlarını ayrı bir dosyaya yazdıracağız. Ardından logger komutuyla deneme mesajı göndererek kuralın çalıştığını kontrol edeceğiz.

    Öncelikle dosyayı oluşturarak başlayalım.

    bash
    mehmet@debian ~$ sudo nano /etc/rsyslog.d/odev.conf

    Dosyanın içerisine,

    local3.*    /var/log/ozel-deneme.log

    yazıyorum ve

    bash
    mehmet@debian ~$ rsyslogd -N1

    sözdenetimini kontrol ediyorum. Ardından konfigürasyonun geçerli olması için,

    bash
    mehmet@debian ~$ sudo systemctl restart rsyslog

    komutunu girip logger ile deneme yapmaya başlıyorum.

    bash
    mehmet@debian ~$ logger -p local3.info "Bu bir rsyslog test log mesajidir."

    burada -p parametresi ile doğrudan local3’ün tetiklenmesini sağladım. Yaptığım test sonucunda log dosyasını kontrol ediyorum,

    başarıyla ödevi tamamladık.

    logrotate

    Log dosyaları sürekli büyürse zamanla diskin dolmasına neden olabilir. Logrotate, eski log dosyalarını döndürmek, belirli sayıda saklamak ve gerekirse sıkıştırmak için kullanılır.

    Logrotate ana yapılandırması genellikle /etc/logrotate.conf dosyasında bulunur. Uygulamalara ve servislere ait ek kurallar ise /etc/logrotate.d altında tutulur.

    logrotate.conf dosyası
    DeğerAçıklama
    daily, monthly, yearly, hourly, weekly, size 10MLogların ne sıklıkla döndürüleceğini belirtir. weekly, logları haftada bir döndürür. Size ile de boyutu x’i geçerse yap demiş oluruz.
    su kullanıcı grupDöndürme işleminin hangi kullanıcı ve grup yetkileriyle yapılacağını belirtir.
    rotate sayiKaç eski log dosyasının saklanacağını belirtir.
    create izin,
    root adm, nocreate
    Döndürme işleminden sonra aynı isimde yeni ve boş bir log dosyası oluşturur. nocreate ile eski dosya rotate edildikten sonra yeni dosya oluşturulmaz.
    nodateext, dateext, dateformat -%Y%m%d, dateyesterdayEski log dosyalarının adına tarih eklenmesini sağlar. Kullanılmazsa dosyalar genellikle .1, .2 şeklinde numaralandırılır.
    nocompress, compress, delaycompress, compresscmd bzip2, compressext .bz2Eski log dosyalarını sıkıştırarak daha az disk alanı kullanmalarını sağlar.
    include /dizin, include /dosya.d dizinlerinin içerisindeki kuralların uygulanması için include eder.
    logrotate.d içindeki nginx’in log ayarları

    Bir logrotate kuralında logların günlük, haftalık veya aylık olarak döndürülmesi belirlenebilir. Eski dosyaların kaç tanesinin tutulacağı ve sıkıştırılıp sıkıştırılmayacağı da yine bu kurallarda yazılır.

    compress seçeneği eski log dosyalarının sıkıştırılmasını sağlar.

    delaycompress ise en son döndürülen log dosyasının sıkıştırılmasını bir sonraki rotasyona erteler. İlk rotasyonda aktif log dosyası .1 uzantısıyla eski dosya haline gelir ancak hemen sıkıştırılmaz. Bir sonraki rotasyonda bu dosya sıkıştırılır. Bu yöntem, bazı uygulamaların kısa bir süre daha eski log dosyasına yazmaya devam edebilmesi için kullanılır.

    Bazı uygulamalar kendi log rotasyonlarını kendileri yapabilir. Her uygulamanın mutlaka logrotate kullanması gerekmez. Ancak sunucu üzerinde kontrolsüz biçimde büyüyen bir log dosyası bırakılmamalıdır. Rotasyonu yapılmayan bir log dosyası mutlaka zamanla diskin dolduracaktır.

    Logrotate sürekli çalışan bir servis değildir. Dağıtıma göre cron görevi veya systemd timer tarafından belirli aralıklarla çalıştırılabilir.

    Zamanlanmış Görevler

    Linux’ta zamanlanmış görevler için iki temel servis kullanabiliriz.

    • atd, yalnızca bir defa çalıştırılacak görevler için kullanılır.
    • crond, belirli aralıklarla tekrar çalıştırılacak görevler için kullanılır.

    Bu iki servis tamamen birbirinin yerine geçmez. Farklı görev türleri için birbirlerini tamamlarlar. Biz derslerde cron servisinin yapısını inceledik.

    Cron’un farklı uygulamaları bulunabilir ve dağıtımlar farklı cron paketleri kullanabilir. Sistem genelindeki görevler /etc/crontab dosyasında veya /etc/cron.d altında tanımlanabilir.

    Kullanıcıya ait zamanlanmış görevleri crontab -e komutuyla düzenleyebiliriz.

    Kullanıcı crontab’ında beş zaman alanı bulunur:

    1. dakika
    2. saat
    3. ayın günü
    4. ay
    5. haftanın günü

    Sistem genelindeki /etc/crontab ve /etc/cron.d dosyalarında bu alanlardan sonra komutun hangi kullanıcıyla çalışacağını belirten bir kullanıcı alanı daha bulunur.

    crontab -e ile açılan kullanıcı crontab’ında kullanıcı adı yazılmaz. Görev, crontab’ın sahibi olan kullanıcıyla çalışır.

    Yıldız işareti o alandaki bütün geçerli değerleri ifade eder. Yani alanlardan birine yıldız koyduğunuzda o periyotta bir kısıtlama olmaksızın çalışacaktır. */3 kullanımı ise ilgili alanda her üç değerde bir çalışmayı belirtir. Örneğin saat alanına */3 yazıldığında görev üç saatte bir çalışır.

    Ay veya haftanın günü alanlarında sayı kullanılabileceği gibi fri gibi gün kısaltmaları da kullanılabilir.

    Not: Cron alanlarını haftanın günü ve ayın günü haricindeki alanlar ve bağlacıyla birbirine bağlıdır. Bu iki alan arasında ya da bağlacı vardır. Bu nedenle ayın 13’ü cuma olduğunda çalışacak bir görev tanımladığımda hem ayın 13.günü hem de her cuma günü çalışıyor. Bunun sebebi, İki alan da bir “gün” belirttiği için, ikisi de aynı anda spesifik değer aldığında (biri yıldız değilken diğeri de yıldız değilken) sistem bunu iki ayrı zamanlama isteği olarak yorumluyor ve “ya da” ile birleştiriyor.

    Bunu bir örnek üzerinden görmek istersek ilk önce sudo timedatectl set-ntp false ile zaman servisini engelliyorum.

    Ardından yeni zamanı ayın 13’ü olmayan herhangi bir cuma gününe ayarlıyorum.

    calisti: Fri Sep  4 12:01:01 UTC 2026

    Devamında zamanı ayın 13’ü olan ama cuma olmayan herhangi bir güne ayarlıyorum.

    calisti: Sun Sep 13 12:01:01 UTC 2026

    İkisi de çalıştı.

    Zamanlanmış görevleri hazırlamak için crontab.guru adresinden de faydalanabiliriz.

    Zamanlanmış görevler sistemde farklı yerlerde bulunabilir:

    • /etc/crontab
    • /etc/cron.d
    • /etc/cron.hourly
    • /etc/cron.daily
    • /etc/cron.weekly
    • /etc/cron.monthly
    • Kullanıcıların crontab dosyalarının tutulduğu spool dizini

    Bir dosya cron.daily altına bırakıldığında günlük, cron.weekly altına bırakıldığında haftalık olarak çalıştırılabilir. Ancak daily veya weekly ifadeleri tek başına kesin bir saat belirtmez. Bu dağıtımdan dağıtıma değişir.

    Not: Eğer zamanlanmış görevlerin çalışacağı belirlenen vakitlerde sistem kapalıysa anacron devreye girer. Sistem açıldığı zaman zamanlanmış görevleri gerçekleştirir.

    Kullanıcıların zamanlanmış görevleri dağıtıma göre /var/spool/cron (rocky) veya /var/spool/cron/crontabs (debian) gibi dizinlerde tutulabilir. Bu dosyaları doğrudan düzenlemek yerine crontab -e kullanmak gerekir.

    Devamını okumak için…


  • Linux Sistem Yönetimi | LKD #5

    Kullanıcı Yönetimi

    Linux sistemlerde yalnızca bizim gibi sisteme giriş yapan kullanıcılar bulunmaz. Sistemde çalışan servisler ve bazı uygulamalar için de ayrı kullanıcı hesapları oluşturulabilir. Sistemde tanımlı kullanıcı hesaplarını /etc/passwd dosyası üzerinden görebiliriz.

    Bu dosyanın her satırında bir kullanıcı hesabına ait bilgiler : ile ayrılırlar.

    Buradaki alanların anlamları şöyledir:

    AlanAnlamı
    mehmetKullanıcı adı
    xParola bilgisinin /etc/shadow dosyasında tutulduğunu belirtir
    1000Kullanıcının UID (user ıd) numarası
    1000Kullanıcının birincil grubunun GID ( grup ıd) numarası
    mehmetKullanıcı hakkında açıklama alanı
    /home/mehmetKullanıcının ev dizini
    /bin/bashKullanıcı giriş yaptığında çalıştırılacak kabuk

    Not: Eskiden parola hash’leri de burada tutulduğu için dosyanın adı passwd idi. Ancak günümüzde /etc/passwd dosyasının sistemdeki kullanıcılar tarafından okunabilmesi gerektiğinden parola hash’lerinin burada tutulması güvenli değil. Bu nedenle parola bilgileri yalnızca yetkili kullanıcıların okuyabildiği /etc/shadow dosyasına taşındı. /etc/passwd içerisindeki x karakteri de geriye dönük uyumluluk için saklanmaya devam ediyor.

    Not: Nginx, PostgreSQL veya SSH gibi servislerin her biri sistemde farklı kullanıcılarla çalışabilir. Bunun sebebi servise yalnızca ihtiyaç duyduğu yetkileri vermek ve servisin sistemin kalanına verebileceği zararı sınırlandırmaktır.

    Örneğin Nginx üzerinde bir güvenlik açığı bulunduğunu düşünelim. Nginx doğrudan root kullanıcısıyla çalışıyorsa açığı kullanan kişi de çok geniş yetkilere sahip olabilir. Servis yalnızca kendisine ait dosyalara erişebilen sınırlı bir kullanıcıyla çalışıyorsa saldırganın erişebileceği alan da sınırlandırılmış olur.

    Linux’ta her kullanıcıya özel bir id tahsis edilir. Linux, kullanıcıları kendi içerisinde kullanıcı adlarıyla değil UID adı verilen sayısal kimliklerle takip eder. Gruplar için de GID adı verilen sayısal kimlikler kullanılır. id kullanici_adi ile bunları görebiliriz.

    Çıktımız şöyle olacaktır:

    uid=1000(mehmet) gid=1000(mehmet) groups=1000(mehmet),4(adm),24(cdrom), 27(sudo),30(dip),46(plugdev),101(lxd)

    burada kullanıcının bulunduğu gruplar yer alır.

    Kullanıcı adları bizim sistemi daha rahat kullanabilmemiz içindir. Dosyanın sahibi gibi bilgiler dosya sisteminde sayısal UID ve GID değerleriyle tutulur. Komutlar bu numaraları /etc/passwd ve /etc/group dosyalarındaki adlarla eşleştirerek bize kullanıcı ve grup adı şeklinde gösterir.

    Bu yüzden bir kullanıcıyı sildiğimizde ona ait dosyalar kendiliğinden silinmez ve sistem artık ilgili UID numarasını bir kullanıcı adıyla eşleştiremediği için dosyanın sahibi kısmında isim yerine doğrudan UID numarasını görürüz. Örneğin, duman kullanıcısının oluşturduğu bir dosya duruyorken duman kullanıcısını sildiğimde,

    duman dizininin sahipliği ve grubunun id şeklinde göründüğü görürüz.

    Not: Daha sonra aynı UID numarası başka bir kullanıcıya verilirse eski dosyalar yeni oluşturulan kullanıcıya aitmiş gibi görünebilir. Çünkü dosya sistemi isme değil id numarasına bakarak hareket eder. Aynı şekilde dosyayı başka bir bilgisayara taşırsak dosya karşı tarafta eşleşen id’nin sahipliğine girer.

    Kullanıcıların UID numaraları olduğu gibi grupların da GID numaraları bulunur. Sistemde tanımlı gruplar /etc/group dosyasında yer alır.

    Bu dosyada da alanlar : ile ayrılırlar. İlk sütun grup adını, ikinci sütun /etc/gshadow dosyasına taşınan parola alanlarını, üçüncü sütun id numaralarını dördüncü sütun ise o gruba sonradan üye olan kişileri gösterir.

    Bir kullanıcının dahil olduğu grupları daha kolay görmek için groups veya id komutunu kullanabiliriz.

    Not: Kullanıcıların ev dizinlerinin illaki /home/kullanici_adi şeklinde olması gerekmez, istersek ev dizinlerinin konumlarını değiştirebiliriz.

    Parolaların hash’li biçimde saklandığı /etc/shadow dosyası,

    Burada bazı kullanıcıların uzun bir parola hash’i varken bazı hesaplarda ! veya * gibi karakterler vardır. Bunun sebebi kullanıcının parola ile oturum açmasının engellenmiş olmasıdır. * hesaba hiçbir zaman parola atanmadığını, ! ise hesabın kilitlendiğini gösterir. Yanlarında uzunca bir hash’e sahip olanlarsa şifre atanılan kullanıcıları gösteriyor.

    mehmet:$y$j9T$ornekSalt$ornekParolaHashi:20691:0:90:7:14:20800:0

    AlanAnlamı
    mehmetKullanıcı adı
    y$j9T$ornekSalt$ornekParolaHashiKullanıcının parola hash’i
    20691Parolanın en son değiştirildiği gün. 1 Ocak 1970’ten itibaren hesaplanır
    0Parola beklemeden tekrar değiştirilebilir
    90Parola en fazla 90 gün kullanılabilir
    7Parolanın süresi dolmadan 7 gün önce kullanıcıya uyarı verilir
    14Parolanın süresi dolduktan 14 gün sonra hesap devre dışı bırakılır
    20800Hesabın tamamen sona ereceği gün. 1 Ocak 1970’ten itibaren hesaplanır
    0Gelecekte kullanılmak üzere ayrılmış alan

    Not2: Bir kullanıcının parolasının hash’ini alalım, ardından parolayı değiştirip tekrar parolamızı girelim. Tekrar hash aldığımızda parolalar birebir aynı olmasına rağmen çıkan hash aldığımız ilk hash’ten farklı olacaktır.

    Basit olarak işlem şu şekilde düşünülebilir:

    Parola + rastgele salt değeri → hash fonksiyonu → parola hash'i

    Aynı parola farklı salt değerleriyle işlendiğinde farklı hash sonuçları ortaya çıkar.

    yeni-kullanici:$y$j9T$NoLPxXWzPciAVN43S07q9/$Y/Q/OawVtSOKPNsO0GkdErN8CL/vENvTxt/LRPzOchD:20693:0:99999:7:::

    şifreyi değiştirip tekrar deneyelim.

    yeni-kullanici:$y$j9T$msqHsK89VsimsncsxRW88/$5mHztvApgr2Y8Llxb/noHwmjCZpzaK9X.nvxTjPkKYB:20693:0:99999:7:::

    Not: Salt gizli olmak zorunda değildir ve genellikle hash bilgisinin içerisinde saklanır. Asıl amacı aynı parolanın her kullanıcıda aynı hash sonucunu oluşturmasını engellemektir.

    Not: Linux’ta kullanıcı doğrulaması yalnızca /etc/shadow dosyasına bakılarak yapılmaz. Arada PAM (Pluggable Authentication Modules) adı verilen bir soyutlama katmanı bulunur. SSH, sudo ve su gibi araçlar parola ve hesap kontrollerini PAM kurallarına göre gerçekleştirir. Bu nedenle /etc/shadow dosyasında parola alanının boş olması, kullanıcının boş parolayla giriş yapabileceği anlamına gelmez. Örneğin Ubuntu’da boş parola tanımlayabildim ancak giriş yapamadım.

    Yeni kullanıcı eklemek için birbirinin yerine geçebilecek iki komudumuz var. Useradd ve adduser. Useradd tek bir satırda tüm işlemi bitirirken adduser, daha insancıl bir deneyim sunuyor. Genellikle programlar useradd kullanırken insanlar adduser kullanırlar.

    Dosya İzinleri

    Bir dosyanın izinlerinde üç kullanıcı sınıfı bulunur:

    • user: Dosyanın sahibi,
    • group: Dosyanın grubu,
    • others: Sahip veya ilgili grup sınıfına girmeyen diğer kullanıcılar.

    Not: others ifadesi “herkes” anlamına gelmez. Dosyanın sahibi ve grup sınıfıyla eşleşmeyen diğer kullanıcıları ifade eder.

    Bir kullanıcı dosyaya erişmeye çalıştığında sistem tüm izinleri üst üste toplamaz. Önce kullanıcının dosyanın sahibi olup olmadığına bakılır. Sahipse yalnızca user alanındaki izinler uygulanır. Sahibi değilse dosyanın grubuyla eşleşip eşleşmediğine bakılır. Bu sınıfa da girmiyorsa others izinleri kullanılır.

    Not: Bir dosya da yazma yetkimizin bulunması o dosyayı silebileceğimiz manasına gelmez. O dosyayı silebilmek için bulunduğu dizinde yazma hakkımız olması gerekir çünkü dosya adı dizin kaydında bulunur. Bizim yapacağımız işlem de dizin kaydından dosyayı kaldırmak olacaktır. (Dizine yazma izninin yanında execute (x) yetkisine de sahip olmamız gerekir)

    Klasik izinlerle dosyanın sahibi, grubu ve diğer kullanıcılar için yetki tanımlayabiliyoruz. Ancak aynı dosyada daha komplike, örneğin aynı grup içerisindeki bir kullanıcıya yazma ve okuma yetkileri verirken başka bir kullanıcıya okuma ve çalıştırma yetkileri vermek gibi, yetkilendirmeler için ACL kullanılır.

    ACL, Access Control List ifadesinin kısaltmasıdır. Bir dosyanın klasik izin alanlarına ek olarak belirli kullanıcı ve gruplara ayrıca yetki tanımlamamızı sağlar.

    Mevcut ACL kurallarını görmek için getfacl kullanabiliriz:

    Belirli bir kullanıcıya okuma ve yazma yetkisi vermek için:

    bash
    mehmet@debian ~$ setfacl -m u:ayse:rw dosya.txt

    Belirli bir gruba yalnızca okuma yetkisi vermek için:

    bash
    mehmet@debian ~$ setfacl -m g:muhasebe:r dosya.txt

    Yaptığımız değişiklikleri tekrar kontrol edebiliriz:

    bash
    mehmet@debian ~$ getfacl dosya.txt

    Not: acl komutlarıyla verdiğimiz yetkileri chmod ile override (ezmek) ettiğimizde #effective satırı açılır. Bu kısım pratikte kişi ya da grupların hangi izinlere sahip olduğunu belirtir.

    Tanımladığımız ACL kuralını kaldırmak için:

    bash
    mehmet@debian ~$ setfacl -x u:ayse dosya.txt

    Not: ACL çıktısındaki mask alanı; dosya sahibi ve others haricinde, tanımlı kullanıcıların ve grupların kullanabileceği en yüksek yetkiyi belirler. Kullanıcının veya grubun etkin yetkisi, kendisine verilen yetkiler ile mask yetkilerinin kesişiminden oluşur.

    Bir dosyaya acl ile müdahale ettiğimizde ls -l çıktısında izinlerin yanında + bulunur, bu dosyaya acl ile kural atandığını gösterir.

    Dosya izinleri ve ACL, sistemdeki erişim kontrolünün tamamı değildir. Dağıtımlar bunlara ek bir katman olarak Debian’da AppArmor, RHEL tabanlı sistemlerde ise SELinux kullanarak ek bir güvenlik katmanı oluşturur.

    Bu nedenle bir dosyanın chmod izinleri uygun görünmesine rağmen erişim engelleniyorsa AppArmor veya SELinux kurallarının da kontrol edilmesi gerekebilir (biz derslerimizde bu konuyla ilgilenmedik)

    Kabukta Komutları Birbirine Bağlamak

    Bir satırda birden fazla komut çalıştırmak, bunu belli durumlara bağlamak için bağlaçlar kullanırız.

    Noktalı virgül, ilk komutun başarılı olup olmadığına bakmadan sıradaki komutu çalıştırır.

    komut1 ; komut2

    Örneğin:

    bash
    mehmet@debian ~$ mkdir deneme ; touch deneme/dosya.txt

    İkinci komutun yalnızca ilk komut başarılı olduğunda çalışmasını istiyorsak bu durumda && kullanırız.

    komut1 && komut2

    Örneğin dizin başarıyla oluşturulursa içine girmek için:

    bash
    mehmet@debian ~$ mkdir yeni-dizin && cd yeni-dizin

    Not: Tek başına kullanılan &, && ile aynı değildir. tek & komutu arka planda çalıştırmak için kullanılır.

    Tam tersi şekilde, ikinci komutun yalnızca ilk komut başarısız olduğunda çalışmasını istiyorsak || kullanırız.

    komut1 || komut2

    Örneğin bir dosya bulunamazsa ekrana hata mesajı yazdırabiliriz:

    bash
    mehmet@debian ~$ ls bulunmayan-dosya || echo "Dosya bulunamadı"

    Not: Noktalı virgül kabukta komutları ayırır. Normal bir karakter olarak kullanmak için önüne ters eğik çizgi konur örneğin, echo \; gibi.

    Dosya Sahipliği ve Yetkileri

    Bir dosyanın sahibini değiştirmek için chown komutu kullanılır.

    bash
    mehmet@debian ~$ sudo chown kullanici:grup dosya.txt

    Bir dosyanın sahibini başka bir kullanıcıya değiştirme işlemini normalde yalnızca root yapabilir.

    Yalnızca grubunu değiştirmek için chgrp kullanılabilir:

    bash
    mehmet@debian ~$ chgrp muhasebe dosya.txt

    Not: Normal bir kullanıcı kendi dosyasının grubunu, üyesi olduğu gruplardan birine değiştirebilir.

    Dosyanın sahibini ve grubunu değiştirebildik. Dosya üzerinde kimin hangi işlemleri yapabileceğini belirleyen izinleri değiştirmek içinse chmod komutunu kullanırız. Sayısal gösterimde yetkilerin değerleri şöyledir:

    YetkiDeğer
    Çalıştırma (x)1
    Yazma (w)2
    Okuma (r)4

    Bu değerleri toplayarak bir kullanıcı sınıfına verilecek yetkiyi belirleyebiliriz. Örneğin rwx değeri 4 + 2 + 1 = 7, rw- değeri ise 4 + 2 = 6 olur.

    bash
    mehmet@debian ~$ chmod 640 dosya.txt

    Bu komut dosyanın sahibine okuma ve yazma, grubuna yalnızca okuma yetkisi verir. Diğer kullanıcıların hiçbir yetkisi olmaz.

    Sembolik kullanımda şu ifadeler bulunur:

    İfadeAnlamı
    uDosyanın sahibi
    gDosyanın grubu
    oDiğer kullanıcılar
    aBütün sınıflar
    +Yetki ekle
    -Yetki kaldır
    =Yetkileri tam olarak belirle

    Örnek kullanımlar:

    chmod u=rw dosya.txt (sahibe read ve write ver)
    chmod u+x dosya.txt (sahibin yetkisine execute ekle)
    chmod g-w dosya.txt (grubun yetkisinden write çıkart)
    chmod o-rwx dosya.txt (others’ın yetkisi tamamen al)

    su ve sudo

    su, başka bir kullanıcı kimliğine geçmek için kullanılır. Kullanıcı adı verilmezse varsayılan olarak root kullanıcısına geçmeye çalışır.

    sudo ise izin verilen tek bir komutu başka bir kullanıcı, varsayılan olarak da root, yetkisiyle çalıştırmamızı sağlar.

    Not: su ve sudo parola konusunda da farklı davranır. su – root komutu hedefteki root kullanıcısının parolasını ister. sudo ise normalde komutu çalıştıran kullanıcının kendi parolasını sorar ve kullanıcının bu işlemi yapmaya yetkili olup olmadığını sudoers kurallarından kontrol eder.

    sudo -i, yetkimiz varsa root kullanıcısının giriş ortamına benzer bir kabuk açar. sudo su komutuyla da root kabuğu açılabilir.

    Bu iki komut arasındaki bir diğer fark çevresel değişkenlerde ortaya çıkar. su ayse ile su – ayse aynı ortamı oluşturmaz. su komutunu – olmadan kullandığımızda mevcut oturumun bazı çevresel değişkenleri korunabilir. su – ayse ise Ayşe sisteme doğrudan giriş yapmış gibi bir login ortamı oluşturmaya çalışır ev dizinine geçer ve hedef kullanıcının giriş dosyalarını kullanır.

    çevresel değişkenlerin değişimi.

    sudo da bütün çevresel değişkenlerimizi olduğu gibi aktarmak zorunda değildir. Hangi değişkenlerin korunacağı sudoers yapılandırmasına bağlıdır. Bu nedenle “sudo her zaman mevcut kullanıcının bütün çevresel değişkenlerini kullanır” şeklinde kesin bir kural söyleyemeyiz.

    su ile başka bir kullanıcının kabuğunda kalmadan tek bir komut çalıştırmak için -c parametresini kullanabiliriz

    bash
    mehmet@debian ~$ su - ayse -c id

    Bu işlem komutu Ayşe kullanıcısıyla çalıştırır ve komut tamamlandığında bizi mevcut kabuğumuza geri döndürür.

    Bir kullanıcıya sudo yetkisi vermemiz, o kullanıcının her komutu root olarak çalıştırabilmesi gerektiği anlamına gelmez. Yetkiyi yalnızca ihtiyaç duyduğu komutla sınırlandırabiliriz.

    Örneğin, ayse kullanıcıs yalnızca rnano ile /etc/wgetrc dosyasını açabilsin.

    which ile rnano’nun binary’sine ait tam yolunu öğreniyorum.

    bash
    mehmet@debian ~$ which rnano

    /usr/bin/rnano çıktısını aldım. Ardından bu kullanıcı için ayrı bir sudoers dosyası açıyorum.

    bash
    mehmet@debian ~$ sudo visudo -f /etc/sudoers.d/ayse

    Burada -f ile ilgili dosyanın yolunu verdim.

    Not: Burada illaki visudo kullanacağız diye bir kural yok, yalnızca visudo’nun bu iş için özelleşmiş olması sebebiyle onu tercih ettik. Başka bir metin editörü de kullansak başarıyla tamamlayabilirdik işlemi.

    ayse ALL=(root) /usr/bin/rnano /etc/wgetrc

    yazıyoruz, kaydedip çıkıyoruz.

    Buradaki parçaların anlamları şöyledir:

    BölümAnlamı
    ayseYetkinin verileceği kullanıcı
    ALLKuralın herhangi bir makine adıyla eşleşmesini sağlar. Sudoers dosyası yalnızca bu bilgisayarda bulunuyorsa kural da yalnızca bu bilgisayarda uygulanır
    (root)Komutun root kullanıcısının yetkileriyle çalıştırılabileceğini belirtir
    /usr/bin/rnanoAyşe’nin sudo ile çalıştırmasına izin verilen program
    /etc/wgetrcrnano programına verilmesine izin verilen tek dosya argümanı

    Dosyayı kaydettikten sonra sözdizimini kontrol ediyoruz:

    bash
    mehmet@debian ~$ sudo visudo -cf /etc/sudoers.d/ayse

    yazıp,

    sıkıntı olmadığı çıktısını aldım.

    Ardından ayse kullanıcısının sudo yetkisiyle kullanabildiği komutları listelemek için,

    bash
    mehmet@debian ~$ sudo -l -U ayse

    yazıp,

    çıktısını alıyorum, en alt satırda wgetrc dosyasını sudo yetkisiyle rnano ile açabileceği yazıyor.

    Kısıtlı kullanıcıya geçerek izin verilen komutu deniyorum:

    bash
    mehmet@debian ~$ su - ayse 
    mehmet@debian ~$ sudo /usr/bin/rnano /etc/wgetrc

    Başka bir dosyayı açmayı denediğimizde sudoers kuralındaki komut satırıyla eşleşmediği için izin verilmemesi gerekir:

    Not: Sudo, /etc/sudoers dosyasını ve /etc/sudoers.d altındaki kuralları uygulamadan önce sahiplik ve izinlerini kontrol eder.

    Bunu denemek için /etc/sudoers.d dizinine ve içindeki ayse dosyasına 777 izni verdik. ayse, nano ile /etc/passwd dosyasını root yetkileriyle açabileceği bir kural ekledi ancak sudo, herkesin yazabildiği dizini ve dosyayı güvenli kabul etmediği için bu kuralı uygulamadı. Daha sonra dizini root:root sahipliğinde 755, ayse dosyasını ise root:root sahipliğinde 440 olarak ayarladığımızda dosyanın içindeki kural geçerli oldu. Bu nedenle sudoers izinlerini düzeltmeden önce dosyanın içeriğini de kontrol etmeliyiz, aksi halde başka bir kullanıcının eklediği zararlı kuralı farkında olmadan etkinleştirebiliriz.

    Burada özellikle nano yerine neden rnano kullandığımızı da açıklamak gerekir. rnano, nano editörünün sınırlandırılmış biçimde çalışan sürümüdür. Temel metin düzenleme işlemleri yapılabilir ancak dosya sisteminde farklı konumlara erişmeye veya dış komut çalıştırmaya yarayan bazı özellikler devre dışı bırakılır.

    Özelliknanornano
    Normal metin düzenlemeYapılabilirYapılabilir
    Farklı bir dosyayı açmaYapılabilirSınırlandırılır
    Dosyayı farklı adla veya konuma yazmaYapılabilirSınırlandırılır
    Dış komut çalıştırmaYapılabilirSınırlandırılır
    Kullanım amacıNormal metin düzenlemeKullanıcının belirli bir dosya üzerinde tutulması

    Not: rnano tek başına eksiksiz bir güvenlik sınırı olarak görülmemelidir. Kullanıcının sahip olduğu diğer komutlar ve dosya izinleri de ayrıca değerlendirilmelidir.

    sudo yetkisi olmayan normal bir kullanıcı da kendi parolasını değiştirebilir. Bunun için passwd komutunu kullanması yeterlidir:

    Başka bir kullanıcının parolasını değiştirmek için root yetkisi gerekir:

    bash
    mehmet@debian ~$ sudo passwd ayse

    Normal kullanıcı /etc/shadow dosyasına doğrudan yazamaz. Buna rağmen passwd komutunun parolayı değiştirebilmesinin sebebi çalıştırılabilir dosya üzerinde SUID bitinin bulunmasıdır.

    SUID sayesinde passwd programı çalışırken dosyanın sahibi olan root kullanıcısının etkili yetkilerini kullanabilir. Ancak bu, kullanıcıya /etc/shadow dosyası üzerinde istediği değişikliği yapma hakkı vermez. Yetki passwd programına verilmiştir, program da kendisini çalıştıran gerçek kullanıcıyı kontrol ederek normal kullanıcının yalnızca kendi parolasını değiştirmesine izin verir.

    suid, sgid ve sticky bit

    Klasik okuma, yazma ve çalıştırma izinlerinin yanında üç özel izin biti bulunur.

    SUID biti çalıştırılabilir bir dosyaya verildiğinde program, onu çalıştıran kullanıcının değil dosya sahibinin izinleriyle çalışır. İzinler kısmında s harfiyle gösterilir.

    Sayısal gösterimde SUID değeri 4 ile ifade edilir:

    bash
    mehmet@debian ~$ chmod 4755 program

    SUID dosyanın sahibinin yetkileri ile çalışırken bunun grup tarafındaki karşılığı SGID bitidir. SGID biti çalıştırılabilir dosyalarda programın dosyanın grup yetkileriyle çalışmasını sağlar. Grup çalıştırma alanında s karakteriyle görünür.

    bash
    mehmet@debian ~$ chmod g+s program
    mehmet@debian ~$ chmod 2755 program

    (ikisi de aynı işe denk gelir)

    SGID bir dizine uygulandığında ise o dizinin altında oluşturulan yeni dosya ve dizinlerin, oluşturan kullanıcının varsayılan grubu yerine üst dizinin grubunu devralmasını sağlar. Ortak çalışma dizinlerinde bu davranış işimize yarar. Sayısal gösterimde SGID biti 2 ile ifade edilir.

    bash
    mehmet@debian ~$ sudo mkdir /srv/ortak
    mehmet@debian ~$ sudo chgrp proje /srv/ortak
    mehmet@debian ~$ sudo chmod 2775 /srv/ortak

    Birden fazla kullanıcının yazabildiği dizinlerde başka bir problem ortaya çıkar: Dizine yazabilen kullanıcılar birbirlerinin dosyalarını silebilirler. Sticky bit, kullanıcıların dizinde dosya oluşturabilmesine rağmen birbirlerinin dosyalarını silmesini engellemek için kullanılır. Bunun en bilinen örneği /tmp dizinidir.

    drwxrwxrwt 10 root root 200 Aug 28 20:54 /tmp

    Çıktıda izinlerin sonunda görülen t karakteri sticky bitin aktif olduğunu gösterir:

    Sticky bit bulunan bir dizinde dosyayı genellikle dosyanın sahibi, dizinin sahibi veya root silebilir. Sayısal gösterimde Sticky bit 1 ile ifade edilir.

    bash
    mehmet@debian ~$ chmod +t ortak-dizin
    mehmet@debian ~$ chmod 1777 ortak-dizin

    Dosya izinlerini öğrendikten sonra yeni oluşturulan dosyaların başlangıç izinlerinin nereden geldiğine de bakabiliriz. Yeni oluşturulan normal dosyaların başlangıç yetkisi en fazla 666, dizinlerin başlangıç yetkisi ise en fazla 777 olabilir. Son yetkiler bu başlangıç değerlerinden umask ile kapatılan bitlerin çıkarılmasıyla belirlenir.

    Yeni dosyaların 666 yetkisiyle oluşmasını istiyorsak hiçbir biti kapatmayan 000 umask değerini kullanabiliriz.

    Normal dosyaların başlangıç değerinde çalıştırma bitleri bulunmadığı için umask 000 kullanıldığında dosya 777 değil 666 olur. Linux, yeni oluşturulan sıradan bir metin dosyasına kendiliğinden çalıştırma yetkisi vermez.

    Aynı umask değeriyle oluşturulan dizin ise 777 olabilir:

    Not: umask 000, sistemdeki diğer kullanıcıların da yeni dosyalara yazabilmesine neden olabilir. Bu nedenle yalnızca ödevi göstermek amacıyla geçici olarak kullanılmalı, kalıcı ve genel bir ayar yapılmadan önce güvenlik etkisi düşünülmelidir. umask değerlerinin kalıcı olmasını istiyorsak home dizininde yer alan .bashrc veya .profile dosyalarına ekleyebiliriz.

    editörler, history ve locate

    nano, dosyayı açtığımız anda direkt yazmaya başlayabildiğimiz daha basit bir metin editörüdür. vi ise farklı çalışma modlarına sahip özelleştirebildiğimiz daha kapsamlı bir editördür.

    vi ile bir dosya açtığımızda başlangıçta komut modunda bulunuruz:

    bash
    mehmet@debian ~$ vi dosya.txt

    Yazı yazabilmek için i veya a tuşuyla insert (edit) moduna geçebiliriz. Tekrar komut moduna dönmek için Esc tuşuna basarız.

    Komut modunda kullanabileceğimiz bazı ifadeler:

    KomutYaptığı işlem
    :wDosyayı kaydeder
    :qEditörden çıkar
    :wqKaydedip çıkar
    :q!Değişiklikleri kaydetmeden çıkar

    less ise bir metin editörü değildir. Dosyayı değiştirmeden görüntülemek için kullanılır:

    bash
    mehmet@debian ~$ less /var/log/syslog

    Dosya içerisinde /aranacak_ifade yazarak ileri yönde arama yapabilir, q tuşuyla çıkabiliriz.

    Dosyaları düzenlerken veya sistem üzerinde işlem yaparken daha önceden yazmış olduğumuz komutlara ulaşmak için history komutunu kullanırız.

    Çıktıda gördüğümüz * işareti, o komutun daha sonrasında ok tuşlarıyla getirilip düzenleme yapıldığını belirtir.

    Bash, komut geçmişini açık terminalin belleğinde tutar ve oturum kapanırken genellikle ~/.bash_history dosyasına kaydeder. Bu nedenle yalnızca dosyayı silmek yeterli olmayabilir; bellekte kalan geçmiş tekrar dosyaya yazılabilir. Hem bellekteki hem de dosyadaki geçmişi temizlemek için şu komut kullanılır:

    bash
    mehmet@debian ~$ history -c && history -w

    Burada history -c bellekteki geçmişi temizler, history -w ise temizlenen listeyi geçmiş dosyasına yazar.

    Geçmişte yazdığımız komutları history ile bulabildiğimiz gibi sistemdeki dosyaları da farklı araçlarla arayabiliriz. find komutu arama sırasında belirttiğimiz dizinleri dolaşırken locate, daha önceden hazırlanmış dosya yolu veritabanı içerisinde arama yapar. Bu nedenle çok hızlı sonuç verir.

    locate paketini indirdiğimizde locate -S ile veritabanı hakkında bilgilere erişebiliriz. Bu komut locate tarafından kullanılan veritabanı hakkında istatistikleri gösterir. Veritabanının konumu, son güncellenme zamanı, boyutu, kayıtlı dosya yolu sayısı ve sıkıştırma oranı gibi bilgiler bu çıktıda görülebilir.

    Ancak bu bilgilere erişmek için ilk önce locate’in kullandığı arama veritabanını güncellemek için,

    bash
    mehmet@debian ~$ sudo updatedb

    komutunu girmemiz gerekir. Bu komutu girmezsek locate -S çıktısı gelmeyecektir.

    Ardından istediğimiz dosya adını girerek sonuca erişebiliriz.

    bash
    mehmet@debian ~$ locate dosya_adi

    locate oldukça hızlıdır. Ancak kullandığı veritabanı güncel değilse yeni oluşturulan dosyaları bulamayabilir veya silinen dosyaların eski yollarını gösterebilir.

    Dosya İndirme ve Karşılaştırma

    curl ve wget, ağ üzerinden veri indirmek için kullanabileceğimiz iki araçtır. Benzer görünseler de kullanım amaçları arasında bazı farklar bulunur.

    wget, özellikle bir dosyayı indirip diske kaydetmek için sade bir kullanıma sahiptir. curl hiçbir parametre verilmediğinde ilgili veriyi doğrudan terminale basar.

    Bir dosyaya kaydetmek için -o, uzak sunucudaki dosya adını korumak için -O kullanabiliriz:

    bash
    mehmet@debian ~$ curl -o dosya.tar.gz https://kamp.com/dosya.tar.gz
    bash
    mehmet@debian ~$ curl -O https://kamp.com/dosya.tar.gz
    Özellikcurlwget
    Varsayılan davranışVeriyi terminale yazarDosyayı diske kaydeder
    API istekleriAyrıntılı şekilde kullanılabilirTemel indirme işlemlerine daha uygundur
    HTTP metodu ve başlık ayarlamaYapılabilirDaha sınırlı

    curl yalnızca dosya indirme ile sınırlayabileceğimiz bir araç değildir, http request düzenlemeleri yapmak, api uç noktalarını kontrol edebilmek gibi çok çeşitli işlevleri bulunur.

    bash
    mehmet@debian ~$ curl -I https://example.com

    İki dosyanın aynı olup olmadığını kontrol etmemiz gerektiği durumlarda diff aracını kullanırız. diff, iki metin dosyasını satır satır karşılaştırarak hangi satırların değiştiğini gösterir.

    bash
    mehmet@debian ~$ diff eski_dosya yeni_dosya

    diff ile kontrol etmek nispeten verimsiz bir yöntemdir. Bu yöntem yerine sadece dosyaların farklı olup olmadığını kontrol etmek istiyorsak hash kontrolü yapmak daha mantıklıdır.

    bash
    mehmet@debian ~$ sha256sum eski.txt yeni.txt

    Hash değerleri aynıysa dosyaların içeriklerinin aynı olduğunu söyleyebiliriz. Farklıysa içeriklerin farklı olduğunu anlarız ancak değişikliğin hangi satırda olduğunu göremeyiz. diff ise bize değişikliğin yerini gösterir. Bu nedenle bu iki araç birbirinin doğrudan alternatifi değildir.

    diff ile yalnızca değişiklikleri ekrana göstermek zorunda değiliz. Bir dosyada yaptığımız değişiklikleri başka bir dosyaya otomatik olarak uygulamak için çıktısını bir yama dosyasına kaydedebiliriz.

    Elimizde eski.txt ve düzenlenmiş yeni.txt dosyaları olsun:

    bash
    mehmet@debian ~$ diff -u eski.txt yeni.txt > degisiklik.patch

    Yamayı eski dosyaya uygulamak için:

    bash
    mehmet@debian ~$ patch eski.txt < degisiklik.patch

    Ardından dosyaları karşılaştırdığımızda aralarında fark kalmadığını görebiliriz:

    bash
    mehmet@debian ~$ diff eski.txt yeni.txt
    mehmet@debian ~$ echo $?

    diff herhangi bir çıktı üretmez ve çıkış kodu 0 olursa iki dosyanın aynı olduğu anlaşılır. Yani kısaca diff ile iki sürüm arasındaki değişiklikleri kaydedebilir, patch ile bu değişiklikleri dosyanın başka bir kopyasına otomatik olarak uygulayabiliriz.

    Devamını okumak için…


  • Linux Sistem Yönetimi | LKD #4

    Paket Yönetimi

    Paket yöneticileri, bir paketi indirmemize, kurmamıza, kaldırmamıza, bağımlılıkları yönetmemize ve sistemimizde halihazırda var olan paketleri güncellememize yarar. Farklı dağıtımlar farklı paket yöneticileri kullanabilirler, dağıtımlar arasında en çok fark da bu konu da yaşanır, örneğin:

    • Debian apt’yi,
    • Rocky linux dnf’i,
    • Arch Linux pacman’i paket yöneticisi olarak kullanır.

    Linux’ta bir paket kurduğumuzda, paketin çalışabilmesi için ihtiyaç duyduğu bağımlılıklar da beraberinde kurulur. Hangi bağımlılıkların gerekli olduğunu tespit eden ve bunların kurulumunu yöneten araçlar ise paket yöneticileridir.

    Kurduğumuz programların hangi kütüphanelere bağımlı olduğunu anlamak için, öncelikle which ile çalıştırılabilir dosyasının nerede olduğunu bulup ldd komutuyla bağımlılıklarını tespit ederiz.

    bash
    mehmet@debian ~$ ldd /usr/bin/nano

    komutunu girdiğimizde çıktısı,

    şeklinde olur. Burada nano’nun çalışması için gerekli olan kütüphaneler listelenmiştir. Sol tarafta nano’nun istediği ana kütüphaneler, sağ taraftaysa onların nerede bulunduğu yazıyor.

    Not: İllaki indirdiğimiz dosyanın bağımlılıkları burada görünür diye bir kural yoktur, bağımlılıkları statik olarak programın içine gömersek ldd çıktısında görünmezler.

    Paket yöneticileri bir paketi güncellerken depo indeksi numarasına bakarak yaparlar, yereldeki indeks numarası depodaki indeks numarasından daha eskiyse bunu güncellerler. (.deb paketini apt ile indirip versiyonunu düşürdüğümde paket yöneticisi versiyonun güncel olmadığını sanıp paketi güncelledi) .

    Debian’da versiyon numaralarını kontrol etmek için sudo apt update komutu çalıştırılır. Rocky’de bu iş dnf update ile tek komutta çözülür.

    Büyük sunucu sistemlerini düşündüğümüzde bir paket güncellenirken aynı anda kullanıcılar sunucuyu yani bahsedilen paketi kullanmaya devam edebilirler. Bunu bir örnek üzerinden inceleyelim,

    Nginx’in 1.24 sürümü sistemimizde kurulu olsun. Servisi başlattığımızda bu sürüme ait process’ler çalışmaya başlar. Nginx’i kesinti oluşturmadan 1.25 sürümüne yükselttiğimizde eski process’ler hemen sonlandırılmaz. Yeni sürüme ait process’ler başlatılır ve yeni bağlantılar bu process’lere yönlendirilir. Eski process’ler ise mevcut bağlantıları tamamladıktan sonra sonlandırılır.

    Bu sayede mevcut bağlantılar kesilmeden servis yeni sürüm üzerinden çalışmaya devam eder.

    Aynı şekilde, bir process tarafından açık tutulan dosya silinse bile process bu dosyayı kullanmaya devam edebilir. Çünkü dosya silindiğinde ilk olarak dosya adı ile inode arasındaki bağlantı kaldırılır. Process’in açık dosya tanımlayıcısı ise hâlâ aynı inode’a erişmeye devam eder. Dosyanın verileri, process dosyayı kapattığında ve dosyaya ait başka bir hard link kalmadığında diskten tamamen kaldırılır.

    Doruk Hoca da bunu bir müzik dosyasını oynatırken başka bir terminalden dosyayı silerek göstermişti. Dosyanın ismi dizinden kaldırılmasına rağmen müzik uygulaması dosyayı açık tuttuğu için müzik çalmaya devam etmişti.

    Bu durum aynı zamanda silinen dosyaları geri kurtarmak istediğimizde de işimize yarar. Dosya bir process tarafından kullanılmaya devam ediyorsa process kapanmadan dosyayı geri kurtarabiliriz.

    Bunu uygulamalı olarak göstermek için öncelikle tail ile bir dosyayı kullanan process oluşturuyorum.

    bash
    mehmet@debian ~$ tail -f silinecek-dosya.txt

    ardından başka bir terminale geçip önce dosyayı siliyorum sonrasında

    bash
    mehmet@debian ~$ ps aux | grep tail

    komutunu girip

    çıktısını alıyorum. tail sürecini çalıştıran process numarası ikinci sütunda yazıyor. /proc dizini altında 2698 numaralı dizine gidersem orada silinmiş dosyayı bulabilirim. İlgili dizini listelemek için,

    bash
    mehmet@debian ~$ ls -l /proc/2698/fd

    komutunu çalıştırdığımda çıktım:

    şeklinde oluyor. Burada da görülebileceği üzere “3 -» ..” ile başlayan dosya benim dosyam. O dosyayı kopyaladığımda tekrar dosyamı kullanabilir hale geleceğim. Bunun için,

    bash
    mehmet@debian ~$ cp /proc/2698/fd/3 ~/nasilkurtardimama

    dosyamı kopyalayıp tekrar okuduğumda sorunsuz şekilde dosyamı kurtarmış oluyorum.

    Linux sistemlerde paketleri depodan bulup indiren, bağımlılıklarını çözen ve paket yönetim sürecini baştan sona yöneten araçların yanında, elindeki paket dosyasını kuran, kaldıran ve kurulu paketlerin kaydını tutan daha düşük seviyeli paket yöneticileri de bulunur.

    Bunlar debian’da dpkg, rocky’de ise rpm’dir.

    Bu paket yöneticileri tek başına herhangi bir depoya bağlanıp paketleri çekip kuramaz. Eksik bağımlılıkları indiremez.

    dpkg ile bir paketi kurmak için,

    bash
    mehmet@debian ~$ apt download nano
    mehmet@debian ~$ sudo dpkg -i nano_7.2-2ubuntu0.2_amd64.deb

    komutlarını girerek kurulumu tamamlayabiliriz (apt ile yalnızca .deb dosyasını indirdim, bunu hızlı bir şekilde örnek olarak göstermek için yaptım) .

    Paket hakkında bilgi almak için,

    bash
    mehmet@debian ~$ dpkg -l nano
    bash
    mehmet@rocky ~$ rpm -q nano

    Paket kurulduğunda sistemimizde kuracağı dosyaları incelemek için,

    bash
    mehmet@debian ~$ dpkg -L nano
    bash
    mehmet@rocky ~$ rpm -ql nano

    şeklinde komut girebiliriz.

    dpkg -L ile ters yönde çalışan yani, bir dosyanın hangi paketle birlikte geldiğini gösteren bir komutumuz daha var:

    bash
    mehmet@debian ~$ dpkg -S /usr/share/doc/nano

    doğrudan dosyayı verip hangi paket ile birlikte geldiğini öğrenebiliyoruz.

    Not: Kurduğumuz paketleri manuel olarak kaldırmak için iki adet komutumuz bulunuyor. remove ve purge. remove, paketi kaldırır ancak yapılandırma dosyalarını bırakır. purge ise paketi yapılandırma dosyalarıyla birlikte kaldırır. Her ikisi de kullanılmayan bağımlılıkları kendiliğinden silmez.

    dpkg -L çıktısıyla nano paketini inceleyelim.
    komutunu çalıştırdığımızda nano paketiyle birlikte sistemimize kurulan dosya ve dizinleri görebiliriz. Komutun çıktısı uzun olduğu için çıktıyı parçalara ayırarak inceledim.

    Çıktının başında /, /etc, /usr ve /usr/share gibi dizinler yer alıyor. dpkg -L yalnızca dosyaları değil, pakete kayıtlı olan dizinleri de listeler.

    /usr/bin/nano, nano editörünü çalıştırdığımız asıl dosyadır. /usr/bin/rnano ise nano’nun bazı işlemleri sınırlandırılmış biçimde çalışan sürümüdür.

    /etc/nanorc, nano’nun sistem genelinde geçerli olan yapılandırma dosyasıdır. Nano’nun çalışma biçimiyle ilgili genel ayarlar bu dosya üzerinden yapılabilir.

    /usr/share/doc/nano dizini altında paketle ilgili açıklamalar, değişiklik kayıtları, telif bilgileri ve örnek yapılandırma dosyaları bulunur. AUTHORS, programı geliştiren kişiler hakkında bilgi verirken README ve faq.html gibi dosyalar programın kullanımıyla ilgili bilgiler içerir. Sonu .gz ile biten belgeler daha az yer kaplamaları için sıkıştırılmıştır.

    /usr/share/doc-base altında bulunan dosyalar, nano ile birlikte kurulan belgelerin Debian’ın belge sistemine tanıtılmasını sağlar. Böylece sistemdeki belge görüntüleme araçları nano’ya ait belgeleri bulabilirler.

    /usr/share/info/nano.info.gz, nano hakkında daha ayrıntılı bilgiler içeren GNU Info belgesidir.

    /usr/share/lintian/overrides/nano dosyasında, nano paketi Lintian ile denetlenirken göz ardı edilecek uyarılar belirtilir. Lintian normalde şüpheli gördüğü durumlar için uyarı verir. Ancak paket geliştiricisi bu durumun bilinçli olarak yapıldığını ve hata olmadığını biliyorsa ilgili uyarıyı bu dosyada istisna olarak tanımlayabilir. Yani bu nano’nun çalışırken doğrudan kullandığı bir dosya değildir.

    /usr/share/man altında nano, rnano ve nanorc için hazırlanmış man sayfaları bulunur.

    Not: Aynı isimde ancak farklı konuları anlatan birden fazla man sayfası bulunabilir. Örneğin passwd hem kullanıcı parolasını değiştirmek için kullandığımız komutun hem de /etc/passwd dosya biçiminin adıdır. man 1 passwd komutuyla parola değiştirme komutunun, man 5 passwd komutuyla ise /etc/passwd dosyasının yapısını anlatan man sayfasını açabiliriz. Yalnızca man passwd yazdığımızda man, bölümleri sırayla arar ve bulduğu ilk sayfayı gösterir.

    Kullanılan man sayfaları şu şekildedir:

    Bölümİçerik
    man 1 Kullanıcı komutları
    man 2Sistem çağrıları
    man 3Kütüphane fonksiyonları
    man 4Özel dosyalar ve aygıtlar
    man 5Dosya biçimleri ve yapılandırma dosyaları
    man 6Oyunlar
    man 7Standartlar, protokoller ve genel kavramlar
    man 8Sistem yöneticisi komutları
    man 9Kernel içi rutinler

    Çıktının büyük bölümünü /usr/share/nano altındaki .nanorc dosyaları oluşturuyor. Bu dosyaların her biri Python, JavaScript, HTML, CSS, SQL ve Markdown gibi farklı programlama dilleri veya dosya türleri için söz dizimi renklendirme kurallarını içerir. Nano bir dosyanın türünü tespit ettiğinde ilgili .nanorc dosyasındaki kuralları kullanarak metni renklendirir.

    Kısacası nano paketi yalnızca /usr/bin/nano dosyasından oluşmaz. Bunun yanında paketle birlikte yapılandırma dosyaları, belgeler, kullanım kılavuzları, paket denetim bilgileri ve farklı dosya türleri için hazırlanan söz dizimi renklendirme kuralları da sistemimize kurulur.

    Yaptığımız güncellemeleri geri almamızı gerektirebilecek durumlarla karşı karşıya gelebiliriz. Örneğin birden fazla paketi aynı anda güncelledik ve güncellemenin ardından sistem düzgün çalışmamaya başladı. Böyle bir durumda hangi paketleri güncellediğimizi tek tek aramak yerine doğrudan tek bir komutla bunları ortaya çıkartabiliriz.

    Rocky’de,

    bash
    mehmet@rocky ~$ sudo dnf history list

    komutunu yazdığımızda

    gibi bir çıktı ile karşılaşırız. Burada

    bash
    mehmet@rocky ~$ sudo dnf history info ID

    ile seçtiğimiz bir işlemin detaylarına ulaşabiliriz.

    İşlemi geri almak için,

    bash
    mehmet@rocky ~$ sudo dnf history undo ID

    komutunu çalıştırırız.

    Bir paketi ve dosyalarını istediğimiz bir dizine kurmak içinse Rocky’de,

    bash
    mehmet@rocky ~$ sudo dnf --installroot=/opt/rocky-kok --releasever=9 install nano

    komutunu çalıştırırız. Burada –installroot diyerek kurulacak dizini verdik, -releasever diyerek kullandığımız Rocky’nin sürümünü söyledik.

    debianda, apt3.2 öncesinde olmayan ancak şimdi doğrudan apt komutu üzerinden bakabileceğimiz bir history bulunuyor.

    bash
    mehmet@debian ~$ apt history-list

    komutunu girdiğimizde

    çıktısını alıyoruz. Bu çıktı da yapılan işlemin türü, hangi pakete işlem yapıldığı ve tarihi gibi bilgiler yer alıyor.

    bash
    mehmet@debian ~$ apt history-info ID

    komutunu girerek seçtiğimiz herhangi bir işlem hakkında detaylı bilgi edinebiliriz. Örneğin,

    nano paketinin indirilmesine dair olan işlemdeki bilgiler yer alıyor.

    Burada yaptığımız işlemi geri almak istediğimizde,

    bash
    mehmet@debian ~$ sudo apt history-undo ID

    komutunu girerek

    paketi geri silebiliriz.

    Belirli bir işlemden sonraki tüm işlemleri geri almak için,

    bash
    mehmet@debian ~$ sudo apt history-rollack ID

    komutunu gireriz,

    ve o işlemden sonraki ilk işlemden itibaren yapılan işler geri alınır.

    Not: debian (apt) tarafında bu özellik apt 3.2 sürümüyle birlikte geldi. Kullandığınız eski sürümlerde bu özellik yer almıyor. Mesela kullandığım 24.04 Ubuntu Server LTS’te bu komutları kullanamazken 26.04 sürümünde kullanabildim.

    Not: Sistemdeki APT paketini tek başına daha yeni bir sürüme yükseltmek teknik olarak mümkün olsa da güvenli ve pratik bir yöntem değildir. APT, sistemdeki birçok temel paket ve kütüphaneyle birlikte çalıştığı için yeni sürüm farklı bağımlılıklar gerektirebilir. Bu özellikleri kullanmak için yalnızca APT’yi değiştirmek yerine ilgili sürümü destekleyen dağıtım sürümüne geçmek daha doğru olur.

    Sıkıştırma ve Paketleme

    Dosyalarda tekrar eden verilerin daha az yer kaplaması için onları sıkıştırırız.

    Bunu basit bir örnek üzerinden inceleyelim. Elimizde,

    AAAAAAAAAABBBBBCCCC

    şeklinde bir veri olduğunu düşünelim. Burada her harfi tek tek tutmak yerine bu veri,

    10A5B4C

    olarak yazıldığında daha az yer kaplayacaktır. Kullandığımız sıkıştırma araçları da temelde bu mantıkla hareket ederler.

    Kullanabileceğimiz açık kaynaklı, özgür yazılım sıkıştırma araçları: gzip, xz …

    Sıkıştırma araçlarında hız ile sıkıştırma oranı arasında genellikle ters bir denge bulunur. Dosyayı daha fazla küçültmeye çalışan araçlar bunun için daha fazla işlem yaptığı için sıkıştırmayı daha yavaş tamamlayabilir. Hızlı çalışan araçlar ise işlemi daha kısa sürede tamamlar ancak dosyayı aynı ölçüde küçültemeyebilir.

    gzip dosya_adi veya xz dosya_adi şeklinde basit bir kullanımları vardır. gz ile sıkıştırdığımız dosyaları gunzip ile, xz ile sıkıştırdığımız dosyaları unxz ile yeniden açabiliriz.

    gzip ve xz gibi sıkıştırma araçları aslında kendilerine verilen veri akışını sıkıştırırlar. Bu nedenle tek bir dosyayı doğrudan sıkıştırabilirler ancak bir dizini, içerisindeki bütün dosyalar ve alt dizinlerle birlikte tek başlarına arşivleyemezler.

    gzip aracının -r seçeneğiyle dizinin içindeki dosyaları ayrı ayrı sıkıştırmak mümkündür. Ancak bu işlem dizinin tamamını tek bir .gz dosyası haline getirmez. Bu işlemi yaptıktan sonra geri almak için /dizin/* şeklinde dizindeki tüm dosyaları kapsayacak şekilde gunzip yapmamız gerekir.

    gzip’in sıkıştırma derecesini arttırmak için 1 ile 9 arasında parametre değerleri verebiliriz.

    Dizin yapısını koruyarak bütün dosyaları tek yerde toplamak istediğimizde tar kullanmamız gerekir.

    Devamını okumak için…


  • Linux Sistem Yönetimi | LKD #3

    / altında yer alan her bir dizinin sistemin işleyişince bir payı vardır.

    /
    bin
    boot
    dev
    etc
    home
    opt
    proc
    root
    sbin
    srv
    sys
    tmp
    usr
    var

    Linux’taki Temel Dizinler

    Linux’ta bütün dosyalar ve dizinler / dizininin altında bulunur. /, dosya sisteminin başladığı en üst noktadır. (Root’un ev dizini ile karıştırmamak için buraya kök dizin diyorum)

    /bin

    Sistemin temel komutlarının bulunduğu dizindir. ls, cp, mv, rm ve cat gibi sık kullandığımız komutlar burada bulunur.

    Eskiden /usr dizini ayrı bir diskte ya da network’te bulunabiliyordu. Bilgisayar açıldığında bu disk henüz sisteme bağlanmamış olabilirdi. Fakat sistemin açılışa devam edebilmesi ve diğer diskleri bağlayabilmesi için bazı temel komutlara ihtiyacı vardı. Bundan ötürü gerekli komutlar, sistem açıldığı anda ulaşılabilen /bin dizininde tutuluyordu.

    /bin : Sistem açılırken ihtiyaç duyulan temel komutlar
    /usr/bin : Sistem açıldıktan sonra kullanılabilecek diğer komutlar

    Günümüzde her iki dizin de aynı diskte bulunabildiğinden böyle bir problem kalmadı, geriye dönük uyumluluk problemleri çıkmasın diye devam ediliyor (belki eskiden yazılmış bur program /usr/bin’i arayabilir… )

    /boot

    Sistemin açılması için gereken dosyalar burada bulunur. Linux çekirdeği ve sistem açılırken kullanılan başlangıç dosyaları bu dizinde yer alır.

    Bu nedenle /boot altında ne işe yaradığını bilmediğimiz bir dosyayı silmememiz gerekir. Burada yapılan yanlış bir işlem sistemin açılmamasına neden olabilir.

    Not: /boot dizini ayrı bir partition üzerinde tutulabilir. Bunun sebebi GRUB’un Linux çekirdeği ve açılış için gerekli diğer dosyalara, kök dosya sisteminin yapısından bağımsız olarak erişebilir olması içindir. Ardından çekirdek yüklenir ve kök dosya sistemi bağlanarak sistem açılışına devam edilir.

    /dev

    Linux’ta aygıtlar dosyalar aracılığıyla temsil edilir. Diskler, disk bölümleri, terminaller ve bazı sanal aygıtlar /dev dizini altında gösterilir.

    Ekran görüntüsü /dev dizinindeki dosyaların bir kısmına aittir.

    Ekran görüntüsünde gördüğümüz üzere dosya izinlerinin başına farklı olarak kimi dosya için c kimisi için de b karakteri kullanılmaktadır.

    c, veriyi sırayla akış hâlinde ileten karakter aygıtlarını (mesela terminal) ; b ise veriyi bloklar hâlinde okuyup yazan disk gibi depolama aygıtlarını gösterir .

    Buradaki dosyalar normal dosyalar gibi veri saklamaz. Çekirdeğin aygıtlarla iletişim kurabilmesi için birer erişim noktası görevi görürler.

    /etc

    Sistem genelinde geçerli olan yapılandırma dosyaları çoğunlukla burada bulunur (Kimi uygulamalar yapılandırma dosyalarını buralarda bulundurmayadabilir) .
    Kısacası /etc altında genellikle programların kendileri değil, programların ve sistemin nasıl davranacağını belirleyen dosyalar bulunur.

    Not: Burada bazı yapılandırma dosyalarının yanında sonu .d ile biten dizinler bulunur. sudoers.d ve rsyslog.d bunlara örnek gösterilebilir.

    Bu dizinler, ana yapılandırma dosyasını doğrudan değiştirmeden ek ayarlar tanımlayabilmek için kullanılır.

    Sonu .d ile biten her dizin kendiliğinden okunmaz. İlgili uygulamanın bu dizindeki dosyaları okuyacak şekilde hazırlanmış olması gerekir (include ettirilmesi gerekir)

    /home

    Normal kullanıcıların kişisel dizinleri genellikle /home altında bulunur.

    Bir kullanıcının ev dizini doğrudan /home dizini altında olmak zorunda değildir, herhangi bir dizinde kullanıcının ev dizini olarak belirlenebilir.
    Her kullanıcının kendisine ait bir ev dizininin bulunması, kullanıcıların kişisel dosyalarının ve ayarlarının birbirinden ayrılmasını sağlar.

    /opt

    Sisteme sonradan eklenen bazı programların kendi dosyalarını toplu halde bulundurabildiği dizindir. opt ifadesi optional anlamına gelir.

    Özellikle üçüncü taraf yazılımlar çalıştırılabilir dosyalarını, kütüphanelerini ve ihtiyaç duyduğu diğer dosyaları /opt altında kendilerine ait tek bir dizinde tutabilir.

    Örneğin bir program /opt/yeniprogram altına kurulduğunda, programa ait dosyalar sistemin farklı dizinlerine dağılmak yerine büyük ölçüde burada bir arada bulunabilir.

    Ancak sisteme sonradan kurduğumuz her programın mutlaka /opt altında bulunması gerekmez. Bu durum programın nasıl paketlendiğine ve hangi yöntemle kurulduğuna göre değişebilir.

    /proc ve /sys

    Bu dizinlerin içerisindeki dosyalar fiziksel olarak diskte tutulmaz. Sistem çalışırken kernel tarafından biz okumak istediğimiz zaman oluşturulurlar.

    /proc, çalışan prosesler ve sistemin o anki durumu hakkında bilgi verir. Bellek kullanımı, işlemci bilgileri ve çalışan prosesler burada görüntülenebilir.

    /sys ise sistemde bulunan aygıtlar ve bu aygıtların kullandığı sürücüler hakkında bilgi verir. Kernel, donanımları kullanıcı alanına bu dizin üzerinden gösterir. Daha okunası bir bölümdür.

    /root

    /root, sistem yöneticisi olan root kullanıcısının ev dizinidir.

    Normal kullanıcıların ev dizinleri /home altında bulunurken root kullanıcısının ev dizini ayrı olarak /root altında tutulur.

    Normal kullanıcıların bu dizine erişimi genellikle yoktur.

    /sbin

    Sistem yönetimiyle ilgili komutlar geleneksel olarak bu dizinde bulunur. Diskleri, dosya sistemlerini, ağı veya sistem servislerini yönetmek için kullanılan bazı komutlar buna örnek gösterilebilir.

    Buradaki komutların çoğu sistem yöneticileri tarafından kullanılır. Ancak “normal kullanıcılar /sbin altındaki komutları hiç çalıştıramaz” demek doğru olmaz.

    Normal bir kullanıcı komutu çalıştırabilir fakat yapılacak işlem root yetkisi gerektiriyorsa izin hatası alır.

    Güncel dağıtımlarda /sbin çoğunlukla /usr/sbin dizinine yönlendiren sembolik bağlantıdır

    Bu davranış kullandığımız dağıtıma göre değişebilir.

    /srv

    Sistemin sunduğu servislerin dışarıya sağladığı veriler bu dizinde tutulabilir. srv ifadesi service anlamına gelir.

    Burada servisin kendisinden ziyade, servisin kullanıcıya veya başka sistemlere sunduğu veriler bulunur.

    Böylece servisin sunduğu veriler; programın kendisinden, yapılandırma dosyalarından ve günlük kayıtlarından ayrılmış olur.

    Fakat internet sitesi dosyalarının mutlaka /srv/www altında bulunması gerekmez. Bazı dağıtımlar ve web sunucusu yapılandırmaları bunun yerine /var/www dizinini kullanabilir. Bu nedenle /srv dizininin boş olması da normaldir.

    /tmp

    Programların ve kullanıcıların geçici olarak ihtiyaç duyduğu dosyalar burada tutulur.
    Örneğin bir program çalışırken geçici bir dosya oluşturabilir ve işi tamamlandığında bu dosyayı silebilir.

    /tmp altındaki dosyaların ne zaman temizleneceği kullanılan dağıtıma ve sistem yapılandırmasına göre değişir. Örneğin debian’da her reboot’ta dosyalar silinirken rocky’de dosyalar 10 gün kullanılmadığında siliniyor.

    /usr

    Sistemde bulunan programların, kütüphanelerin ve ortak dosyaların büyük bir bölümü /usr altında bulunur.

    Programlar bu kısmı bir kök gibi görerek programlarını burada bulundururlar.

    /usr/share altında mimariden bağımsız ortak dosyalar ve belgeler bulunabilir.

    /var

    Sistem çalıştıkça sürekli değişen veya büyüyen dosyalar burada tutulur. var ifadesi variable, yani değişken anlamına gelir.

    /var/log altında sistemin ve servislerin oluşturduğu günlük kayıtları bulunur. Bir servisin neden çalışmadığını araştırırken bakacağımız yerlerden biri burasıdır.

    /var/cache programların oluşturduğu önbellek dosyalarını tutar. /var/lib altında uygulamaların çalışma sırasında kullandığı bağımlılıklar bulunabilir.

    /var/spool yazdırma veya e-posta gibi sırada bekleyen işleri tutabilir. /var/tmp ise geçici dosyalar için kullanılır fakat buradaki dosyalar genellikle /tmp altındaki dosyalardan daha uzun süre korunur (kullandığım her iki dağıtımda – rocky ve debian – /var/tmp altındaki dosyaları reboot sonrası silmedi)

    Devamını okumak için…


  • Linux Sistem Yönetimi | LKD #2

    Linux’ta yollar ikiye ayrılır:

    1. Mutlak (Absolute) Yol

    Nerede bulunduğumuza bağlı olarak değişmeyen yollardır. Örneğin, /var/log .

    2. Göreceli (Relative) Yol

    Nerede bulunduğumuza bağlı olarak değişen yollardır. Örneğin, ../../../

    Not: Pratik olarak kullanabileceğimiz bir yöntem, / ile başlayan yolların mutlak, başlamayan yolların göreceli olduğu şeklindedir.

    Linux’ta Dosya Yapısı

    Öncelikle derste de sayısız kere tekrar ettiğimiz bir konuyu belirtmek istiyorum, linux’ta her şey birer dosyadır. Kullandığımız aygıtlar, sürücüler, servisler, paketler, dizinler ve kalan her şey birer dosyadır.

    Dosyalar 3 temel ana birimden oluşurlar. Bunlar,

    • Dosyanın adı (dizin kaydı)
    • Dosyanın inode’u (ne olduğunu yazının ilerleyen bölümlerinde detaylı bir biçimde ele alacağız)
    • Veri blokları

    ls -l komutunu kullandığımızda karşımıza dizinde yer alan dosyaların listesi gelir.

    Yukarıdaki çıktıda bazı sütunlar görünüyor. Bunların neler olduğunu kısaca,

    • dosya türü ve izinleri
    • hard link sayısı (yazının devamında ne olduğu detaylıca anlatılıyor)
    • sahibi
    • grubu
    • boyutu
    • son değiştirilme zamanı
    • adı

    şeklinde ifade edebiliriz. Bu saydığımız bilgiler yukarıda saydığımız dosya yapısına göre belirli alanlarda bulunurlar. Bu alanları şöyle ifade edebiliriz:

    Dizin kaydı

    • Dosya adı
    • Dosya adı ile inode numarası arasındaki eşleştirme

    Inode

    • Dosya türü
    • Sahip
    • Grup
    • İzinler
    • Dosya boyutu
    • Hard link sayısı
    • Zaman bilgileri
    • Veri bloklarının adresleri

    Veri blokları

    • Dosyanın gerçek içeriği
    • Metin, görüntü ve program verisi gibi baytlar

    Buradaki bilgilere biraz daha detaylıca göz atmak istersek stat <dosya_adi> komutunu kullanabiliriz.

    Inode, tabloda gösterilen bilgileri tutar ve diskte dosyanın içeriğinin bulunduğu blokları işaret eder. ls -li komutunu verdiğimizde inode numaralarını da içeren aşağıdaki çıktıyı alabiliriz,

    bu çıktı da görüldüğü üzere ilk sütunda her dosyaya ait inode numarası belirtilmiş.

    grep – find ve diff

    grep ve find komutları filtreleme yapmamıza yarayan komutlardır. Bu komutlar arasında önemli bir ayrım vardır. grep doğrudan dosyanın içeriği yani veri kısmında arama yaparken find komutuysa bazı parametreleriyle dizin kaydında, bazı parametreleriyleyse Inode bilgilerinde inceleme yapar.

    Bir dosyayı kopyalayıp diff komutuyla aslını ve kopyasını karşılaştırdığınızda alacağınız çıktı iki farklı dosya olmasına rağmen boş olacaktır. Çünkü bu komut, dosyaların içeriğinde yani veri kısmında çalışır

    mv, cp ve rm

    mv, bir dosyayı farklı bir konuma taşımak için kullandığımız bir komuttur. Aynı dosya sistemi içinde çalıştırıldığında kısa bir süre içinde gerçekleşir çünkü verileri gerçekten fiziksel olarak bir noktadan başka bir noktaya taşımaz. Yalnızca dizin kaydına müdahale eder. Eğer farklı dosya sistemleri arasında taşıma yapmak isterseniz, hedef sistemde yeni bir dosya ve inode oluşturulur. Ardından mevcut sistemdeki bilgiler karşı tarafa kopyalanır ve kopyalama başarılı olduktan sonra kaynak bilgiler silinir (dizin kaydı kaldırılır) .

    cp, verileri diskte bir noktadan başka bir noktaya kopyalar. Asıl ve kopya dosyalar farklı bloklarda saklanırlar ve farklı inode’lara sahip olurlar, yani birbirlerinden tamamen bağımsızdırlar.

    rm, bir dosyanın dizin kaydıyla inode bağlantısı keser. Bağlantı kesildikten sonra inode boşa düşer ve diskte ilgili alan yeniden kullanılabilir hale gelir yani doğrudan veriler silinir diyemeyiz. Verileri kurtarma yazılımları da buradaki duruma göre başarılı veya başarısız sonuç verebilirler.

    rm dosya_adi

    Dosya adı kaldırılır

    Hard link sayısı azaltılır

    Başka bir hard link veya dosyayı açık tutan program var mı?

    Evet

    Inode ve veri blokları kullanımda kalır

    İçeriğe diğer hard link veya açık program üzerinden erişilebilir

    Son hard link kaldırıldığında ve dosyayı açık tutan program kapandığında Hayır tarafındaki adımlar uygulanır

    Hayır

    Inode ve veri blokları yeniden kullanılabilir olarak işaretlenir

    Eski veri bir süre fiziksel olarak kalabilir

    Alanın üzerine yeni veriler yazılabilir

    Linkler

    Linux’ta iki çeşit linkleme yöntemi vardır. Bunlar,

    • Hard Link: mevcut inode’a bağlanan yeni bir dizin kaydıdır. Başka bir ifadeyle iki farklı dosya adı aynı inode’u ve aynı veri bloklarını gösterir

    Hard linklerden biri silinirse hiçbir şey olmaz, diğer link sorunsuz şekilde çalışmaya devam eder. Hard link sayısı bir eksilir.

    Her dizin oluşturulduğunda varsayılan olarak 2 adet hard link ile beraber gelir. Bunlar,

    • Üst dizindeki dizin adı
    • Dizinin kendi içindeki .

    Mesela,

    /var dizini için hard link hesabını yapalım. ls çıktısında ikinci sütundaki alan o dizinin hard link sayısını gösterir. Burada dizinleri saydığımızda 11 adet dizin bulunuyor, 2 adet de varsayılan olarak geliyordu. Bu durumda /var dizini için 13 adet hardlink olduğunu söyleyebiliriz.

    Not: Bu dizinde yer alan .. bu dizinin hardlink sayısına etki etmez, bir üst dizinin hardlink sayısına etki eder.

    ln kaynak_dosya yeni_ad ile hard link oluşturabiliriz.

    Not: cp komutu sahip dosyadan bağımsız yeni bir kopya oluştururken hard linkler, kaynak dosya ile aynı inode’yi kullanan bir dosya oluşturur.

    Not2: Bir dosyaya hardlink yapılmış diğer tüm dosyaları görebilmek için doğru kabul edilen 2 yöntem vardır:

    1-) : find’in -samefile parametresiyle bulabiliriz.

    2-) : find’in -inum parametresiyle bulabiliriz (önce inode numarasına bakıp onunla filtrelememiz gerekir)

    • Sembolik Link: hedef dosyanın inode’una doğrudan bağlanmaz. Hedefin yolunu saklayan, kendisine ait inode’u bulunan özel bir dosyadır.

    Sembolik link silinirse hiçbir şey olmaz, ancak şemada gördüğümüz hedef (gerçek) dosya silinirse sembolik linkte geçersiz duruma düşer.

    Not: Sembolik linkler dosya içeriklerini değil, yollarını kayıt altına alırlar. Bunu bir örnek üzerinden anlayabiliriz,

    İlk önce bu işlemleri yapabileceğimiz temiz bir dizin oluşturarak başlıyorum ve içine giriyorum.

    bash
    mehmet@debian ~$ mkdir ~/symlink-deneyi
    mehmet@debian ~$ cd ~/symlink-deneyi

    Ardından dosya isminde bir dosya oluşturup içine ayırt edici bir metin yazıyorum, oluşturduğum dosyanın adı mehmet ve içerisindeki veri de dosya1 olsun.

    Ardından yeni bir dosya daha oluşturup onun içine de ayırt edici bir metin yazıyorum, dosyanın adı can ve içerisindeki metin de dosya2 olsun.

    Sembolik link oluşturuyorum, İlk oluşturduğum dosyaya bağlıyorum.

    bash
    mehmet@debian ~$ ln -s dosya baglanti

    Dosyanın içeriğini okuyorum, dosya1 yazıyor.

    Ardından ilk oluşturduğum dosyayı siliyorum ve sembolik linki okumaya çalıştığımda hata alıyorum.

    İkinci oluşturduğum dosyaya ilk oluşturduğum ve sildiğim dosyanın adını verip sembolik linkimi tekrar okuduğumda içerisinde can yazdığını görüyorum ve sembolik linklerin sadece yolu tuttuğunu öğreniyorum.

    Bir dosyaya bağlı tüm sembolik linkleri görebilmek için find’in lname parametresini kullanabiliriz.

    bash
    mehmet@debian ~$ find aranacak_dizin -lname kaynak_dosya_yolu

    Not1: Sembolik linkleri taşıyacağımız zaman hedefin absolute ya da relative path olması sembolik linkin çalışıp çalışmayacağını değiştirebilir. Eğer absolute hedefte taşıyorsak çalışır ama relative hedefte taşıyorsak çalışmaz. Çünkü sembolik linkin kaynağını ararken öncelikle bulunduğumuz dizinde arama yaparız, relative de bulamayacağımız için link kırılır.

    Not2: Farklı dosya sistemleri arasında hard link oluşturulamaz ama sembolik link oluşturulabilir. Dizinler için ise aynı dosya sisteminde olunsa dahi hiçbir şekilde hard link tanımlanamaz; dizinleri bağlamak için sadece sembolik link kullanılabilir.

    ÖzellikHard linkSembolik link
    Aynı inode’u kullanır mı?EvetHayır
    Hedef yolunu saklar mı?HayırEvet
    Hedefin bir adı silinirse çalışır mı?EvetLink durumuna bağlı
    Farklı dosya sistemine geçebilir mi?HayırEvet
    Dizine bağlantı oluşturabilir mi?Normalde sınırlandırılmıştırEvet
    Kendi inode’u var mı?HayırEvet

    lsblk

    Sistemimizde bulunan depolama birimlerini lsblk komutu ile görüntüleyebiliriz.

    Çıktısında görüldüğü üzere birimler, onlar üzerinde yaptığımız yapılandırmalar, boyutları, bağlandıkları noktalar gibi bilgiler yer alıyor.

    Sistemimize yeni bir disk takacağımız zaman buradaki çıktıyı kullanarak hareket ederiz. Örneğin sda isimli disk , sda1, sda2 ve sda3 alanlarına bölünmüş durumda. Ya da SWAP alanımızın ne büyüklükte olduğu gibi bilgilere rastlayabiliyoruz.

    Buradaki alanlar,

    Sütun Anlamı
    NAME Depolama biriminin adı
    MAJ:MIN Çekirdeğin aygıtı tanımak için kullandığı ana ve alt aygıt numaraları(MAJ hangi aygıta ait olduğı, MIN ise aygıtın altında hangi birimde olduğunu tanımlar
    RM Aygıtın çıkarılabilir olup olmadığı (0 ise çıkarılamaz, 1 ise çıkarılabilir)
    SIZE Birimin toplam boyutu
    RO Birimin salt okunur olup olmadığı (read only, 0 salt okunur değil, 1 salt okunabilir)
    TYPE Disk, bölüm, LVM veya ROM gibi birim türü
    MOUNTPOINTS Dosya sisteminin bağlandığı dizin veya dizinler

    lsblk ile sadece mevcut durumu görüntüleyebiliriz, değişiklik yapmak istersek farklı araçlar kullanmamız gerekli.

    Depolama Birimi Yapılandırma ve Bağlama

    lsblk çıktısında gördüğümüz üzere diskin yanında farklı depolama aygıtları da takabiliyoruz. Sanal makinede bu süreci simüle etmek için şöyle bir yol izleyeceğiz:

    Öncelikle sanal makineyi kapatıp, makinenin ayarlarından depolama bölümüne geliyoruz.

    mavi ile odaklanılmış bölümde üstteki oluştur seçeneğine tıklıyoruz.

    Burada var olan depolama birimlerini görüyoruz, yukarıdaki oluştur seçeneğine tıklayıp

    gelen yeni bölümde disk alanımızı da belirleyip işlemi tamamlıyoruz.

    Not: Burada tam boyutu önceden ayır seçeneği işaretlendiğinde ana bilgisayarımızda ilgili alan doğrudan ayrılır, ilgili alan işaretlenmediği taktirde birim üzerine yazdıkça dosyanın boyutu artar ve tam kapasiteye ulaştığında durur.

    Sistemimize geri döndüğümüzde lsblk çıktımızda ilgili alan sistemde görünecektir.

    sdd başarıyla eklendi.

    Biz bir diski sistemimize takarken şu adımları izleyerek ilerliyoruz:

    1-) diski sistemimize taktıktan sonra lsblk ile durumunu kontrol ediyoruz.

    2-) diski kullanmaya karar verdiysek bölümleme yapıp yapmayacağımızı kararlaştırıyoruz.

    Bir diski eğer farklı dosya sistemleriyle birlikte kullanmak istersek diski bölümlere (partition) ayırmamız gerekebilir. Örneğin sda’da olduğu gibi sda1, sda2, sda3 şeklinde bir bölümleme yapmamız muhtemeldir.

    Bölümleme işlemlerini fdisk ya da parted (daha kapsamlı bir araç olduğu söylendi, inşallah onu da denerim) aracıyla yapabiliriz. fdisk disklerimizi bölümlememize yardımcı olan bir araçtır.

    Fdisk ile bölümleyeceğimiz alanının yolunu vererek başlıyoruz.

    bash
    mehmet@debian ~$ sudo fdisk /dev/sdd

    çıktısı ile karşılaşıyoruz. Burada yardım almak için m tuşuna basabileceğimiz söyleniyor, basıyoruz.

    burada fdisk ile bölümleme sürecinde hangi seçenekleri kullanabileceğimiz ve bu seçeneklerin ne anlama geldiği açıkça yazıyor.

    Diski bölümlemeye başlamadan önce kullanabileceğimiz partition tablosu türlerine göz atalım:

    • MBR partition tablosu
    • GPT partition tablosu

    MBR, eski sistemlerde yaygın olarak kullanılan bir partition tablosu türüdür. Partition konumlarını 32 bitlik sektör adresleriyle kaydeder. Sektör boyutunun 512 bayt olduğu disklerde erişebildiği alan şu şekilde hesaplanır:

    2³² sektör × 512 bayt ≈ 2 Tb

    Bu nedenle MBR, bu koşullarda yaklaşık 2 tb’ye kadar olan diskleri destekler.

    MBR partition tablosunda en fazla dört ana partition kaydı bulunur. Bu kayıtların tamamı primary partition olarak kullanılabilir. Dörtten fazla bölüm oluşturmak istiyorsak kayıtlardan birini extended partition olarak ayırabiliriz (birden fazla extended olamaz) .

    Örneğin şu yapı oluşturulabilir:

    • 3 primary partition
    • 1 extended partition ( ve içinde bir sürü logical partition)

    Extended partition normal bir dizin veya doğrudan dosya saklamak için kullanılan bir dosya sistemi değildir. Logical partition’ları içerisinde barındıran özel bir kapsayıcı görevi görür. Extended partition içerisinde disk alanı ve sistem sınırları elverdiği ölçüde birden fazla logical partition oluşturulabilir.

    Linux’ta primary ve extended partition’lar için genellikle 1–4 arasındaki numaralar kullanılır. Logical partition’ların numaralandırılması ise 5’ten başlar.

    GPT, MBR’nin sınırlamalarını ortadan kaldırmak amacıyla geliştirilmiş daha modern bir partition tablosu türüdür.

    GPT, partition konumlarını 64 bitlik sektör adresleriyle kaydeder. Bu nedenle MBR’nin yaklaşık 2 tb’lik sınırından çok daha büyük diskleri destekleyebilir.

    GPT partition tabloları genellikle 128 partition kaydını destekleyecek şekilde oluşturulur. Ancak bu sayı kullanılan sisteme ve partition tablosunun yapılandırmasına göre değişebilir.

    İlk önce bir MBR oluşturacağım, sonrasında yeni bir disk alanı ekleyip onda da GPT ile düzenleme yapacağım.

    MBR için o ile devam ediyorum.

    n’ye basarak yeni bir partition oluştur diyorum.

    p’ye basarak primary oluşturuyorum ve default olarak devam etmesi için enter’a basıyorum.

    Ardından bitiş vektörü, yani alanın ayarlanması için +512M büyüklüğünde bir alan ayırıyorum. Tekrar n bastığımda,

    3 boş alanımın kaldığını görüyorum. Bu sefer kalan alanın tamamını bir extended oluşturum ona veriyorum.

    extended alanımı oluşturduktan sonra bu alanın içerisinde logical alanlar oluşturmak için yeniden n basıyorum.

    Not: Disk içerisinde herhangi bir alan kalmadığı için sistem doğrudan bizi extended içerisinde logical alan bölümlemeye itti.

    Bu kısmı fazla da uzatmadan kalan boşluğu da son kalan logical alanıma verip tamamlıyorum. Kaydetmeden önce çıktıyı görmek için p basıyorum,

    işlemin sorunsuz bir şekilde tamamlandığını görüp w basıyorum ve kaydediyorum.

    Yeni lsblk çıktısında,

    sdd alanının partition’lara bölündüğünü görüyorum.

    Bir defa da GPT ile bölümleme yapmak istiyorum (bunun için yeni bir disk ekledim ve onu bölümlüyorum)

    Öncelikle g basarak gpt bölümlemesi yapacağımı söylüyorum, devamında herhangi bir bölüm seçmeden doğrudan alanı belirterek bölümleme yapmaya devam ediyorum, w ile kaydediyorum ve ayrılıyorum.

    İster gpt ister mbr kullanalım, bölümlemeyi bitirdikten sonra ayırdığımız bölümlere dosya sistemi kuruyoruz. Günümüzde sıklıkla kullanılan iki farklı dosya sistemi bulunuyor: ext4 ve xfs.

    ext4, dosya sistemi oluşturulurken belirli sayıda inode için yer ayırır. Sabit boyutlu bir ext4 dosya sistemindeki inode kapasitesi, dosya sistemi oluşturulurken belirlenir. Diskte boş alan bulunsa bile inode’lar tükenirse yeni dosya oluşturulamaz.

    XFS ise inode’ları ihtiyaç ortaya çıktıkça dinamik olarak oluşturur. Bu nedenle başlangıçta sabit sayıda inode ayrılması gerekmez.

    Biz yapacağımız işlemde ext4 kullanacağız. Birçok partition’a sahip olduğumuz için her biri için sırasıyla şu komutu uygulayacağız

    bash
    mehmet@debian ~$ sudo mkfs.ext4 /dev/partition_adi

    Not: Extended partition için ayrıca bir dosya sistemi uygulamayız, yalnızca logical birimlere uygularız.

    Not2: mkfs işlemi hedef partition’daki mevcut verileri siler. Yapmadan önce partition adı kontrol edilmelidir.

    Geriye son bir işlem olarak oluşturduğumuz ve yapılandırdığımız depolama birimlerini mevcut yapımıza bağlamak kalır.

    Öncelikle mount point (depolama birimini bu alana bağlayacağız) olarak kullanacağımız dizini oluşturuyoruz:

    bash
    mehmet@debian ~$ sudo mkdir /mnt/sdd1

    Ardından /dev/sdd1 partition’ını bu dizine bağlıyoruz:

    bash
    mehmet@debian ~$ sudo mount /dev/sdd1 /mnt/sdd1

    İşlemi lsblk ile kontrol ediyoruz:

    Çıktıda /dev/sdd1 partition’ının /mnt/sdd1 dizinine bağlandığını görebiliriz. Artık partition’ın içerisindeki verilere bu dizin üzerinden erişebiliriz.

    mount komutuyla yaptığımız bağlantı geçicidir. Bilgisayarı yeniden başlattığımızda bağlantı kaldırılır. Partition’ın sistem açılırken otomatik olarak bağlanması için /etc/fstab dosyasına eklenmesi gerekir.

    İlk olarak partition’ın UUID değerini öğreniyoruz:

    bash
    mehmet@debian ~$ sudo blkid /dev/sdd1

    UUID, dosya sistemine ait benzersiz kimliktir. Sisteme yeni diskler eklendiğinde /dev/sdd1 gibi aygıt adları değişebileceği için /etc/fstab içerisinde UUID kullanmak daha güvenlidir.

    Dosyada hata yapma ihtimaline karşı önce yedeğini alıyoruz:

    bash
    mehmet@debian ~$ sudo cp /etc/fstab /etc/fstab.yedek

    Dosyanın sonuna aşağıdaki satırı ekliyoruz. buraya_UUID_degeri kısmına blkid çıktısında gördüğümüz UUID değerini yazmamız gerekir:

    UUID=buraya_UUID_degeri /mnt/sdd1 ext4 defaults,nofail 0 2

    Bu satırdaki alanlar sırasıyla bağlanacak dosya sistemini, bağlama noktasını, dosya sistemi türünü ve mount seçeneklerini belirtir. nofail, disk sistemde bulunmadığında açılışın bu disk nedeniyle engellenmemesini sağlar. Sondaki 0, dosya sisteminin dump ile yedeklenmeyeceğini; 2 ise root dosya sisteminden sonra kontrol edilebileceğini belirtir.

    Dosyayı kaydettikten sonra systemd’nin yeni yapılandırmayı okumasını sağlıyoruz:

    bash
    mehmet@debian ~$ sudo systemctl daemon-reload

    Ardından /etc/fstab dosyasını hata açısından kontrol ediyoruz:

    bash
    mehmet@debian ~$ sudo findmnt --verify --verbose

    Çıktıda parse veya bağlantı hatası bulunmuyor, mevcut bağlantıyı kaldırıyoruz:

    bash
    mehmet@debian ~$ sudo umount /mnt/sdd1

    Bu defa yalnızca bağlama noktasını belirterek partition’ı tekrar bağlıyoruz:

    bash
    mehmet@debian ~$ sudo mount /mnt/sdd1

    Kaynak aygıtı komutta belirtmediğimiz için mount, gerekli bilgileri /etc/fstab dosyasından bulur. Bağlantıyı kontrol etmek için:

    bash
    mehmet@debian ~$ findmnt /mnt/sdd1

    Son olarak sistemi yeniden başlatıp bağlantının kalıcı olduğunu kontrol ediyoruz.

    Sistem tekrar açıldığında aşağıdaki komut /dev/sdd1 bölümünün /mnt/sdd1 dizinine bağlı olduğunu gösteriyorsa işlem başarıyla tamamlanmıştır:

    diski fdisk ile bölümlendirirken sektörler üzerinden işlem yaparız. Ardından mkfs ile bölümün üzerine bir dosya sistemi kurarız. Kurduğumuz dosya sistemi, bölümdeki sektörleri bloklar hâlinde gruplandırarak kullanır.

    Umount işlemi

    Partition ile işimiz bittiğinde bağlantıyı kaldırmak için umount komutunu kullanıyoruz:

    bash
    mehmet@debian ~$ sudo umount /mnt/sdd1

    Bağlantının kaldırıldığını tekrar kontrol ediyoruz.

    /dev/sdd1 satırındaki bağlanma noktasında artık /mnt/sdd1 görünmüyor yani başarıyla umount edebildik (/mnt/mkfs-deneyi hala görünüyor ancak biz onu kaldırmayı hedeflememiştik, kaldırmak istersek sdd1 için aynı işlemi tekrar ederiz)

    Not: İçinde veri bulunan bir dizinin üzerine başka bir dosya sistemi mount edilirse dizinin eski içeriği silinmez, mount işlemi devam ettiği sürece görünmez hâle gelir (bir nevi yeni bölüm eski bölümün üstünü örter)

    Verileri görebilmemizin bir yolu, altta kalan bölümü başka bir alana mount etmektir. Bu sayede verilere yeniden erişebiliriz.

    Örneğin burada, /dev/sdd1 veri2 dizinine bağlı. Üstüne /dev/sdd5 bağlandığında sdd1 içindeki verilere veri2 dizininden erişemez oluyoruz. Bunun için yeni bir veri dizini açıp sdd1’i oraya mount ediyoruz, işimizi bitiriyoruz.

    Not:Aynı disk üzerinde bulunan iki boş alanı tek parça hâline getirebilmek için bu alanların fiziksel olarak yan yana bulunması gerekir.

    Soldaki bölümün ana bölüm olduğunu düşünelim. Dosya sistemine ait başlangıç bilgileri bölümün başında bulunduğu için ana bölüm, hemen sağında bulunan boş alana doğru kolayca genişletilebilir. Ancak boş alan ana bölümün solundaysa bu alan doğrudan bölüme eklenemez. Önce bölümün başlangıcının sola taşınması gerekir.

    Devamını okumak için…


  • Linux Sistem Yönetimi | LKD #1

    Linux Sistem Yönetimi | LKD #1

    21-30 Ağustos 2026 tarihleri arasında Linux Kullanıcıları Derneği tarafından düzenlenen Mustafa Akgül Özgür Yazılım Yaz Kampı’nda Linux Sistem Yönetimi kursunda Doruk Fişek ve Onur Akdeniz hocalarımdan aldığım ders notlarımdır.


    Linux, aslında tek başına bir işletim sistemi değil, bir çekirdektir. Çekirdek baz alınarak oluşturulmuş birçok dağıtım bulunur. Rocky Linux, Arch Linux ve Linux Mint bunlardan bazılarıdır.

    Bu dağıtımların temel ortak noktası Linux çekirdeğini kullanmaları bunun haricinde paket yöneticileri, yazılım depoları, varsayılan ayarları hitap ettikleri gruplara veya kullanım amaçlarına göre birbirlerinden ayrışır. Örneğin Ubuntu ve Debian apt, Fedora ve Rocky Linux dnf, Arch Linux ise pacman paket yöneticisini kullanırlar.

    Özetle, Linux çekirdeğinin yanında farklı sistem araçları, kütüphaneler, paketler … gibi spesifik yapıları tercih edilmesiyle dağıtımlar ortaya çıkarlar. Bu kadar fazla dağıtımın ortaya çıkabilmesi de özgür yazılım anlayışının getirdiği bir özgürlüktür

    Özgür yazılım anlayışı sayesinde kişiler, topluluklar veya kurum-kuruluşlar mevcut bir Linux dağıtımını değiştirip geliştirerek kendi dağıtımlarını oluşturabilirler. Ancak baz aldıkları yazılımların mevcut lisans koşullarına uymaları gerekir. Kendi geliştirdikleri bölümlerin lisanslarını ise kendileri belirleyebilirler.

    Bahsettiğimiz üzere tüm dağıtımlar ortak bir çekirdeği kullanırlar. Çekirdek, en basit tabirle donanıma en yakın bileşendir. İşletim sisteminde donanım erişimini yöneten parçadır. Görevleri arasında işlemci zamanını süreçler arasında paylaştırmak, bellek kullanımını yönetmek, uygulamaların bellek alanlarını yönetmek gibi işler bulunur.

    Bir yazılımın özgür sayılabilmesi için şu dört temel özgürlüğü sağlaması gerekir:

    • İstenilen amaç dahilinde (herhangi bir amaç olabilir) kullanılabilmeli,
    • Kaynak kodları incelenebilmeli,
    • Çoğaltılabilmeli ve dağıtılabilmeli,
    • Değiştirilebilmeli ve değiştirilen sürüm de dağıtılabilmeli.

    Özgür yazılımlar ücretsiz olmak zorunda değildir. Dört temel özgürlüğü koruduğumuz sürece geliştirdiğimiz özgür yazılımı para karşılığında satabiliriz. Yani free-software’deki “free” kelimesi ücretsiz olmayı değil, kullanıcıya sağlanan özgürlükleri ifade eder.

    Kamp süresince konuları işlerken sunucu dağıtımları kullanacağımız anlatıldı. Bir sunucunun 7/24 kesintisiz şekilde çalışması gerektiğinden özellikle bu dağıtımları tercih ettik. Çünkü saydığımız dağıtımların geliştiricileri, depolardaki paketlere belirli bir süre boyunca güvenlik yamaları sunmaya devam eder. Böylece olası güvenlik açıklarında sistemlerimiz daha dayanıklı olurlar. Bu süre Rocky Linux’ta yaklaşık 10 yıl, Debian’da ise yaklaşık 5 yıldır.

    Başlıca Komutlar

    Terminalde kullanabileceğimiz başlıca komutlar şöyledir: ls, pwd, cd, mkdir, rmdir, touch, cp, mv, cat, less …

    ls

    • ls komutu, dosyaları listelememizi sağlar. Bulunduğumuz dizinde ls yazdığımızda,

    gibi bir çıktı alırız.

    Buradaki sütunların hangi anlamlara geldiğini ilerleyen günlerde inceleyeceğiz.

    ls komutu gibi diğer komutları da kullanırken yardım alabileceğimiz birkaç yardımcı (komut ~ parametre) bulunur. Bu yardımcılar,

    • man
    • info
    • –help

    Not: man komutu yalnızca komutlar için değil nadiren de olsa konfigürasyon sayfaları için de yazılabilirler.

    Not 2: Komutlarla birlikte kullandığımız parametrelerde tek tire – tek harfli kısa seçenekleri ifade eder ve bunları birleştirebiliriz. Yani ls -a -l -h yazmak yerine ls -alh şeklinde kısaltarak yazabiliriz. Çift tire — ise kelime halindeki uzun seçenekleri belirtmek için kullanılır, ls –context veya ls –all gibi. Çift tireli parametreleri tek tireliler gibi birbirine bağlayamaz, her birini ayrı ayrı yazmamız gerekir.

    ls komutunun çıktısında son sütunda gördüğümüz ‘isim’ şeklindeki ifade, (üstteki resimde bunun örneğini görmüyoruz) içerisinde boşluk bulunan isimlendirmeler için kullandığımız yapıdır. Bunun haricinde \ da kullanarak boşluklu isimlendirmeyi sağlayabiliriz (bunu mehmet\ can\ duman\ ile sağlarız) .

    Standart Girdi-Çıktı Kanalları

    Linux’ta üç temel giriş-çıkış kanalı bulunur. Bunlar,

    • 0: Standart input (stdin)
    • 1: Standart çıktı (stdout)
    • 2: Standart hata (stderr)

    Komutların çıktıları aksi belirtilmedikçe varsayılan olarak 1 olurlar, başarılı çıktı terminale düşer. Yani 2 numaralı çıktıyı başka bir dosyaya yönlendirdiğimizde bizim terminalimizde 1 çıktısını görürüz.

    Örneğin,

    bash
    mehmet@debian ~$ ls -al /home/mehmet deneme 2> ilkdosya

    komutun çıktısında (ilgili dizinde deneme dosyasının bulunmadığını ve yalnızca /home/mehmet çıktısının başarılı bir şekilde üretildiğini varsayıyoruz) ilgili hata mesajı ilkdosya’ya yazılır, başarılı mesaj doğrudan terminale düşer.

    bash
    mehmet@debian ~$ ls -la /home/mehmet dosya5 > dosya 2>&1

    Bu komutun çıktısındaysa 2 ve 1 numaraları çıktılar doğrudan dosya’ya birlikte yazılırlar.

    tail ve head

    tail: Varsayılan olarak son 10 satırı verir, -n parametresiyle birlikte kullanıldığında kaç satırı vermesi gerektiğini ayarlayabiliriz.

    head: Varsayılan olarak ilk 10 satırı verir, tail ile aynı şekilde -n parametresiyle kaç satırı verebileceğini ayarlayabiliriz.

    Bu komutları tek başlarına kullanabileceğimiz gibi tek bir satırda birlikte de kullanabiliriz. Örneğin,

    bash
    mehmet@debian ~$ ls --help | head -n 10 | tail -n 5

    komutuyla ls --help çıktısının 6 ve 10. satırlar arasını aldık. İlk önce –help parametresiyle tüm çıktıyı aldık, head ile ilk 10 satırı aldık, tail ile aldığımız ilk 10 satırın son 5 satırını aldık.

    cd

    Bulunduğumuz dizini değiştirmek için kullanırız. (change directory) – parametresiyle birlikte kullanıldığında bir önceki dizine döner. .. parametresiyle birlikte kullanıldığında bir üst dizine gider. (örneğin /home/mehmet’te iken /home geçiş)

    Not: cd – bir önceki dizini bulabilmek için OLDPWD adı verilen bir değişkenini kullanır. Yazının ilerleyen kısımlarında da değineceğimiz bu değişken PWD ile beraber bulunduğumuz dizinleri tutarlar. PWD (print working directory), şu anda bulunduğumuz dizinin yolunu, OLDPWD , bir önceki geçtiğimiz dizinin yolunu tutar.

    Kendimiz bir değişken tanımlaması yapmak ya da var olan bir değişkeni güncellemek istersek export komutunu kullanarak,

    bash
    mehmet@debian ~$ export OLDPWD=/var

    şeklinde yapabiliriz (Burada var olan bir değişkende güncelleme yapıyoruz, ad=isim formatında, ayrıca export komutunu illaki kullanmak zorunda değiliz, biz bu değişkeni alt uygulamaların da kullanmasını istediğimiz için tercih ettik) .

    Yaptığımız tanımlamayı görmek istediğimizde printenv yazmamız yeterli (Bir diğer özet kullanım printenv Degisken_Adi şeklinde) .

    Not: Yaptığımız bu tanımlama yalnızca bizim için oturum süresince geçerli olacak bir tanımlamadır. Eğer kalıcı olarak sunucudaki diğer kullanıcıları da etkileyebilecek bir tanımlama yapmak istiyorsak farklı dosyalarda yazım yapmamız gereklidir.

    Not 2: Tek bir komut için de bir değişken tanımlayabiliriz, tanımladığımız değişken sadece o komutun çalışması sırasında kullanılır ve diğer komutlara uygulanmaz. Bunun için LANG="tr_TR.UTF8" nano dosya yazdığımızda — eğer nano türkçe dil paketini destekliyorsa — türkçe dilinde çalışacaktır bir seferliğine.

    Tam bu nokta da bize verilen 1.gün ödevini de yapmak istiyorum. Ödev şöyleydi:

    Bir ortam değişkenin değerini nasıl kalıcı olarak değiştirebileceğinizi, bunu hem kendiniz hem de sunucunuzda bulunan bütün kullanıcılar için nasıl uygulayacağınızı gösterin.

    Bulunduğumuz kullanıcının değişkenlerini düzenlemek için ~/.profile dosyasına girip en alt satıra,

    export KAMP_DERSI=linux yazdığımızda ardından,

    bash
    mehmet@debian ~$ source ~/.profile

    ile değişkeni anlık oturumumuzda da geçerli hale getirebiliriz (Bu yöntemin haricinde, ~/.profile dosyasına ekleme yaptıktan sonra oturumu kapatıp yeniden giriş yapmak da değişkenin kalıcı olarak kaydedilmesini sağlayacaktır)

    Not: Ben değişikliği .profile dosyasında yapmayı tercih ettim, bir başkası .bashrc dosyasında da aynı değişikliği yaparsa aynı sonucu alacaktır.

    Eğer oluşturacağımız değişkenin sistemdeki tüm kullanıcılar için geçerli olmasını istiyorsak değişkeni /etc/environment dosyasına yazarız. Yalnız burada export ifadesini kullanmayız, doğrudan KURS_DERSI=linux yazıp dosyayı kapatırız (çünkü bu bash’in doğrudan çalıştırdığı bir dosya değildir) .

    Aynı .profile dosyasında olduğu gibi oturumu yeniden başlatabiliriz veya login’i tetikleyecek herhangi bir işlem yapabiliriz (örneğin, yeniden ssh ile bağlanmak gibi)

    Not: /etc/environment dosyasında yaptığımız değişikliğin aktif olabilmesi için yeni bir oturum açmamız gerekir. Mesela SSH ile giriş yaptığımızda bize yeni bir /bin/bash kabuğu verildiği için değişikliğimiz burada aktif oldu. Ancak SCP ile dosya aktarımı yaptığımızda yalnızca şifremizi girdik ve herhangi bir kabuğa sahip olmadık. Bu yüzden yaptığımız değişiklik, hâlihazırda açık olan oturumumuza etki etmedi.

    Yazdırdığımız değişkenleri echo $degisken_adi komutu ile terminalde doğrudan yazdırabiliriz.

    Not: /etc/environment dosyasında yaptığımız değişiklikler hem mevcut kullanıcılar (oturumlarını yeniden başlattıklarında) hem de yeni eklenecek kullanıcıların tamamında geçerli olacaktır.

    Not2: Aynı anda hem ~/.bashrc hem de /etc/environment dosyalarında değişiklik yaparsak, .bashrc dosyasında yapılan değişiklik geçerli olur. Çünkü kullanıcıların kendilerine ait dosyalarında yaptığı değişiklikler global değişiklikleri override ederler.

    file

    File dosya_adi kullanımlarımızla dosyanın bir ön bilgisini ortaya çıkartabiliriz. file bu işlemi yaparken dosyanın başında yer alan ve dosyanın imzasını taşıyan veriden yararlanır. Buradaki baytlara bakarak dosyanın türüne karar verir.

    Not: Bir dosyanın uzantısını değiştirmek onun tipini doğrudan değiştirmez, hala dosyanın eski tipi görünür. Eğer kullandığımız uygulama doğrudan dosya uzantısına bakarak işlem yapmıyorsa dosya uzantısı yalnızca bir illüzyondan ibarettir.

    Görüldüğü üzere bir .txt dosyası olmasına rağmen file komutuyla dosyanın aslında bir .jpeg dosyası olduğunu görebiliyoruz.

    Devamını okumak için…


  • CCNA – #4 | Spanning Tree Protocol

    2.katmanda switch’ler arasında yedeklilik sağlamak için Spanning Tree adında bir protokol kullanırız. Yedeklilik mekanizmalarıyla bir noktada sorun olduğunda bir diğer noktadan verinin iletilebileceğini ve ağın çökmeyeceğini garanti ederiz.

    Yedekliliği sağlarken birden fazla switch kullanmak da ağın çökmesine yol açacak farklı durumlara yol açabilir. Switch’ler çalışma mantığı gereği aldıkları çerçeveleri gelen arayüz haricindeki tüm arayüzlerden flood edebilirler (bilinmeyen bir kayıt ise), eğer birden fazla switch döngü oluşturacak şekilde birbirlerine bağlanırlarsa daima frame’ler switch’ler arasında gidip geleceğinden ağda “broadcast storm” adı verilen tıkanıklık durumu oluşur. Beraberinde CAM tablosunda MAC adresleri ve arayüz eşleşmeleri çok sık değiştiğinden “MAC flapping” de denen kararsızlık durumu oluşur.

    Bu tıkanıklık ve kararsızlık durumlarına karşın IEEE 802.1D standartı geliştirilmiştir. Bizim Spanning Tree Protocol olarak bildiğimiz bu standart, ağlarda doğru yöntemlerle yedeklilik sağlanmasına katkı sağlar.

    STP, switch’lerde varsayılan olarak gelir. Elimizdeki switch’i bir başka switch ile bağladıktan sonra CLI’da “show spanning-tree” komutunu çalıştırarak bunu görebiliriz.

    Not: Eskiden ağlarda bridge adı verilen bir cihaz da kullanılırmış, şimdilerde kalmamış fakat bridge terimi kullanılmaya devam ediliyor. Bridge derken kastettiğimiz şey Switch’lerdir.

    STP, aynı yere giden portlardan birini blocking durumuna alır, bu port aktif çalışan portta bir aksaklık olması durumunda devreye girer.

    STP, temelde arayüzler arasında state değişiklikleri yaparak ağda tıkanıklık veya döngü oluşmasını engeller. STP durumları şöyledir:

    Durum Süre BPDU Alır? BPDU Gönderir? MAC Öğrenir? Trafik İletir?
    Disabled Hayır Hayır Hayır Hayır
    Blocking 20 sn (Max Age) Evet Hayır Hayır Hayır
    Listening 15 sn (Fwd Delay) Evet Evet Hayır Hayır
    Learning 15 sn (Fwd Delay) Evet Evet Evet Hayır
    Forwarding Sürekli Evet Evet Evet Evet

    Not: Learning ve Listening süreleri varsayılan olarak 15 saniyedir, bu süre forward delay zamanlayıcısı tarafından belirlenir.

    Root Bridge ve Root Port Seçimleri

    Switch’ler kendi aralarında iletişim kurmak ve STP’yi uygulayabilmek için 2 saniyede bir “Hello BPDU” paketleri gönderirler. Bu paketler sayesinde hem ağdaki durum hem de switch’ler arasında root’un kim olacağı belirlenir.

    Root bridge seçiminde “Bridge ID” adı verilen bir alan kullanılır. Bu alan geleneksel olarak,

    • Bridge Priority: 16 bit. Varsayılan değeri 32768’dir.
    • MAC Adresi: 48 bit.

    Bridge Priority değerleri eşit olduğunda , en düşük MAC adresine sahip olan switch Root Bridge seçilir

    Günümüzdeyse VLAN’lar için de STP kullandığımızdan,

    • Bridge Priority: 4 bit.
    • Extended System ID (VLAN ID): 12 bit. (VLAN numarası buraya eklenir).
    • MAC Adresi: 48 bit

    şeklinde hesaplama yapılır.

    Not: Bridge değerleri 4096’şar adımlar halinde artar veya azalır.

    Bir örnek yapalım,

    VLAN 1 için:
    32768 (Ana Priority)
    + 1 (VLAN ID)
    ——————–
    = 32769 (Toplam Priority)
    Oluşan Bridge ID (BID):
    32769.0002.17E8.05BB

    Her switch için ayrı ayrı hesaplamalar yapılır, priority değerlerinin eşit olması durumunda MAC adreslerine bakılır. En düşük MAC’e sahip cihaz root bridge olur.

    Bir switch root olarak seçildiğinde bütün portları designated (yönlendirilmiş) olur. Yani hiçbir portu yedeğe atılmamıştır, hepsi çalışır.

    Tam bu noktada bir portun alabileceği tüm durumlardan bahsetmem iyi olabilir.

    Root Port Kök Port: Root switch’e giden en kısa ve ana yoldur (Aktif).
    Designated Port Atanmış Port: Veri iletmekle görevli porttur (Aktif).
    Alternate Port Yedek Port: Ana yol koparsa devreye girecek porttur (Engelli).

    Kalan switch’ler root seçilen switch’e ulaşabilmek için kendi arayüzlerini yukarıda saydığım state’lere güncelleme yapılır.

    Root port seçilirken de root bridge seçimine benzer bir yol izlenir. Öncelikle,

    • Root Bridge giderken en az maliyete sahip olan arayüz root seçilir, eğer maliyetler aynıysa,
    • Komşu switchlerdeki en düşük bridge ID aranır, oradan da bir sonuç çıkmazsa,
    • En düşük arayüz ID’ye bakılır. (Komşunun portuna ait ID’ye bakıyoruz, kendi portumuz değil)

    Maliyetler için,

    HızMaliyet
    10 mbps100
    100 mbps19
    1 gbps4
    10 gbps2

    Not: Root bridge’in karşısındaki port otomatik olarak root port olur. Ayrıca root port’un karşısındaki port da daima designated olmak zorundadır.

    Not2: Eğer iki switch arasındayken root port veya designated port seçimi yapacaksak

    • Root bridge’e giderken yol maliyetleri
    • En düşük bridge ID’li komşu.
    • En düşük port priority değeri (show spanning-tree komutunun çıktısıyla kendi switch’imize ait port priority değerini öğreniriz fakat bize lazım olan bağlantının yapıldığı port’un priority değeridir)
    • Komşu portların arasından en düşük numaraya sahip olan

    sırasıyla uygulayarak seçimi yaparız.

    STP Zamanlayıcıları

    State’ler arasında geçiş yapmak için zamanlayıcılar kullanılır. Zamanlayıcılar hem diğer switch’lerin genel durumları hakkında bilgi sağlanmasını sağlar hem de olası değişiklik durumlarında seçim süreçlerinin tekrarlanmasını sağlar.

    Zamanlayıcılar şöyledir,

    Zamanlayıcı Süre Açıklama
    Hello Timer 2 Saniye Root Bridge’in BPDU gönderme sıklığıdır. Diğer switch’ler BPDU üretmez; Root’tan aldıklarını güncelleyip sadece Designated Port’larından iletirler.
    Forward Delay 15 Saniye Listening ve Learning durumlarının her birinin süresini belirler. Bir portun iletime geçmesi toplam 30 saniye (15+15) sürer.
    Max Age Timer 20 Saniye Komşudan BPDU alımı kesildikten sonra topoloji değişikliği yapmadan önce beklenen süredir. BPDU gelmezse paket geçersiz sayılır.

    Not: Max Age 20 saniye boyunca BDPU alınmadığında sıfırlanır ve ağ için seçim süreci yeniden başlar.

    Not2: Forwarding port hiçbir bekleme yapmadan doğrudan blocking port’a dönüşebilir ancak blocking bir port forwarding moda geçmek istiyorsa normal şartlar altında en az 30 saniye beklemesi gerekir.

    BPDU Alanları

    2 bytes Protocol ID Yönetimsel ve idari kullanımlar
    1 byte Version
    1 byte Message type
    1 byte Flags
    8 bytes Root ID Root Bridge’i ve yol maliyetini belirlemek için kullanılan BID ve yol bilgileri
    4 bytes Cost of path
    8 bytes Bridge ID
    2 bytes Port ID
    2 bytes Message age BPDU mesajlarının ne sıklıkla gönderileceğini belirleyen zamanlayıcı alanları
    2 bytes Max age
    2 bytes Hello time
    2 bytes Forward delay
    • Protocol ID: Spanning Tree için her zaman Hexadecimal 0000 değerindedir
    • Protocol Version Identifier: Klasik Spanning Tree için 0 olarak ayarlanı
    • Message Type: 0x00 -> Configuration BPDU, 0x80 -> Topology Chance BDPU, 0x02 -> RSTP.
    • Flags: Diğer switch’lere topoloji değişikliklerini bildirmek için kullanır. Klasik STP (daha sonraları farklı stp türleri olduğunu da öğreneceksin) 8 bitlik alanın yalnızca 1. ve 8. bitlerini kullanır.
    • Root ID: Root Bridge’in bilgilerini içerir. Bridge Priority, Extended System ID (VLAN ID) ve Root Bridge’in MAC adresinden oluşur.
    • Root Path Cost: BPDU’yu gönderen switch’in Root Bridge’e olan toplam yol maliyetidir. Root Bridge’in kendisi tarafından gönderilen BPDU’da bu değer 0’dır.
    • Bridge Identifier: BPDU’yu gönderen switch’in öncelik, extended system ID ve MAC adresini içerir. Eğer gönderen switch Root Bridge ise Root ID ile Bridge ID alanları tamamen aynı içeriğe sahip olur
    • Port ID: BPDU’nun gönderildiği fiziksel arayüzün bilgisidir. İki kısımdan oluşur: Port Priority decimal 128 ve Port Numarası birleştirilir. (örneğin 2. port için Hex 02 birleşerekHex 8002 şeklinde gösterilir)
    • Message Age: Root Bridge de 0 olarak başlar ve her geçtiği switch’te değeri 1 düşülür, maks 20 kere switch’e uğrayabilir, 20’den sonra paket düşürülür.
    • Max Age, Hello, Forward Delay Timers: Root Bridge üzerindeki zamanlayıcı konfigürasyonları, tüm ağdaki switch’lerin kullanacağı zamanlayıcı değerlerini belirlerler.

    STP İsteğe Bağlı Özellikler

    STP bazı dezavantajlarını gidermek için beraberinde isteğe bağlı özellikler getirmiştir. CCNA kapsamında öğrendiklerim PortFast, BPDU Guard – BPDU Filter, Loop Guard ve Root Guard.

    PortFast: Uç cihazlara bağlanan switch’lerin (learning + listening) uzun bekleme süreçlerinden geçmesine gerek yoktur. Çünkü bir end point cihaz sebebiyle tıkanıklık veya kararsızlık durumu oluşma riski yoktur. Bundan ötürü uç cihazlara bağlanan switch arayüzlerinde bekleme sürelerini sıfırlamak için portfast’i etkinleştirebiliriz.

    Portfast iki farklı şekilde etkinleştirilebilir.

    • Global konfigürasyon modunda tüm arayüzler için.
    • Tek bir arayüz için.

    Not: Portfast yalnızca Access portlarda etkili olur, trunk portlarda yapıldığında hata alınmaz ancak işe yaramaz.

    Arayüz modunda spanning-tree portfast default komutuyla etkinleştirilir. Ardından ayrıcalıklı yürütme modundayken show spanning-tree summary komutuyla açıldığını doğrulayabiliriz.

    Tek bir arayüzde etkinleştirmek istiyorsak ilgili arayüze gidip spanning-tree portfast komutunu girmemiz yeterlidir. Bu komutu girdikten sonra karşımıza aşağıdaki metinler çıkacaktır.

    Burada yalnızca end-point’lere bağlı arayüzlerde etkinleştirmemiz hususunda bir uyarı var, aksi taktirde ağ içinde döngülere neden olabiliriz.

    Eğer tek bir arayüzdeki detayları görüntülemek istiyorsak show spanning-tree interface [arayüz] detail komutunu gireriz ilk arayüzde.

    Portfast’i kapatmak için spanning-tree portfast disable komutunu gireriz.

    Not: Az önce yalnızca access portlarda etkinleştirilebildiğinden bahsetmiştim, aslında bu biraz eksik. Trunk portlarda da etkinleştirebiliyoruz, bunun için spanning-tree portfast trunk komutunu girmemiz yeterli.

    Not 2: Elimde gerçek bir cisco switch olmadığı için tam olarak doğruluğundan emin olamadığım bir bilgi var, gerçek switch’lerde spanning-tree portfast komutunu girdiğimizde running-config dosyasında sonuna edge takısı ekleniyormuş, ben bunu packet tracer’da gözlemleyemediğim için net bir bilgi olarak sunamıyorum.

    BPDU Guard: Portfast etkinleştirilmiş bir portta kablo takıldığı anda forwarding süreci başlatılır. Eğer bu portun karşısındaki porta bilgimiz dışında biri bir switch takarsa ağda döngüler oluşabilir. Hatta yeni takılan switch en düşük priority’e sahipse root bridge bile seçilebilir. Bu gibi sebeplerden BDPU guard adı verilen bir özellik geliştirilmiştir.

    BPDU guard yetkisiz arayüzlerden gelen “hello bpdu” mesajlarını kabul etmez, porta bu mesaj geldiği anda portu err-disabled moduna alır ve bloklar. Kabloyu çıkartsak bile port bloklanmış olarak kalır.

    Bloklanmış portu iki yöntemle geri kazanabiliriz:

    • Sırasıyla shutdown ve no shutdown komutlarını gireriz ve port tekrar aktif olur.
    • ErrDisable Recovery özelliğini kullanarak portu geri kazanabiliriz. 300 saniye sonra otomatik olarak port yeniden ağa katılır. (bunu deneyemedim packet tracer’da çalışmadı ama komutun aklımda kalması için buraya not alıyorum) errdisable recovery cause bpduguard komutunu girerek portu geri kazanırız.

    Errdisable Recovery varsayılan olarak 300 saniyedir, değiştirmek için errdisable recovery interval [saniye] komutunu kullanmamız gerekir. show errdisable recovery komutuyla portun açılmasına ne kadar süre kaldığını da takip edebiliriz.

    BPDU Filter: Portfast etkilenleştirilmiş arayüzler BPDU mesajları göndermeye devam ederler, bu da ağda boşuna bant genişliği harcanmasına sebep olur. Diğer yandan BPDU içerisindeki bilgilerin ifşa olmasına sebep olabilir. Bu gibi durumlara karşın BPDU filter’ı aktif ederiz.

    Diğer isteğe bağlı özelliklerde olduğu gibi 2 farklı yöntemle aktif edebiliriz.

    • Genel konfigürasyon modundayken spanning-tree portfast bpdufilter default komutunu gireriz, bu sayede port BPDU aldığı anda klasik STP portuna dönüşür, yani listening – learning – forwarding kısımlarını uygular bir döngü durumu oluştuğunda blocking moda geçer. Cisco bu duruma “best of both worlds” der. (kaynak: jeremy’s it lab)
    • Arayüzlerde ayrı ayrı aktif edebiliriz. spanning-tree bpdufilter enable komutunu girip yalnızca o arayüzde çalışacak şekilde ayarlayabiliriz. Bu sıkıntılı bir durumdur çünkü o arayüzü STP dışına attığımızdan ağ çökebilir.

    Not: Burada kafa karışıklığını önlemek için arayüz bazlı ve genel konfigürasyon modunda bdpufilter etkinleştirmenin farkını yazmak istiyorum. Arayüz bazlı etkinleştirme yaptığımızda portu gelen tüm BDPU çağrılarına devre dışı bırakmış oluruz, genel konfigürasyon yaptığımızda port tetikte bekler, bir BDPU aldığında harekete geçebilir.

    Not 2: Eğer BPDU Filter global olarak etkinleştirilmiş ve aynı anda BPDU Guard’da çalışıyorsa BDPU alındığında anında bdpu filter devre dışı kalır ardından BDPU Guard portu blocking moda alır.

    Eğer BDPU Filter arayüzde etkinleştirilmiş ve aynı anda BDPU Guard çalışıyorsa BDPU alındığında port gelen BDPU’yu tamamen yok saydığı için BDPU Guard hiç tetiklenmez ve ağda döngüler oluşabilir.

    Root Guard: Başka bir switch’in sonradan root bridge rolünü ele geçirmesini engeller. Yalnızca arayüz bazında yapılandırılabilir, spanning-tree guard root komutunu girmek yeterlidir.

    Bu durumda eğer herhangi bir porttan superior bdpu (düşük priority sahibi bdpu) alırsa o portu broken moda geçirir. Broken iken 1.katmanda açık ancak 2. katmanda down durumda olur. CLI üzerinde show spanning-tree çıktısında durum BKN (Broken) ve neden ROOT_Inc olarak görüntülenir. Eski haline çevirmek için superior bdpu’ların kesilmesini beklememiz yeterlidir.

    Loop Guard: Olası tek yönlü bağlantı durumlarında switch bpdu almayı kestiğinde portun karşısındaki cihazın switch dışında başka bir ağ cihazı olduğunu düşünüp portunu açabilir. Bu durumda ağda döngü meydana gelir, loop guard bu noktada karşı tarafa güvenmez ve portu blocking durumda tutmaya devam eder. Fiziksel bağlantı up/up olur fakat 2.katman bağlantısı down durumdadır.

    İki şekilde ayarlayabiliriz:

    • Global konfigürasyon modundayken spanning-tree loopguard default girmemiz yeterli. Bu komut switch üzerindeki tüm root ve non-designated portlarda Loop Guard’ı otomatik etkinleştirir.
    • Arayüz bazlı ayar çekmek için spanning-tree guard loop komutunu gireriz.

    Belirli portta kapatmak için arayüz altında spanning-tree guard none komutu girilir.

    Hattı eski haline çevirmek otomatiktir, yani sorun çözüldüğünde kendiliğinden eski haline döner.

    LOOP GUARD’I PEK DE DENEMEDİM, DENESEM İYİ OLABİLİR !!!

    RSTP Çalışma Mekanizması

    RSTP, port durumunu değiştirmek için klasik STP gibi zamanlayıcı beklemez. Switch’ler kendi arasında el sıkışma mekanizmasını kullanır. Bu sayede portlar doğrudan yönlendirme durumuna geçer.

    Kök seçim mantığı klasik STP ile aynıdır:

    • En düşük Bridge ID’ye sahip cihaz Root Bridge olur.
    • Kök köprüye en düşük maliyetle ulaşan port Root Port olur.
    • Segment üzerinde en düşük kök maliyetine sahip port Designated Port seçilir.
    Güncellenmiş Port Maliyetleri

    RSTP, 10 Gbps ve üzeri hızları ayırt edebilmek için maliyet değerlerini büyütmüştür:

    • 10 Mbps = 2.000.000
    • 100 Mbps = 200.000
    • 1 Gbps = 20.000
    • 10 Gbps = 2.000
    • 100 Gbps = 200
    Port Durumları
    • Discarding: Blocking, Disabled ve Listening durumlarının birleşimidir. Port veri iletmez ve MAC adresi öğrenmez.
    • Learning: MAC adreslerini öğrenir ancak veriyi henüz iletmez.
    • Forwarding: Hem MAC adreslerini öğrenir hem de veriyi iletir.
    Port Rolleri
    • Root Port: Kök köprüye giden en kısa yoldur.
    • Designated Port: Segment üzerinde veri ileten porttur.
    • Alternate Port: Başka bir anahtardan daha üstün bir BPDU alan ve engelleme durumunda bekleyen porttur. Bu port kök portun yedeği olarak çalışır; eğer kök port çökerse alternatif port, hiçbir geçiş durumu beklemeden anında yeni kök port olarak yönlendirme durumuna geçer. Bu anında geçiş işlevi klasik STP’deki isteğe bağlı “uplink fast” özelliğinin yerini alır.
    • Backup Port: Aynı anahtar üzerindeki başka bir arayüzden daha üstün bir BPDU alan ve durumunda bekleyen porttur. Bu durum sadece iki arayüzün bir hub aracılığıyla aynı çakışma etki alanına bağlandığı durumlarda oluşur. Belirlenmiş port çökerse, yedek port anında onun yerini alarak iletime başlar. Hub üzerinde hangi portun belirlenmiş hangisinin yedek olacağına karar verilirken en düşük port kimliğine (port ID) sahip olan belirlenmiş port seçilir. Hub’lar modern ağlarda kullanılmadığı için gerçek hayatta bu role neredeyse hiç rastlanmaz
    STP’den Farklı Özellikler

    Klasik STP’de elle yapılandırılan bazı özellikler RSTP’de doğrudan yapının içine gömülü gelir:

    • UplinkFast & BackboneFast: Bağlantı kopmalarında bekleme sürelerini atlayıp hızlı geçiş sağlayan bu mekanizmalar RSTP’de otomatik çalışır.
    • PortFast: PC ve sunucu gibi cihazların bağlı olduğu portların doğrudan Forwarding durumuna geçmesini sağlar.
    • Klasik STP’de protokol ve BPDU tipi 0 iken, RSTP’de 2 olarak gönderilir.
    • Klasik STP’de sadece Root Bridge BPDU üretirken, RSTP’de tüm switch’ler kendi designated portlarından BPDU üretir.
    • Komşu kaybı tespiti klasik STP’de 20 saniye sürerken, RSTP’de üst üste 3 BPDU (6 saniye) alınamadığında komşu düşmüş kabul edilir ve MAC tablosu temizlenir.

    RSTP Bağlantı Türleri

    • Edge Port: Son kullanıcılara bağlı portlardır.
    • Point-to-Point: İki switch arasındaki full-duplex bağlantılardır. Hızlı el sıkışma sadece bunlarda çalışır.
    • Shared: Hub gibi half-duplex çalışan hatlardır. (hub kullanılmadığından pek rastlanmaz)

    RSTP, eski STP çalıştıran cihazlarla uyumludur. Eski bir switch’e bağlanan port durumu tespit ederek otomatik olarak klasik STP’nin yavaş zamanlayıcılarına geri döner.

    EtherChannel (LAG / Port Channel)

    EtherChannel, switch’ler arasındaki birden fazla kabloyu birleştirip tek bir sanal port gibi çalıştıran teknoloji.

    Ağa bant genişliği artsın diye paralel kablo taktığında normalde Spanning Tree (STP) döngü olmasın diye o portları kapatır. EtherChannel bu hatları tek bir mantıksal port yaptığı için STP engeline takılmadan bütün hatların bant genişliğini aynı anda kullanırsın.

    Yük Dengeleme Mantığı (Flow-Based)

    Trafiği paket paket değil akış (flow) bazlı dağıtır. Aynı akışa ait paketler farklı yollardan gidip alıcıda sırası bozulmasın (out-of-order) diye hepsi tek hat üzerinden gönderilir. Farklı akışlar ise algoritmaya göre diğer hatlara bölünür.

    Yük dengelemede şunlara bakılabilir:

    • Kaynak / Hedef MAC
    • Kaynak / Hedef IP
    • Katman 4 TCP/UDP portları

    Paket IP taşımıyorsa sistem otomatik MAC adresine göre dağıtım yapar.

    Yapılandırma ve Protokoller

    EtherChannel 3 farklı şekilde kurulur:

    • LACP (802.3ad): Açık standart active ve passive modları var. İki taraf da Passive olursa hat kurulmaz. Grupta 16 port tanımlanabilir ama aynı anda en fazla 8 tanesi aktif çalışır, kalan 8’i yedek bekler.
    • PAgP: Cisco’ya özel desirable ve auto modları var. İki taraf Auto olursa çalışmaz.
    • Static (On Modu): Protokolsüz elle birleştirme. Karşı tarafın da on olması lazım. Hata olunca portu otomatik kapatamadığı için pek tercih edilmez.

    Portların gruba girebilmesi için şu ayarların iki tarafta da birebir aynı olması lazım. Yoksa port gruptan atılır ya da askıya alınır:

    • Hız ve Duplex (Full/Half)
    • Switchport modu (Access / Trunk)
    • İzin verilen VLAN’lar ve Native VLAN

    EtherChannel hem Katman 2 hem de Katman 3 seviyesinde kurulabilir.

    Katman 2 EtherChannel Yapılandırması

    1. Birleştirilecek fiziksel arayüz aralığına girilir.
    2. Grup numarası ve protokol modu tanımlanır. Bu komut verildiğinde arka planda otomatik olarak Port-channel sanal arayüzü oluşur.
    3. Otomatik oluşan bu sanal arayüze girilerek Trunk ayarları yapılır. Sanal arayüzde yapılan Trunk konfigürasyonu gruptaki tüm fiziksel üye portlara otomatik uygulanır.

    Katman 3 EtherChannel Yapılandırması

    Modern ağ tasarımlarında switch’ler arası Katman 3 yönlendirilmiş portlar (routed ports) kullanımı yaygındır. Bu sayede Spanning Tree süreçlerine hiç ihtiyaç kalmaz.

    1. Fiziksel üye portlar no switchport komutuyla yönlendirilmiş porta dönüştürülür.
    2. Portlar gruba dahil edilir.
    3. Oluşturulan mantıksal Port-channel arayüzüne IP adresi atanır. IP adresi fiziksel portlara tek tek değil, doğrudan mantıksal arayüze tanımlanmalıdır.

    EtherChannel yapısının durumunu, üyelerini ve çalışma parametrelerini kontrol etmek için kullanılan temel komutlar şunlardır:

    show etherchannel summary

    En sık kullanılan ve özet bilgiyi veren komuttur. Çıktıdaki kritik bayraklar (flags) ve anlamları:

    • S (Büyük S): Katman 2 (Switchport) EtherChannel.
    • R (Büyük R): Katman 3 (Routed) EtherChannel.
    • U (Büyük U): Kullanımda (In Use), aktif ve çalışır durumda.
    • P (Büyük P): Portun Port-Channel grubuna başarıyla dahil edildiğini ve düzgün çalıştığını gösterir.
    • D (Büyük D): Portun kapalı (Down) olduğunu gösterir.
    • s (Küçük s): Portun askıya alındığını (Suspended) gösterir. VLAN, hız veya duplex uyuşmazlığında ortaya çıkar.

    show etherchannel load-balance

    Cihaz üzerinde aktif olan yük dengeleme metodunu listeler.

    port-channel load-balance <metot>

    Global konfigürasyon modunda yük dengeleme algoritmasını/kriterini değiştirmek için kullanılır.

    show etherchannel port-channel

    Hangi protokolün kullanıldığı ve grubun hangi modda çalıştığı gibi derin teknik detayları gösterir.