Chạy chương trình tùy ý như daemon từ init script


10

Tôi cần cài đặt một chương trình như một dịch vụ trong Red Hat. Nó không tự nền, quản lý tệp PID hoặc quản lý nhật ký của chính nó. Nó chỉ chạy và in ra STDOUT và STDERR.

Sử dụng các tập lệnh init tiêu chuẩn làm hướng dẫn, tôi đã phát triển như sau:

#!/bin/bash
#
#   /etc/rc.d/init.d/someprog
#
# Starts the someprog daemon
#
# chkconfig: 345 80 20
# description: the someprog daemon
# processname: someprog
# config: /etc/someprog.conf

# Source function library.
. /etc/rc.d/init.d/functions

prog="someprog"
exec="/usr/local/bin/$prog"
[ -e "/etc/sysconfig/$prog" ] && . "/etc/sysconfig/$prog"
lockfile="/var/lock/subsys/$prog"
RETVAL=0

check() {
    [ `id -u` = 0 ] || exit 4
    test -x "$exec" || exit 5
}

start() {
    check
    if [ ! -f "$lockfile" ]; then
        echo -n $"Starting $prog: " 
        daemon --user someproguser "$exec"
        RETVAL=$?
        [ $RETVAL -eq 0 ] && touch "$lockfile"
        echo
    fi
    return $RETVAL
}

stop() {
    check
    echo -n $"Stopping $prog: "
    killproc "exec"
    RETVAL=$?
    [ $RETVAL -eq 0 ] && rm -f "$lockfile"
    echo
    return $RETVAL
}

restart() {
    stop
    start
}   

case "$1" in
start)
    start
    ;;
stop)
    stop
    ;;
restart)
    restart
    ;;
status)
    status "$prog"
    RETVAL=$?
    ;;
*)
    echo $"Usage: $0 {start|stop|restart|status}"
    RETVAL=2
esac

exit $RETVAL

Có thể là lỗi của tôi là sao chép-dán và sửa đổi một số tập lệnh hiện có trong /etc/init.d. Trong mọi trường hợp, dịch vụ kết quả hoạt động kỳ lạ:

  • Khi tôi khởi động nó service someprog start, chương trình sẽ in ra thiết bị đầu cuối và lệnh không hoàn thành.
  • nếu tôi CTRL-C, nó sẽ in "Phiên kết thúc, giết vỏ ... ... bị giết. FAILED". Tôi phải làm điều này để lấy lại dấu nhắc shell của tôi một lần nữa.
  • Bây giờ khi tôi chạy service someprog status, nó báo nó đang chạy và liệt kê PID của nó. Tôi có thể thấy nó trong psnên nó đang chạy.
  • Bây giờ khi tôi chạy service someprog stopnó không dừng lại. Tôi có thể xác minh rằng nó vẫn đang chạy ps.

Tôi cần thay đổi những gì để someprogđược gửi đến nền và được quản lý như một dịch vụ?

Chỉnh sửa: Bây giờ tôi đã tìm thấy một vài câu hỏi liên quan, không có câu hỏi nào trong số đó có câu trả lời thực tế ngoài "làm gì khác":

Chỉnh sửa: câu trả lời này về cách gấp đôi có thể đã giải quyết được vấn đề của tôi, nhưng bây giờ chương trình của tôi tự thực hiện hai lần và nó hoạt động: /programming//a/9646251/898699


Bạn có đang bắt đầu chương trình với tiện ích "daemon" được cung cấp bởi libslack. libslack.org/daemon/#documentation Trong trường hợp này, chương trình có thể được dừng lại dưới tên daemon -n --stop. Ngoài ra, hãy thử chuyển hướng đầu ra (khi bắt đầu chương trình) sang tệp hoặc / dev / null và kiểm tra.
Ankit

2
Phụ thuộc vào phiên bản redhat của bạn, bạn có thể chỉ cần tạo một trình bao bọc đơn giản cho nó khi mới bắt đầu và gọi nó trực tiếp. Sau đó, upstart sẽ quản lý dịch vụ cho bạn. Đây là một điều EL6 mặc dù.
Matthew Ife

Câu trả lời:


1

Lệnh "không hoàn thành" vì daemonchức năng không chạy ứng dụng của bạn trong nền cho bạn. Bạn sẽ cần thêm một &phần cuối của daemonlệnh như vậy:

daemon --user someproguser $exec &

Nếu someprogkhông xử lý SIGHUP, bạn nên chạy lệnh với nohupđể đảm bảo rằng quy trình của bạn sẽ không nhận được thông báo SIGHUPcho quá trình của bạn thoát khi trình bao cha mẹ thoát. Điều đó sẽ trông như thế này:

daemon --user someproguser "nohup $exec" &

Trong stopchức năng của bạn , killproc "exec"không làm gì để dừng chương trình của bạn. Nó nên đọc như vậy:

killproc $exec

killprocyêu cầu đường dẫn đầy đủ đến ứng dụng của bạn để dừng nó đúng cách. Trước đây tôi đã gặp một số rắc rối killproc, vì vậy bạn cũng có thể tiêu diệt PID trong PIDFILE mà bạn nên viết someprogPID với một cái gì đó như thế này:

cat $pidfile | xargs kill

Bạn có thể viết PIDFILE như thế này:

ps aux | grep $exec | grep -v grep | tr -s " " | cut -d " " -f2 > $pidfile

nơi $pidfilechỉ đến /var/run/someprog.pid.

Nếu bạn muốn [OK] hoặc [FAILED] trên stopchức năng của mình , bạn nên sử dụng successvà các failurechức năng từ đó /etc/rc.d/init.d/functions. Bạn không cần những thứ này trong starthàm vì daemongọi cái thích hợp cho bạn.

Bạn cũng chỉ cần trích dẫn xung quanh chuỗi có khoảng trắng. Tuy nhiên, đó là một sự lựa chọn phong cách, do đó tùy thuộc vào bạn.

Tất cả những thay đổi này trông như thế này:

#!/bin/bash
#
#   /etc/rc.d/init.d/someprog
#
# Starts the someprog daemon
#
# chkconfig: 345 80 20
# description: the someprog daemon
# processname: someprog
# config: /etc/someprog.conf

# Source function library.
. /etc/rc.d/init.d/functions

prog=someprog
exec=/usr/local/bin/$prog
[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
lockfile=/var/lock/subsys/$prog
pidfile=/var/run/$prog
RETVAL=0

check() {
    [ `id -u` = 0 ] || exit 4
    test -x $exec || exit 5
}

start() {
    check
    if [ ! -f $lockfile ]; then
        echo -n $"Starting $prog: " 
        daemon --user someproguser "nohup $exec" &
        RETVAL=$?
        if [ $RETVAL -eq 0 ]; then
          touch $lockfile
          ps aux | grep $exec | grep -v grep | tr -s " " | cut -d " " -f2 > $pidfile
        fi
        echo
    fi
    return $RETVAL
}

stop() {
    check
    echo -n $"Stopping $prog: "
    killproc $exec && cat $pidfile | kill
    RETVAL=$?
    if [ $RETVAL -eq 0 ]; then
      rm -f $lockfile
      rm -f $pidfile
      success; echo
    else
      failure; echo
    fi
    echo
    return $RETVAL
}

restart() {
    stop
    start
}   

case "$1" in
start)
    start
    ;;
stop)
    stop
    ;;
restart)
    restart
    ;;
status)
    status $prog
    RETVAL=$?
    ;;
*)
    echo $"Usage: $0 {start|stop|restart|status}"
    RETVAL=2
esac

exit $RETVAL

Xin lỗi phải mất gần 4,5 năm để bạn có được một câu trả lời thích hợp.
Stuporman

-1

Nếu đây là chương trình của bạn, xin vui lòng viết nó như một daemon thích hợp. Đặc biệt là nếu nó để phân phối lại. :)

Bạn có thể thử monit . Hoặc có thể một cái gì đó như runit hoặc daemontools. Những người hùng mạnh không có sẵn các gói. Daemontools đến từ DJB, nếu điều đó ảnh hưởng đến quyết định của bạn (theo một trong hai hướng.)


-1

Tôi đã thực hiện một số nghiên cứu thêm và có vẻ như câu trả lời là "bạn không thể làm điều đó". Chương trình được chạy thực sự phải tự khởi động đúng cách: rẽ nhánh và tách các tập tin tiêu chuẩn của nó, tách khỏi thiết bị đầu cuối và bắt đầu một phiên mới.

Chỉnh sửa: rõ ràng là tôi sai - việc gấp đôi sẽ hiệu quả. /programming//a/9646251/898699


Bạn có thể làm điều đó bằng cách sử dụng upstart như đã nêu trong các ý kiến.
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.