Systemd Öncesi init ve runlevel’lar
Bilindiği gibi Linux sistemlerde sistem açılışında runlevel dediğimiz sistemin sunacağı hizmetlere göre yapılandırıldığı çalışma seviyeleri mevcuttur. Basitce windows sistemlerde Safe mode ile girdiğimiz ve sistemlerin tekli kullanıcı moda’ta sorunları çözebileceğimz şekilde de Linux işletim sisteminde RunLevel ‘lar günlük hayatımızda karşımıza çıkar.
Linux dünyasında RunLevel’lar değişik dağıtımlarda farklı işlevlere sahip olabilmektedir. Bu yazımızda daha çok Red Hat bazlı (Centos,OEL vs) işletim sistemlerin RunLevel’ları anlatılacaktır. Bu RunLevel’lar eskiden init dediğmiz ve işletim sistemi kernel yüklemesinden sonra çalışan ve PID (Process ID) 1 olan süreçlerle yönetilmekte idi. init süreci /etc/inittab dosyasını okuyup sistemin hangi Run Level’dan başlayacağına karar verirdi. Aşağıda /etc/inittab dosyasından bir kesit sunulmaktadır.
# Default runlevel. The runlevels used by RHS are: # 0 – halt (Do NOT set initdefault to this) # 1 – Single user mode # 2 – Multiuser, without NFS (The same as 3, if you do not have networking) # 3 – Full multiuser mode # 4 – unused # 5 – X11 # 6 – reboot (Do NOT set initdefault to this) # id:3:initdefault: |
Buradaki id:3:initdefault: satırı bizim işletim sistemimizin RunLevel 3 ‘den başlayacağını göstermektedir. Red Hat sistemlerde RunLevel’lar
· 0 – halt (Sistemi kapatmak –poweroff veya halt- için kullanılan runlevel)
· 1 – Single user mode (Sistemi kurtarmak için kullanılan ve network ayarlarının aktive edilmediği tekli kullanıcı mode’u. Bazı yerlerde S veya s olarak da adlandırılır.
· 2 – Multiuser NFS olmadan çoklu kullanıcı mode’u (Bu runlevel 3. Runlevel ile genel olarak aynıdır. Tek fark network ayarlarını içermemesidir.)
· 3 – multiuser mode (Network ayarlarını nda aktive edildiği ve genellikle kullanılan RunLevel’dır.
· 4 – kullanılmıyor.
· 5 – X11 (Runlevel 3 e ek olarak görsel ekranın- ki biz buna X veya X11 de deriz- da başlatıldığı runlevel. Runlevel 3’den sonra en çok tercih edilen runlevel’dır.)
· 6 – reboot (Sistemin kapatılıp tekrar açıldığında kullanılan RunLevel’dır.
İnit süreci ön tanımlı runlevel’ı ayarladıktan sonra sistemde /etc/rc.d/init.d/ altında bulunan ve rpm paketleri içinde gelen servis scriptlerini (bunlar bir shell scripttir!) çalıştırır. Örnek olarak eğer runlevel 3 de isek ve sshd servisi çalışacaksa bunun başlangıç scripti /etc/rc.d/init.d/sshd altında yer almakta. Bunun runlevel 3 de çalışmasını da /etc/rc.d/rc3.d/S55sshd scripti sağlamakta idi. Buradaki S harfi bunun start edilleceği, 55 ise başlangıç sırasını belirtmektedir.
# ls -la /etc/rc.d/rc3.d/S55sshd lrwxrwxrwx 1 root root 14 Jun 6 2011 /etc/rc.d/rc3.d/S55sshd -> ../init.d/sshd |
Systemd Tarihçesi ve init ‘e göre avantajları
Linux sistemlerde yaygın olarak kullanılmaya başlayan systemd 30 Mart 2010 Lennart Poettering ve Kay Sievers tarafından init sisteminin alternatifi olarak yazıldı. Bu yapı yeni Linux sistemleri ile (RedHat tabanlı sistemlerde RHEL 7 ile, SLES’de SLES 12 de, Debian da Debian 8 ile) yerini systemd ye bıraktı. Her ne kadar systemd üzerinde tartışmalar devam etse ve bazıları UNIX felsefesine aykırı da bulsa systemd’nin önümüzdeki yıllarda daha fazla kabul göreceği de düşünürsek systemd’yi önyargısız olarak inceleyip,öğrenmekte fayda var.
Diğer dağıtımlardaki durumuna https://en.wikipedia.org/wiki/Systemd adresindeki “Adoption and reception” kısmından da erişilebilen systemd nin genel olarak şu avantajları mevcuttur.
1. SysV init script’leri ile tam uyumludur. Init.d altındaki scriptleri de çalıştırabilir.
2. Serivslerin parallel olarak başlatılabilmesi (dolayısıyla daha hızlı sistem açılışı ve kapanışı)
3. Servislerin on-deman aktivasyonu. Yani bir servisi başlatırken onun ihtiyacı olan diğer servislerin de otomatik başlatılması
4. Sistem servislerinin snapshot’ının alınabilmesi (Yani basitçe ifade ile kendi runlevel’larınızı oluşturabilme diyebiliriz buna)
5. Servis bir şekilde ölürse bunun tesbiti ve ilgili servisin tekrar başlatılması
Systemd Bileşenleri
Systemd unit adı veridğimiz bileşen ve bunların kendi arasındaki ilişkilerinden oluşmaktadır. Systemd binary’si /usr/lib/systemd/systemd dosyası olarak sistemde bulunmakta ve systemd rpm paketi tarafından kurulmaktadır. Systemd binary’si eski yapıdaki /sbin/init programının yerini alır. Şu an için RHEL 7 ‘de zaten /sbin/init tam manasıyla /usr/lib/systemd/systemd dosyasına bir linktir.
Systemd Önemli Dizinler
Dizin |
Açıklaması |
/usr/lib/systemd/system/ |
RPM paketleri systemd servislerinin yapılandırma dosyasını buraya kurmaktadır. |
/run/systemd/system/ |
Runtime dediğimiz işletim sistemi çalışırken bu dizin kullanılır. |
/etc/systemd/system/ |
Systemd servisleri enable veya disable edildiğinde /usr/lib/systemd/system dizinindeki dosyalar buraya linklenir. |
Az önce bahsettiğimiz gibi systemd bileşenleri unit yapılandırma dosyalarından oluşmaktadır. Bu yapılandırma dosyaları sadece servisler için değil runlevel’ların yerini alan target (evet artık runlevel yerine target’lar var. Yazınının ilerleyen kısımlarında bunlardan da bahsedeceğiz) lar, mount edilecek bileşenleri içeren kısımlar ve birçok bileşenden oluşabilmektedir. Bu dosyalar /usr/lib/systemd/system dizini altında şu uzantılarla yer alabilmektedir.
Unit Tipi |
Dosya Uzantısı |
Açıklaması |
Service unit |
.service |
Sistem servisi |
Target unit |
.target |
Systemd unit grubu (eski runlevel’lar) |
Automount unit |
.automount |
Automount edilecekler |
Device unit |
.device |
Kernel’ın tanıdığı cihaz dosyaları. |
Mount unit |
.mount |
Mount edilecek dosya sistemleri |
Path unit |
.path |
Dosya sistemindeki dosya veya dizinler |
Scope unit |
.scope |
Sonradan çalıştırılan harici programlar. |
Slice unit |
.slice |
Sistem süreçlerini yöneten belirli bir hiyerarşideki unit dosyaları. |
Snapshot unit |
.snapshot |
Systemd’nin snapshotları (kendimizin oluşturuduğu runlevel’lar denebilir) |
Socket unit |
.socket |
IPC için kullanılan dosyaları oluşturan unit dosyaları |
Swap unit |
.swap |
Swap dosyası veya swapleri aktive eden unit dosysaları |
Timer unit |
.timer |
Systemd timer |
Yukarıda tipleri verilen unit dosyalarından en önemlileri ve günlük hayatta en çok kullandığımız bileşenler servisler ve target’lardır. Uzantısı .service olarak bildirilenler servisleri (Ör: sshd.service), uzantısı .target olanlar ise Target’ları yani eski adı ile runlevel’ları (Ör: multi-user.target) oluşturmaktadır.
Systemd Komutları
Systemctl
Sistem servislerini yönetmek için kullanılan komutlar eskiden (RHEL 7 öncesi) chkconfig ve service komutları idi. Chkconfig bir servisi enable/disable etmek için kullanılırken, service komutu ilgili servisi start/stop/restart işlemleri için kullanılırdi. Yani ilgili runlevel’da bir servisi açıp,kapamak için chkconfig komutu kullanılırken ayrıca bir de service komutu ile servisi start etmek gerekiyordu. Systemd ile gelen tek bir komutla yanı systemctl komutu ile artık bu iki işlev birleştirildi. Yani artık servislerin enable,disable edilmesi ve stop/start işlemleri systemctl komutu ile yapılabilir hale geldi.
Eski yapıya bir örnek vermek gerekirse önceklike bir servis enable ediliyordu chkconfig komutu ile
# chkconfig sshd on # chkconfig –list sshd sshd 0:off 1:off 2:on 3:on 4:on 5:on 6:off |
Daha sonra ilgli servis start ediliyordu:
# service sshd start |
Şimdi bu işlemi sadece systemctl komutu ile yapıyoruz.
# systemctl enable sshd # systemctl start sshd
Burada ek olarak şunu da yapabilirdik.
# systemctl enable sshd.service # systemctl start sshd.service
|
Sshd servisi veya unit dosyası tek olduğu için ve o da bir servis olduğu için .service kısmını yazmamıza gerek bulunmamakta. Zaten sshd yazıp TAB tuşuna bastığınızda shell bizim için otomatikman bunu sshd.service olarak tamamlayabilmektedir. Diğer systemctl komutları şu şekildedir. Aşağıda eski sistemlerde kullanılan service ve chkconfig komutları karışılığı da ayrıca verilmiştir.
service |
systemctl |
Açıklama |
service name start |
systemctl start name.service |
Servisi başlatır. |
service name stop |
systemctl stop name.service |
Servisi durdurur. |
service name restart |
systemctl restart name.service |
Servisi restart eder. |
service name condrestart |
systemctl try-restart name.service |
Servis eğer başlatılmışsa restart eder. |
service name reload |
systemctl reload name.service |
Servisi reload eder (-1 sinyali) |
service name status |
systemctl status name.service
veya
systemctl is-active name.service |
Servis çalışıyor mu diye kontrol eder. |
service –status-all |
|
Bütün servisleri (her bir servisin bir unit dosyası olduğunu unutmayalım) listeler. |
chkconfig |
systemctl |
Açıklama |
chkconfig name on |
systemctl enable name.service |
Servisi enable eder. |
chkconfig name off |
systemctl disable name.service |
Servisi disable eder. |
chkconfig –list name |
systemctl status name.service
veya
systemctl is-enabled name.service |
Bir servis enable edilmiş mi sorgular. |
chkconfig –list |
systemctl list-unit-files –type service |
Bütün servisleri listeler. |
Örnek kullanım. Aşağıda sshd servisi disable edilip stop edildikten sonra (Disable edien servis stop edilmez!. Stop komutu ile ayrıca servis durdurulmalıdır. Yine aynı şekilde enable edilen servis start edilmez, start komutu ile başlatılmalıdır)
[root@egitim ~]# systemctl disable sshd rm ‘/etc/systemd/system/multi-user.target.wants/sshd.service’
[root@egitim ~]# systemctl stop sshd
[root@egitim ~]# systemctl enable sshd ln -s ‘/usr/lib/systemd/system/sshd.service’ ‘/etc/systemd/system/multi-user.target.wants/sshd.service’
[root@egitim ~]# systemctl start sshd
[root@egitim ~]# systemctl status sshd sshd.service – OpenSSH server daemon Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled) Active: active (running) since Fri 2015-10-02 15:09:20 EEST; 8s ago Main PID: 2894 (sshd) CGroup: /system.slice/sshd.service └─2894 /usr/sbin/sshd -D
Oct 02 15:09:20 egitim.faruk.net systemd[1]: Started OpenSSH server daemon. Oct 02 15:09:20 egitim.faruk.net sshd[2894]: Server listening on 0.0.0.0 p…. Oct 02 15:09:20 egitim.faruk.net sshd[2894]: Server listening on :: port 22. Hint: Some lines were ellipsized, use -l to show in full. |
Target’lar (Eski adı ile Runlevel’lar)
System yapısı ile artık runlevel’lar yeni bir isim aldı. Değişik servislerin birleşmesi ile oluşan runlevel’lara artık target ismi verilmektedir. Bu runlevel’ların geriye dönük isimlendirilmeler korunsa da uzun vadede bu takma adlar (aliaslar) kaldırılacaktır. Eskiden 0-6 arası runlevel’lar varken yeni yapıdaki target’lar şu şekildedir.
Runlevel |
Target Unit |
Açıklama |
0 |
runlevel0.target, poweroff.target |
Poweroff target |
1 |
runlevel1.target, rescue.target |
Rescue yani kurtarma target’ı |
2 |
runlevel2.target, multi-user.target |
Çoklu kullanıcı target’ı (runlevel2,runlevel 3 ve 4 aynı). |
3 |
runlevel3.target, multi-user.target |
Çoklu kullanıcı target’ı (runlevel2,runlevel 3 ve 4 aynı). |
4 |
runlevel4.target, multi-user.target |
Çoklu kullanıcı target’ı (runlevel2,runlevel 3 ve 4 aynı). |
5 |
runlevel5.target, graphical.target |
Grafik ekranın başlatıldığı target. |
6 |
runlevel6.target, reboot.target |
Reboot target. |
Örnek kullanımlar:
Öntanımlı sistemin çalıştığı target’I sorgulamak için:
# systemctl get-default graphical.target
|
Reboot sırasında sistemin sıfırdan açıldığı target değiştirmek için (aslında yapılan bir link işlemi)
rm '/etc/systemd/system/default.target'
ln -s '/usr/lib/systemd/system/multi-user.target' '/etc/systemd/system/default.target'
|
Sistem çalışırken bir anda farklı bir target’a geçmel için ( eskiden init 3 ile yapılan işlem)
#
|
Ayrıca bunlara ek olarak systemctl poweroff, systemctl reboot , systemctl halt komutları da kullanılmaktadır. Zaten bu 3 komutta artık systemctl komutuna bir linktir.
[root@egitim ~]# ls -la /sbin/poweroff lrwxrwxrwx. 1 root root 16 Sep 12 00:02 /sbin/poweroff -> ../bin/systemctl
[root@egitim ~]# ls -la /sbin/reboot lrwxrwxrwx. 1 root root 16 Sep 12 00:02 /sbin/reboot -> ../bin/systemctl
[root@egitim ~]# ls -la /sbin/halt lrwxrwxrwx. 1 root root 16 Sep 12 00:02 /sbin/halt -> ../bin/systemctl |
Unit dosyaları
Şu ana kadar anlattığımız üzere bütün servis ve target’lar aslında /usr/lib/system/system altında bulunan dosyalardan oluşmaktadır. Örnek olarak sshd.service dosyasının içine bakarsak:
/usr/lib/system/system/sshd.service
[Unit] Description=OpenSSH server daemon After=network.target sshd-keygen.service Wants=sshd-keygen.service
[Service] EnvironmentFile=/etc/sysconfig/sshd ExecStart=/usr/sbin/sshd -D $OPTIONS ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartSec=42s
[Install] WantedBy=multi-user.target |
Burada görüldüğü gibi bir unit file içinde ini dosyalarına benzer bir format bulunmaktadır. Burada Unit, Service ve Install ana başlıkları mevcuttur.
Unit kısmında Description,After ve Wants kısımları servisin açıklamasını, Servisin hangi servislerden sonra başlatılması gerektiğini ve servisin hangi servisin de başlatılmış olduktan sonra başlatıldığı göstermektedir.
Service kısmında servisi start stop etmek için asıl parametreler yer almaktadır. Burada RestartSec kısmı önemlidir. Mesela olursa servis bir şekilde ölürse systemctl bu servisi 42 sn sonra tekrar başlatmaktadır.
Son kısım Install kısmı ise servisin runlevel3 yani yeni adı ile multi-user.target tarafından servis kurulumu aşamasında ihtiyaç duyulduğu manasına gelmektedir.
Journalctl komutu
Systemd altyapısı loglarını journal denen formatta /run/log/journal/
dizinine atmaktadır. Aslında tıpkı systemd, init altyapısını nasıl değiştirdiyse ileride systemd-journald servisi de rsyslog altyapısını değiştirebilir. Tabiki şu an için bu sadece tartışılan bir konu ama ileride olması olası. Peki neden? Buradaki amaç logların indexlenerek , binary bir dosyada saklanması ve istenen log satırlarının komutlarla hızlıca bulunması (normalde syslog loglarını grep veya tail –f ile incelemekteyiz). Tabiki bu olur mu bilmiyoruz ama şu an için diyebileceğimiz
1. Systemd logları journald vasıtasıyla tutmaktadır.
2. Bu loglar /run/log/journal dizininde bulunmakta ve her sistem reboot edilişinde tekrar oluşturulmaktadır
3. Eğer bu log dosyalarının kalıcı olması isteniyorsa /var/log/journal dizini oluşturulup ilgili systemd-journald servisi tekrar başlatılmalıdır. (systemctl restart systemd-journald.service)
4. Journald loglarını görmek için ve loglarda arama yapmak için journalctl komutu kullanılır.
Örnek journalctl komutu kullanımı:
Sistem boot ettikten sonraki bütün journal loglarını görmek için:
# journalctl -b |
Sadece belirli prioritydeki logları görmek için. Mesela error seviyesindeki
# journalctl –p err |
Tail –f komutundaki gibi yeni gelen logları takip için:
# journalctl -f |
Belirli bir tarihten sonraki logları görmek için:
# |
Yararlı sayfalar:
http://www.freedesktop.org/wiki/Software/systemd/
https://access.redhat.com/articles/754933
http://0pointer.de/blog/projects/why.html