การเรียกใช้ daemon ในสคริปต์ /etc/init.d กำลังบล็อกไม่ทำงานในพื้นหลัง


9

ฉันมีสคริปต์ Perl ที่ฉันต้องการ daemonize โดยพื้นฐานแล้วสคริปต์ Perl นี้จะอ่านไดเรกทอรีทุก ๆ 30 วินาทีอ่านไฟล์ที่พบแล้วประมวลผลข้อมูล เพื่อให้ง่ายขึ้นที่นี่ให้พิจารณาสคริปต์ Perl ต่อไปนี้ (เรียกว่า synpipe_server มีลิงก์สัญลักษณ์ของสคริปต์นี้/usr/sbin/):

#!/usr/bin/perl
use strict;
use warnings;

my $continue = 1;
$SIG{'TERM'}  = sub { $continue = 0; print "Caught TERM signal\n"; };
$SIG{'INT'} = sub { $continue = 0; print "Caught INT signal\n"; };

my $i = 0;
while ($continue) {
     #do stuff
     print "Hello, I am running " . ++$i . "\n";
     sleep 3;
}

ดังนั้นสคริปต์นี้พิมพ์บางสิ่งบางอย่างโดยทั่วไปทุก 3 วินาที

จากนั้นเมื่อฉันต้องการ daemonize สคริปต์นี้ฉันก็ใส่ bash script นี้ (หรือที่เรียกว่า synpipe_server) ใน/etc/init.d/:

#!/bin/bash
# synpipe_server : This starts and stops synpipe_server
#
# chkconfig: 12345 12 88
# description: Monitors all production pipelines
# processname: synpipe_server
# pidfile: /var/run/synpipe_server.pid
# Source function library.
. /etc/rc.d/init.d/functions

pname="synpipe_server"
exe="/usr/sbin/synpipe_server"
pidfile="/var/run/${pname}.pid"
lockfile="/var/lock/subsys/${pname}"

[ -x $exe ] || exit 0

RETVAL=0

start() {
    echo -n "Starting $pname : "
    daemon ${exe}
    RETVAL=$?
    PID=$!
    echo
    [ $RETVAL -eq 0 ] && touch ${lockfile}
    echo $PID > ${pidfile}
}

stop() {
    echo -n "Shutting down $pname : "
    killproc ${exe}
    RETVAL=$?
    echo
    if [ $RETVAL -eq 0 ]; then
        rm -f ${lockfile}
        rm -f ${pidfile}
    fi
}

restart() {
    echo -n "Restarting $pname : "
    stop
    sleep 2
    start
}

case "$1" in
    start)
        start
    ;;
    stop)
        stop
    ;;
    status)
        status ${pname}
    ;;
    restart)
        restart
    ;;
    *)
        echo "Usage: $0 {start|stop|status|restart}"
    ;; esac

exit 0

ดังนั้น (ถ้าฉันเข้าใจ doc สำหรับ daemon เป็นอย่างดี) สคริปต์ Perl ควรทำงานในพื้นหลังและควรเปลี่ยนเส้นทางผลลัพธ์ไปที่/dev/nullถ้าฉันเรียกใช้งาน:

service synpipe_server start

แต่นี่คือสิ่งที่ฉันได้รับแทน:

[root@master init.d]# service synpipe_server start
Starting synpipe_server : Hello, I am running 1
Hello, I am running 2
Hello, I am running 3
Hello, I am running 4
Caught INT signal
                                                           [  OK  ]
[root@master init.d]# 

ดังนั้นมันจึงเริ่มต้นสคริปต์ Perl แต่รันโดยไม่ต้องแยกออกจากเซสชันเทอร์มินัลปัจจุบันและฉันสามารถเห็นผลลัพธ์ที่พิมพ์ในคอนโซลของฉัน ... ซึ่งไม่ใช่สิ่งที่ฉันคาดหวัง นอกจากนี้ไฟล์ PID ว่างเปล่า (หรือด้วยการป้อนบรรทัดเท่านั้นไม่มีการส่งคืน pid โดยdaemon )

ไม่มีใครมีความคิดเกี่ยวกับสิ่งที่ฉันทำผิดหรือเปล่า?

แก้ไข: บางทีฉันควรจะบอกว่าฉันอยู่ในเครื่อง Red Hat

Scientific Linux SL release 5.4 (Boron)

มันจะทำงานได้ไหมถ้าแทนที่จะใช้ฟังก์ชั่น daemon ฉันจะใช้สิ่งที่ชอบ:

nohup ${exe} >/dev/null 2>&1 &

ในสคริปต์ init หรือไม่

คำตอบ:


4

ฉันขอแนะนำให้คุณ daemonize สคริปต์โดยตรงแทนที่จะเพิ่มเลเยอร์พิเศษของdaemonฟังก์ชันสคริปต์ redhat เป็นการยากที่จะทำให้ daemons ถูกต้องหากคุณพยายามเขียนด้วยตนเอง Proc :: Daemonค่อนข้างตรงไปตรงมา

นอกจากนี้ที่นี่เป็นการอภิปรายของวิธีการเขียน Perl ภูต

โบนัสคำตอบ: ใช้daemontoolsและพร :: daemontools นั่นเป็นระบบการจัดการภูตที่ครอบคลุมและคุณอาจติดตั้ง daemontools อยู่แล้ว บางคนไม่ชอบ daemontools แต่มันก็ทำให้งานเสร็จ

ไม่ว่ากี่ครั้งที่ฉันเขียนดีมอนยังคงดูแปลก ๆ อยู่ บางทีฉันควรใช้dæmon


2

หากคุณใช้ Debian และอนุพันธ์ของมันให้ใช้start-stop-daemonกับตัวเลือก -b เพื่อเริ่มกระบวนการของคุณโดยไม่มีปัญหา


นี่เป็นเครื่อง RedHat ดังนั้นควรใช้daemonและkillprocแทน
MariuszS

1
สิ่งนี้แก้ไขปัญหาของฉันในวันนี้ ใน Ubuntu ฉันคัดลอก /etc/init.d/skeleton และไม่สามารถหาสาเหตุที่มันไม่ทำงานในพื้นหลัง ฉันคิดว่ามันถูกตั้งค่าสำหรับพื้นหลังแล้ว แต่กลับกลายเป็นว่าไม่ใช่
Ryan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.