2012-02-24 14 views
6

Tôi có một máy chủ web nơi tôi chạy một số chương trình khởi động chậm như daemon. Đôi khi chúng cần khởi động lại nhanh (hoặc dừng) khi tôi biên dịch lại chúng hoặc chuyển sang cài đặt khác của chúng.Cho phép người dùng khác dừng/khởi động lại các bash daemon đơn giản - sử dụng tín hiệu hoặc điều gì?

Lấy cảm hứng từ http://mywiki.wooledge.org/ProcessManagement, tôi đang viết một kịch bản gọi daemonise.sh trông giống như

#!/bin/sh 
while :; do 
    ./myprogram lotsadata.xml 
    echo "Restarting server..." 1>&2 
done 

để giữ một "daemon" chạy. Kể từ khi tôi đôi khi cần để ngăn chặn nó, hoặc chỉ khởi động lại nó, tôi chạy kịch bản mà trong một phiên màn hình, như:

$ ./daemonise.sh & DPID=$! 
$ screen -d 

Sau đó, có lẽ tôi biên dịch lại myprogram, cài đặt nó vào một con đường mới, bắt đầu những cái mới lên và muốn giết một tuổi:

$ screen -r 
$ kill $DPID 
$ screen -d 

này hoạt động tốt khi tôi là người duy trì mà thôi, nhưng bây giờ tôi muốn cho người khác dừng/khởi động lại chương trình, bất kể ai bắt đầu nó. Và để làm cho mọi thứ trở nên phức tạp hơn, tập lệnh daemonise.sh trên thực tế bắt đầu khoảng 16 chương trình, khiến bạn khó có thể giết tất cả các chương trình nếu bạn không biết PID của chúng.

Cách thức "thực hành tốt nhất" cho phép người dùng khác dừng/khởi động lại trình tiện ích con là gì?

Tôi đã nghĩ về các phiên màn hình được chia sẻ, nhưng điều đó nghe có vẻ như bị hack và không an toàn. Giải pháp tốt nhất mà tôi đã đưa ra cho bây giờ là để bọc bắt đầu và giết chết trong một kịch bản mà bắt tín hiệu nhất định:

#!/bin/bash 
DPID= 
trap './daemonise.sh & DPID=$!' USR1 
trap 'kill $DPID' USR2 EXIT 

# Ensure trapper wrapper doesn't exit: 
while :; do 
    sleep 10000 & wait $! 
done 

Bây giờ, nên người dùng khác cần phải ngăn chặn các daemon và tôi không thể làm điều đó , cô ấy chỉ cần biết pid của trình bao bọc và ví dụ: sudo kill -s USR2 $wrapperpid. (Ngoài ra, điều này làm cho nó có thể chạy các daemon khi khởi động lại, và vẫn giết chúng một cách sạch sẽ.)

Có giải pháp nào tốt hơn không? Có vấn đề rõ ràng với giải pháp mà tôi không thấy?

(Sau khi đọc Bash Wiki Greg, tôi muốn tránh bất kỳ giải pháp liên quan đến pgrep hoặc PID-files ...)

+1

+1 cho liên kết Wiki của Greg's Bash. Chúc may mắn! – shellter

+1

tệp pid là quy ước tốt nhất – reconbot

+0

@wizard là đúng. bạn sẽ không nhận được một câu trả lời đáng giá bởi vì bạn về cơ bản nói "tôi biết bánh xe tồn tại, nhưng tôi muốn phát minh ra của riêng tôi". –

Trả lời

1

Tôi khuyên bạn nên một init script PID dựa. Bất cứ ai có sudo đặc quyền để kịch bản sẽ có thể bắt đầu và ngừng các quá trình máy chủ.

+1

"PID dựa"? Bạn có nghĩa là PID-file dựa? Nếu tôi sẽ cho phép người dùng khác sudo dừng 16 tiến trình cùng một lúc trên một máy chủ, tôi không muốn mạo hiểm PID trỏ đến các tiến trình sai. Làm thế nào bạn sẽ đảm bảo không ai trong số các quá trình đã dừng lại và đưa PID của họ để các quá trình khác mà không kiểm soát chúng từ cha mẹ? – unhammer

+1

Cho phép các chương trình của bạn tạo và dọn dẹp các tệp pid của riêng chúng. Các cơ hội mà một chương trình sẽ sụp đổ và nó pid được đưa ra cho quá trình khác là khá thấp (nó sẽ phải quấn quanh tất cả các pids có sẵn thường là một int 64 bit). Nếu bạn vẫn còn lo lắng thì hãy xem những gì các quá trình là trước khi bạn giết nó. (/ proc/PID/cmdline là một cách dễ dàng.) – reconbot

+1

@wizard: Nền tảng nào đã được bật? Tôi đang chạy Ubuntu 11,10 64 bit và/proc/sys/kernel/pid_max nói '32768'. Điều đó không * không * mất một thời gian dài để bọc. – l0b0

1

Khi cải thiện cách tiếp cận của bạn: bạn có nên đảm bảo rằng lệnh sleep trong sleep 10000 & wait $! được chấm dứt đúng cách nếu tập lệnh pidwrapper của bạn thoát không?

Nếu không, sẽ vẫn có quá trình sleep đang treo lơ lửng trong bảng tiến trình trong một thời gian.

Tương tự, sẽ không rõ ràng hơn khi chấm dứt myprogram trong daemonise.sh đúng khi khởi động lại (i. E. Nếu daemonise.sh nhận tín hiệu TERM)?

Ngoài ra, có thể ngăn chặn thông báo công việc và kiểm tra sự tồn tại của pid trước khi tiêu diệt.

#!/bin/sh 
# cat daemonise.sh 

# cf. "How to suppress Terminated message after killing in bash?", 
# http://stackoverflow.com/q/81520 

trap ' 
    echo "server shut down..." 1>&2 
    kill $spid1 $spid2 $spid3 && 
     wait $spid1 $spid2 $spid3 2>/dev/null 
    exit 
' TERM 

while :; do 
    echo "Starting server..." 1>&2 
    #./myprogram lotsadata.xml 
    sleep 100 & 
    spid1=${!} 
    sleep 100 & 
    spid2=${!} 
    sleep 100 & 
    spid3=${!} 
    wait 
    echo "Restarting server..." 1>&2 
done 

#------------------------------------------------------------ 

#!/bin/bash 
# cat pidwrapper 

DPID= 

trap ' 
    kill -0 ${!} 2>/dev/null && kill ${!} && wait ${!} 2>/dev/null 
    ./daemonise.sh & DPID=${!} 
' USR1 

trap ' 
    kill -0 ${!} 2>/dev/null && kill ${!} && wait ${!} 2>/dev/null 
    kill -0 $DPID 2>/dev/null && kill $DPID && wait ${DPID} 2>/dev/null 
' USR2 

trap ' 
    trap - EXIT 
    kill -0 $DPID 2>/dev/null && kill $DPID && wait ${DPID} 2>/dev/null 
    kill -0 ${!} 2>/dev/null && kill ${!} && wait ${!} 2>/dev/null 
    exit 0 
' EXIT 

# Ensure trapper wrapper does not exit: 
while :; do 
    sleep 10000 & wait $! 
done 

#------------------------------------------------------------ 

# test 

{ 
wrapperpid="`exec sh -c './pidwrapper & echo ${!}' | head -1`" 
echo "wrapperpid: $wrapperpid" 
for n in 1 2 3 4 5; do 
    sleep 2 
    # start daemonise.sh 
    kill -s USR1 $wrapperpid 
    sleep 2 
    # kill daemonise.sh 
    kill -s USR2 $wrapperpid 
done 
sleep 2 
echo kill $wrapperpid 
kill $wrapperpid 
} 
+0

Vâng ... Tôi thực sự thích nhìn thấy những gì đã được chấm dứt :-) nhưng yeah mà hoạt động. Đã không nghĩ về quá trình ngủ đi lạc từ wrapper. – unhammer

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