Mengapa saya mendapatkan status keluar yang berbeda untuk ps | grep dalam naskah?


11

Saya menjalankan skrip di bawah ini:

#!/bin/bash

ps ax  | grep -q [v]arnish
if [ $? -eq 0 ];then
        echo varnish is running...
        exit 0
else
        echo "Critical : varnish is not running "
        exit 2
fi

Outputnya seperti ::

[root@server ~]# sh -x check_varnish_pro.sh
+ ps ax
+ grep -q '[v]arnish'
+ '[' 0 -eq 0 ']'
+ echo varnish is running...
varnish is running...
+ exit 0

Ketika saya menjalankan yang sama di baris perintah saya mendapatkan status keluar sebagai 1:

[root@server ~]# ps ax  | grep -q [v]arnish; echo $?
1

Kasing seperti pernis tidak diinstal di server. Skrip ini berfungsi dengan baik di server tempat pernis diinstal.

Mengapa status keluar berbeda ketika dijalankan menggunakan skrip dan baris perintah? Bagaimana cara memperbaiki skrip ini?


Gunakan sistem pengawasan proses nyata, bukan jenis peretasan ini. Sistem operasi Anda hampir pasti memiliki cara built-in untuk memastikan bahwa daemon yang ingin Anda begadang secara otomatis dimulai kembali dari kegagalan, baik itu pemula, daemontools, systemd, launchd, atau salah satu dari banyak, banyak alternatif lain. Semua dari mereka akan lebih kuat dan mampu daripada jenis hackery linting tangan ini.
Charles Duffy

Jawaban:


10

Saat Anda menjalankan skrip bernama check_varnish_pro.shtes

ps ax  | grep -q [v]arnish

berhasil karena ada skrip bernama check_pernis_pro berjalan.


14

Secara umum, itu adalah ide yang buruk untuk mencoba pendekatan sederhana dengan psdan grepuntuk mencoba menentukan apakah suatu proses berjalan.

Anda akan jauh lebih baik menggunakan pgrepini:

if pgrep "varnish" >/dev/null; then
  echo "Varnish in running"
else
  echo "Varnish is not running"
fi

Lihat manual untuk pgrep. Pada beberapa sistem (mungkin bukan pada Linux), Anda mendapatkan -qbendera yang sesuai dengan bendera yang sama grepyang menghilangkan kebutuhan untuk mengarahkan ulang /dev/null. Ada juga -fbendera yang melakukan pertandingan pada baris perintah penuh dan bukan hanya pada nama proses. Satu juga dapat membatasi kecocokan dengan proses milik pengguna tertentu menggunakan -u.

Menginstal pgrepjuga memberi Anda akses pkillyang memungkinkan Anda memberi sinyal proses berdasarkan namanya.

Juga, jika ini adalah daemon layanan , dan jika sistem Unix Anda memiliki cara untuk menanyakan informasi (misalnya, apakah sudah aktif dan berjalan atau tidak), maka itu adalah cara yang tepat untuk memeriksanya.

Di Linux, Anda memiliki systemctl( systemctl is-active --quiet varnishakan mengembalikan 0 jika berjalan, 3 sebaliknya), pada OpenBSD yang Anda miliki rcctl, dll.


Sekarang ke skrip Anda:

Dalam skrip Anda, Anda mem-parsing keluaran dari ps ax. Output ini akan berisi nama skrip itu sendiri check_varnish_pro.sh, yang jelas berisi string varnish. Ini memberi Anda positif palsu. Anda akan melihat ini jika Anda menjalankannya tanpa -qflag untuk grepsaat pengujian.

#!/bin/bash
ps ax | grep '[v]arnish'

Menjalankannya:

$ ./check_varnish_pro.sh
31004 p1  SN+     0:00.04 /bin/bash ./check_varnish_pro.sh

Masalah lain adalah bahwa meskipun Anda mencoba untuk "menyembunyikan" grepproses agar tidak terdeteksi grepsendiri dengan menggunakan [v]dalam pola. Pendekatan itu akan gagal jika Anda menjalankan skrip atau baris perintah di direktori yang memiliki file atau direktori varnishdi dalamnya (dalam hal ini Anda akan mendapatkan false positive, lagi). Ini karena polanya tidak dikutip dan shell akan melakukan penggumpalan nama file dengannya.

Lihat:

bash-4.4$ set -x
bash-4.4$ ps ax | grep [v]arnish
+ ps ax
+ grep '[v]arnish'
bash-4.4$ touch varnish
+ touch varnish
bash-4.4$ ps ax | grep [v]arnish
+ ps ax
+ grep varnish
91829 p2  SN+p    0:00.02 grep varnish

Kehadiran file varnishakan menyebabkan shell untuk mengganti [v]arnishdengan nama file varnishdan Anda mendapatkan hit pada pola di tabel proses ( grepproses).


4
karena semuanya adalah file "di linux land".
zee

@ z_- Tidak yakin bagaimana itu terhubung, tetapi ini berlaku bahkan pada Unices non-Linux.
Kusalananda

4
Bukan hanya proses grep; naskah yang dinamai check_varnish_pro.shjuga merupakan faktor.
TNW

@TNW Saya tidak menemukan itu pada awalnya, tetapi Anda benar. Saya akan menambahkannya.
Kusalananda

3

@AlexP menjelaskan dengan sangat ringkas apa yang sebenarnya terjadi, tetapi gagasan @ Kusalananda tentang menggunakan pgrep/ pkilluntuk proses kritis sangat tidak disarankan . Solusi yang lebih baik meliputi:

  • Meminta layanan apakah berjalan. systemctl status varnishdharus mengatasinya pada instalasi * nix modern.
  • Jika karena keadaan yang tidak menguntungkan Anda tidak memiliki layanan yang tersedia, Anda dapat mengubah skrip startup untuk melaporkan masalah segera setelah proses keluar:

    varnish || true
    some_command_to_send_an_alert_that_the_service_has_died
  • Alternatif lain, ubah skrip yang memulai layanan untuk merekam PID, dan kemudian periksa status secara berkala dengan kill -0 "$pid".

Saya setuju, saya hanya menangani aspek skrip shell dari masalah. Perhatikan bahwa systemctlhampir hanya tersedia di Linux (AFAIK), dan tidak pada semua sistem mirip Unix modern.
Kusalananda

Pertanyaan aslinya memiliki tag "linux"; Saya tidak yakin mengapa itu dihapus oleh @muru.
l0b0

Terima kasih l0b0. Saya punya dua pertanyaan "Mengapa" dan "Bagaimana meningkatkan". @ AlexP menjawab pertanyaan pertama saya dan jawaban Anda adalah solusi yang lebih baik untuk pertanyaan kedua. Tetapi Kusalananda menjelaskan hal-hal terkait hal ini yang menurut saya akan sangat membantu bagi orang yang memiliki masalah serupa. Jadi saya bingung sekarang untuk menerima sebagai jawaban.
prado

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.