Cara "tepat" untuk menguji apakah suatu layanan berjalan dalam skrip

96

Masalahku:

Saya sedang menulis skrip bash dan di dalamnya saya ingin memeriksa apakah layanan yang diberikan berjalan.

Saya tahu cara melakukannya secara manual, dengan $ service [service_name] status.

Tapi (terutama sejak pindah ke systemd) yang mencetak sejumlah teks yang agak berantakan untuk diurai. Saya berasumsi ada perintah yang dibuat untuk skrip dengan output sederhana atau nilai pengembalian yang bisa saya periksa.

Tetapi Googling hanya menghasilkan satu ton hasil "Oh, hanya ps aux | grep -v grep | grep [service_name]". Itu bukan praktik terbaik, bukan? Bagaimana jika instance lain dari perintah itu sedang berjalan, tetapi tidak ada yang memulai dengan skrip init SysV?

Atau haruskah saya tutup mulut dan tangan saya kotor dengan pgrep kecil?

Nick S
sumber

Jawaban:

140

systemctlmemiliki is-activesub- perintah untuk ini:

systemctl is-active --quiet service

akan keluar dengan status nol jika serviceaktif, bukan nol, sehingga ideal untuk skrip:

systemctl is-active --quiet service && echo Service is running

Jika Anda menghilangkannya --quietjuga akan menampilkan status saat ini ke keluaran standarnya.

Seperti yang ditunjukkan oleh don_crissti , beberapa unit dapat aktif meskipun tidak ada yang berjalan untuk menyediakan layanan: unit yang ditandai sebagai "RemainAfterExit" dianggap aktif jika mereka keluar dengan sukses, gagasan bahwa mereka menyediakan layanan yang tidak memerlukan daemon ( misalnya mereka mengkonfigurasi beberapa aspek sistem). Namun, unit yang melibatkan daemon hanya akan aktif jika daemon masih berjalan.

Stephen Kitt
sumber
Hati-hati dengan layanan oneshot. Mereka hanya inactiveatau activatingdan keduanya systemctl statusdan systemctl is-activekeluar dengan 3. (pada systemd-241 ) Penanganan masalah:systemctl show service | grep -qx ActiveStatus=activating
Alois Mahdal
@ Allois Saya ingin tahu skenario seperti apa yang Anda temui di mana Anda ingin mempertimbangkan layanan oneshot menjadi aktif; Apakah kamu punya contoh?
Stephen Kitt
Tentu, @StephenKitt. Alat foomelakukan sesuatu pada sistem yang melibatkan reboot dan menggunakan layanan sekali pakai, katakanlah, foo_cleanuppada boot berikutnya untuk membersihkan segalanya. Aku pengujian ini (script saya juga dijadwalkan sebagai layanan) dan ingin mengumpulkan kesalahan setelah itu, tetapi ketika adalah setelah (Vsauce musik)? Nah salah satu kriterianya adalah yang foo_cleanupsudah selesai ("berhenti aktif").
Alois Mahdal
Mungkin perlu untuk menunjukkan bahwa 'gagal' juga merupakan opsi, dan berguna jika Anda perlu melakukan tindakan berdasarkan layanan yang tidak dimulai.
Phill Healey
33

systemctlmemang memiliki mode yang cocok untuk skrip; gunakan showdaripada status, dan tambahkan opsi -p/ --propertiesdan --valueuntuk mendapatkan hanya output yang Anda inginkan.

Berikut ini sebuah contoh (dari sistem Ubuntu 17.04):

$ systemctl show -p SubState --value NetworkManager
running

Menjalankan (atau sebaliknya) adalah a SubState. Jika Anda ingin tahu apakah suatu layanan aktif, gunakan properti tersebutActiveState

$ systemctl show -p ActiveState --value x11-common
inactive
$ systemctl show -p SubState --value x11-common
dead

Catatan dari man:

show [PATTERN...|JOB...]
           Show properties of one or more units, jobs, or the manager
           itself. If no argument is specified, properties of the
           manager will be shown. If a unit name is specified, properties
           of the unit are shown, and if a job ID is specified,
           properties of the job are shown. By default, empty properties
           are suppressed. Use --all to show those too. To select specific
           properties to show, use --property=. This command is intended
           to be used whenever computer-parsable output is required. Use
           status if you are looking for formatted human-readable output.

-p, --property=
           When showing unit/job/manager properties with the show command,
           limit display to properties specified in the argument. The
           argument should be a comma-separated list of property names,
           such as "MainPID". Unless specified, all known properties are
           shown. If specified more than once, all properties with the
           specified names are shown. Shell completion is implemented for
           property names.

--value
           When printing properties with show, only print the value, and
           skip the property name and "=".
Zanna
sumber
2
+1 untuk jawaban canggih. mohon tentukan distro yang akan menerima --versionopsi dengan systemctl.
SK Venkat
11

Sebagai pelengkap jawaban Zanna, --valueopsi untuk systemctl showtelah diperkenalkan dengan versi 230 dari systemd . Jadi mungkin tidak tersedia di distro tertentu seperti debian jessie.

Dalam hal ini, seseorang dapat meniru opsi dengan menggunakan sed:

$ systemctl show -p ActiveState sshd | sed 's/ActiveState=//g'
active
$ systemctl show -p SubState sshd | sed 's/SubState=//g'  
running
Oxmel
sumber
1
+1 untuk menunjukkan versi & distro --value intro yang tidak akan berfungsi.
SK Venkat
3

saya menemukan ini berguna untuk eksekusi baris perintah atau jika Anda membuat skrip.

Disalin dari @StephenKitt

Ini akan memeriksa apakah layanan tidak aktif dan melakukan restart layanan

systemctl is-active --quiet <service name> || <service name> restart

di ||sana memeriksa apakah nilai kembali dari systemctl adalah non-nol yang berarti jika tidak aktif seperti yang dijelaskan oleh penulis.

asterisk
sumber
Anda juga dapat menggunakan `is-gagal 'untuk menguji apakah diperlukan restart. Tampaknya sedikit lebih intuitif untuk memulai kembali layanan yang gagal.
Phill Healey
ya, tetapi bagi saya .. saya ingin berlatih sendiri dan menganggap semuanya berjalan ketika tidak. jadi saya bisa memverifikasi hal-hal lain dengan itu. hanya jika Anda hanya ingin memeriksa apakah itu tidak berjalan, maka 'gagal' adalah pilihan yang tepat. :)
asterisk
3


Saya terlambat ke pesta, namun menggunakan systemctl aktif bersama &&dan ||untuk ini dalam skrip tidak akan terjadi sepanjang waktu. Di bawah ini adalah yang saya gunakan untuk kucing jantan tetapi dapat menggunakannya dalam metode mengambil argumen dan memberikan nama layanan sebagai argumen jika Anda harus memeriksa beberapa layanan tetapi di luar ruang lingkup di sini.

STATUS=`systemctl is-active tomcat.service`
  if [[ ${STATUS} == 'active' ]]; then
    echo "Execute your tasks ....."
  else 
    echo " Service not running.... so exiting "  
    exit 1  
  fi

Ini adalah bagaimana saya memanfaatkan .... Hanya berbagi milik saya.

dan untuk kesederhanaan dan kemudahan, ikuti yang lain yang dijelaskan di sini:

systemctl -q is-active tomcat.service  && echo "Tomcat Runnung" || echo "Service is not running at all "
SAGAR Nair
sumber
Bagaimana itu lebih baik daripada sekadar if systemctl is-active --quiet tomcat.service? Juga, [[bukan shell standar.
Toby Speight
@TobySpeight Anda perlu membaca posting saya sedikit lebih seperti yang saya sebutkan di posting saya "Ini adalah bagaimana saya memanfaatkan .... Hanya berbagi milikku." Saya tidak pernah mengatakan, ini adalah penggunaan shell standar, jika Anda membuatnya menjadi braket tunggal, itu akan menjadi tapi itu di luar jangkauan di sini. Selain itu saya di bawah ini menyebutkan penggunaan satu baris mudah untuk melakukannya menggunakan &&dan ||.
SAGAR Nair
2

Alih-alih menggunakan perintah sed seperti dalam jawaban Oxmel, itu cukup untuk digunakan cut -d'=' -f 2untuk semua jenis properti yang ditanyakan:

sebagai contoh:

$ systemctl show -p ActiveState sshd | cut -d'=' -f2
active
$ systemctl show -p SubState sshd | cut -d'=' -f2
running
Mohamed El
sumber
Itu bagus tetapi Anda benar-benar perlu memberikan penjelasan tentang apa yang dilakukan perintah-perintah itu.
Phill Healey
-1

Baru saja menemukan skrip kecil yang hebat ini:

#!/bin/bash
service=replace_me_with_a_valid_service

if (( $(ps -ef | grep -v grep | grep $service | wc -l) > 0 ))
then
  echo "$service is running!!!"
else
  /etc/init.d/$service start
fi

Sumber

Terry
sumber
Tidak semua layanan memiliki executable dengan nama yang sama, dan setiap pengguna dapat menjalankan perintah yang tidak sengaja cocok - ini adalah resep untuk bencana.
Toby Speight