Tại sao tôi nhận được trạng thái thoát khác nhau cho ps | grep trong một kịch bản?


11

Tôi đang chạy bên dưới kịch bản:

#!/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

Đầu ra giống như ::

[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

Khi tôi chạy cùng dòng lệnh, tôi sẽ nhận được trạng thái thoát là 1:

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

Trường hợp giống như véc ni không được cài đặt trong máy chủ. Kịch bản này hoạt động tốt trong một máy chủ nơi cài đặt véc ni.

Tại sao trạng thái thoát khác nhau khi chạy bằng cách sử dụng tập lệnh và dòng lệnh? Làm thế nào để cải thiện kịch bản này?


Sử dụng một hệ thống giám sát quá trình thực sự, không phải loại tin tặc này. Hệ điều hành của bạn gần như chắc chắn sẽ có một cách tích hợp để đảm bảo rằng các trình tiện ích bạn muốn ở lại sẽ tự động được khởi động lại khi thất bại, có thể là mới, daemontools, systemd, launchd hoặc một trong nhiều, nhiều lựa chọn thay thế khác. Tất cả trong số họ sẽ mạnh mẽ hơn và có khả năng hơn loại tin tặc cuộn tay này.
Charles Duffy

Câu trả lời:


10

Khi bạn chạy một kịch bản có tên là check_varnish_pro.shthử nghiệm

ps ax  | grep -q [v]arnish

là thành công vì có một kịch bản có tên là check_véc ni_pro đang chạy.


14

Nói chung, đó là một ý tưởng tồi để thử cách tiếp cận đơn giản psgrepcố gắng xác định xem một quy trình nhất định có đang chạy hay không.

Bạn sẽ tốt hơn nhiều khi sử dụng pgrepcho việc này:

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

Xem hướng dẫn cho pgrep. Trên một số hệ thống (có thể không phải trên Linux), bạn nhận được một -qcờ tương ứng với cùng một cờ để grepthoát khỏi nhu cầu chuyển hướng đến /dev/null. Ngoài ra còn có một -fcờ thực hiện trận đấu trên dòng lệnh đầy đủ thay vì chỉ trên tên quy trình. Người ta cũng có thể giới hạn sự phù hợp với các quy trình thuộc về một người dùng cụ thể bằng cách sử dụng -u.

Cài đặt pgrepcũng cung cấp cho bạn quyền truy cập pkillcho phép bạn báo hiệu các quá trình dựa trên tên của họ.

Ngoài ra, nếu đây là một trình nền dịch vụ và nếu hệ thống Unix của bạn có cách truy vấn thông tin đó (ví dụ: liệu nó có hoạt động hay không), thì đó là cách kiểm tra thích hợp .

Trên Linux, bạn có systemctl( systemctl is-active --quiet varnishsẽ trả về 0 nếu nó đang chạy, 3 nếu không), trên OpenBSD bạn có rcctl, v.v.


Bây giờ đến kịch bản của bạn:

Trong kịch bản của bạn, bạn phân tích đầu ra từ ps ax. Đầu ra này sẽ chứa tên của chính tập lệnh check_varnish_pro.sh, rõ ràng chứa chuỗi varnish. Điều này cung cấp cho bạn một dương tính giả. Bạn sẽ phát hiện ra điều này nếu bạn đã chạy nó mà không có -qcờ greptrong khi thử nghiệm.

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

Chạy nó:

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

Một vấn đề khác là mặc dù bạn cố gắng "che giấu" grepquá trình khỏi bị phát hiện bởi grepchính nó bằng cách sử dụng [v]trong mẫu. Cách tiếp cận đó sẽ thất bại nếu bạn tình cờ chạy tập lệnh hoặc dòng lệnh trong một thư mục có tệp hoặc thư mục có tên varnishtrong đó (trong trường hợp đó bạn sẽ lại nhận được dương tính giả). Điều này là do mẫu không được trích dẫn và shell sẽ thực hiện tên tệp toàn cầu với nó.

Xem:

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

Sự hiện diện của tệp varnishsẽ khiến shell thay thế [v]arnishbằng tên tệp varnishvà bạn nhận được một cú đánh vào mẫu trong bảng quy trình ( grepquy trình).


4
bởi vì tất cả mọi thứ là một tập tin "trong đất linux".
zee

@ z_- Không hoàn toàn chắc chắn về cách nó được kết nối, nhưng điều này vẫn đúng ngay cả trên các Unice không phải của Linux.
Kusalananda

4
Không chỉ quá trình grep; kịch bản được đặt tên check_varnish_pro.shcũng là một yếu tố.
TNW

@TNW Lúc đầu tôi không phát hiện ra điều đó, nhưng bạn nói đúng. Tôi sẽ thêm nó vào.
Kusalananda

3

@AlexP giải thích rất ngắn gọn những gì đang thực sự xảy ra, nhưng ý tưởng sử dụng pgrep/ pkillcho một quá trình quan trọng của @ Kusalananda rất không được khuyến khích . Các giải pháp tốt hơn bao gồm:

  • Hỏi dịch vụ cho dù nó đang chạy. systemctl status varnishdnên quan tâm đến việc cài đặt * nix hiện đại.
  • Nếu trong một số trường hợp không may bạn không có dịch vụ, bạn chỉ cần thay đổi tập lệnh khởi động để báo cáo sự cố ngay khi quá trình thoát:

    varnish || true
    some_command_to_send_an_alert_that_the_service_has_died
  • Hoặc thay đổi tập lệnh khởi động dịch vụ để ghi lại PID, và sau đó kiểm tra trạng thái theo định kỳ kill -0 "$pid".

Tôi đồng ý, tôi chỉ giải quyết các khía cạnh kịch bản shell của vấn đề. Lưu ý rằng systemctlhầu như chỉ có sẵn trên Linux mặc dù (AFAIK) và không có trên tất cả các hệ thống giống như Unix hiện đại.
Kusalananda

Câu hỏi ban đầu có thẻ "linux"; Tôi không chắc tại sao điều đó đã bị xóa bởi @muru.
l0b0

Cảm ơn l0b0. Tôi đã có hai câu hỏi "Tại sao" và "Cách cải thiện". Câu trả lời của @ AlexP đã giải quyết câu hỏi đầu tiên của tôi và câu trả lời của bạn là giải pháp tốt hơn cho câu hỏi thứ hai. Nhưng Kusalananda giải thích những điều liên quan đến điều này mà tôi nghĩ sẽ hữu ích cho những người có vấn đề tương tự. Vì vậy, tôi bối rối bây giờ để chấp nhận như là câu trả lời.
prado

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.