Linux’ta servisler, uygulamaların arkaplanda asenkron biçimde çalışmalarını sağlar. Web uygulama veya yazdığınız herhangi bir sistem yazılımı, servisler sayesinde sistemle birlikte otomatik olarak açılıp, arkaplanda çalışır hale getirilebilirler.

Servisleri pratikliğinden dolayı genelde “systemd” isimli bir program kullanarak oluşturmaktayız. Ubuntu, Debian, Fedora, Arch Linux, Gentoo, RHEL/CentOS gibi birçok platformlarda varsayılan olarak yüklü gelmektedir. systemd yalnızca servis değil; soket, aygıt, mounting ve swapping gibi pek çok farklı kaynak türleri için kullanılabilmektedir, fakat bu yazıda sadece servis özelliğinden bahsedeceğiz.

systemd’de servis oluşturmak için bize gereken tek şey, çalıştırılacak olan komuttur. Bunu ExecStart= parametresinden hemen sonrasında belirtiyoruz.

Örnek bir systemd servis dosyası formatı:

[Unit]
Description=Örnek blog sitesi
After=network.target

[Service]
Type=simple
Restart=always
WorkingDirectory=/opt/iamdual/
ExecStart=/usr/bin/python3 /opt/iamdual/server.py

[Install]
WantedBy=multi-user.target

Bu komutları /etc/systemd/system/blog.service dosyasına yazdıktan sonra servisimizi “systemctl” ile aktifleştirip başlatabiliriz.

systemctl daemon-reload
systemctl enable blog.service
systemctl start blog
# veya: service blog start

Servis oluşturulup aktifleştirildikten sonra sunucu (daha doğrusu systemd) çalışmaya başladıktan sonra veya daha önce başlamamış ise start komutu verdikten sonra servis, otomatik olarak başlamaktadır. Bir sorun meydana geldiğinde ise journalctl -xfe komutuyla servisin açılmasına engel olan hatanın çıktısını bulabiliriz.

Şimdi systemd servis dosyalarında kullanılabilecek bölümler, bazı parametreler ve değerleri hakkında biraz bilgi verelim.

[Unit] bölümü neredeyse tüm systemd config dosyalarında (kısaca unit’lerde) bulunur. Bu bölümde servis hakkındaki metadata bilgileri yer alır. Servis adı, açıklaması, ne zaman çalıştırılacağı ve çalışması için nelerin gerektiği belirtilir.

  • Description=: Servisin kısa ve öz bir açıklaması girilir.
  • Requires=: Servis için gerekli olan unit’ler girilir. Girilenler mevcut servis ile aynı anda başlatılır. Eğer girilenlerden birisi bile başarısız olursa servis başlatılmaz.
  • Wants=: Requires= ile pek çok benzer yanı bulunur; tek farkı girilenlerden biri başarısız olsa bile mevcut servis başlatılmaya çalışılır.
  • BindsTo=: Requires= ile pek çok benzer yanı bulunur; tek farkı girilenlerden biri başarısız olursa, mevcut servisin çalıştırılması durdurulur.
  • Before=: Servisten sonra çalıştırılacak unit’ler buraya girilir ve girilenler mevcut servisten önce çalıştırılmaz.
  • After=: Servisten önce çalıştırılacak unit’ler buraya girilir ve girilenler mevcut servisten sonra çalıştırılmaz.
  • Conflicts=: Servisle birlikte çalıştırılamayacak olarak unit’ler buraya girilir ve girilenler mevcut servis başladığında sonlandırılır.

[Service] bölümü sadece servis dosyalarında bulunur ve servis hakkındaki detayları içerir. Çalıştırılacak komut, hangi durumda yeniden başlatılacağı, hangi user/group ile çalıştırılacağı vs. bu kısımdan ayarlanır.

  • Type=: Servisin türü bu parametrede belirtilir.
    • simple: Varsayılan servis türüdür. Servisi başlatan komut terminalde SIGINT (ctrl+C) ile sonlandırana kadar çalışıyorsa, türü bu olmalıdır.
    • exec: Bu simple ile benzer özelliklere sahiptir fakat, simple servisi başlatıldıktan sonra servisin hata tespit takibi geciktirilirken, exec ile hata tespiti servis komutu çalıştırıldıktan hemen sonra yapılmaya başlanır.
    • forking: Servisi başlatan komut arkaplanda çalışmaya başlıyorsa (daemonized), seçilmesi gereken servis türü bu olmalıdır.
    • oneshot: Servis herhangi bir şey döndürmeden, sadece tek bir komut gönderecekse, bu tür seçilebilir. ExecStart= ve Type= belirtilmediği taktirde bu tür geçerli olur.

Bazı servis türlerinde kullanımı zorunlu parametreler mevcuttur. Örnek olarak:

  • PIDFile=: forking kullanıldıysa, başlatılan işlemin PID numarasının saklanacağı dosya ismini belirtmek için kullanılır. Servisin takibi buradan yapılır.
  • RemainAfterExit=: oneshot kullanıldıysa, servisin hala çalışır durumda olduğunu işlem sonlandıktan sonra bile belirtmek için kullanılır. yes veya no değeri alır.

Bir servis için yaygın olarak kullanılan parametreler aşağıdaki gibidir:

  • ExecStart=: Servisi başlatacak olan komut.
  • ExecStartPre=: Servis başlamadan önce çalıştırılacak olan komut.
  • ExecStartPost=: Servis başladıktan sonra çalıştırılacak olan komut.
  • ExecReload=: Servis yenilendikten sonra çalıştırılacak olan komut.
  • ExecStop=: Servis durdurulduktan sonra çalıştırılacak olan komut.
  • WorkingDirectory=: Servis çalıştırılırken kullanılacak olan path.
  • Environment=: Servis çalıştırılırken kullanılacak olan environment değeri.
  • EnvironmentFile=: Servis çalıştırılırken kullanılacak olan environment dosyası.
  • TimeoutStartSec=: Servisin başlaması için beklenecek maksimum süre.
  • TimeoutStopSec=: Servisin sonlanması için beklenecek maksimum süre.
  • TimeoutSec=: TimeoutStartSec= ve TimeoutStopSec= için kısayol parametresi.
  • RestartSec=: Restart= kullanılıyorsa, yeniden başlatmak için beklenecek süre.
  • Restart=: systemd’nin hangi durumda servisi otomatik olarak yeniden başlatılacağını belirtir. Aşağıda hangi değerlerin kullanılabileceğini gösteren tabloyu görebilirsiniz.
Restart sebeplerinoalwayson-successon-failureon-abnormalon-abort
Başarılı exit kodu (0)XX
Başarısız exit kodu*XX
Başarısız sinyal**XXXX
Zaman aşımıXXX

* Sıfır olmayan 1-255 sayıları arasındaki exit kodları.

** SIGHUP, SIGINT, SIGPIPE, SIGTERM dışındaki sinyaller.

Diğer parametreler hakkında bilgi edinmek için bu ve bu kaynağı inceleyebilirsiniz.