Bu yazımda Systemd’den bahsedeceğim, pek hikaye gibi bir yazı beklemeyin, hızlı bir şekilde teknik bilgiye hazır olun.
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 kavramina 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 file’larda tanımlanır. Bunların yaptığı işi de kısaca özetlemek gerekirse 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 için aşağıdaki komut kullanılabilir:
# systemctl get-default
Sistemdeki tüm target’lerı görüntülemek için ise systemctl aşağıdaki şekilde kullanılabilir:
# 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ı
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
Bir servisin durumunu kontrol etmek için;
systemctl status application.service
Bütün servisleri görmek için;
systemctl list-units — type=service — all
Bir servisin detayları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.
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