2010-07-21 36 views
5

Tôi đã tìm kiếm nhưng không tìm thấy những gì tôi đang tìm kiếm. Tóm lại, tôi đã tạo một tập lệnh bash để chạy trong một vòng lặp vô hạn, ngủ và kiểm tra xem một tiến trình có đang chạy hay không. Vấn đề duy nhất là ngay cả khi quá trình đang chạy, nó nói nó không phải là và mở một thể hiện khác.cách sử dụng tập lệnh shell để giám sát chương trình?

Tôi biết tôi nên kiểm tra theo tên quá trình và không xử lý id, vì một quá trình khác có thể nhảy vào và lấy id. Tuy nhiên tất cả các chương trình perl được đặt tên Perl5.10.0 trên hệ thống của tôi, và tôi dự định có nhiều phiên bản của cùng một chương trình perl đang mở.

Sau đây "nếu" luôn trả về false, tôi đang làm gì sai ở đây ???

while true; do 

if [ ps -p $pid ]; then 
    echo "Program running fine" 
    sleep 10 

else 
    echo "Program being restarted\n" 
    perl program_name.pl & 
    sleep 5 
    read -r pid < "${filename}_pid.txt" 
fi 

done 

Trả lời

9

Loại bỏ các dấu ngoặc vuông. Phải là:

if ps -p $pid; then 

Dấu ngoặc vuông là đường cú pháp cho lệnh test. Đây là một con thú hoàn toàn khác nhau và không gọi ps tại tất cả:

if test ps -p $pid; then 

Trong thực tế rằng sản lượng "-bash: [: -p: nhà điều hành nhị phân mong đợi" khi tôi chạy nó.

+0

Tuyệt vời, tôi vừa mới bắt đầu kịch bản lệnh shell ngày hôm nay và nó đã giúp tôi phát điên. Tôi sẽ có một vấn đề cú pháp đơn giản bất cứ ngày nào trên một cái gì đó điên rồ phức tạp mặc dù. Cảm ơn một lần nữa. PS: Bạn đã trả lời rất nhanh (tôi đã đăng, đi vào phòng tắm, và trở lại giải pháp TÌNH YÊU TUYỆT VỜI TUYỆT VỜI!) Tôi phải đợi để kiểm tra câu trả lời đúng, nhưng tôi sẽ làm trong một thời gian ngắn. – user387049

+0

@ user387049: Câu trả lời của John Kugelman phù hợp với kiến ​​thức vỏ của bạn. Tuy nhiên, kịch bản của bạn là một cách giám sát kém chương trình; [Câu trả lời của msw] (http://stackoverflow.com/questions/3304559/how-to-use-a-shell-script-to-supervise-a-faulty-program/3304634#3304634) giải thích lý do. Một giải pháp mạnh mẽ hơn nhiều sẽ là sử dụng một chương trình giám sát hiện có, chẳng hạn như những người được đề cập bởi [Jonas] (http://stackoverflow.com/questions/3304559/how-to-use-a-shell-script-to- giám sát-một-lỗi-chương trình/3306727 # 3306727). – Gilles

0

Đó là điều giết -0 $ pid. Nó trả về thành công nếu một quá trình với pid $ pid tồn tại.

+0

Vấn đề với lệnh đó là bạn chỉ có thể kiểm tra các quá trình có nguồn gốc từ người dùng của bạn, người chạy tập lệnh. – Anders

+1

@Anders: Nếu kịch bản của bạn cũng chịu trách nhiệm khởi động lại quy trình (như trong ví dụ trên), thì đó là một giả định hợp lý. –

7

Ngoài lỗi cú pháp đã được chỉ ra, đây là một cách tệ hại để đảm bảo rằng quy trình vẫn còn hoạt động.

Trước tiên, bạn nên tìm hiểu lý do tại sao chương trình của bạn sắp chết; tập lệnh này không sửa lỗi, nó cố gắng ẩn một tập lệnh.

Thứ hai, nếu điều quan trọng là chương trình vẫn đang chạy, tại sao bạn mong đợi tập lệnh shell lỗi (ít nhất một lần) sẽ thực hiện công việc? Sử dụng một hệ thống cơ sở được thiết kế đặc biệt để khởi động lại quá trình máy chủ. Nếu bạn nói nền tảng nào bạn đang sử dụng và bản chất của quá trình máy chủ của bạn. Tôi có thể đưa ra lời khuyên cụ thể hơn.

thêm để đáp ứng với bình luận:

Chắc chắn, có những nhu cầu cấp bách kỹ thuật, nhưng như OP đã nêu trong OP, vẫn còn là một lỗi trong nỗ lực này tại một giải pháp:

Tôi biết tôi nên kiểm tra theo tên quá trình và không xử lý id, vì một quá trình khác có thể nhảy vào và lấy id.

Vì vậy, bây giờ bạn bị bỏ lại với tập lệnh theo dõi PID, không phải là quá trình "vú em".Mặc dù rất có thể là nhỏ, kịch bản như tình hình hiện nay có một cửa sổ thứ hai mười trong đó

  1. sự "giám sát" quá trình thất bại
  2. tôi bắt đầu lên tuần dài quá trình emacs của tôi mà lấy cùng PID
  3. kịch bản vú em tiếp tục trên blissfully không biết rằng phụ thuộc của nó đã thất bại

Kịch bản không chỉ đơn thuần là lỗi, nó không hợp lệ vì nó giả định rằng PID là định danh ổn định của một quá trình. Có nhiều cách để điều này có thể được xử lý tốt hơn ngay cả ở cấp độ hệ vỏ. Cách đơn giản nhất là không bao giờ tách thực thi perl khỏi tập lệnh vì tập lệnh không làm gì khác ngoài việc xem tiến trình con. Ví dụ:

while true ; do 
    if perl program_name.pl ; then 
     echo "program_name terminated normally, restarting" 
    else 
     echo "oops program_name died again, restarting" 
    fi 
done 

Điều này không chỉ ngắn hơn và đơn giản hơn mà còn thực sự chặn cho điều kiện bạn thực sự quan tâm: trạng thái chạy của chương trình perl. Kịch bản gốc liên tục kiểm tra một dấu hiệu proxy xấu của tình trạng chạy trạng thái chạy (PID) và do đó có thể làm cho nó sai. Và, vì toàn bộ mục đích của kịch bản nữ này là để xử lý các lỗi lầm, sẽ rất tệ nếu nó bị lỗi bởi thiết kế.

+0

Trước tiên, người ta không thể luôn luôn sửa chữa nguyên nhân của vấn đề bởi vì nó ra khỏi bàn tay. Thứ hai, tôi đồng ý, mặc dù, một kịch bản được thiết kế tốt có thể dễ dàng thực hiện các tác vụ như thế này mà không bị "lỗi". Nhưng có, một trong những nên luôn luôn sử dụng chức năng hiện có nếu nó tồn tại. – Anders

+0

Trong khi sửa chữa vấn đề cơ bản sẽ là tốt nhất, điều này có vẻ như một tuyến đường dễ dàng hơn và ổn định hơn. Các lỗi tôi nhận được từ Perl là lỗi phân đoạn, không nhất quán rời khỏi phạm vi hoặc chỉnh sửa biến được chia sẻ. Bây giờ các lỗi này không phù hợp với bản thân, ngay cả khi tôi bắt đầu chương trình sao lưu và chạy cùng một tệp đầu vào tôi có thể không nhận được lỗi nào. Ngoài ra kịch bản shell của tôi không còn là lỗi nữa, nó chỉ là vấn đề đó nên tôi hoàn toàn mong đợi nó hoạt động. – user387049

+0

@ user387049: nó vẫn còn lỗi, xem "thêm" của tôi ở trên. – msw

3

Tôi hoàn toàn đồng ý rằng không quan trọng với PID gần như luôn luôn là một ý tưởng tồi. Kịch bản while true ; do ... done khá tốt, tuy nhiên đối với các hệ thống sản xuất có một vài giám sát viên quá trình thực hiện chính xác điều này và nhiều hơn nữa, ví dụ:

  • cho phép bạn gửi tín hiệu đến quá trình giám sát (mà không biết đó là PID)
  • kiểm tra bao lâu một dịch vụ đã được lên hoặc xuống
  • chụp sản lượng của nó và ghi nó vào một file log

Ví dụ về người giám sát quá trình như vậy là daemontools hoặc runit. Để có một cuộc thảo luận chi tiết hơn và các ví dụ, hãy xem Init scripts considered harmful. Không bị quấy rầy bởi tiêu đề: Các init script truyền thống phải chịu chính xác cùng một vấn đề như bạn làm (chúng bắt đầu một daemon, giữ nó trong một tệp và sau đó để lại daemon một mình).

1

Tôi đồng ý rằng bạn nên tìm hiểu lý do tại sao chương trình của bạn sắp chết ở nơi đầu tiên. Tuy nhiên, một kịch bản shell bao giờ chạy có lẽ không phải là một ý tưởng hay. Điều gì sẽ xảy ra nếu kịch bản lệnh giám sát này bị chết? (. Và vâng, thoát khỏi dấu ngoặc vuông xung quanh ps -p $pid Bạn muốn trạng thái thoát của ps -p $pid lệnh Các dấu ngoặc vuông là một sự thay thế cho lệnh test..)

Có hai giải pháp khả thi:

  1. Sử dụng cron để chạy tập lệnh shell "giám sát" của bạn để xem liệu quá trình bạn đang giám sát vẫn đang chạy hay chưa và khởi động lại. Quá trình được giám sát có thể đưa PID của nó vào một tệp. Chương trình giám sát của bạn sau đó có thể đưa tập tin này vào và lấy PID để kiểm tra.

  2. Nếu chương trình bạn đang giám sát đang cung cấp dịch vụ trên một cổng cụ thể, hãy biến dịch vụ này thành dịch vụ inetd. Bằng cách này, nó không chạy ở tất cả cho đến khi có một yêu cầu trên cổng đó. Nếu bạn thiết lập chính xác, nó sẽ chấm dứt khi không cần thiết và khởi động lại khi cần thiết. Mất ít tài nguyên hơn và hệ điều hành sẽ xử lý mọi thứ cho bạn.

Các vấn đề liên quan