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

| Alan | Anlamı |
|---|---|
| USER | Süreci çalıştıran kullanıcı |
| PID | Sürecin kimlik numarası |
| %CPU | Sürecin işlemci kullanım oranı |
| %MEM | Sürecin RAM kullanım oranı |
| VSZ | Sürecin toplam sanal bellek alanı |
| RSS | Sürecin fiziksel RAM üzerinde kapladığı alan |
| TTY | Sürecin bağlı olduğu terminal. ? herhangi bir terminale bağlı olmadığını gösterir |
| STAT | Sürecin durumu ve ek özellikleri |
| START | Sürecin başlatıldığı zaman |
| TIME | Sürecin kullandığı toplam işlemci süresi |
| COMMAND | Çalıştırılan komut ve parametreleri |
ps aux, komutu çalıştırdığımız andaki süreçleri listeler. top ise bu listeyi belirli aralıklarla yenileyerek işlemci ve bellek kullanımını anlık olarak takip etmemizi sağlar.

ps veya top çıktısında isimleri köşeli parantez içerisinde görünen süreçler genellikle kernel space’de çalışan süreçlerdir. Köşeli parantez bulunmayanlar ise user space’de çalışan normal süreçlerdir.
Not: cpu ve memory alanlarında 0.0 durumu, ondalığın daha gerisinde bir güç harcandığını belirtir.
Nice Değeri
Nice değeri, bir sürecin diğer süreçlere göre işlemciyi kullanma önceliğini etkiler. Linux’ta nice değeri -20 ile 19 arasındadır.
Nice değeri küçüldükçe süreç daha öncelikli, büyüdükçe daha az öncelikli hale gelir. Yani nice değeri 10 olan bir süreç, nice değeri 0 olan bir sürece göre işlemci sırasında daha geri planda kalabilir.
Yeni bir programı belirli bir nice değeriyle başlatmak için nice, çalışmakta olan bir sürecin nice değerini değiştirmek için renice komutunu kullanabiliriz.
Normal bir kullanıcı kendi sürecini daha az öncelikli hale getirebilir. Ancak nice değerini düşürerek sürece daha yüksek öncelik vermek istediğinde yetki hatası alabilir. Ben de negatif bir nice değeri vermeye çalıştığımda permission denied hatası aldım.
top ve ps çıktısındaki NI alanı nice değerini gösterir. PRI veya PR alanı ise çekirdeğin süreç için kullandığı öncelik bilgisidir. Nice değeri kullanıcı tarafından değiştirilebilirken süreçlerin çalıştırılma sırasına son kararı çekirdek verir.
İşlemci Kullanımı ve Load Average
Bir sürecin işlemci kullanımı %100 değerini geçebilir. Çok çekirdekli bir sistemde %100, yaklaşık olarak bir çekirdeğin tamamen kullanılması anlamına gelir. Örneğin %250 işlemci kullanan bir süreç, yaklaşık iki buçuk çekirdek kadar işlemci zamanı kullanıyor olabilir.
Sistemde kaç işlemci ve çekirdek bulunduğunu lscpu komutuyla görebiliriz. İşlemciyle ilgili bilgilere /proc/cpuinfo dosyasından da ulaşabiliriz.

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

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

w veya who komutudur. Bu çıktı da IDLE oturumun ne kadar süredir boşta olduğunu, JCPU terminale bağlı süreçlerin toplam işlemci süresini, PCPU o anda çalışan sürecin işlemci süresini, WHAT ise çalışan süreç veya komutu gösterir.
Eğer buradaki değerler sistemdeki çekirdek sayımızı geçtiyse sistemimiz çok yoğun yük altında demektir.
USB ve PCI Aygıtları
lsusb komutuyla sisteme bağlı USB aygıtlarını listeleyebiliriz. -v seçeneğini kullandığımızda aygıtların üreticisi, kimliği ve özellikleri gibi daha ayrıntılı bilgiler gösterir.

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

Bellek Kullanımı
free komutuyla sistemdeki fiziksel bellek ve swap kullanımı hakkında bilgi alabiliriz. -m seçeneği değerleri Mb cinsinden gösterir. Değerlerin boyutuna göre Mb veya Gb biçiminde daha okunabilir (insani) bir çıktı almak için -h seçeneğini kullanabiliriz. Detaylı bilgi almak için -v parametresini de kullanabiliriz.
Burada kullanılabilir bellek alanı için yalnızca free sütununa bakmak doğru değildir. Kullanılmayan belleğin bir kısmını önbellek olarak değerlendirir. Yeni bir uygulamanın kullanabileceği yaklaşık alanı görmek için available sütunu daha faydalıdır.

kill
kill komutu yalnızca süreçleri zorla kapatmak için kullanılmaz. Asıl görevi süreçlere sinyal göndermektir.
Herhangi bir sinyal belirtmeden kill kullandığımızda sürece varsayılan olarak 15 numaralı SIGTERM sinyali gönderilir. Bu sinyal sürece kapanmadan önce elindeki işleri tamamlayabilmesi için fırsat verir.
9 numaralı SIGKILL sinyali ise süreci doğrudan sonlandırır. Süreç bu sinyali yakalayamaz ve kapanma işlemini düzenli biçimde tamamlayamaz. Bu nedenle bir yazma işlemi veya başka bir operasyon yarıda kalabilir.
1 numaralı SIGHUP sinyali birçok daemon tarafından yapılandırma dosyasını yeniden okumak için kullanılır. Ancak bunun nasıl yorumlanacağı programa bağlıdır.

Not: kill -l çıktısında 32 ve 33 numaralarının görünmemesinin sebebi çekirdek için ayrılmış olmalarıdır.
Zombi Süreçler
Süreçler kendi aralarında ata ve çocuk ilişkisi kurarlar. Bir çocuk süreç sona erdiğinde ata sürecin onun çıkış bilgisini alması gerekir.
Ata süreç bu bilgiyi almazsa çocuk süreç, çalışması bitmiş olmasına rağmen süreç tablosunda zombi olarak kalır. ps çıktısında zombi süreçler Z durumuyla görülebilir.
Zombi süreç zaten çalışmasını tamamladığı için doğrudan öldürülemez. Sorunun çözülmesi için ata sürecin çocuk sürecin çıkış bilgisini toplaması gerekir. Gerekli olduğunda hatalı ata süreç yeniden başlatılabilir veya sonlandırılabilir.
Çocuk değil de ata süreç sonlandırıldığında geride kalan çocuk süreçler PID 1 tarafından sahiplenilebilir.

Servisler
Servis ile süreç tamamen birbirinden ayrı yapılar değildir. Bir servis çalıştığında arka planda bir veya daha fazla süreç oluşturabilir. Bir servis çalışırken arka planda bir veya birden fazla süreç oluşturabilir.
Servisleri systemctl komutuyla yönetebiliriz. Bir servisi başlatmak, durdurmak veya durumunu görüntülemek için start, stop ve status işlemlerini kullanabiliriz.

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

Buradaki STATE servisin açılışta otomatik başlatılacak şekilde ayarlanıp ayarlanmadığını, PRESET ise dağıtımın servis için belirlediği varsayılan ayarı gösterir.
Paketlerle gelen servis dosyaları /usr/lib/systemd/system/, kendi oluşturduğumuz servisler ve yaptığımız özel ayarlar ise /etc/systemd/system/ altında bulunur. /usr/lib altındaki dosyaları doğrudan değiştirmeyiz; çünkü paket güncellemelerinde yaptığımız değişiklikler kaybolabilir.
Paket tarafından getirilen servis dosyasını doğrudan değiştirmek yerine systemctl edit kullanarak ek bir ayar dosyası oluşturabiliriz. Böylece paket güncellendiğinde yaptığımız değişikliğin üzerine yazılması engellenmiş olur.
komutu girdiğimizde önceki ayarları yorum satırına alarak gelmiş olan bir dosya açılır. Burada değişikliklerimizi yaptıktan sonra …/ssh.service.d/override.conf dosyası oluşturulur.
Bir servis dosyası 3 ana bölümden oluşur.
Unit, service ve install.

Unit bölümünde servisin açıklaması ve diğer unit’lerle ilişkisi bulunur.
Description, servisin kısa açıklamasıdır.
Documentation, servisle ilgili bakılabilecek belgeleri gösterir.
target, sistem açılırken ulaşılan belirli bir aşamayı ifade eder. After=network.target yazarak SSH servisinin ağla ilgili temel işlemlerden sonra başlatılmasını isteriz. Buradaki network.target bir servis değil, başlatma sırasını belirlememize yardımcı olan bir hedeftir.
ConditionPathExists, belirtilen dosya koşuluna göre servisin çalıştırılıp çalıştırılmayacağını belirleyebilir. Örneğin yukarıdaki servis dosyasında, /etc/ssh/sshd_not_to_be_run dosyası yoksa servis başlatılacak.
EnvironmentFile, servisin değişken okuyacağı dosyayı gösterir. Dosya yolunun önündeki – işareti, dosya bulunmazsa bunun hata olarak kabul edilmemesini sağlar.
ExecStartPre, ana servis başlamadan önce çalıştırılacak kontrolü belirtir. (sshd -t)
ExecStart, servisi başlatacak asıl komuttur.
ExecReload, servis yeniden yüklendiğinde çalıştırılacak komutu belirtir. (kill -l çıktısındaki 1 numaralı SIGHUP)
Restart=on-failure, servis bir hata nedeniyle kapanırsa yeniden başlatılmasını sağlar.
Type=notify, servis hazır olduğunda systemd’ye bildirim göndereceğini belirtir.
RuntimeDirectory, servis çalışırken ihtiyaç duyulan geçi duyulan geçici dizinin oluşturulmasını sağlar.
RuntimeDirectoryMode=0755, SSH için oluşturulan /run/sshd dizininin izinlerini belirler. Buradaki mode, dosya veya dizine verilecek izin anlamına gelir.
WantedBy=multi-user.target, servis etkinleştirildiğinde multi-user.target altında çalışacak unit’lerden biri hâline gelmesini sağlar.
Alias=sshd.service, servisinin sshd.service adıyla da kullanılabilmesini sağlar. Buradaki Alias, servise verilen takma ad anlamına gelir.
Not: Target birimleri, sistemin ulaşması gereken durumu belirtir. Kendileri çalışan bir program değildir.
systemctl start, servisi o anda başlatır. systemctl enable ise servisin sistem açılışında otomatik olarak başlatılabilmesi için gerekli bağlantıları oluşturur. Sistem başlarken başlayacak servisler o sembolik bağlar aracılığıyla anlaşılır ve başlatılır.
SysV init ve systemd
Systemd öncesinde SysV init sistemi yaygın olarak kullanılıyordu. Servis betikleri /etc/init.d altında bulunuyor ve belirli bir sıraya göre çalıştırılıyordu.
Systemd ise birbirinden bağımsız servisleri paralel olarak başlatabilir. Bir servisin diğerinden önce veya sonra başlaması gerekiyorsa unit dosyalarında bağımlılık ve sıralama ilişkileri tanımlanır.
Bu nokta da bize verilen ödevi yapmak istiyorum. Sistem açıldığında otomatik olarak çalışan bir servis dosyası hazırlayacağız. Servis her çalıştığında /tmp altında bulunan bir dosyaya “ben açıldım” ifadesiyle birlikte o anki tarihi yazacak.
İlk önce servis dosyamın tanımını /etc/systemd/system altında deneme.service adıyla yapıyorum.
Dosyamda unit, service ve İnstall alanları için gerekli kısımları giriyorum. Görüldüğü üzere bir servis tanımında bütün alanların girilmesi gerekliliği yok, bu servisten servise ve gereksinimlere göre değişiyor.

şeklinde dosyamı hazırlayıp kaydedip çıkıyorum. Ardından değişikliklerin geçerli olması için,
daemon’a dosyayı yeniden okutuyorum.
Açılışta başlaması için,
komutunu giriyorum ve sembolik link oluşuyor. Status ile durumunu kontrol ediyorum.

ardından makinemi reboot edip kontrol ediyorum.

başarıyla görevi tamamladık (her açılışta >> dememize rağmen önceki kaydın silinmesinin nedeni dosyayı /tmp’de oluşturuyor olmamız.
Loglama
Sistemdeki log dosyalarının önemli bir bölümü /var/log altında bulunur. Servislerin ve uygulamaların oluşturduğu hata, uyarı ve bilgilendirme kayıtlarını burada görebiliriz.
Uygulamalar loglarını farklı yöntemlerle oluşturabilirler.
- Bir uygulama kendi log dosyasını açıp kayıtlarını doğrudan bu dosyaya yazabilir.
- Uygulama mesajını syslog sistemine gönderebilir ve rsyslog bu mesajı belirlenen dosyaya yazabilir.
- Systemd ile gelen journald servisi de servislerden ve uygulamalardan gelen kayıtları toplayabilir.
Rsyslog’un ana yapılandırma dosyası /etc/rsyslog.conf, ek yapılandırmaların bulunduğu dizin ise /etc/rsyslog.d şeklindedir. Hangi log mesajının hangi dosyaya yazılacağı bu dosyalardaki kurallarla belirlenebilir.
Rsyslog her sistemde varsayılan olarak kurulu olmak zorunda değildir. Benim kullandığım minimized Ubuntu Server kurulumlarında rsyslog varsayılan olarak bulunmuyordu. Rocky Linux’ta ise kurulu olarak geldi.
Örnek olarak bir rsyslog kuralı oluşturup belirlediğimiz log mesajlarını ayrı bir dosyaya yazdıracağız. Ardından logger komutuyla deneme mesajı göndererek kuralın çalıştığını kontrol edeceğiz.
Öncelikle dosyayı oluşturarak başlayalım.
Dosyanın içerisine,
local3.* /var/log/ozel-deneme.log
yazıyorum ve
sözdenetimini kontrol ediyorum. Ardından konfigürasyonun geçerli olması için,
komutunu girip logger ile deneme yapmaya başlıyorum.
burada -p parametresi ile doğrudan local3’ün tetiklenmesini sağladım. Yaptığım test sonucunda log dosyasını kontrol ediyorum,

başarıyla ödevi tamamladık.
logrotate
Log dosyaları sürekli büyürse zamanla diskin dolmasına neden olabilir. Logrotate, eski log dosyalarını döndürmek, belirli sayıda saklamak ve gerekirse sıkıştırmak için kullanılır.
Logrotate ana yapılandırması genellikle /etc/logrotate.conf dosyasında bulunur. Uygulamalara ve servislere ait ek kurallar ise /etc/logrotate.d altında tutulur.

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

Bir logrotate kuralında logların günlük, haftalık veya aylık olarak döndürülmesi belirlenebilir. Eski dosyaların kaç tanesinin tutulacağı ve sıkıştırılıp sıkıştırılmayacağı da yine bu kurallarda yazılır.
compress seçeneği eski log dosyalarının sıkıştırılmasını sağlar.
delaycompress ise en son döndürülen log dosyasının sıkıştırılmasını bir sonraki rotasyona erteler. İlk rotasyonda aktif log dosyası .1 uzantısıyla eski dosya haline gelir ancak hemen sıkıştırılmaz. Bir sonraki rotasyonda bu dosya sıkıştırılır. Bu yöntem, bazı uygulamaların kısa bir süre daha eski log dosyasına yazmaya devam edebilmesi için kullanılır.
Bazı uygulamalar kendi log rotasyonlarını kendileri yapabilir. Her uygulamanın mutlaka logrotate kullanması gerekmez. Ancak sunucu üzerinde kontrolsüz biçimde büyüyen bir log dosyası bırakılmamalıdır. Rotasyonu yapılmayan bir log dosyası mutlaka zamanla diskin dolduracaktır.

Logrotate sürekli çalışan bir servis değildir. Dağıtıma göre cron görevi veya systemd timer tarafından belirli aralıklarla çalıştırılabilir.
Zamanlanmış Görevler
Linux’ta zamanlanmış görevler için iki temel servis kullanabiliriz.
- atd, yalnızca bir defa çalıştırılacak görevler için kullanılır.
- crond, belirli aralıklarla tekrar çalıştırılacak görevler için kullanılır.
Bu iki servis tamamen birbirinin yerine geçmez. Farklı görev türleri için birbirlerini tamamlarlar. Biz derslerde cron servisinin yapısını inceledik.
Cron’un farklı uygulamaları bulunabilir ve dağıtımlar farklı cron paketleri kullanabilir. Sistem genelindeki görevler /etc/crontab dosyasında veya /etc/cron.d altında tanımlanabilir.
Kullanıcıya ait zamanlanmış görevleri crontab -e komutuyla düzenleyebiliriz.
Kullanıcı crontab’ında beş zaman alanı bulunur:
- dakika
- saat
- ayın günü
- ay
- haftanın günü
Sistem genelindeki /etc/crontab ve /etc/cron.d dosyalarında bu alanlardan sonra komutun hangi kullanıcıyla çalışacağını belirten bir kullanıcı alanı daha bulunur.
crontab -e ile açılan kullanıcı crontab’ında kullanıcı adı yazılmaz. Görev, crontab’ın sahibi olan kullanıcıyla çalışır.

Yıldız işareti o alandaki bütün geçerli değerleri ifade eder. Yani alanlardan birine yıldız koyduğunuzda o periyotta bir kısıtlama olmaksızın çalışacaktır. */3 kullanımı ise ilgili alanda her üç değerde bir çalışmayı belirtir. Örneğin saat alanına */3 yazıldığında görev üç saatte bir çalışır.
Ay veya haftanın günü alanlarında sayı kullanılabileceği gibi fri gibi gün kısaltmaları da kullanılabilir.
Not: Cron alanlarını haftanın günü ve ayın günü haricindeki alanlar ve bağlacıyla birbirine bağlıdır. Bu iki alan arasında ya da bağlacı vardır. Bu nedenle ayın 13’ü cuma olduğunda çalışacak bir görev tanımladığımda hem ayın 13.günü hem de her cuma günü çalışıyor. Bunun sebebi, İki alan da bir “gün” belirttiği için, ikisi de aynı anda spesifik değer aldığında (biri yıldız değilken diğeri de yıldız değilken) sistem bunu iki ayrı zamanlama isteği olarak yorumluyor ve “ya da” ile birleştiriyor.
Bunu bir örnek üzerinden görmek istersek ilk önce sudo timedatectl set-ntp false ile zaman servisini engelliyorum.
Ardından yeni zamanı ayın 13’ü olmayan herhangi bir cuma gününe ayarlıyorum.

calisti: Fri Sep 4 12:01:01 UTC 2026
Devamında zamanı ayın 13’ü olan ama cuma olmayan herhangi bir güne ayarlıyorum.

calisti: Sun Sep 13 12:01:01 UTC 2026
İkisi de çalıştı.
Zamanlanmış görevleri hazırlamak için crontab.guru adresinden de faydalanabiliriz.

Zamanlanmış görevler sistemde farklı yerlerde bulunabilir:
- /etc/crontab
- /etc/cron.d
- /etc/cron.hourly
- /etc/cron.daily
- /etc/cron.weekly
- /etc/cron.monthly
- Kullanıcıların crontab dosyalarının tutulduğu spool dizini
Bir dosya cron.daily altına bırakıldığında günlük, cron.weekly altına bırakıldığında haftalık olarak çalıştırılabilir. Ancak daily veya weekly ifadeleri tek başına kesin bir saat belirtmez. Bu dağıtımdan dağıtıma değişir.
Not: Eğer zamanlanmış görevlerin çalışacağı belirlenen vakitlerde sistem kapalıysa anacron devreye girer. Sistem açıldığı zaman zamanlanmış görevleri gerçekleştirir.
Kullanıcıların zamanlanmış görevleri dağıtıma göre /var/spool/cron (rocky) veya /var/spool/cron/crontabs (debian) gibi dizinlerde tutulabilir. Bu dosyaları doğrudan düzenlemek yerine crontab -e kullanmak gerekir.