Linux Notlarım

Cem Topkaya
60 min readJul 15, 2020

--

  • Linux dizin yapısı
  • rsync İle Dizinler Arasında Senkronizasyon
  • Sabit ve Sembolik Bağlantılar
  • stdin, stdout, stderr
  • Eğer Hatayı Baskılamak İstersek
  • log ve error Fonksiyonları
  • Bir Günlük Kaydının İçeriği
  • echo $? ile sonuç kodu gösterimi
  • Grup İşlemleri
  • grup yaratmak
  • Kullanıcı Ekleme (userAdd mi, addUser mı?)
  • Bir Kullanıcıyı SUDOERs Grubuna Eklemek
  • Kullanıcıları Listelemek
  • Konsolda Kullanıcı Değiştirmek
  • groupadd, chmod, chown, chgrp
  • chroot
  • apt Komutları
  • apt ile paketi sadece indirmek (kurmadan)
  • systemd
  • history İşlemleri
  • Linux, kernel versiyonunu öğrenmek
  • hostnamectl
  • /etc/os-release
  • CPU Bilgileri
  • lshw
  • inotify-tools İle Dizin ve Dosya İzleme
  • Bir Dosyayı İzlenen Dizine ve Dışına Taşımak
  • touch & echo İle Bir Dosya Oluşturmak
  • Varolan Dosyanın İçeriğini Değiştirmek
  • Dizini Listelediğimizde
  • Varolan Dosyayı Sildiğimizde
  • Yeni Dizin Oluşturduğumuzda
  • --parents Anahtarıyla Dizinler Oluşturduğumuzda
  • Yerel DEB (repo) Havuzu Oluşturma
  • 1. apt-mirror Yöntemiyle
  • Apache İle Paketleri Sunmak
  • 2. Paket Havuzu Yöntemiyle
  • Flat Repository Format *
  • apache2 Docker sürümünü kuralım.
  • Hata giderme: Packages with multiple instances but no — multiversion specified
  • Debian Paketi Hazırlamak
  • Çalıştırılabilir Programı Hazırlamak
  • Paketi Hazırlamak
  • Kullanım Kılavuzu
  • DEBIAN/control Dosyasını Hazırlayalım
  • Lisans İçin copyright Dosyası Oluşturma
  • Debian Paketini Yapılandıralım
  • Debian Paketi ve Bağımlılıklarını İndirmek
  • Depends (Bağımlılıklar)
  • Recommends (Öneriler)
  • Suggests
  • Enhances
  • Pre-Depends
  • Depends ve Pre-Depends Farkı
  • Debian Paketindeki Bağımlılık İlişkileri
  • Ağ Arayüzlerinin Donanım Durumları
  • Ağ Arayüzlerinin Ip Adresleri

Linux Dizin Yapısı

  • /bin: Bu, temel komutlar için alet kutunuzdur. Mesela ls, cat veya cp burada bulunur. "Herkesin ihtiyacı olan temel araçlar çekmecesi" gibi düşün.
  • /sbin: /bin’in kardeşi ama sistemle ilgili araçlar için ayrılmıştır. reboot veya ifconfig gibi komutlar burada yaşar. Daha çok yönetici kitlesine hitap eder.
  • /usr/bin: /bin’den biraz daha süslü. Kullanıcı tarafından yüklenen veya o kadar kritik olmayan programlar burada. Örneğin, vim veya git.
  • /etc: Kütüphaneci gibi. Kullanıcı bilgileri için /etc/passwd veya DNS için /etc/hosts gibi ayar dosyalarını burada bulursun. Sistem ayarlarının merkezi burasıdır.
  • /var: Gazeteci diyebiliriz. Her şeyi kaydeder, yani günlükler burada tutulur. Örneğin, var/log/syslog.
  • /tmp: Dağınık masa. Geçici dosyalar burada durur ama yeniden başlatıldığında temizlenir.
  • /home: Kendi kişisel alanın. Her kullanıcının dosyalarını saklaması için bir klasörü vardır. Örneğin, /home/kullaniciadi.
  • /root: Root kullanıcısı için VIP alan. /home gibi ama sadece yöneticiye özel.
  • /proc: Bir tür casus dizin. Gerçek dosyalar değil, çekirdek verilerine arayüz sağlar. Örneğin, işlemci bilgisi için /proc/cpuinfo.
  • /dev: Atölye gibi. Sistemdeki tüm cihazlar (diskler, USB’ler vs.) için bir dosya vardır. Örneğin, /dev/sda.
  • /mnt ve /media: Park alanları. /mnt elle bağlamak için, /media ise otomatik olarak USB gibi cihazları bağlamak için kullanılır.
  • /opt: Üçüncü taraf yazılımlar için otel. Paket yöneticisi dışında yüklenen şeyler burada tutulur.
  • /lib: Programların çalışmasına yardımcı olan kütüphaneler burada. .so dosyaları gibi bağımlılıklar buraya kaydedilir. 32-bit kütüphaneler (bazı sistemlerde kullanılmaz). Paket yöneticisi tarafından kurulan uygulamaların kütüphaneleri sistem seviyesinde kullanılan ve paket yöneticisi tarafından yönetilen şu dizinlere gider: /lib, /usr/lib, veya /usr/lib/x86_64-linux-gnu.
  • /lib64: 64-bit kütüphaneler.
  • /usr/local: Kendi “yerel” alanın diyebiliriz; yani, sistemde yapılan özelleştirmeler buraya gelir. Dağıtım paket yöneticilerinden bağımsız olarak yüklenen yazılımlar burada bulunur.
    Örneğin, kaynak koddan derleyip yüklediğin bir program /usr/bin yerine /usr/local/bin gibi bir yere kurulur. Böylece, sistemin varsayılan dosyalarına karışmadan çalışır.
  • /usr/local/bin: Kendi yüklediğin kullanıcı programları buraya gelir.
    Örnek: Kaynaktan derlediğin bir uygulama (make install) genelde çalıştırılabilir dosyasını buraya atar.
    Örneğin, bir Python betiği buraya eklenebilir ki herkes bu betiği komut olarak çalıştırabilsin.
  • /usr/local/sbin: Yönetici yetkisi gerektiren özelleştirilmiş araçlar burada durur. Root kullanıcısı için yüklenmiş sistem programları buraya yerleştirilir.
  • /usr/local/lib: Kaynaktan yüklenen veya özelleştirilmiş yazılımların bağımlılık dosyaları buraya gelir. Kütüphaneler (örneğin, .so dosyaları) burada saklanır.
  • /usr/local/include: Yazılım geliştirme sırasında kullanılan başlık dosyaları (header files) burada bulunur.
    Örnek: C/C++ projelerinde kullanılan .h dosyaları.
  • /usr/local/etc: Kendi yüklediğin yazılımların ayar dosyaları buraya gelir.
    Örnek: Elle kurulan bir uygulamanın yapılandırması /usr/local/etc/app.conf gibi bir dosyada tutulabilir.
  • /usr/local/share: Genel veriler veya paylaşılan dosyalar burada saklanır.
    Örnek: Dil dosyaları, ikonlar, yardım belgeleri, dokümantasyon dosyaları.
  • /usr/local/man: Elle yüklediğin yazılımların kılavuz (man) dosyaları buraya gelir.
    Örnek: man komutu ile çağırabileceğin belgeler, /usr/local/man içinde bulunur.
  • /usr/local/src: Kaynak kodlar burada saklanır.
    Örnek: Bir yazılımın kaynak kodunu indirip buraya koyabilirsin ve burada derleme yapabilirsin.
  • /usr/local/games: Kullanıcı tarafından yüklenen oyunlar buraya gelir.
  • /usr/local/var: Uygulamaların oluşturduğu değişken/veri dosyaları burada tutulur.
    Örnek: Bir manuel kurulan veritabanı sunucusunun kendi veritabanı dosyaları.

rsync İle Dizinler Arasında Senkronizasyon

Ref: *

Kaynak dizin ile hedef dizin arasında dosyaların senkronizasyonunu sağlar.

  • -r : recursive (alt dizinlerin içerdiği dosyaları da senkronize eder)
  • -v : verbose (transfer edilen dosyaları ve eşleştirme özetini görüntüler)
  • -n : dry-run (dosya geçişini sağlamaz ancak gerçekleşmiş gibi özetler)
  • -a : arşiv kipi
  • -z : Veri taşınırken sıkıştırılarak aktarılır
rsync -anv dir2/ dir1

Dizin adını takip eden bölü işaretinin hikmeti:

# dir2'nin sonundaki bölü işareti, dir2'nin içeriğini gönderir 
# aksi halde dir1 dizinini kendisiyle birlikte kopyalar
$ rsync -anv dir1/ dir2

Ayrıca uzak bilgisayarlar arasında da eşleştirmeyi yapar:

$ rsync -a ~/dir1 kullaniciAdi@uzakMakine:hedef_dizin

-P Anahtarıyla --partial ve --progress anahtarlarının özelliklerini birlikte kullanarak eşleştirmeyi yapar.

$ rsync -a --delete kaynak hedef$ rsync -a --exclude=hariç_tutulacaklar_deseni kaynak hedef$ rsync -a --exclude=HARİÇ*.py --include=DAHİL*.c source destination$ rsync -a --delete --backup --backup-dir=/path/to/backups /path/to/source destination

Sabit ve Sembolik Bağlantılar

Hard Links (Sabit bağlantılar): Sabit bir bağlantıyı, mevcut bir dosya için ek bir ad olarak düşünebilirsiniz. Sabit bağlantılar, iki veya daha fazla dosya adını aynı inode ile ilişkilendirir. Tek bir dosya için bir veya daha fazla sabit bağlantı oluşturabilirsiniz. Farklı bir dosya sistemi veya bölümdeki dizinler ve dosyalar için sabit bağlantılar oluşturulamaz.

Soft Links “symbolic/symlink” (Yumuşak bağlantılar): Windows’taki kısayol gibi bir şeydir. Bir dosya veya dizine dolaylı bir göstericidir. Sabit bağlantıdan farklı olarak, sembolik bir bağlantı, farklı bir dosya sistemi veya bölümdeki bir dosyaya veya dizine işaret edebilir.

$ ln -s tam_fiziki_dosya_yolu sembolik_bağlantı_yolu

Sembolik bağın hedef yolunun üzerine yazmak için -f (--force) argümanı kullanılır.

Windows bilgisayarınızdaki kaynak kodlarınızın olduğu dizini WSL içinde Visual Studio Code ile geliştirme yapmak için açarsanız ciddi bir yavaşlıkla karşılaşacaksınız. Bu dizini WSL içinde sembolik bağlantı ile ev dizininize bağlayabilirsiniz.

$ ln -s /mnt/c/projeler/kod_repo ~/kod_dizini

Bağlantıları kaldırmak için bağlantının adını rm veya unlink ile kaldırabiliriz.

stdin, stdout, stderr

Her işlemin çalışabileceği üç varsayılan akış vardır. Bunlar stdin, stdout ve stderr’dir.

stdin akışı, sürecinize gelen girdiyi işliyor. Örneğin düğme basışları veya > veya | operatörüyle yönlendirilen çıktıları işler.

stdout (standart çıktı) akışı, uygulamanızın çıktısı içindir.

stderr hata mesajları içindir.

Aşağıda ayrıntılı göreceğiz ancak bir değinelim yönlendirilmiş çıktıya.

Bir uygulamanın gerçek sonucundan ayrı olarak hata ve tanılama bilgileriyle çalışmak için yönlendirme (>) ve boru (|) operatörlerini kullanmamıza olanak tanır. > Bir komutun çıktısını bir dosyaya yönlendirmemize izin verirken, 2> ise stderr çıktısını bir dosyaya yeniden yönlendirmemize izin verir.

// std.js // console.log("log ile stdout çıktısı")
// console.error("error ile stderr çıktısı")
process.stdout.write("process.stdout.write log ile stdout çıktısı")
process.stderr.write("process.stderr.write error ile stderr çıktısı")
$ echo "yoksa oluştur ve yaz, varsa üstüne yaz" > cikti.txt
$ cat cikti.txt
yoksa oluştur ve yaz, varsa üstüne yaz
$ echo "yoksa oluştur ve yaz, varsa sonuna ekle" >> cikti.txt
$ cat cikti.txt

Yönlendirme operatörleri olan > ile standart çıktı olan yere yani monitöre değil de cikti.txt adında bir dosya yoksa yaratarak, varsa üstüne yazıyor metni.

Ancak >> operatörüyle bu kez dosyanın üstüne yazmıyor sonuna ekliyor.

Çıktının değil de girdinin yönünü vermek istiyorsak bu kez < karakterini kullanacağız. Aşağıdaki örnekte -s (subject) anahtarı konu bilgisini, sonraki argüman gidecek eposta adresini (To) ve < operatörüyle NewsFlash dosyası iletiye dosya eki olarak eklenir. Burada stdin değeri NewsFlash içeriği olarak mail uygulamasında değerlendirilir.

*nix sistemlerde her şey dosyadır

Linux üstünde her şey bir dosyayla ilişkilidir. Bir programın giriş/input, çıkış/output ve hata çıktıları(varsayılan olarak standart çıktıya yönlüdür) da dosyalarla ilişkilendirilir. Standart girişleri yaptığımız klavye de bir dosya ile ilişkiliyken standart çıktıyı gördüğümüz monitör de bir dosyayla ilişkilidir.

Bir programın standart çıktısı FD1 ile tanımlı file descriptor 1 dosyasına yani monitörün dosya tanımlayıcısına yönelmiştir.

$ ls olanDizin olmayanDizin > out.txt 2> err.txt$ ls olanDizin olmayanDizin > outVeErr.txt  2>&1

> başarılı (stdOut) çıktılarımızı bir dosyaya yazmak için kullanıyoruz.

2> hata (stdErr) çıktılarımızı bir dosyaya yazmak için kullanıyoruz.

2>&1 hata çıktılarımızı başarılı çıktıların dosyasına yazmak için kullanıyoruz.

Biraz Tafsilat…

Hatalı çıktıyla birlikte başarılı çıktıyı verecek şekilde bir komut çalıştıralım:

Önce hata satırını yazdı, sonra başarılı sonuçları. Bir nevi Javascript dilinde kullanılan error first deseni.

  • Standart çıktıyı bir dosyaya yazdıralım
  • Hata çıktısını başka bir dosyaya yazdıralım
  • Her iki çıktıyı (hem standart çıktıyı hem hata çıktısını) aynı dosyaya yazdıralım. Burada dikkat edeceğimiz nokta şudur:
$ ls olanDizin olmayan_dizin > iki_cikti_tek_dosyada  2>&1

2 ile hata çıktılarını >& ile 1 çıktılarını yönlendirdiğimiz yere, yani iki_cikti_tek_dosyada isimli yere yönlendiriyoruz

Son işlemin başarımını veya oluşan hata kodunu görmek için $? komutunu kullanırız

ls komutu başarıyla sonuçlandığı için 0 sonucunu görürken ls -2 komutu hatalı olduğu için 1 kodunu donuyor.

#!/bin/bash# hata olsun diye ls çektik ve hata mesajını boşluğa gönderdik 
# böylece hata sonucu ekran görüntülenmeyecek ve yeni satıra geçecek
ls olmayanDizin 2> /dev/null
if [ $? -eq 0 ]
then
echo "Olmayan dizin/dosya listelenemez"
else
echo "Dosya/dizin varmış" >&2
fi

Eğer hatayı baskılamak istersek

$ cp ./src/*/*.h ./aaa 2>/dev/null || :

log ve error Fonksiyonları

Node.js içinde console.log() ve console.error() fonksiyonlarını ele alalım.

Bu ikisi aynı görünse de, aslında sistem tarafından farklı şekilde ele alınırlar. Node.js belgelerinin konsol bölümünü kontrol ederseniz, console.error stderr kullanırken console.log’un stdout’a yazdırdığını görürsünüz.

console.error([data][, …args]), Prints to stderr with newline.

console.log([data][, …args]), Prints to stdout with newline.

console.info([data][, …args]), The console.info() function is an alias for console.log().

Bir Günlük Kaydının İçeriği

Buraya kadar uygulamanın 3 akışını da inceledik. Şimdi bir çıktı (günlük, log) nasıl olur onu inceleyelim.

  • Timestamp — Günlük kaydına konu işin ne zaman olduğunu bilmek için
  • Computer/Server Name — Günlükler farklı makineler/uygulamalardan toplanıyorsa yani dağıtılmış bir sistemde çalıştırmanız durumunda günlük kaydının kaynağını bilmek için
  • Process IDpm2 gibi bir şey kullanarak birden çok düğüm işlemi (process) çalıştırmanız durumunda hangi işlemin bu kaydı oluşturduğunu bilmek için (Örn. bir uygulama 4 thread koşturup veya aynı makinede 4 farklı uygulama günlük kaydı oluşturuyorsa)
  • Message — Günlük kaydına sebep olan durumun mesaj olarak içeriği
  • Stack Trace —bir hata kaydetmemiz durumunda
  • Belki bazı ek değişkenler/bilgiler

debug

Aşağıdaki örnekte etiket isimlerini debug fonksiyonuna parametre olarak girerek birer nesne alıyoruz.

var debug = require('debug')
// etiket adı: 'modulA:fonkB:log'
const log = debug('modulA:fonkB:log')

Bu nesnelerin .log([…]) metotlarını ya stdOut veya stdErr akışına yönlendirmek için console.log veya console.error metotlarına bağlıyoruz.

const err = debug('modulA:fonkB:error')
err.log = console.error.bind(console);

Artık günlük kaydını attığımızda stdOut ve stdErr akışlarını yönlendirdiğimiz (>) dosyalarda kayıtlarımızı göreceğiz.

Küresel veya yerel ölçekte bu nesneleri oluşturabiliriz.

Ortam değişkenlerinde günlük seviyesini DEBUG anahtarı ile belirleyebiliriz.

Nesnelerin hangi seviyede görüntülenmelerini istiyorsak ortam değişkenlerinde DEBUG_DEPTH anahtarı ile ayarlayabiliriz

https://www.npmjs.com/package/debug#environment-variables

pino

// test_pino-debug.js
// DEBUG=* node test_pino-debug.js
const pino = require('pino');
const logger = pino({
prettyPrint: true,
level: process.env.LOG_LEVEL || 'info'
}, process.stderr);
logger.error('PINO: ERROR seviyesi');
logger.info('PINO: INFO seviyesi');
logger.debug('PINO: DEBUG seviyesi');

LOG_LEVEL ortam değişkenlerinde verilerek çeşitli seviyede çıktıları baskılayabiliriz.

Temel bilgileri bizim için çeker (Bilgisayar adı, İşlem ID, Tarih, Log seviyesi vs.).

const pino = require('pino');
const logger = pino({ level: process.env.LOG_LEVEL || 'info' });
// const logger = pino({ level: process.env.LOG_LEVEL || 'debug' });
logger.debug('debug seviyesinde görünür olacak');
logger.info('info Seviyesi en alt düzeydir. Üst seviyelerde görünür');
var obje = { ozellik: "değer", sayi: 12, dizi: [1, 2, 3] }
logger.info('String: %s, Object: %o', obje, obje);

Ek olarak günlük kaydının debug paketi gibi bir etiketle görüntülenmesini istersek .child({..}) özelliğini kullanabiliriz.

// test_pino.js
// $ node test_pino.js
// $ LOG_LEVEL=info node test_pino.js
const pino = require('pino');
const logger = pino({
prettyPrint: true,
level: process.env.LOG_LEVEL || 'info'
}, process.stderr);
var obje = {
a: 1, b: {
b: 1,
c: {
c: 2
}
}
}
logger.debug('DEBUG seviyesi. String: %s, Object: %o', obje, obje);
function deneme(){
const child = logger.child({ etiket_adi: 'root:deneme' })
child.info('İç günlükleyici INFO seviyesi');
}
deneme()
logger.error('ERROR seviyesi');

pino-debug

debug paketi bir etiket ile günlük kaydı oluşturacak fonksiyonlar yaratır ve ekranda renklendirir.

let log = require(‘debug’)(‘debug-paketi:root:INFO’); log(‘DEBUG Paketi > root:INFO etiketi’);

debug paketi sayesinde çeşitli seviyelerin gösterilmesini DEBUG=express:* gibi bir ortam değişkeniyle etiketi express: ile başlayan günlük kayıtlarını görüntüler. Aşağıdaki örnek süzgeçle sadece üzerinde çalıştığınız modülün (modulA) ilgili kısmındaki (fonkC) tüm günlükleri görebiliyorsunuz.

DEBUG=modulA:*C:* ile etiketi modulA: ile başlayan *C: ile devam eden ve sonrasında * her şey olanları görüntüle

pino-debug ise pino paketinde child metoduyla fazladan girdiğiniz bilgiyi günlük kaydına ekler gibi debug paketinin etiketlerini de {ns: etiket_adı} olacak şekilde uygular. Bunu aşağıdaki gibi yapar ve fazladan debug paketinde bir etiketi console.[error|log|info|trace] fonksiyonlarına bağlama işini çok daha kolay yapar.

const logger = require('pino')()
logger.info('hi!')
// Çıktısı:{"level":30,"time":1531171074631,"msg":"hi!","pid":657,"hostname":"makineAdı"}

Yukarıda normal çıktısını gördüğümüz yapıya fazladan (extra) bilgi ekleyeceğiz ({ns: etiket_adı}):

const child = logger.child({ ns: 'etiket' })
child.info('hey!')
// Çıktısı:{"level":30,"time":1531171082399,"msg":"hey!","pid":657,"hostname":"makineAdı","ns":"etiket"}

Ayrıca hangi etiketli günlüklerin görüntülenmesini ayarlar içinde auto özelliğini true yapınca kodunuzdaki gibi, false yapınca ortam değişkenlerinde DEBUG anahtarına verilen değere göre yapar:

Hangi parçaları bir araya getirerek nasıl bir sonucu oluşturduğunu aşağıdaki gibi görelim ve tafsilatlı anlatımına geçelim:

Biraz ayrıntı…

// test_pino-debug.js
// DEBUG=* node test_pino-debug.js
const pino = require('pino');
const logger = pino({
prettyPrint: true,
level: process.env.LOG_LEVEL || 'info'
}, process.stderr);
logger.error('PINO: ERROR seviyesi');
logger.info('PINO: INFO seviyesi');
logger.debug('PINO: DEBUG seviyesi');
// ek olarak aşağıdaki kod geliyor
//...
var info = require('debug')('root:info');
info("DEBUG: root:INFO etiketi")
var cocukInfo = require('debug')('root:fn:info');
const fn = ()=> cocukInfo("DEBUG: root:fn:INFO etiketi")
fn()

Şimdi pino’nun child özelliği ile kayıtlara etiketmiş gibi bilgi ekleyelim:

const pino = require('pino');
const logger = pino({
prettyPrint: true,
level: process.env.LOG_LEVEL || 'info'
}, process.stderr);
logger.error('PINO: ERROR seviyesi');
logger.info('PINO: INFO seviyesi');
logger.debug('PINO: DEBUG seviyesi');
// debug Paketi ile kayıt oluşturmak
var info = require('debug')('root:info');
info("DEBUG: root:INFO etiketi")
var cocukInfo = require('debug')('root:fn:info');
const fn = () => cocukInfo("DEBUG: root:fn:INFO etiketi")
fn();
// child İle ek özellik ekleyelim
(function () {
console.log('')
const pinoCocukInfo = logger.child({ etiket: 'anonim fn:pino cocuk:info' })
pinoCocukInfo.info("root:anonimFn:INFO seviyesi")
})()

Şimdi pino-debug ile debug paketindeki etiket bilgilerini pino’nun child ile ek özelliği olarak gösterelim.

Referans:

Grup İşlemleri

Grup Yaratmak (groupadd -g <id değeri> <adı>)

$ sudo groupadd yazilimcilar

Grupları /etc/group dosyasında aşağıdaki formda tutuyor.

GrupAdı : x (debian için şifre gizler, freebsd için “şifre yok”) : grupId : gruba üye kullanıcılar (ali,veli, mecnun gibi)

$ grep yazilimcilar /etc/group
yazilimcilar:x:1003:

Sıradaki grup ID değeri 1003 olduğu için otomatik yazilimcilar:x:1003 değeri atanmış.

$ cat /etc/group
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:syslog,ubuntu
tty:x:5:
disk:x:6:
mail:x:8:
irc:x:39:
users:x:100:
systemd-journal:x:101:
systemd-timesync:x:102:
systemd-network:x:103:
systemd-resolve:x:104:
ubuntu:x:1001:
rabbitmq:x:118:
mongodb:x:119:mongodb

Not: Grupların hepsini değil, bir kısmını seçtim.

Dikkat!
Mongo, RabbitMQ gibi uygulamalar kendi gruplarını tanımlamış ve hatta mogoDb kendine bir kullanıcı oluşturmuş mongodb adında ve bu gruba eklemiş.

Dikkat!
Hatta adm ve users gruplarını işletim sistemi oluşturmuş ve içine syslog ve ubuntu kullanıcılarını eklemiş. Bu grupların ID değerleri ne kadar küçük ;)

Kullanıcı Ekleme (userAdd mi, addUser mı?)

Kullanıcının olup olmadığını kontrol etmek için id komutunu -u parametresiyle kullanabiliriz:

useradd, sistemle birlikte derlenen yerel ikili dosyadır (çalıştırılabilir dosya-exe gibi yani-). Ancak adduser, arka planda useradd binary uygulamasını (ikilisini dediğimizde binary -derlenmiş uygulama- düşünebilirsiniz) kullanan bir perl betiğidir. adduser, arka uç kullanıcı eklentisinden daha kullanıcı dostu ve etkileşimlidir (yani şifre, telefon numarası, bina veya oda numarası gibi ek bilgileri (gecos) sorabilir). Eğer bir betik içinde (shell script gibi) kullanacaksanız bu etkileşim işinizi zorlaştırabilir. Örneğin şifre ve diğer bilgileri girmemek için ek parametreler vermeniz gerekir (adduser --disabled-password --gecos "" cem). Sağlanan özelliklerde hiçbir fark yoktur.

adduser/deluser bir perl betiği olduğu için tüm dağıtımlarda bulunmayabilir, (ör. SuSE’de) bu yüzden user[add|del] gibi ikili komutları kullanmak isteyebilirsiniz. ***

Şimdi yazılımcılar grubuna bir kullanıcı ekleyelim. Ama kullanıcının daha önceden yaratılmış olma ihtimaline karşılık kullanıcıyı silelim (varsa ev dizinini de silerek userdel -r) sonra ev diziniyle (--create-home)birlikte kullanıcı yaratalım (useradd -m) sonra kullanıcıya şifre atayalım (passwd) ve en sonunda kullanıcının kullanıcı gruplarını güncelleyelim (birden fazla grup işlemi için -G anahtarı, tek grup işlemi için -g anahtarını kullanırız: usermod -G) :

$ sudo userdel -r cemt
$ sudo useradd -m cemt
$ sudo passwd cemt
$ sudo usermod -G users,yazilimcilar cemt

Bir Kullanıcıyı SUDOERs Grubuna Eklemek

Bir kullanıcı yarattınız ama sudo ile kullanamıyorsunuz çünkü kullanıcı sudo grubuna üye değil.

Eğer kullanıcıyı sudo grubuna ekleyerek en üst seviyede (root seviyesinde) yetkilendirmeyi de eklemek istersek :
$ usermod -aG sudo cemt
-a : append
-G : group
# Kullanıcının üye olduğu grupları listelemek için
$ groups cemt

Kullanıcıya Kabuk Atama

/etc/shells dosyasında sistemki kabukları görüntüleyebiliriz

/etc/shells

/bin/false ve /sbin/nologin Farkı

Bir kullanıcı yaratırken ona kabuk ataması da yapabiliriz. Örneğin kullanıcı giriş yaptığında bash, sh, zsh gibi farklı kabuklar kullanacak şekilde sisteme girişi ayarlanabilir.

Aynı şekilde kullanıcı eğer sisteme giriş yapamaz şekilde ayarlanmak istenirse /sbin/nologin veya /bin/false kabuk olarak ayarlanabilir.

/sbin/nologin kabuk olarak ayarlandığında, o kabuğa sahip kullanıcı oturum açarsa, ‘Bu hesap şu anda kullanılamıyor’ diyen kibar bir mesaj alırlar. Bu mesaj /etc/nologin dosyası ile değiştirilebilir (ubuntu /etc/nologin içindeki yazıyı okudu).

This account is currently not available.

Bu kullanıcı için geçerli bir kabuk ayarlanmadığından, su -l <hesapadi> veya login <hesapadi> ile oturum açmaya çalıştığınız hesap şu anda kullanılamıyor demektir.

/bin/false, ikili dosyası ise false döndürerek hemen çıkan bir ikili dosyadır, bu nedenle, shell olarak false olan biri oturum açtığında, false çıktığında hemen oturumu kapatılır.

/bin/true olarak kabuğu ayarlamak, birinin oturum açmasına izin vermemekle aynı etkiye sahiptir, ancak false, kişinin kabuğunun olmadığı kavramını iletmek için çok daha iyi olduğundan, true yerine bir kural olarak kullanılır.

# docker exec --user cem cubuntu bash

komutu çalıştırıldığında docker bir kullanıcı girişi yapmaz!
Sadece bash komutunu cem kullanıcısıyla çalıştırır.

Kullanıcı girişini: login, ssh, mgetty, gdm komutlarıyla yapabiliriz.

Bu yüzden login ile kullanıcı girişi yaparak /bin/false ile hata üretip giriş yapamadığımızı root kullanıcısına düştüğümüzü yukarıdaki ekran çıktısında görebiliriz.

Kullanıcıyı oluştururken hem ev dizinini hem gruplarını verelim

$ sudo useradd -m -G users,yazilimcilar kodcu
--create-home anahtarının kısa hali -m ve home dizini içinde kullanıcı adıyla aynı dizinini oluşturdu

Kullanıcı yaratıldığında /etc/passwd ve /etc/group içinde izlerini göreceğiz:

$ grep kodcu /etc/passwd
$ grep kodcu /etc/group

$ su <kullanıcı_adı> Komutuyla kullanıcı girişi yapalım ve ev dizinine $ cd ~ komutuyla gidelim. Bulunduğumuz klasörü yazdırmak için $ pwd komutunu kullanalım. Kullanıcımızın kayıtlı olduğu grupları $ groups komutuyla listeleyelim.

vagrant@ubuntu-xenial:/home$ su kodcu
Password:
kodcu@ubuntu-xenial:/home$
kodcu@ubuntu-xenial:/home$ cd ~

kodcu@ubuntu-xenial:~$ pwd
/home/kodcu
kodcu@ubuntu-xenial:~$ groups
kodcu users yazilimcilar

Bir kullanıcının gruplarını ad veya ID değerleriyle listelemek için $ id -G komutunu kullanalım.

$ id -G kodcu

Referanslar

Kullanıcıları Listelemek

$ cat /etc/passwd
$ getent passwd

Ref: linuxize.com

Konsolda Kullanıcı Değiştirmek

Aktif kullanıcı bilgileri için:

$ echo $HOME$ pwd$ echo $USER
ubuntu
$ who
ubuntu tty1 2021-07-29 08:05
ubuntu pts/0 2021-08-11 05:57 (192.168.13.254)
ubuntu pts/2 2021-08-11 06:07 (192.168.13.254)
ubuntu pts/3 2021-08-11 06:48 (10.20.203.140)
$ whoami
ubuntu
$ who am i
ubuntu pts/3 2021-08-11 06:48 (10.20.203.140)
$ w
06:53:25 up 109 days, 17:16, 4 users, load average: 0.08, 1.75, 2.62
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
ubuntu tty1 29Jul21 12days 0.40s 0.20s -bash
ubuntu pts/0 192.168.13.254 05:57 3:51 1.77s 1.77s -bash
ubuntu pts/2 192.168.13.254 06:07 7:29 1.07s 1.07s -bash
ubuntu pts/3 10.20.203.140 06:48 0.00s 0.41s 0.14s w
Şu anki kullanıcının bilgilerini döner id:
$ id
uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),0(root),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),110(lxd)
$ id cem$ groups cem

sudo komutu, root kullanıcısının kerelik veya sınırlı süreli erişimle komutu çalıştırır. Genellikle, bir yönetici komutunu hızlı bir şekilde çalıştırmak ve ardından kullanıcı hesabının normal izinlerine dönmek için sudo komutu kullanılır.

Varsayılan olarak, bazı Linux sürümleri (Ubuntu gibi) root hesabı devre dışı bırakılır. Bu, root kullanıcısına atanmış bir parola olmadığı anlamına gelir. Ancak su - komutu çalıştırarak ve şu anda oturum açmış olan kullanıcının şifresini girerek root’a geçebilirsiniz.

su daha eski ancak daha özellikli bir komuttur. su komutu, geçerli kullanıcıdan başka bir kullanıcıya geçmenizi sağlar. root Kullanıcısından farklı bir kullanıcı olarak komut çalıştırmanız gerekiyorsa, kullanıcı hesabını belirtmek için --login [kullanıcı adı] (veya -l) seçeneğini kullanın. Ek olarak, su, anında farklı bir kabuk yorumlayıcısına geçmek için de kullanılabilir.

$ su -l <geçiş yapılmak istenen kullanıcı adı>
$ login <kullanıcı adı>

--shell (-s) Farklı Kabukta Çalıştırma

su -s /bin/sh -c ‘echo $0’

--login (-l) Farklı Kullanıcıda Çalıştırma

su -l postgres
su -s /usr/bin/zsh -c ‘echo $0; echo $HOME’ -l postgres

––preserve–environment (-p) Ortam Değişkenlerini Korumak

su -s/bin/sh -c ‘echo $0; echo $HOME; echo $DENEME;’ -p postgres
root@f4216b28bfe7:/# su -l postgres
postgres@f4216b28bfe7:~$

Process Yok Etmek (killing processes)

Hem tophem de ps, bir işlemin hangi kullanıcı altında çalıştığını gösterir. topdurumunda, ikinci sütun kullanıcı adını içerir. ps aux ile ilk sütun kullanıcı adını içerir.

top
ps aux

Normal bir kullanıcıysanız, kendi süreçlerinizi (process) öldürebilirsiniz, ancak diğer kullanıcılara ait olanları öldüremezsiniz. Ancak, bir root kullanıcısı tüm işlemleri öldürebilir. root Kullanıcısı olarak çalıştırmak için herhangi bir komuttan önce sudo ekleyebilir veya su yazarak komutu çalıştırabilirsiniz.

Linux’ta, bir süreç öldürüldüğünde, sürece bir “sonlandırma sinyali” gönderilir. Temel Linux sinyallerinin hepsinin bir numarası vardır (1–30+). Birçok farklı sinyal türü olmasına rağmen, çoğunlukla “SIGTERM” ve “SIGKILL” sinyalleri ile ilgileniyoruz. SIGTERM sinyali 15 sayısı ile SIGKILL ise 9 sayısıyla eşleşir.

SIGKILL’in oldukça yıkıcı olduğunu ve süreç sinyalle ne yapmak isterse istesin süreci sonlandıracağını unutmayın.

kill -<durdurma sinyali sayısı> <surec_id>
sleep <kaç saniye bekleyecegiz> &

sleep komutunu & ile devam ettiriyoruz çünkü terminal ile işlemimize devam etmek istiyoruz aksi halde terminal süre doluncaya kadar kullanılmaz olacaktı.

Varsayılan olarak, tüm süreç öldürme komutları, programın çıkmadan önce bazı kodları çalıştırmasına ve böylece “barışçıl (gracefully)” sonlandırılmasına izin veren “SIGTERM” kullanır.

kill -15 637

SIGKILL ile sonlandırdığımızda Killed, SIGTERM ile sonlanınca Terminated mesajı aldığımıza dikkat!

Zombi Process (Zombi Süreçler)

Zombi süreci, ana süreç, içinde yaratılan süreçten önce çıktığında gerçekleşir.

Aşağıdaki kod içinde ana thread hemen çıkarken, fork ile açılmış yan süreç 60 saniye beklemeye alınır. Dolayısıyla ps veya top ile bakıldığında süreç Zombie süreç olarak görünür. Böyle bir süreci öldüremezsiniz çünkü bu sadece tüm süreçler listesindeki bir girdidir ve onunla ilişkili gerçek bir süreci yoktur. Bir süreç sona erdiğinde, linux çekirdeği, bilgiyi etrafta tutmalıdır, böylece ana süreç, alt sürecin görevlerini tamamlayıp tamamlamadığını ve kendi başına sonlandırılıp sonlandırılmadığını veya öldürüldüğünü öğrenebilir. Ebeveyn bunu yapana kadar, bu “zombi” işlemler, işlemler listesinde görünecektir. Böyle bir süreci öldüremezsiniz çünkü bu sadece tüm süreçler listesindeki bir girdidir ve onunla ilişkili gerçek bir süreci yoktur.

Ancak 60 saniye sonra yavru süreç de çıkış yapınca sürecimiz de artık çalışan uygulamalarda görünmez hale gelir.

# cat zombi.c
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main ()
{
pid_t child_pid;
child_pid = fork ();
if (child_pid > 0) {
sleep (60);
}
else {
exit (0);
}
return 0;
}
Z: Zombie, D: kesintisiz uyku (uninterruptible sleep)
$ killall <uygulama adı>Eğer sonlandırma kodunu girmek istersek (-9 : SIGKILL)
$ killall -9 <uygulama adı>
30 dakikadan fazla çalışan çalışan uygulamaları kapatmak:
$ killall -o 30m <uygulama adı>
30 saniyeden az çalışan çalışan uygulamaları kapatmak:
$ killall -y 30s <uygulama adı>
s: saniye
m: dakika
h: saat
d: gün
w: hafta
M: ay
y: yıl

Aynı işi süreç ID değeriyle yapmak istersek kill ve pkill komutlarını kulanabiliriz.

Linux’te Dosya İzinleri

Linux’te Dosya İzinleri

Önce Dosya/Dizin komutlarını öğrenelim:

chmod : yetkilerini değiştirir

$ chmod <yetki> <dosya/dizin>

chown : sahibini değiştirir

$ chown <yeni_sahibin_kullanıcı_adı> <dosya/dizin>

chgrp : yetkili grubu değiştirir

$ chgrp <yeni_sahibin_kullanıcı_adı> <dosya/dizin>

Dosya ve dizinlerdeki yetkiler şunlardır:

  • 0 = : izin mizin yok
  • 1 = x : Çalıştırma (eXecute)
  • 2 = w: Yazma (Write)
  • 3 = r : Okuma (Read)
  • 4 = r — : Okuma ver diğerlerini kaldır
  • 5 = r — x : Okuma ve Çalıştırma ver yazmayı kaldır
  • 6 = rw — : Okuma ve Yazma ver Çalıştırmayı kaldır
  • 7 = rwx : Hepsini ver
https://www.linode.com/docs/tools-reference/linux-users-and-groups/

Bu yetkileri şunlara verir veya alırız:

  • u = User — dosya sahibine
  • g = Gruba
  • o = Other — Diğer kişilere

Yetki verme alma işlemini chmod komutuyla şöyle yaparız:

  • chmod g+w filename > Gruba dosyanın üstüne yazma yetkisi(w) + ver
  • chmod g-wx filename > Gruptan Write ve eXecute yetkisini — kaldır
  • chmod o+w filename > diğerlerine(o) yazma(Write) yetkisi ver
  • chmod o-rwx foldername > dizinde diğerlerinin r,w,x yetkilerini kaldır
  • chmod -rwx fileName> herkesin r,w,x yetkilerini kaldır
  • chmod a-rwx fileName> herkesin r,w,x yetkilerini kaldır

Herkese tam yetki verip, tüm yetkilerini alalım

$ ls cem.txt -l
--------w- 1 vagrant vagrant 18 Jul 15 06:24 cem.txt
$ chmod +rwx cem.txt -v
mode of 'cem.txt' changed from 0002 (-------w-) to 0777 (rwxrwxrwx)
$ ls cem.txt -l
-rwxrwxrwx 1 vagrant vagrant 18 Jul 15 06:24 cem.txt
$ chmod -rwx cem.txt -v
mode of 'cem.txt' changed from 0777 (rwxrwxrwx) to 0002 (-------w-)
chmod: cem.txt: new permissions are -------w-, not ---------
$ ls cem.txt -l
--------w- 1 vagrant vagrant 18 Jul 15 06:24 cem.txt

Gelin şimdi sayılarla yapalım:

$ chmod 0777 cem.txt$ ls cem.txt -l
-rwxrwxrwx 1 vagrant vagrant 18 Jul 15 06:24 cem.txt
$ chmod 2 cem.txt -v
mode of 'cem.txt' changed from 0777 (rwxrwxrwx) to 0002 (-------w-)
$ ls cem.txt -l
--------w- 1 vagrant vagrant 18 Jul 15 06:24 cem.txt
$ chmod 777 cem.txt -v
mode of 'cem.txt' changed from 0002 (-------w-) to 0777 (rwxrwxrwx)
$ ls cem.txt -l
-rwxrwxrwx 1 vagrant vagrant 18 Jul 15 06:24 cem.txt

chroot (UnixV7) — 1979

Herşey aslında bir toz bulutuydu… “chroot” tanıtıldı ve UNIX sistemlere eklendi. Böylece prosesler için dosya sisteminde özgün konumlar oluşturuldu ve proses izolasyonu için ilk adımlar atılmış oldu. Bu teknoloji ile birlikte bir process ve onun alt proseslerini diğer tüm sistemden izole etmek mümkündü. Bunu yapabilmek için kullanılacak kütüphaneler ayrı bir “root directory” altına taşınır ve bu klasör altında çalışırdı. Böylece global sistem etkilenmeden, bu belirlenen ortamda root gibi davranarak istediğinizi yapabilirdiniz. Bununla beraber root process leri kolayca chroot yapılmış ortamdan çıkabiliyordu. Bu nedenle biraz eksik kalmış bir teknolojiydi. Mart 1982'de Bill Joy chroot u Unix v7.0' a koyulmuştur. *

Öncelikle kaynağın sahibini (Gökhan ALKAN, gokhan@enderunix.org) ve bir gün kaynağından (http://www.enderunix.org/docs/chrootnedir.pdf) ulaşılamazsa bu güzel anlatılmış bilgi yine erişilebilir olsun diye kendime de not almak için buraya yapıştırayım.

1. Motivasyon Bu makalede özellikle sunucu servis yazılımlarının ve uygulamaların chroot ortamında çalıştırılması, kademeli güvenlik anlayışı gibi yaklaşımlardan ziyade basit olarak chroot nedir ve neden chroot kullanmak gerekli sorusuna cevap aranmaya çalışılacaktır. 2. Chroot Nedir? Chroot yazılımlar için yeni bir kök (/) dizini tanımlar. Kısaca çalıştırılacak olan servis ya da uygulama için gerekli kütüphane, yapılandırma, sürücü dosyaları (device file), bu servis için belirlenen kök dizinde bulunan ilgili yollara (path) kopyalanır ve hapsedilmiş olarak çalıştırılır. Peki chroot kullanmanın getirdiği avantajlar ve dezavantajlar nelerdir ve neden kullanmak gerekli sorusunu kendinize sormuş olabilirsiniz. Kısaca bu sorunun cevabı, eğer sistem üzerinde chroot ortamında çalışan bir servis ya da uygulamadan kaynaklanan bir açıklığı kullanarak sisteme sızan bir saldırgan, bütün dosya sistemine ve işletim sistemi kaynaklarına erişim sağlayamayacak ve sadece chroot için belirlenen kök dizine ve burada bulunan kaynaklara erişim sağlayabilecektir. Ayrıca kısıtlı dosya sistemi erişimi sağlaması yanında kısıtlı komutlara erişim ile de sistem üzerinde bulunan komutlar kümesine erişim de kısıtlanmış olacaktır. Aşağıdaki şekilde ( Şekil 1 Chroot Kullanımı İle Yeni Dosya Sistemi Hiyerarşisi ) chroot kullanımı ile dosya sistemine erişim şematize edilmiştir.

3. Chroot Nasıl Çalışır?

Chroot komutu ‘chroot /chroot [komut seti]’ şeklinde çalıştırıldığında artık yeni kök dizini olarak ‘/chroot’ görülecektir.

NOT: Burada “/chroot” dizini özellikle belirtilmemiştir. Bu dizin yerine isteğe göre herhangi bir dizin seçilebilir.

# mkdir /chroot 
# chroot /yeni_dizin

Bütün bu işlemler için chroot komutu, chroot sistem çağrısını kullanır. Kısaca önce belirlenen yeni kök dizini içerisine girilir ve arkasından chroot sistem çağrısı çalıştırılır ve son olarak belirlenen kullanıcı kimliğine bürünülerek root kullanıcı haklarından vazgeçilir.

# chdir(“/chroot”); 
# chroot(“/chroot”);
# setuid(500);

NOT: Sistem üzerinde 500 uid’sine sahip bir kullanıcı olduğu varsayılmıştır.

4. Örnek Chroot Ortamının Oluşturulması Daha öncede belirtildiği gibi sadece saldırganın bütün dosya sistemine ve işletim sistemi kaynaklarına erişimi engellenmiş olacaktır. Aşağıda chroot kullanıma basit bir örnek verilmiştir. Bash kabuğu chroot ortamı altında çalıştırılacak ve birkaç örnek komut chroot ortamı altında çalıştırılacaktır.

# mkdir /chroot
# which bash
/bin/bash
#
# cd /chroot
# mkdir /bin
# mkdir /lib
# ldd /bin/bash
linux-gate.so.1 => (0x00712000)
libtermcap.so.2 => /lib/libtermcap.so.2 (0x00c49000)
libdl.so.2 => /lib/libdl.so.2 (0x00c43000)
libc.so.6 => /lib/libc.so.6 (0x00afe000)
/lib/ld-linux.so.2 (0x00ae0000)
#

Bu çıktıya göre bash için gerekli kütüphane dosyaları teker teker belirlenmeli ve ilgili dizinlere kopyalanmalıdır. Hangi kütüphane dosyalarına ihtiyaç olduğu ‘ldd’ komutu aracılığı ile öğrenilebilir.

# cp –p /lib/libtermcap.so.2 /home/ga/chroot/lib
# cp –p /lib/libdl.so.2 /home/ga/chroot/lib
# cp –p /lib/libc.so.6 /home/ga/chroot/lib
# cp –p /lib/ld-linux.so.2 /home/ga/chroot/lib

Ardından chroot komutu ile bash kabuğu chroot olarak belirtilen dizinde çalışmaya başlayacaktır.

Chroot ortamı altında çalıştırılmak istenen komutlar ve bu komutlar için gerekli kütüphane dosyaları ‘ldd’ komutu yardımı ile bulunarak ilgili dizinlere kopyalanmalıdır.

# cp –p /bin/bash /chroot/bin
# cp –p /bin/pwd /chroot/bin
# chroot /chroot/ /bin/bash
bash-3.2# pwd
/
bash-3.2# exit

Görüldüğü gibi ‘pwd’ komutu çalıştırıldığında ‘/chroot’ dizinini kök (/) dizini olarak
görülmektedir. Chroot ortamından çıkmak için ‘exit’ komutu kullanılabilir. ‘pwd’ gibi
çalıştırılmak istenen komutlar gerekli kütüphane dosyaları ile birlikte ilgili dizinlere
kopyalanarak çalıştırılabilirler.
Burada verilen basit bir örnektir. Asıl chroot kullanım amacı dosya sistemi hiyerarşisi
üzerinde dağıtık biçimde erişim sağlayabilen servisler için kullanımı olmalıdır. Bu şekilde
saldırgan, sistem üzerinde çalışan bir servisten ya da uygulamadan kaynaklanan bir açıklık ile
sisteme sızmayı başardığında bütün dosya sistemine erişimi engellenmiş olacaktır.

5. Kaynaklar

Linux Paket Yöneticileri

  1. DEB (Debian, Ubuntu, knoppix)
    DEB dosyaları, Debian tabanlı dağıtımlar için kurulum dosyalarıdır. Ubuntu, Debian’ın APT ve DPKG’ye dayalı paket yönetimine dayanmaktadır.
    Dpkg(Debian Paket Yönetim Sistemi), Debian Linux ailesi için bir temel paket yönetim sistemidir. .deb paketleri hakkında bilgi edinmek, paketleri; yüklemek, kaldırmak için kullanılır.
    APT (Advanced Package Tool-Gelişmiş Paket Aracı), .deb dosyalarının yönetimini sağlayan, çok popüler, ücretsiz, güçlü ve daha çok kullanışlı bir komut satırı dpkg paket yönetim sistemi için bir ön uçtur (dpkg paketin bağımlılıklarını yükleyemezken apt yükleyebilir).
    Synaptic Paket Yöneticisi, apt’nin komutlarını kullanarak kullanıcı arayüzü üstünden işleri yapabilmeyi sağlar
https://wiki.ubuntu-tr.net/index.php?title=Synaptic_Paket_Y%C3%B6neticisi
  1. RPM (Red Hat Paket Yöneticisi)
    RPM dosyaları, Red Hat tabanlı dağıtımlar (Red Hat Enterprise Linux, CentOS ve Fedora) için kurulum dosyalarıdır. APT benzeri YUM (Yellow Dog Update Modifier) paket yöneticisi ile RPM dosyalarının yönetimi sağlanır.
  2. Pacman Paket Yöneticisi — Arch Linux
    Arch Linux ve az bilinen bazı Linux dağıtımları için popüler ve güçlü ancak basit bir paket yöneticisidir, diğer ortak paket yöneticilerinin yükleme, otomatik bağımlılık çözünürlüğü, yükseltme, kaldırma ve yazılım indirme gibi temel işlevlerinden bazılarını sağlar.
  3. Zypper Paket Yöneticisi — openSUSE
    OpenSUSE Linux’ta bir komut satırı paket yöneticisidir ve libzypp kitaplığını kullanır, ortak işlevleri arasında depo erişimi, paket kurulumu, bağımlılık sorunlarının çözümü ve daha fazlası bulunur.
  4. Portage Paket Yöneticisi — Gentoo
    Gentoo için bir paket yöneticisidir. Portage projesinin temel amacı, geriye dönük uyumluluk, otomasyon ve daha pek çok işlevsellik için basit ve sorunsuz bir paket yönetim sistemi oluşturmaktır.

RPM ve DEB biçimlerinin her ikisi de, bazı meta verilerle birlikte kurulum dosyalarını içeren arşiv dosyalarıdır. Hiçbiri yürütülebilir (çalıştırılabilir) dosyalar değilerdir. DEB dosyaları dpkg, aptitude, apt-get ile kullanılır. Rpm dosyaları ise yum ile birlikte kullanılır.

RPM paketi içindeki spec dosyasında, uygulamanın hangi sürümünün yükleneceğini ve çalışması için başka hangi küçük uygulamaların yüklenmesi gerektiği yazılıdır.

DEB dosyası da, tıpkı RPM paketinin spec dosyasına çok benzeyen bir control kontrol dosyasına sahiptir.

dpkg Komutları

list ile get-selections Farkı

--get-selections [<pattern> ...] Get list of selections to stdout.
-l|--list [<pattern> ...] List packages concisely.

Çıktıları arasındaki 5 satır sadece başlık farkıdır.

Yüklü (install) ve kaldırılmak üzere işaretlenmiş (deinstalled) paketleri listeler.

dpkg --get-selections

list de aynı çıktıyı insanın okumasına daha kolay sunar.

dpkg -l

Sadece bir paketi listelemek istiyorsanız -l anahtarına tüm paketin adını veya yıldız karakteriyle içinde geçenleri listeleyebiliriz

Birinci sütundaki karakterlerin anlamları:

İlk karakter: İlk karakter, biz (veya bazı kullanıcılar) paketi kurulum için işaretliyormuş gibi istenen durumu belirtir.

  • u: Bilinmiyor (bilinmeyen bir durum)
  • i: install — Yükle (kurulum için işaretlenmiştir)
  • r: remove — Kaldır (kaldırılmak üzere işaretlenmiştir)
  • p: purge —Temizleme (temizleme için işaretlenmiştir)
  • h: hold — bekle

İkinci Karakter: İkinci karakter kurulu olsun ya da olmasın mevcut durumu ifade eder.

  • n: Not installed — Paket kurulu değil
  • i: installed — Paket başarıyla kuruldu
  • c: Cfg dosyaları — Yapılandırma dosyaları mevcut
  • u: unpacked — Paketlenmemiş- Paket açılmamış halde duruyor
  • f: Failed to remove-cfg — Yapılandırma dosyaları kaldırılamadı
  • h: Half-installed — Paket yalnızca kısmen kurulur
  • W: wait — tetik-bekle
  • t: Tetik-bekleme

Üçüncü Karakter: Bu, hata durumuna karşılık gelir. Olası değer şunları içerir:

  • R: Reinst-required Paket kurulmalıdır.

Paketin Veri İçeriğini Görüntülemek

ar t <paket_adı>

Şimdi paketin (control, data ve metadata kısımlarından) veri içeriğini görüntülemek için -L kullanabiliriz:

Yüklü Dosyanın Hangi Pakete Ait Olduğunu Görüntülemek

-S Anahtarı sayesinde bir dosya veya dizinin hangi paketler tarafından kullanıldığının bilgisini görebiliriz.

dpkg -S <dosya_adı>

Dosyanın hangi pakete ait olduğunu dpkg -S ile, paketin yüklü, kaldırılacak olarak işaretlenip işaretlenmediğini dpkg -l veya apt list <paket> --installed ile görebiliriz

apt list --installed

Bir paketi kurmak için dpkg -i <paketin-yeri> kullanıyoruz ancak paketin tüm bağımlılıklarınında kullanıcı tarafından önceden kurulmuş olması gerekiyor. Paketi uzak sunucudan indiren ve bağımlılıklarını otomatik kuran bir sisteme gerek olduğu için dpkg işimizi görmüyor ve apt kullanıyoruz.

apt-get Kabuk betiğinde kullanıyorsanız

Paketi Belirli Bağımlılıkları Olmadan Kurmak

dpkg --ignore-depends=bar -i foo_1.2.3_amd64.deb

apt-get ile bağımlılıklar hariç kurulum yapmak için bağımlı olduğu paketin sonuna “-” karakteri koyarak aşağıdaki komutu kullanabiliriz:

apt-get install foo bar-

apt Kullanıcı etkileşimli kullanıyorsanız tavsiye edilir.

apt Komutları

apt ile paketi sadece indirmek (kurmadan)

  1. Yöntem bulunduğu dizine indirir
  2. Yöntem apt’nin cache dizinine indirir

apt download <paket-adı>

$ sudo apt download paketi_adı

Paketi indirdiği dizin: ./

apt install --download-only <paket-adı>

$ sudo apt-get install --download-only paketi_adı

Paketi indirdiği dizin: /var/cache/apt/archives

root@3484284873b1:~# apt download wget
Get:1 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 wget amd64 1.17.1-1ubuntu1.5 [299 kB]
Fetched 299 kB in 0s (491 kB/s)
W: Can't drop privileges for downloading as file '/root/wget_1.17.1-1ubuntu1.5_amd64.deb' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied)

Aldığımız hata root kullanıcısı olmamız rağmen ortaya çıkıyor. Bunun sebebi şu bug. Bu yüzden indirme işini apt yerine apt-get üstünden yapıyoruz ancak kurulum yapmak yerine sadece indirme işlemi yapılmış oluyor:

apt-get install --download-only wget
apt-get install — download-only wget

Yükleme tamamlandığında tüm paketler /var/cache/apt/archives dizininde yer alacaklar.

Ref: https://unix.stackexchange.com/

apt-get remove paketAdı/ apt-get remove --purge paketAdı

remove
remove is identical to install except that packages are removed instead of installed. Note that removing a package leaves its configuration files on the system. If a plus sign is appended to the package name (with no intervening space), the identified package will be installed instead of removed.

purge
purge is identical to remove except that packages are removed and purged (any
configuration files are deleted too). **

apt-get remove paketAdı

remove, ikili dosyaları kaldırır, ancak paket yapılandırma veya veri dosyalarını kaldırmaz.

apt-get purge paketAdı, veya apt-get remove --purge paketAdı

Paket adı ile ilgili her şeyi kaldıracak. Özellikle yapılandırmayı bozduğunuz için bir uygulamayla ‘her şeye yeniden başlamak’ istediğinizde kullanışlıdır.

apt search aranan_kelime

“patroni” kelimesini arıyoruz. FULL TEXT SEARCH ile paketlerin tüm metinlerinde arıyor.

systemd

Systemd linux işletim sisteminin en temel öğelerinden biridir. Systemd bir init servisidir. Init kelimesi aslında “initialization” kelimesinden gelmektedir. Bu işlem bilgisayar açılırken başlar ve sistem kapanıncaya kadar çalışmaya devam eder. İşletim sistemi açılırken başlayan ilk işlemdir. Systemd’yi yalnızca bir işlem olarak düşünmek aslında doğru değildir. 2013'de Poettering dediği gibi systemd aslinda bir işlem değil, büyük bir yazılım paketidir ve içinde 69 adet farklı binary bulunur. Systemd Linux’da user space’in ilk işlemidir ve user space’i başlatır. PID olarak 1 alır. Systemd kernel tarafından başlatılır. Şu an günümüzdeki çoğu linux sistemi systemd kullanır. Systemd hakkında ciddi tartışmalar hala devam etmektedir. Bazıları systemd’yi UNIX felsefesine aykırı bulmaktadır.

Systemd’de unit kavramına değinelim şimdi de. Systemd’de unitler sistemin yönetebildiği herhangi bir kaynağa denir. Farklı tip unitler mevcuttur. Genelde bu unitlerin bir kopyası /lib/systemd/system dizininde tutulur fakat sadece bura ile sınırlı değildir. Tüm pathleri görmek için bu komutu çalıştırabilirsiniz:

systemctl show — property=UnitPath

Systemd’in ana görevlerinden biri aslında daemon olmasıdır. Zaten sonunda ki d harfide buradan gelmektedir. Daemon ne dersek ise daemonlar özetle otomatik başlatılan, arka planda çalışıp kullanıcı ile interaktif iletişimde bulunmayan, sürekli çalışan programlardır. Genelde bir olayı beklerler ve o olay olduğunda ona cevap olarak çeşitli işlemler yaparlar.

Systemctl ise systemd servislerini yönetmek, durdurmak, başlatmak ve durumlarını kontrol etmek gibi işlemlerin yapılmasını sağlayan bir komuttur. Systemctl ile systemd servislerini yönetmek çok kolaydır. Makale sonunda temel birkaç systemctl örneğini verdiğim gibi basit kelimeler ile systemd servislerini yönetebilirsiniz.

Systemd ile nasıl linux servisi yaratabiliriz?

O kadar teoriden sonra şimdi de biraz pratik yapma zamanı. Systemd ile nasıl bir linux servisi oluşturabiliriz ona bakalım. Systemd ile servis oluşturmadan önce root kullanıcısına geçmenizi öneririm.

Bu systemd servisim ile bir de docker container’ı çalıştıracağım. Bunun için aşağıdaki docker komutu ile bir docker container’ı olusturalim:

docker run -p=7474:7474 -p=7687:7687 — volume=/home/  user/neo4j/data:/data — name neo4jdocker -d neo4j

Şimdi systemd klasöründe .service uzantılı bir dosya yaratalım.
Bu path’de örnek bir dosya açalım: /etc/systemd/system/neo4j.service

Eğer root yetkileri olmadan normal kullanıcı ile de bu servisi başlatmak istiyorsanız aşağıdakine benzer bir dizinde kullanabilirsiniz.

$HOME/.config/systemd/user/neo4j.service

Örnek service dosyamız:

[Unit]
Description=neo4j Container
Requires=docker.service
After=docker.service[Service]
Restart=always
ExecStart=/usr/bin/docker start -a neo4jdocker
ExecStop=/usr/bin/docker stop -t 3 neo4jdocker[Install]
WantedBy=local.target

Daha sonra bu komut ile servisi başlatalım:

sudo systemctl start neo4j.service

sistem açılışında otomatik başlaması içinse;

sudo systemctl enable neo4j.service

Servisin durumunu görmek için;

sudo systemctl status neo4j.service

Burada önemli olan bir husus her zaman full dizin kullanmalısınız. Yani /usr/bin/docker yerine sadece docker yazamazsınız. Şimdi servis dosyamızda ki her bir bölümü ayrı ayrı inceleyelim.

İlk kısımda unit’in kendisine ait özelliklere ve onun bağımlılıklarına yer veriyoruz. Bu kısımda description ekleyebiliriz. Description’da bu unit’i tanımlayacak bir cümle yazabilirsiniz. Daha sonra “after” geliyor. Burada ise bizim unit’imizin hangi servislerden sonra başlatılacağını belirtiyoruz. Bizim servisimiz docker ile çalıştığı için ön şart olarak docker koyuyoruz. Burada koyabileceğimiz diğer seçenekler ise Requires ve Wants. After ile sadece belirtilen servisin başlayıp başlamadı kontrol edilir eğer belirtilen servis başlamış ise bizim servisimizde başlatılacaktır. Fakat requires ve want seçenekleriyle ayrıyetten bir tetikleme gerçekleştirebiliriz. Bu iki seçenek de belirttiğimiz servisleri otomatik olarak tetikleyecektir. Bu ikisinin farkı ise birinde zorunluluk varken bir diğerinde yoktur. “Requires”da belirttiğimiz servis başlamaz ise bizim servisimizde başlamayacaktır fakat “wants”da soft dependency vardır yani eğer belirttiğimiz servis başarısız dahi olsa yine de bizim servisimiz tetiklenecektir.

Şimdi de servis kısmını açıklayalım. Servis kısmında daha çok unit başladığı anda hangi komutların çalıştırılacağına dair bilgileri koyarız. ExecStart komutu ile servisimiz başladığı anda hangi komutun çalıştıracağını belirtiriz, ExecStartPre veya ExecStartPost seçeneklerini de koyabiliriz, yine bunlara benzer olarak ExecStop ile servis durdurulduğu anda hangi komutun çalıştırılacağı, ExecReload ile servis yenilendiği anda hangi komutun çalıştırılacağını belirtebiliriz.

Bunlara benzer daha bir çok parametre var. Bunların hepsini türkçeye çevirmeye üşendiğim için aşağıda referans olması amacı ile bir makale paylaşacağım. Ayrıca daha detaylı bilgi için aşağıdaki komutu da çalıştırabilirsiniz:

man systemd.service

Systemd targets

Eski init sistemlerde kullanılan runlevel mantığı systemd ile yerini “systemd targets” isimli konsepte bırakmış bulunuyor. Bu “systemd targets”lar .target uzantılı unit dosyalarında tanımlanır. Bunların yaptığı iş, servisleri gruplandırarak hangi servis unit’lerinin hangi çalışma modunda çalıştığını belirlemektir.

Öntanımlı target’ın hangisi olduğunu görüntülemek:

# systemctl get-default
systemctl get-default

Sistemdeki tüm target’lerı görüntülemek:

# systemctl list-units --type target

Eğer default target’ı değiştirmek isterseniz aşağıdakine benzer bir komut kullanabilirsiniz:

# systemctl set-default multi-user.target

Örnek systemctl Komutları

enable ettiğiniz hizmet, bilgisayarı reboot ettiğinizde otomatik başlatıyor olacak. disable ettiğinizde ise artık bilgisayarı restart ettiğinizde çalışmıyor bulacaksınız.

*.service Dosyasını bir yerlerde anlattığım hizmet dizinlerinden birinde oluşturduğunuzda hizmetleri listelediğinizde (systemctl list-units --type=service --all) göremezsiniz. Ancak enable ettiğinizde göreceksiniz. Ama hizmeti başlatmak için start komutu vermeniz yeterli. Sistemi tekrar başlattığınızda (restart, reboot, halt ne derseniz artık) yine çalışmıyor bulacaksınız (ta ki enable edinceye değin).

Bir servisi başlatmak için;

sudo systemctl start application.service

Bir servisi durdurmak için;

sudo systemctl stop application.service

Bir servisi yeniden başlatmak için;

sudo systemctl restart application.service

Bir servisi etkin hale getirmek ve devre dışı bırakmak için:

sudo systemctl disable application.service
sudo systemctl enable application.service

enable, belirtilen birimi ilgili yerlere bağlar, böylece otomatik olarak önyükleme sırasında veya ilgili donanım takıldığında veya birim dosyasında belirtilenlere bağlı olarak diğer durumlarda başlar.

MariaDB’yi ilk kurduğunuzda, systemctl’i çalıştırıp mariadb.service’i etkinleştirmeniz (systemctl enable mariadb.service) işletim sisteminizin önyüklemesinde servisinizin başlatılmasını sağlar.

MariaDB’yi başlatmak için systemctl start mariadb.service’i çalıştırmak veya sadece sisteminizi yeniden başlatmak (reboot) isteyebilirsiniz.

Devre dışı bırakmak için artık önyüklemede başlamaması için systemctl’yi disable ile çalıştırın mariadb.service’i devre dışı bırakın.

Bir servisin durumunu kontrol etmek için;

systemctl status application.service

Bütün servisleri listelemek için;

systemctl list-units --type=service --all

Bir servisin ayrıntılarını görmek için;

systemctl cat application.service
veya
systemctl show application.service

Systemd hakkında öğrenilecek ve yazacak çok fazla şey var, daha fazla şey öğrendikçe bu yazımı güncelleyip sizlerle paylaşacağım.

Berk Karabacak’ın artık google önbelleğinden erişilebilen makalesidir.

Okuması faydalı kaynaklar;

https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files
https://wiki.archlinux.org/index.php/systemd
https://www.freedesktop.org/software/systemd/man/systemd.service.html

history İşlemleri

history ile bash üstünde koşturduğumuz komutları listeliyoruz.

Eğer history’den bir komutu çağırmak istersek yukarı/aşağı oku kullanıyoruz. Ama sıra numarasını kullanarak doğrudan komutu çalıştırabiliriz: $ !SıraNo

Eğer listeden atmak istediğimiz bir aralık varsa history -d <sıra numarası> komutunu çalıştırıyoruz.

$ for line in $(seq 683 700)
> do
> history -d 683
> done

Başka bir örnek:

Türkçe Linux kaynak olarak çok güzel bir hazine: http://www.enderunix.org/docs/

Linux, kernel versiyonunu öğrenmek

hostnamectl

WSL içinde PID 1 olarak init çalışmadığı için çalışmıyor
Konteyner içinde PID 1 olarak init çalışmadığı için çalışmıyor
Ayrıca dbus paketinin kurulması da gerekiyor hostnamectl’in çalışması için

/etc/os-release

İşletim sistemi, versiyonu öğrenmek için:

$ cat /etc/os-release
$ lsb_release -a

Ayrıca bilgisayar adını öğrenmek ve değiştirmek için:

$ hostnamectl

Linux Kernel’in versiyonunu öğrenmek için:

$ uname -r
$ cat /proc/version

CPU Bilgileri

İşlemcimizin mimarisine dair bilgi edinmek için lscpu komutunu çalıştıralım

$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 16
On-line CPU(s) list: 0-15
Thread(s) per core: 1
Core(s) per socket: 1
Socket(s): 16
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 42
Model name: Intel Xeon E312xx (Sandy Bridge, IBRS update)
Stepping: 1
CPU MHz: 1995.174
BogoMIPS: 3990.34
Virtualization: VT-x
Hypervisor vendor: KVM
Virtualization type: full
L1d cache: 32K
L1i cache: 32K
L2 cache: 4096K
L3 cache: 16384K
NUMA node0 CPU(s): 0-15
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology tsc_known_freq pni pclmulqdq vmx ssse3 cx16 pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx hypervisor lahf_lm ibrs ibpb kaiser tpr_shadow vnmi flexpriority ept vpid xsaveopt arat

İşlemci bilgilerini tutan dosya /proc dizini altında cpuinfo dosyasında saklıdır:

$ ll /proc/cpuinfo
-r--r--r-- 1 root root 0 Jan 15 22:38 /proc/cpuinfo

İçeriğini okumak için:

$ cat /proc/cpuinfo

En basit haliyle 16. işlemci çekirdeğinin bilgilerini aşağıdaki gibi alabiliriz:

processor       : 15
vendor_id : GenuineIntel
cpu family : 6
model : 42
model name : Intel Xeon E312xx (Sandy Bridge, IBRS update)
stepping : 1
microcode : 0x1
cpu MHz : 1995.174
cache size : 16384 KB
physical id : 15
siblings : 1
core id : 0
cpu cores : 1
apicid : 15
initial apicid : 15
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology tsc_known_freq pni pclmulqdq vmx ssse3 cx16 pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx hypervisor lahf_lm ibrs ibpb kaiser tpr_shadow vnmi flexpriority ept vpid xsaveopt arat
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit
bogomips : 3990.34
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management:

Her soketin çekirdekleri için aynı bilgi dönecektir. Eşsiz değerleri elde etmek için uniq uygulamasına pipe ile bağlıyoruz.

Bilginin belirli bir kısmını çekmek için:

---> üretici bilgisi 16 çekirdek için aynı olduğundan eşsizi çekelim
$ cat /proc/cpuinfo | grep 'vendor' | uniq
vendor_id : GenuineIntel
$ cat /proc/cpuinfo | grep 'model name' | uniq
model name : Intel Xeon E312xx (Sandy Bridge, IBRS update)
$ cat /proc/cpuinfo | grep processor | wc -l
16
$ cat /proc/cpuinfo | grep 'core id'
core id : 0
core id : 0
core id : 0
core id : 0
core id : 0
core id : 0
core id : 0
core id : 0
core id : 0
core id : 0
core id : 0
core id : 0
core id : 0
core id : 0
core id : 0
core id : 0

Ayrıntılı işlemci bilgisi:

$ sudo dmidecode --type processor
[sudo] password for jenkins:
# dmidecode 3.0
Getting SMBIOS data from sysfs.
SMBIOS 2.8 present.
Handle 0x0400, DMI type 4, 42 bytes
Processor Information
Socket Designation: CPU 0
Type: Central Processor
Family: Other
Manufacturer: QEMU
ID: A1 06 02 00 FF FB 8B 0F
Version: pc-i440fx-zesty
Voltage: Unknown
External Clock: Unknown
Max Speed: 2000 MHz
Current Speed: 2000 MHz
Status: Populated, Enabled
Upgrade: Other
L1 Cache Handle: Not Provided
L2 Cache Handle: Not Provided
L3 Cache Handle: Not Provided
Serial Number: Not Specified
Asset Tag: Not Specified
Part Number: Not Specified
Core Count: 1
Core Enabled: 1
Thread Count: 1
Characteristics: None
Handle 0x0401, DMI type 4, 42 bytes
Processor Information
Socket Designation: CPU 1
Type: Central Processor
....

lshw

lshw, bir bilgisayarın donanım yapılandırması hakkında derinlemesine bilgi toplamak için minimal bir araçtır. Donanım sınıfını, bu durumda CPU’yu seçmek için -C seçeneğini kullanabilirsiniz:

Referans: https://www.tecmint.com/check-linux-cpu-information/

inotify-tools İle Dizin ve Dosya İzleme

inotify-tools paketi kurulduktan sonra betik olarak dizin takip edilebilir. Komut olarak kullanılabilen argümanlardan --monitor sayesinde sürekli itibarde ilgili dizini takip eder. --daemon Argümanı da --monitor gibi çalışır ancak arka planda çalışır.

Süzebileceğiniz olaylar:

Events:
access : dosya/dizin içerikleri okundu
modify : dosya/dizin içerikleri yazıldı
attrib : dosya/dizin özellikleri değiştirildi
close_write : yazılabilir kipte açıldıktan sonra dosya/dizin
kapatıldı
close_nowrite : salt okunur kipte açıldıktan sonra dosya/dizin
kapatıldı
close : dosya/dizin, okuma/yazma kipine bakılmaksızın kapalı
open : dosya veya dizin açıldı
moved_to : dosya veya dizin izlenen dizine taşındı
moved_from : izlenen dizinden taşınan dosya veya dizin
move : izlenen dizine veya dizinden taşınan dosya veya
dizin
create : izlenen dizinde oluşturulan dosya veya dizin
delete : izlenen dizinde silinen dosya veya dizin
delete_self : dosya veya dizin silindi
unmount : bağlanmamış dosya veya dizini içeren dosya sistemi

Bir Dosyayı İzlenen Dizine ve Dışına Taşımak

Başka bir konsoldan cem dosyasını /tmp dizinine taşıyoruz: mv /cem /tmp

# inotifywait /tmp
Setting up watches.
Watches established.
/tmp/ MOVED_TO cem

Aynı şekilde /tmp dizininden cem dosyasını taşıyoruz: mv cem ..

# inotifywait /tmp
Setting up watches.
Watches established.
/tmp/ MOVED_FROM cem

touch & echo İle Bir Dosya Oluşturmak

Başka bir konsolda /tmp# touch deneme

/# inotifywait --monitor /tmp
Setting up watches.
Watches established.
/tmp/ CREATE deneme
/tmp/ OPEN deneme
/tmp/ ATTRIB deneme
/tmp/ CLOSE_WRITE,CLOSE deneme

Başka bir konsolda /tmp# echo aaa > dene

/# inotifywait --monitor /tmp
Setting up watches.
Watches established.
/tmp/ CREATE dene
/tmp/ OPEN dene
/tmp/ MODIFY dene
/tmp/ CLOSE_WRITE,CLOSE dene

Varolan Dosyanın İçeriğini Değiştirmek

/tmp/ MODIFY dene
/tmp/ OPEN dene
/tmp/ MODIFY dene
/tmp/ CLOSE_WRITE,CLOSE dene

echo ile dosya içeriğine ekleme yaptığımızda: /tmp# echo bbb >> dene

/tmp/ OPEN dene
/tmp/ MODIFY dene
/tmp/ CLOSE_WRITE,CLOSE dene

Dizini Listelediğimizde

ls -al komutuyla listeleyelim:

/tmp/ OPEN,ISDIR
/tmp/ ACCESS,ISDIR
/tmp/ ACCESS,ISDIR
/tmp/ CLOSE_NOWRITE,CLOSE,ISDIR

Varolan Dosyayı Sildiğimizde

/tmp/ DELETE dene

Yeni Dizin Oluşturduğumuzda

mkdir yeni Komutu çalıştığında çıktı:

/tmp/ CREATE,ISDIR yeni

--parents Anahtarıyla Dizinler Oluşturduğumuzda

mkdir --parents yepis/yeni/bir/dizin komutuyla:

/tmp/ CREATE,ISDIR yepis
/tmp/ OPEN,ISDIR yepis
/tmp/ CLOSE_NOWRITE,CLOSE,ISDIR yepis

Bash Betiği İle Sürekli Takip Etmek

#!/bin/bashunset IFS       # varsayılan olarak boşluk, tab ve yeni satırdır
set IFS = "\t" # \t ile ayıracağız çünkü değişkenlere atamak gerek
# sürekli takip için --monitor
# sadece close_write olayını süzüyoruz (dosya içerik işlemi)
# /tmp ve /root dizinlerini izleyeceğiz
inotifywait --monitor -e close_write \
/tmp/ /root/ \
2</dev/null |&
# inotify'ın ürettiği satırı değişkenlere böleceğiz
# çıktı: /tmp/ CLOSE_WRITE,CLOSE dene
# \t ile bölerek ilki dizin, ikincisi işlem, sonuncusu dosya olacak
while read -r dir op file
do
echo "ADIM: $step, DIZIN: $dir, DOSYA: $file, ISLEM: ${op}"
[[ "${dir}" == '/tmp/' && "${file}" == *.txt ]] &&
echo "$file $dir $op."
[[ "${dir}" == '/root/' && "${file}" == YEDEK*.txt ]] &&
echo "root dizinine yedek dosya geldi gibi"
[[ "${dir}" == '/tmp/' && "${file}" == SHUT ]] && break ((step+=1))
done

Komut: /tmp# echo hadi >> metin.txt
Çıktı:

ADIM: 2, DIZIN: /tmp/, DOSYA: metin.txt, ISLEM: CLOSE_WRITE,CLOSE
metin.txt /tmp/ CLOSE_WRITE,CLOSE.

Komut: /tmp# echo hadi >> /root/YEDEKhede.txt
Çıktı:

ADIM: 3, DIZIN: /root/, DOSYA: YEDEKhede.txt, ISLEM: CLOSE_WRITE,CLOSE
root dizinine yedek dosya geldi gibi

Yerel DEB (repo) Havuzu Oluşturma

1. apt-mirror Yöntemiyle

Önce apt-mirror ile bir debian paket havuzunu makinemize çekelim ve diğer sunucularımızın güncellemeler için uzak makinelere gitmesini engelleyip, internet yükümüzü azaltmayı sağlayalım.

Önce apt-mirror paketini indirip ayarlarını yapalım

$ apt install -y apt-mirror
$ sudo vim /etc/apt/mirror.list

Paketlerin yolu olarak /repo/apt-mirror dizinini verelim:

apt-mirror’ın aynalayacağı debian reposunu ada end config satırının altına yazıyoruz.

Sonuç olarak mirror.list dosyamız:

Şimdi apt-mirror’ı çalıştırarak paketleri 20 thread açarak indirmeye başlayalım:

Paketleri Sunmak

Dosya yolu vererek file:// protokolüyle diğer sunucuların bu paket havuzuna ulaşmasını sağlayabiliriz ama Apache internet sunucusu ile bunu sağlayalım

Artık deb repo olarak kendi makinamızı gösterip güncelleyebiliriz:

/etc/apt/sources.list
$ apt update

Bir paket yüklemek istediğimizde

2. Paket Havuzu Yöntemiyle

Ref: *, *

İkili paketler, .deb ile biten bağımsız dosyalardır. Her zaman katı bir adlandırma kuralını izlerler: paket-adı_versiyon_mimari.deb.

  • Paket adı yalnızca küçük harf, rakam ve birkaç noktalama karakteri içermelidir. Asla bir alt çizgi içeremez(büyük I karakteri de sorun çıkarabilir).
  • Sürüm, yukarı akış kaynağının sürümünü ve Debian paketinin sürümünü bir tire ile ayrılmış olarak gösterir.
  • Mimari, işlemci tipini (ve Hurd paketleri için işletim sistemini) gösterir. Paket derlenmiş çalıştırılabilir dosyalar içermiyorsa all mimarisine sahip olacaktır.
  • Debian paketi olan ikili dosya esasen bir arşiv dosyasıdır ve açıldığı vakit 3 temel bileşenden oluştuğu görülür:
  • 1. debian-binary
  • 2. control.tar.gz paket için “kontrol” bilgisini içeren sıkıştırılmış bir tarball.
  • 3. data.tar.gz kök dizine göre paketin içeriğini içeren bir sıkıştırılmış tarball.

Bir Debian deposu birkaç sürüm (release) içerir. Debian sürümleri, “Oyuncak Hikayesi” filmlerinin (wheezy, jessie, stretch, …) karakterlerinden sonra adlandırılır. Kod adlarının suites olarak adlandırılan takma adları vardır (stable -kararlı-, oldstable -eski kararlı-, testing -test etme-, unstable -kararsız). Bir sürüm birkaç bileşene (components) bölünmüştür. Debian’da bunlar main, contrib, non-free olarak adlandırılır ve içerdikleri yazılımın lisans koşullarını belirtir. Bir sürümde ayrıca çeşitli mimariler (amd64, i386, mips, powerpc, s390x, …) ve kaynaklar ve mimariden bağımsız paketler için paketler bulunur.

Sources.list dosyasındaki bir girdinin yapısı
Her sürüm aynı dizin yapısına sahip olacaktır

The base can be http:, ftp: or file: URI.

The distribution is usually stable, frozen or unstable for official Debian releases, but it can be anything. The distribution may specify multiple directory levels.

kararsız dağıtımı, aktif olarak geliştirme sürecinin yaşandığı dağıtımdır. Bu dağıtım genelde, geliştiriciler ve bu çerçeveye dahil olanlar tarafından kullanılmaktadır.

test dağıtımı, henüz kararlı dağıtıma girmemiş paketlerin bulunduğu dağıtımdır. Bu paketler kararlı dağıtıma girmek için beklemektedir. Bu dağıtımı kullanmanın en büyük avantajı ise, yazılımların güncel sürümlerini sunmasıdır. *

The component is usually main, contrib or non-free in official Debian releases. Other common components are local (for internal use only) and unofficial (for distribution). Again, this string can be anything.

Flat Repository Format *

Öncelikle Düz Depo Formatını anlamak için bir özet yaparak inceleyelim ve sonrasında tafsilatlı kurulumuna geçeceğiz

deb uri directory/

Yani: Apache ile http veya https protokolü üzerinden deb paketlerinin sunumunu sağlamak isteriz. Apache kurulduğunda varsayılan olarak /usr/local/apache2 dizinini sunucunun varsayılan kök dizin olarak httdp.conf içinde tayin etmiştir.

Apache ayarları içinde istekleri karşılayacak dizin tayini varsayılan olarak şu şekilde yapılmıştır:

DocumentRoot "/usr/local/apache2/htdocs"
<Directory "/usr/local/apache2/htdocs">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>

Bu dizin yapısı yerine aşağıdaki dizin yapısını kullanmak için httpd.conf içine şu ekleyemi yapalım:

Buna göre http://localhost/repos/apt/debian isteğini /srv/repos/apt/debian dizinine yönlendiriyor.

Alias /repos/apt/debian /srv/repos/apt/debian<Directory "/srv/repos/">
Options Indexes FollowSymLinks Multiviews
Require all granted
</Directory>

Artık bu dizin içinde a ve b adında dizinler yaratıp içlerine çeşitli deb paketleri kopyalayarak Packages dosyasını oluşturmak için dpkg-scanpackages komutunu çalıştıralım.

Eğer makinanızda dpkg-scanpackages uygulaması yoksa dpkg-dev paketini yüklemeniz gerekiyor

# apt install dpkg-dev
dpkg-scanpackages -m b /dev/null > ./b/Packages

Şimdi istemcide /etc/apt/sources.list dosyasında aşağıdaki değişikliği yapalım ve apt update ile paket bilgilerini çekerek bakalım.

deb [trusted=yes arch=amd64] http://localhost/repos/apt/debian/ b
apt update ile paket bilgilerini çekelim

Paketleri sorgulamak için apt list veya apt show komutlarını kullanabiliriz:

apt list cem

apache2 Docker sürümünü kuralım.

# apache ayarlarını docker'dan çekerek host makineye aktaralım 
# belki üstünde değişiklik yaparak sürekli bu halini kullanırız
c:\> docker run --rm httpd:2.4 cat /usr/local/apache2/conf/httpd.conf > httpd.conf# Eğer sitelerin olduğu dizini (htdocs) host makineden bağlamak istersek tıpkı httpd.conf gibi -v anahtarı kullanırız# Docker içinde 80 portunda koşacak ama host 90 portundan bağlanacakc:\> docker run --privileged -dit --name myapache -p 90:80 -v "%cd%":/usr/local/apache2/htdocs/ -v "%cd%"/httpd.conf:/usr/local/apache2/httpd.conf httpd:2.4

Konteynere terminalimizi bağlayarak deb repo oluşturmakta kullanacağımız paketi kuralım:

c:\> docker exec -it myapache bash
root@myapache:/usr/local/apache2# apt-get install dpkg-dev -y

Artık hazırız!

Ana dizinimiz apache’nin web sayfalarını tuttuğu htdocs dizini. Apache’nin ayar dosyasıyla oynamak istemediğim için bu dizini tercih ettim.

cd /usr/local/apache2/htdocs

Deb paketlerini, mimarilerine göre (32 bit uygulama paketleri için i386, 64 bit uygulama paketleri için amd64 isimli dizinleri gibi paketin çalışacağı işlemci mimarisine göre farklı dizinler oluşturacak şekilde) ./debs dizininde yeni dizinler oluşturup deb paketlerini bu dizinlere koyacağız.

# pwd
/usr/local/apache2/htdocs/debs
# tree
.
|-- amd64
| |-- Packages.gz
| |-- cem.0.8.0.20.400-debug.deb
| |-- cem.0.8.0.20.500-debug.deb
| |-- cem.0.8.0.21.100-debug.deb
| |-- cem.0.8.0.21.200-debug.deb
| |-- cem.0.8.0.21.deb
| `-- wget_1.20.1-1.1_amd64.deb
`-- wget
|-- DEBIAN
| |-- conffiles
| |-- control
| `-- md5sums
|-- etc
| `-- wgetrc
`-- usr
|-- bin
| `-- wget

wget’in deb dosyasını indirdim ve wget adında bir dizine açtım.

  • Artık control dosyasındaki versiyon bilgilerini değiştirerek aynı paketi sürekli derleyip yeni versiyonlar üretebilirim.
  • Bu versiyonları dpkg-scanpackages --multiversion . /dev/null | gzip -9c > amd64/Packages.gz komutuyla tarayıp endeks dosyası olan sıkıştırılmış Pacakges.gz dosyası oluşturabilir
  • apt show cem -a ile listeleyebilirim.
# cd /usr/local/apache2/htdocs/debs/amd64
#apt download wget
# cd /usr/local/apache2/htdocs/debs
# dpkg dpkg-deb -R amd64/wget_1.20.1-1.1_amd64.deb wget
# nano wget/DEBIAN/control

Paketin adı wget idi ve onu cem ile değiştirdim. Sanki yeni versiyonlar oluyormuş gibi sürekli versiyon bilgisini değiştirip wget dizininden paket oluşturdum.

# dpkg-deb -b ./wget ./amd64/cem.0.8.0.19.800-debug.deb

Şimdi 64 bitlik yazılımların olduğu amd64 dizindeki deb dosyalarını tarayıp endeks oluşturalım ve yine aynı dizinde Packages.gz dosyasına bu endeksi yazalım (32 bit uygulamalar için i386 dizinine giderek aşağıdaki komutu ...| gzip -9c > i386/Packages.gz olacak şekilde çalıştırın):

# cd /usr/local/apache2/htdocs/debs/amd64
# dpkg-scanpackages -m . /dev/null | gzip -9c > amd64/Packages.gz

Yukarıdaki kısımda control dosyasını düzenlemek ve paket oluşturmak, paketlerin endeksini oluşturmak için komutları yazarsak:

# yap versiyon bilgisindeki değişikliği
Package: cem
Version: 0.8.0.230.debug
Architecture: amd64
...
# sonra kaydet, çık
$ nano wget/DEBIAN/control
# sonra
# 1. paket haline getir (ismi de farklı olsun ki
# diğer paketlerle aynı dizinde yer alabilsin)
# 2. paketleri tara ve endeks oluştur
$ dpkg -b wget amd64/cem.0.8.0.230.debug.deb && dpkg-scanpackages --multiversion ./amd64 /dev/null | gzip -9c > ./amd64/Packages.gz

Artık istemci makinemizde ayar yapabiliriz. İstemciden kastımız paket havuzuna paket yöneticisi komutları (apt-get list, yum install vs.) çalıştıracağımız makine.

Önce kurduğumuz paket havuzunun adresini /etc/apt/sources.list dosyasına ekleyelim. Biraz inceleyelim:

  • paket kaynakları çeşitli olabilir (file, cdrom, http, ftp, copy gib) burada http’yi seçiyoruz. Aynı makinede hem paketleri hem apt’yi çalıştıracağımız için file da olabilirdi (file:/usr/local/apache2/debs/amd64 gibi).
  • https yerine http://… diye istek yapacağımız için [trusted=yes] diye yazıyoruz,
  • İstemci olarak, bu ayarı yaptığımız makine 64 bitlik uygulamaları kurabileceğimiz bir makine. Bu yüzden amd64/ diye sonuna ekliyoruz.
  • Kılavuzda deb [ options ] uri suite [component1] [component2] […] şekliyle seçimli özellikleri köşeli parentez içinde belirtiyoruz. Mimari için [arch=x,y,z] birden fazla mimariyi seçebiliriz. Örneğin x86–64 mimarilerini destekleyen bir komut kümesine sahip işlemcimiz olabilir. [trusted=yes] ile Release dosyası imzalanmasa veya imza kontrol edilemese bile bu kaynaktan gelen paketlerin her zaman kimlik doğrulamasının yapıldığını gösterecek şekilde ayarlanabilir.
deb [trusted=yes] http://localhost/debs/ amd64/veya hem mimari hem de imzasız paketler için (araya bir boşluk)deb [trusted=yes arch=amd64] http://localhost/debs amd64/

Şimdi repodan son paketleri çekmek için apt update komutunu çalıştırdığımızda amd64 paketlerinin listesini çekecek. Sonra paketimizi hem show hem list argümanlarıyla sorgulayalım.

# apt update
# apt show wget
# apt show cem -a
# apt list cem -a

En son 0.8.0.19.800-debug versiyonunu oluşturduk ve versiyon sıralamasına göre en altta gösterdi.

Tüm işlemleri hızlıca görelim:

# yap versiyon bilgisindeki değişikliği
Package: cem
Version: 0.8.0.230.debug
Architecture: amd64
...
# sonra kaydet, çık
$ nano wget/DEBIAN/control# sonra
# 1. paket haline getir (ismi de farklı olsun ki
# diğer paketlerle aynı dizinde yer alabilsin)
# 2. paketleri tara ve endeks oluştur
# 3. Hem deb sunucu hem istemci olarak aynı makine kabul edelim
# ve paket listesini güncelleyip, paketi arayalım
$ dpkg -b wget amd64/cem.0.8.0.230.debug.deb && dpkg-scanpackages --multiversion ./amd64 /dev/null | gzip -9c > ./amd64/Packages.gz && apt update && apt list cem -a

Ref: *

Hata giderme: Packages with multiple instances but no --multiversion specified

Ref: **

cem İsimli paketten birden fazla versiyon (sürüm) mevcut ve eğer -m veya --multiversion anahtarları ile taramayı gerçekleştirmezsek sadece bir paketi girdi olarak görebiliriz:

6 Sürüm cem paketi ve 1 sürüm wget paketini sadece 2 girdi olacak şekilde paketler dosyası oluşturdu. Paketleri listelemek istediğimizde sadece 1 tane sürümünü görebileceğiz:

apt list cem -a

Ama -m anahatarıyla tüm sürümleri paketledi:

# dpkg-scanpackages -m . /dev/null | gzip -9c > amd64/Packages.gz

Şimdi tüm sürümlerini listede görebiliriz:

Ref: https://www.percona.com/blog/2020/01/02/how-to-create-your-own-repositories-for-packages/

Debian Paketi Hazırlamak

Hazır bir debian paketi sıkıştırılmış dosyadır ve içini görüntlediğimizde şu bölümlerden oluştuğunu görürüz:

  • debian-binary, paket bilgisini barındırır
  • control.tar.gz, paketin üst bilgilerini ve konfigürasyon ve bakım betik dosyalarını barındırır
  • data.tar.gz, dosya sisteminde olacak dosyaları içerir

Önce ar programının olduğu binutils paketini kuralım:

$ apt install binutils

Şimdi deb uzantılı dosyamızı açalım:

$ ar t zlib1g-dev_1.2.8.dfsg-2ubuntu4.3_amd64.deb

dpkg -I veya --info komutuyla paketin bilgilerini görelim:

dpkg -I zlib1g-dev_1.2.8.dfsg-2ubuntu4.3_amd64.deb

.changes Dosyasıyla Ne Yapmak Nereye Varmak İstemektedir

Debian Package Upload Tool (dput) İle Paket Yükleme

Çalıştırılabilir Programı Hazırlamak

“Merhaba Mars” programını C dilinde yazalım derleyelim ve debian paketi haline getirip dağıtalım.

src/c/merhabamars dizinlerini oluşturmak için

# mkdir -p src/c/merhabamars
# cd src/c/merhabamars
# vim merhabamars.c

Kodumuzu yazalım:

#include <stdio.h>
int main (void) {
puts("Merhaba Mars");
return 0;
}

Şimdi derleyip çıktılarımızı üretelim. -Wall ile tüm uyarıları görelim ve -o ile çıktı dosyasının adını verelim. Eğer -o anahtarını kullanmazsak a.out adında bir dosya üretecek.

# gcc -Wall merhabamars.c -o merhabamars
# ls
merhabamars merhabamars.c

Şimdi programımızı çalıştıralım:

# ./merhabamars
Merhaba Mars

Strip komutu, daha çok, hafif olması için gerekli minimum bilgileri içeren bir üretim kalitesinde nesne dosyası üretmek istediğiniz durumlarda kullanılır. Yürütülebilir dosyanızın veya nesne dosyanızın tersine mühendislik yapılmasını istemiyorsanız da kullanabilirsiniz. Aşağıdaki komutu çalıştırdıktan sonra çalıştırılabilir dosyanızın daha küçüldüğünü göreceksiniz.

# strip merhabamars

Paketi Hazırlamak

/usr/bin dizininde çalıştırılabilir dosyamız

/usr/man/man1 dizininde programın nasıl kullanıldığını gösteren manuel dosyamız

/DEBIAN dizininde kurulum betiklerini ve paket bilgisini içeren dosyalarımız

Oluşturmak için:

# mkdir -p paket/{DEBIAN,usr/bin, usr/man/man1,usr/share/doc/merhabamars}

Çalıştırılabilir dosyamızı paket/usr/bin dizinine kopyalayalım:

Kullanım Kılavuzu (man)

.\" HEADER anlaminda TH
.\" merhabamars uygulamasinin birinci bolumu
.\" olusturma tarihi
.\" Surum numarasi
.TH merhabamars 1 "23.07.2021" "1.0-0" "merhabamars kullanim kilavuzu"
.\" SECTION HEADER anlaminda SH
.\" SH NAME icin merhabamars kullaniyoruz
.SH NAME
merhabamars \- "Merhaba Mars" yazisini goruntuler
.\" Komutun kullanimina dair kisa aciklama icin SYNOPSIS
.SH SYNOPSIS
$ merhabamars , komutu basarili tamamlandiginda 0 sonuc koduyla cikis yapar.
.\" Daha uzun cok satirli aciklama icin DESCRIPTION bolumu kullanilir
.SH DESCRIPTION
MerhabaMars uygulamamiz cok derin bir mevzuda calistirilmak icin hummali calismalarin sonucunda
kolerali gunlerden gecilerek hazirlanmis ve nice cadilarin yakildigi orta cag karanligindan
yeni cagin acilmasina kadar tum karanliklari aydinlatmistir.
.\" Eger uygulama secenek kabul ediyorsa burada yazilir ama bizim yok
.SH OPTIONS
Bu uygulamanin secenegi yoktur.
.\" Uygulamanin bagli oldugu diger komutlari buraya yaziyoruz. Ornek olsun diye puts komutunu yazalim
.SH SEE ALSO
puts
.SH AUTHOR
Milletimin Yildizi (o@benim.milletimin.yildizidir.parlayacak)

man Paketi (yüklü değilse: apt install man) ile bakalım:

Sıkıştıralım dosyamızı:

gzip -9 ./merhabamars.1

DEBIAN/control Dosyasını Hazırlayalım

Package: merhabamars
Version: 1.0.0
Section: misc
Priority: optional
Architecture: amd64
Depends: libc6
Maintainer: Cem Topkaya (cem.topkaya@hotmail.com)
Description: Marsin karanlık tarafina sert inen Turk

Debian paketleme sistemlerinin desteklediği linux mimarilerin listesini dökmek için (dpkg-architecture -L):

# dpkg-architecture -L

dpkg’nin geliştirmede kullanılan tüm sürümlerini yüklemek için dpkg-dev paketini kurmamız gerekir:

apt-get install dpkg-dev

Lisans İçin copyright Dosyası Oluşturma

Önce lisans dosyalarının dizinlerini oluşturalım

Apache 2.0 Lisansı için sayfanın sonundaki metni kopyalayıp, copyright dosyamıza yapıştıralım:

Linux varsayılan olarak /usr/share/common-licenses/Apache-2.0 dosyası mevcuttur

Debian Paketini Yapılandıralım

Temel kural olarak debian paketi haline getireceğimiz dizindeki tüm dosyaları (-R anahtarıyla) root kullanıcısı ve root grubunun yetkisine vermemiz gerekiyor:

# chown -R root.root paket/
dpkg-deb — build paket/ merhabamars-1.0.0-amd64.deb

Derlediğimiz paketi kurduğumzuda çalıştığını göreceğiz. which merhabamars ile uygulamanın /usr/bin/merhabamars yolunda olduğunu, uygulamanın kullanım kılavuzundaki açıklamasını what merhabamars ile görebiliyoruz.

Debian Paketi ve Bağımlılıklarını İndirmek

$ apt-get --print-uris --yes install <my_package_name> | grep ^\' | cut -d\' -f2 > downloads.list$ wget --input-file downloads.list

Ref: stackoverflow

Debian Paketindeki Bağımlılık İlişkileri

İzin verilen ilişkiler sırasıyla

  • << kesinlikle daha önceki,
  • <= eşit veya daha önceki,
  • = tam olarak bu sürüm numarasına denk,
  • >= daha sonraki veya eşit,
  • >> kesinlikle daha sonraki sürüm numaraları.

Bir debian paketi aşağıdaki gibi tanımlanabilir *:

Package: 0ad-data
Version: 0.0.23.1-1
Installed-Size: 2044173
Maintainer: Debian Games Team <pkg-games-devel@lists.alioth.debian.org>
Architecture: all
Pre-Depends: dpkg (>= 1.15.6~)
Suggests: 0ad
Description: Real-time strategy game of ancient warfare (data files)
Homepage: http://play0ad.com/
Description-md5: 26581e685027d5ae84824362a4ba59ee
Tag: role::app-data
Section: games
Priority: optional
Filename: pool/main/0/0ad-data/0ad-data_0.0.23.1-1_all.deb
Size: 701878080
MD5sum: 48a0f2d3af77e4cf01638e4429bddbd8
SHA256: 0fa3fb9ef1999054d041f2425b677312e4d4e7bf43ac499665f7f69a21f8b0a9

5 Farklı bağımlılık tip tanımını debian paketi içinde yapabiliriz *:

  • Depends
  • Recommends
  • Suggests
  • Enhances
  • Pre-Depends

Depends (Bağımlılıklar)

Mutlak bağımlılıkları gösterir. Depends (Bağımlılar) alanında listelenen tüm paketler doğru şekilde yapılandırılmadıkça paket yapılandırılmayacaktır. Mesela bir kütüphaneyi kullanıyorsa deb paketiniz bağımlı olduğunuz kütüphane paketini depends alanında tanımlamalıyız. postinst ile kurulum yaptığınızda çalıştıracağınız betiği veya prerm ile uygulamayı kaldırdığınızda çalışmasını istediğiniz betiği belirtirsiniz. Bu iki komut dosyaları çalıştığında eğer kurulması gereken ön bağımlı paketleri kullanacaksa depends alanında bu paketler tanımlanmalıdır. Postinst configure durumunda, bağımlı paketler önce paketten çıkarılır ve yapılandırılır. Prerm veya diğer postinst eylemler durumunda, paket bağımlılıkları normalde en azından paketten çıkarılır, ancak bağımlılığın önceki bir yükseltmesi başarısız olursa yalnızca “Yarı Yüklü” olabilir. Son olarak, bağımlı paketin postrm komut dosyası tarafından paket kaldırıldıktan sonra tamamen temizlenmesi gerekiyorsa Bağımlılar alanı kullanılmalıdır. Postrm çalıştırıldığında paket bağımlılıklarının kullanılabilir olacağına dair bir garanti yoktur, ancak bağımlı paketin bir bağımlılık bildirmesi durumunda (özellikle postrm kaldırma durumunda) mevcut olma olasılığı daha yüksektir. Postrm komut dosyası, bağımlılık mevcut değilse, bağımlılık gerektiren eylemleri nazikçe atlamalıdır.

Recommends (Öneriler)

Güçlü ancak mutlak olmayan bir bağımlılık ilan eder. Öneriler alanı, olağandışı kurulumlar dışında tümünde bununla birlikte bulunabilecek paketleri listelemelidir.

Suggests

Paketin bir veya daha fazla başka paket için daha yararlı olabileceğini bildirmek için kullanılır. Bu alanı kullanmak, paketleme sistemine ve kullanıcıya, listelenen paketlerin bununla ilgili olduğunu ve belki de kullanışlılığını artırabileceğini, ancak bunlar olmadan da kurulabilir.

Enhances

Bu alan Suggests (öneriler’e) benzer ancak ters yönde çalışır. Bir paketin başka bir paketin işlevselliğini geliştirebileceğini bildirmek için kullanılır.

Pre-Depends

Bu alan Depends gibidir, ancak dpkg’yi önceden bağımlılığı bildiren paketin kurulumuna bile başlamadan önce adı geçen paketlerin kurulumunu tamamlamaya zorlaması dışında, bir ön bağımlılık bildiren bir paket yaklaşık olduğunda bu şekilde çalışır. paketten çıkarılmalı, bağımlı paket tamamen yapılandırılmışsa veya bağlı paket (ler) yalnızca paketten çıkarılmışsa veya yapılandırılmış olmaları koşuluyla “Yarı Yapılandırılmış” durumda olsa bile ön bağımlılık karşılanabilir geçmişte bir noktada doğru bir şekilde (ve o zamandan beri kaldırılmamış veya kısmen kaldırılmamış).

Depends ve Pre-Depends Farkı

depends ve pre-depends de esas paketin kurulumundan önce ihtiyaç duyduğu bağımlılıklardan bahseder, ancak pre-depends, depends içinde belirtilen paketlerden önce bağımlılık paketlerinin kurulumunu ve yapılandırmasını zorlar. dpkg, tüm pre-depends paketler ele alınana kadar ana paketi bile açmayacaktır. Depends ile, bağımlılık paketlerinin ve asıl paketin sırası önemli değildir. pre-dependsde tanımlı paketlerin yapılandırılıp yapılandırılmadığının, kurulup kurulmadığının doğrulanmasını dikkate alır. Bu olmadan, ana paket açılmayacak, yapılandırılmayacak veya kurulmayacaktır. Ana paketle çalışma sürecine başlamadan önce bağımlılıkların kurulu olması gerekir. pre-depends normalde paketin kararlılığının önemli olduğu ve sistemi veya programı çok kötü bir şekilde etkilemeyeceği durumlarda kullanılır

Ağ Yığını (Network Stack)

Özetle; “fiziki ağ arayüzü” + “yönlendirme (routing)” + “IP” den oluşan yığındır. Yani OSI katmanındaki 1, 2 ve 3 katmanlarını içerir (2. katmanda ARP ve ROUTING tabloları oluşur). Linux üstünde bu katmanların bilgilerini 1 için ip link , 2 için ip route, 3 için ip addr komutlarını kullanırız.

OSI Katmanları için: https://bit.ly/3dhkArC

Verinin iletimi üst katmandan alt katmana doğru olur. Diğer bilgisayarda ise önce fiziki katman ile karşılanan veri üst katmanlara doğru hareket eder.

4- Taşıma (Transport) Katmanı [data => segment]

Veri (data) halinde alınan bilgi, taşıma katmanında kesim (segment) adı verilen birimlere ayrılır. Bu şekilde veri alıcı makinede tekrar biraraya getirilirken doğru sıralanması sağlanmış olur.

3- Ağ (Network) Katmanı [segment => packet]

Ağ katmanına kesimler (segment) halinde gelen verilere bu katmanda kaynak ve hedef adres bilgileri eklenir ve kesimler pakete dönüşür (segment > packet). IPv4 olan adreslerin MAC adreslerine dönşümünde ARP kullanılırken, IPv6 adresleri “Neighbour Discovery Protocol” ile dönüştürülür *. Bu katmanda artık veriler ağlar arasında dolaşmaya hazırlanmaya başlar. Artık verimiz routerdan çıkarak istenilen cihaz adresine gönderilmek üzere paketlenir. Verinin hedef adresi. ağ içerisindeki bir cihaz adresi de olabilir ağ dışında ise, paket NAT işlemine tabi tutulur.

2- Veri Bağlantı (Data Link) Katmanı [packet => frame] *

Veri-bağlantı katmanında paketlere MAC adresleri eklenerek çerçeve (frame) adını verdiğimiz yapı oluşur.

1- Fiziki (Physical) Katman [frame=>bit array]

En son aşama olarak fiziki katmana gelen çerçeveler burada bir bit dizisine dönüştürülerek iletime hazır hale getirilir. Fiziki katman, donanım bazında verilerin CPU ile ayarlanıp internet donanımına ya da kablosuz ağ ile ilgili donanıma transferi ile ilgili protokollerle bağdaştırılır.

Ağ Arayüzlerinin Donanım Durumları

Kullanılabilir ağ arayüzlerinin donanım temelinde durumlarını görüntülemek için ip link komutunu çalıştırırız.

lo: Linux Host Itself (Loopback arayüzü)

# Ağ Arayüzünü Etkinleştir ve Devre Dışı Bırak
$ ip link set wlan0 <up|down>
# Bilgisayarınıza bir IP adresi atamak/silmek için
$ ip addr <add|del> 192.168.1.8/24 dev wlan0
# veya
$ ip a <add|del> 192.168.1.8/255.255.255.0 dev wlan0
# IP adresini atadıktan sonra, değişiklikleri görüntüleyin:
$ ip addr show wlan0
# Yönlendirme tablonuzda ayarlandığı gibi ağınızda alacağı rota paketlerini görmek için IP komutunun route nesnesini kullanabilirsiniz. Sistemin yönlendirme tablosu bilgilerini kontrol etmek için aşağıdaki komutu çalıştırın.
$ ip route show
# Varsayılan rotayı değiştirmek veya silmek için IP komutu aşağıdaki gibi kullanılabilir.
$ ip route <add|del> default via 192.168.1.1
# IP komutu, çeşitli ağ arayüzlerinin istatistiklerini göstermek için de kullanılabilir. Bunu yapmak için -s seçeneğiyle IP komutunu kullanabilir ve ardından ağ cihazını belirtebilirsiniz.
$ ip -s link
# Belirli bir ağ arabirimi hakkında bilgi almanız gerekiyorsa, ls seçeneğini ve ardından ağ arabiriminin adını (wlan0) ekleyin. Bu, özellikle ağ bağlantısındaki hataları giderirken çok yararlı olabilir. Bunu yapmak için aşağıdaki komutu çalıştırın:
$ ip -s link ls wlan0
# Adres Çözümleme Protokolü (ARP), bir IP adresini, genellikle MAC adresi olarak bilinen ilgili fiziksel adresine çevirmek için kullanılır. ip komutu ile komşu veya komşu seçeneğini kullanarak LAN'ınıza bağlı cihazların MAC adresini görüntüleyebilirsiniz.
$ ip neighbour

Ref: https://lintut.com/how-to-use-linux-ip-command/

Ağ Arayüzlerinin IP Adresleri

Ağ arayüzlerinin adreslerini almak için ip addr komutu çalıştırılır.

IP Adresinin bırakıp tekrar almak için (release , renew) sudo dhclient komutu çalıştırılır.

Ağ İsim Uzayları *

Ağ isim alanı, özellikle ağ yığınını sanallaştırır. Her ağ isim alanı, ağ arabirimleri, IP adresleri, yönlendirme tabloları, tüneller, güvenlik duvarları vb. gibi kendi kaynak kümesine sahiptir. Örneğin, bir ağ isim alanına eklenen iptables kuralları yalnızca bu isim alanına giren ve çıkan trafiği etkiler.

/proc/[pid]/ns/cgroup (since Linux 4.6)
/proc/[pid]/ns/ipc (since Linux 3.0)
/proc/[pid]/ns/mnt (since Linux 3.8)
/proc/[pid]/ns/net (since Linux 3.0)
/proc/[pid]/ns/pid (since Linux 3.8)
/proc/[pid]/ns/pid_for_children (since Linux 4.12)
/proc/[pid]/ns/time (since Linux 5.6)
/proc/[pid]/ns/time_for_children (since Linux 5.6)
/proc/[pid]/ns/user (since Linux 3.8)
/proc/[pid]/ns/uts (since Linux 3.0)

Bir ağ isim uzayı içerisinde ağ yığınının tüm bileşenleri bulunur (routing, ip, fiziki ağ arayüzü vs.). Linux varsayılan olarak her prosesi “root network namespace” e atar böylece uygulamaların internete erişmesi sağlanır. Komut satırında ip link komutunu çalıştırdığımızda “root network namespace” üstündeki ağ arayüzlerini, ip addr komutuyla IP adreslerini görüntüleriz.

ip link
ip addr
ip route
iptables -L

netns İle Ağ Yalıtımı

3 Tip ağ yapısı kuralım:

  1. peer (çift) türünde
  2. bridge (köprü) türünde

Aşağıda okuyacaklarınız şu sırayla yapılıyor:

  1. Network Namespace’i tanıyalım
  2. Linux makinasında ağ yığınını görelim
  3. Linux makinasında ağ isim uzayı yaratalım ve bu uzaya ait ağ arabirimlerini görelim
  4. Başka bir isim uzayı yaratalım ve her 2 isim uzayına ağ arabirimi tanımlayıp,
  5. Bu ağ arabirimlerinin birbirilerini yani iki ağ isim uzayının iletişimini sağlayacak şekilde eşleştirelim (peer)

Bir ağ isim uzayıyla prosesin ağ erişim kaynaklarını diğerlerinden ayırabilir eriştirmeyebiliriz. Proseslerin PID bilgilerini farklı bir ağ isim uzayında çalışacak şekilde ekleyerek bu yalıtımı sağlarız.

Usage: ip netns list
ip netns add NAME
ip netns attach NAME PID
ip netns set NAME NETNSID
ip [-all] netns delete [NAME]
ip netns identify [PID]
ip netns pids NAME
ip [-all] netns exec [NAME] cmd …
ip netns monitor
ip netns list-id [target-nsid POSITIVE-INT] [nsid POSITIVE-INT]
NETNSID := auto | POSITIVE-INT

İsimli ve yalıtılmış ağ yaratmak için netns komutunu kullanıyoruz.

# Oluşturulmuş ağ isim uzaylarını listelemek için 2 yöntem:
# komut veya herşeyin dosya olduğu linux'te dizini listeleyerek

$ ip netns
$ ls /var/run/netns
# isim uzayı eklemek
$ ip netns add web-konteyneri
$ ip netns
web-konteyneri
$ ls /var/run/netns
web-konteyneri

İsim uzayı içinde komut çalıştırabiliriz. Sanki bir bilgisayarın ağ arayüzlerinin durumlarını görüntüler gibi. Bu komut docker exec <konteynerID> <komut>, kubectl exec.. komutlarına çok benziyor ip netns exec <nsAdı> <komut>:

$ ip netns exec web-konteyneri ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default ...
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default..
link/sit 0.0.0.0 brd 0.0.0.0
$ ip netns exec web-konteyneri ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT gr...
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAU...
link/sit 0.0.0.0 brd 0.0.0.0

2 Ağ arabirimi oluşmuş ve DOWN durumdalar. Loopback ağ arayüzüne odaklanalım; faal görünmüyor (DOWN) ve IP almamış.

ip netns exec web-konteyneri ip addr

Yeni ağ isim uzayımızdaki loopback arabiriminin durumunu UP yapalım exec komutuyla:

ip netns exec web-konteyneri ip link set lo up

“Root network namespace” üstüne ağ arabirimi yaratmak için ip link add komutunu kullanacağız. Ağ arayüzlerinin alabileceği türler:

bridge - Ethernet Bridge device
bond - Bonding device
dummy - Dummy network interface
hsr - High-availability Seamless Redundancy device
ifb - Intermediate Functional Block device
ipoib - IP over Infiniband device
macvlan - Virtual interface base on link layer address (MAC)
macvtap - Virtual interface based on link layer address (MAC) and TAP.
vcan - Virtual Controller Area Network interface
vxcan - Virtual Controller Area Network tunnel interface
veth - Virtual ethernet interface
vlan
- 802.1q tagged virtual LAN interface
vxlan - Virtual eXtended LAN
ip6tnl - Virtual tunnel interface IPv4|IPv6 over IPv6
ipip - Virtual tunnel interface IPv4 over IPv4
sit - Virtual tunnel interface IPv6 over IPv4
gre - Virtual tunnel interface GRE over IPv4
gretap - Virtual L2 tunnel interface GRE over IPv4
erspan - Encapsulated Remote SPAN over GRE and IPv4
ip6gre - Virtual tunnel interface GRE over IPv6
ip6gretap - Virtual L2 tunnel interface GRE over IPv6
ip6erspan - Encapsulated Remote SPAN over GRE and IPv6
vti - Virtual tunnel interface
nlmon - Netlink monitoring device
ipvlan - Interface for L3 (IPv6/IPv4) based VLANs
ipvtap - Interface for L3 (IPv6/IPv4) based VLANs and TAP
lowpan - Interface for 6LoWPAN (IPv6) over IEEE 802.15.4 / Bluetooth
geneve - GEneric NEtwork Virtualization Encapsulation
macsec - Interface for IEEE 802.1AE MAC Security (MACsec)
vrf - Interface for L3 VRF domains
netdevsim - Interface for netdev API tests
rmnet - Qualcomm rmnet device
xfrm - Virtual xfrm interface

Linux host’a birbirleriyle eş (peer) iki sanal ağ arayüzü (veth) tanımlayalım:

$ man ip link  # Okuma ve yazmasını kolaylaştırmak içinÖrnek komutta 
-
BÜYÜK HARFle yazılanları biz gireceğiz
-
{.|.} süslü parantez arasında seçenekler var
-
[..] köşeli parantez mecburi değil:
$ ip link add DEVICE type { veth | vxcan } [ peer name NAME ]
Bizim komutumuz:
$ ip link add \
dev \ # aygıt olarak tanımla. Yazmasak da olur.
arabirimA \ # ilk ağ arayüzünün adı
type veth \ # Virtual ethernet interface türünde olacak
peer name arabirimB \ # eth0-b adında 2. ağ arayüzüyle eş olsun

Linux hostumuza iki sanal ağ yaratıp görüntüleyelim. Daha sonra bu 2 ağ arabirimini yaratacağımız network namespace ile ilişkilendirecek ve artık linux host üstünde göremeyeceğiz:

2 Adet sanal ağ arayüzünü çift (pair) olacak şekilde oluşturalım

Şimdi ağ isim arayüzlerini ve onların ağ yığınlarını görüntüleyelim:

  • Tanımlı ağ isim uzaylarını listele
  • db-konteyneri ağ isim uzayını ekle
  • Ağ isim uzaylarını 2 türlü listele
  • veth Tipindeki ağları görüntüle
    - arabirimA ve arabirimB
    Her birinin 2 ağ arabirimi var ve
    hepsinin durumu DOWN
  • web-konteynerinde tanımlı arayüzlerin 3 (IP), 2 (MAC) ve 1. katman (Fiziki) bilgilerini çekiyoruz.
  • Aynı şekilde db-konteyneri ağ isim uzayının ağ yığın bilgilerini görüntülüyoruz.

Şimdi bir veth tipindeki arayüzü host makinadan alıp web-konteyneri ağ isim uzayına ekleyelim.

Ağ türlerinden “sanal ağ arayüzünü” (veth) yarattığımız ağ isim uzayına (web-konteyneri’ne) ekleyelim

$ ip link set dev arabirimA netns web-konteyneri

$ ip link show type veth
28: arabirimB@if29: <BROADCAST,MULTICAST> mtu 1500 .. state DOWN..
link/ether 9e:01:be:d8:d4:59 brd ff:ff:ff:ff:ff:ff link-netns web-konteyneri
$ ip netns exec web-konteyneri ip a
1: lo: <LOOPBACK> mtu 65536 .. state DOWN ..
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: sit0@NONE: <NOARP> mtu 1480 .. state DOWN ..
link/sit 0.0.0.0 brd 0.0.0.0
29: arabirimA@if28: <BROADCAST,MULTICAST> mtu..state DOWN ..link-netns db-konteyneri

Aynı akışla db-konteyneri oluşturalım ve arabirimB yi bu ağ isim uzayına ekleyelim:

$ ip netns add db-konteyneri
$ ip link set dev arabirimB netns db-konteyneri
$ ip addr
$ ip netns exec db-konteyneri ip addr
1: lo: <LOOPBACK>...
2: sit0@NONE: <NOARP>...
28: arabirimB@if29: <BROADCAST,MULTICAST>...-netns web-konteyneri
ip netns exec db-konteyneri ip link show type veth

Şimdi IP adresi (3. katman) eklemek için ip address add <IP> dev <arayüz>

ip netns exec db-konteyneri ip address add 10.11.13.22/24 dev arabirimB

Şimdi yine MAC katmanı (ARP ve ROUTING tabloları 2. katmanın işidir) ağ yönlendirmesinden sorumludur. Bakalım routing tablosuna ip route:

$ ip netns exec db-konteyneri ip route
10.11.12.0/24 dev arabirimB proto kernel scope link src 10.11.12.22 linkdown

Neden linkdown görünüyor? Acaba arabirimB arayüzü mü DOWN? LOWERLAYERDOWN Ne demek?

$ ip netns exec db-konteyneri ip addr show type veth
28: arabirimB@if29: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN group default qlen 1000
link/ether 9e:01:be:d8:d4:59 brd ff:ff:ff:ff:ff:ff link-netns web-konteyneri
inet 10.11.12.22/24 scope global arabirimB
valid_lft forever preferred_lft forever

veth Arayüzünün karşısındaki eş (peer network) ağ arabirimi (arabirimA) DOWN durumda olmalı ki LOWERLAYERDOWN durumuna gelinsin. Yani eşler arasında iletişimin olması için her iki ağ arayüzünün de UP durumda olması gerekiyor (yani elektrik 1 ağ arayüzünde var diğerinde yoksa state LOWERLAYERDOWN olacaktır).

O halde her iki ağ isim uzayındaki ağ arabirimlerini UP hale getirip tekrar bakalım:

db-konteyneri’nin ağ arayüzü arabirimB UP durumda ancak karşısındaki ağ arayüzü arabirimA DOWN durumda olduğu için NO-CARRIER ve LOWERLAYERDOWN olarak görünüyor (ayrıntı için).

$ ip netns exec db-konteyneri ip addr show type veth
28: arabirimB@if29: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN group default qlen 1000
link/ether 9e:01:be:d8:d4:59 brd ff:ff:ff:ff:ff:ff link-netns web-konteyneri
inet 10.11.12.22/24 scope global arabirimB
valid_lft forever preferred_lft forever
$ ip netns exec web-konteyneri ip addr show type veth
29: arabirimA@if28: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether a2:b4:61:27:7e:3b brd ff:ff:ff:ff:ff:ff link-netns db-konteyneri

Ve arabirimA'yı UP hale getirince elektrik siyalleşmesi başlıyor:

$ ip netns exec web-konteyneri ip link set arabirimA up$ ip netns exec web-konteyneri ip addr show type veth
29: arabirimA@if28: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether a2:b4:61:27:7e:3b brd ff:ff:ff:ff:ff:ff link-netns db-konteyneri
inet6 fe80::a0b4:61ff:fe27:7e3b/64 scope link
valid_lft forever preferred_lft forever

Tekrar fiziki katmanlar arasına baktığımızda artık NO-CARRIER durumunun kalktığını ve fiziki katmanda bir sinyalleşme olduğunu (LOWER_UP) görebiliyoruz:

$ ip netns exec db-konteyneri ip addr show type veth
28: arabirimB@if29: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 9e:01:be:d8:d4:59 brd ff:ff:ff:ff:ff:ff link-netns web-konteyneri
inet 10.11.12.22/24 scope global arabirimB
valid_lft forever preferred_lft forever
inet6 fe80::9c01:beff:fed8:d459/64 scope link
valid_lft forever preferred_lft forever

LOWER_UP, fiziksel bir katman bağlantı bayrağıdır (IP’nin genellikle bulunduğu ağ katmanının altındaki katman). LOWER_UP, bir Ethernet kablosunun takılı olduğunu ve cihazın ağa bağlı olduğunu gösterir. LOWER_UP, ek olarak ağ arayüzünün etkinleştirildiğini gösteren UP’dan farklıdır.

NOT: Renklendirme için ip link | GREP_COLOR=’01;36' grep -P ‘^[[:digit:]]:’ | GREP_COLOR=’02;36' grep -P ‘<.*>’ | GREP_COLOR=’04;36' -P ‘state\s.*(?=\smode)’

ip link
ip netns add web-konteyneri && ip netns add db-konteyneri && ip link add arabirimA type veth peer name arabirimB && ip link
ip link set dev arabirimA netns web-konteyneri && ip link set dev arabirimB netns db-konteyneri && ip link
ip netns exe web-konteyneri ip link && ip netns exe db-konteyneri ip link
ip netns exec web-konteyneri ip link set arabirimA up && ip netns exec db-konteyneri ip link set arabirimB up && ip netns exe db-konteyneri ip link && ip netns exe web-konteyneri ip link
$ ip netns exec web-konteyneri ip address add 10.11.13.11/24 dev arabirimA
$ ip netns exec db-konteyneri ip address add 10.11.13.22/24 dev arabirimB
$ for ns in "web-konteyneri" "db-konteyneri"; do echo $ns; ip netns exec $ns ip addr show type veth | head -1; done
web-konteyneri
7: arabirimA@if6: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN group default qlen 1000
db-konteyneri
6: arabirimB@if7: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
$ ip netns exec web-konteyneri ip link set dev arabirimA up
$ ip netns exec db-konteyneri ip link set dev arabirimB up
$ for ns in "web-konteyneri" "db-konteyneri"; do echo $ns; ip netns exec $ns ip addr show type veth | head -1; done
web-konteyneri
7: arabirimA@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
db-konteyneri
6: arabirimB@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
$ ip netns exec web-konteyneri ping 10.11.13.22
PING 10.11.13.22 (10.11.13.22) 56(84) bytes of data.
64 bytes from 10.11.13.22: icmp_seq=1 ttl=64 time=0.054 ms
64 bytes from 10.11.13.22: icmp_seq=2 ttl=64 time=0.023 ms
^C
--- 10.11.13.22 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 3170ms
rtt min/avg/max/mdev = 0.023/0.033/0.054/0.012 ms
$ ip netns exec db-konteyneri ping 10.11.13.11
PING 10.11.13.11 (10.11.13.11) 56(84) bytes of data.
64 bytes from 10.11.13.11: icmp_seq=1 ttl=64 time=0.037 ms
64 bytes from 10.11.13.11: icmp_seq=2 ttl=64 time=0.022 ms
^C
--- 10.11.13.11 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1054ms
rtt min/avg/max/mdev = 0.022/0.029/0.037/0.007 ms

İki ad alanı da aynı subnet mask içinde oldukları için routing yapmamız gerekmedi.

Ağ arayüzlerini silelim:

$ ip netns exec web-konteyneri ip link delete arabirimA

Peer olarak oluşturulan arabirimA ve arabirimB arayüzlerinden birinin silinmesiyle diğeri de otomatik silinir.

arabirimB’nin Otomatik silindiğini görmek için:

$ ip netns exec db-konteyneri ip link

Şimdi Köprü türünde bir bağlantıyla konteynerlerimizi bağlayalım

  • Switch gibi kullanacağımız bridge ağında gateway için bridge tipinde 1 ağ arayüzü,
  • Ve 2 Konteyner için 1'er ağ arayüzü ancak bunların her birini bir nevi switch üstündeki portlara bağlayacağımız için yine peer olacak şekilde ayrıca 2 ağ arabirimiyle birlikte oluşturalım
$ ip link add dev kopru1 type bridge
$ ip link add dev veth-web type veth peer name veth-kopru2
$ ip link add dev veth-db type veth peer name veth-kopru3

Gateway olarak çalışacak kopru1 arayüzüne IP değeri verip UP yapalım:

$ ip address add 10.11.13.1/24 dev kopru1
$ ip link set dev kopru1 up

Şimdi sanal ağ çiftlerinin birini ağ isim alanına bağlayalım, diğerinin gateway’ini kopru1 olacak şekilde ayarlayalım

$ ip link set dev veth-web netns web-konteyneri
$ ip link set dev veth-db netns db-konteyneri
$ ip link set veth-kopru2 up
$ ip link set veth-kopru3 up
$ ip link set veth-kopru2 master kopru1
$ ip link set veth-kopru3 master kopru1
$ ip netns exec web-konteyneri ip link set dev veth-web up
$ ip netns exec web-konteyneri ip address add 10.11.13.11/24 dev veth-web
$ ip netns exec web-konteyneri ip route add default via 10.11.13.1
$ ip netns exec web-konteyneri ip route
$ ip netns exec db-konteyneri ip link set dev veth-db up
$ ip netns exec db-konteyneri ip address add 10.11.13.22/24 dev veth-db
$ ip netns exec db-konteyneri ip route add default via 10.11.13.1
$ ip netns exec db-konteyneri ip route
$ ip address show kopru1
12: kopru1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 0e:22:50:a3:f4:d0 brd ff:ff:ff:ff:ff:ff
inet 10.11.13.1/24 scope global kopru1
valid_lft forever preferred_lft forever
inet6 fe80::b82b:2cff:fe5e:83a4/64 scope link
valid_lft forever preferred_lft forever
$ ip address show veth-kopru2
8: veth-kopru2@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master kopru1 state UP group default qlen 1000
link/ether ee:14:8e:63:0a:38 brd ff:ff:ff:ff:ff:ff link-netns web-konteyneri
inet6 fe80::ec14:8eff:fe63:a38/64 scope link
valid_lft forever preferred_lft forever
$ ip address show veth-kopru3
10: veth-kopru3@if11: <BROADCAST,MULTICAST> mtu 1500 qdisc noop master kopru1 state DOWN group default qlen 1000
link/ether 0e:22:50:a3:f4:d0 brd ff:ff:ff:ff:ff:ff link-netns db-konteyneri

Şimdi ping ile kontrol edelim bağlanmışlar mı diye

$ ip netns exec web-konteyneri ping 10.11.13.22 -c 2
$ ip netns exec db-konteyneri ping 10.11.13.11 -c 2

--

--

Cem Topkaya
Cem Topkaya

Written by Cem Topkaya

Evlat, kardeş, ağabey, eş, baba, müzik sever, öğrenmek ister, paylaşmaya can atar, iyi biri olmaya çalışır, hakkı geçenlerden helallik ister vs.

No responses yet