сборка сервиса на perl — правильно ли

#perl #bash #service

#perl #bash #Обслуживание

Вопрос:

Я попытался собрать скрипт, который я видел, плюс использовал существующий скрипт, чтобы заставить что-то запускаться как сервис. Теперь у меня есть следующий pl-скрипт и сценарии init.d / start / stop.

Они работают, но мне интересно, правильно ли я все сделал, потому что, когда я запускаю сервис, и я бы запустил его снова, он просто запустился бы снова и выдал новый PID-номер (это то, что я хочу? разве это не должно говорить «уже запущено?») Также я не понял, что делает «кэширующая» часть STDIN и STDOUT. Ни проверка файла (файл, установленный в начале, и в последнем цикле проверяется на более новую версию … не уверен, что это делает) Далее:

 #!/usr/bin/perl

#use strict;
use POSIX;
use DateTime;
use Fcntl qw(:flock);
use File::CacheDir qw(cache_dir);

Log("Initializing...");

# Find and read config file
if (@ARGV != 1) {
    print("Usage: miniserv.pl <config file>");
    die;
}

if ($ARGV[0] =~ /^([a-z]:)?//i) {
    $config_file = $ARGV[0];
}
else {
    print("NO CORRECT CONFIG FILE SPECIFIED");
    die;
}

%config = amp;read_config_file($config_file);
Log("Initialized...");
Log("Loaded config file.");


my $file = $0;
my $age = -M $file;
Log("File - ".$file.", age - ".$age);



# Change dir to the server root
@roots = ( $config{'root'} );
for($i=0; defined($config{"extraroot_$i"}); $i  ) {
    push(@roots, $config{"extraroot_$i"});
}
chdir($roots[0]);
Log("Changed working directory: ".$roots[0]);


Status("Daemonizing...");
my $pid = fork;
if(!defined $pid)
{
    LogError("Unable to fork : $!");
    die;
}
if($pid)
{
    Log("Parent process exiting, let the deamon (".$pid.") go...");
    sleep 3;
    exit;
}
POSIX::setsid;


if(-e $config{'pidfile'})
{
    open(PID, "<".$config{'pidfile'});
    my $runningpid = <PID>;
    close PID;
    unlink $config{'pidfile'};
    while(-e "/proc/".$runningpid)
    {
        Status("Waiting for ".$runningpid." to exit...");
        Log("Waiting for ".$runningpid." to exit...");
        sleep 1;
    }
}

open(PID, ">".$config{'pidfile'}) || die "Failed to create PID file $_[0] : $!";
print PID $$;
close PID;

Log("The deamon is now running...");
Status("Deamon running");

my $stdout = cache_dir({base_dir => $config{'root'}.'/cache', ttl => '1 day', filename => "STDOUT".$$});
my $stderr = cache_dir({base_dir => $config{'root'}.'/cache', ttl => '1 day', filename => "STDERR".$$});
Log("STDOUT : ".$stdout);
Log("STDERR : ".$stderr);
open STDIN, '/dev/null';
open STDOUT, '>>'.$stdout;
open STDERR, '>>'.$stderr;

while(1)
{
    #### Code to be performed by the daemon





    if($age - (-M $file))
    {
        Log("File modified, restarting");
        open(FILE, $file ." |");
        close(FILE);
        last;
    }
    if(!-e $config{'pidfile'})
    {
        Log("Pid file doesn't exist, time go exit.");
        last;
    }
    sleep 5;
}



sub Log
{
    my $string = shift;
    if($string)
    {
        my $time = DateTime->now();
        if(open(LOG, ">>".$config{'logfile'}))
        {
            flock(LOG, LOCK_EX);
            print LOG $$." [".$time->ymd." ".$time->hms."] - ".$string."rn";
            close LOG;
        }
    }
}

sub LogError
{
    my $string = shift;

    if($string)
    {
        my $time = DateTime->now();
        if(open(LOG, ">>".$config{'errorlog'}))
        {
            flock(LOG, LOCK_EX);
            print LOG $$." [".$time->ymd." ".$time->hms."] - ".$string."rn";
            close LOG;
        }
    }
}

sub Status
{
    my $string = shift;
    if($string)
    {
        $0 = "My Daemon- ".$string;
    }
    return $0;
}


# read_config_file(file)
# Reads the given config file, and returns a hash of values
sub read_config_file
{
    local %rv;
    if(-e $_[0]) 
    {
        open(CONF, $_[0]) || die "Failed to open config file $_[0] : $!";
        while(<CONF>) {
            s/r|n//g;
            if (/^#/ || !/S/) { next; }
            /^([^=] )=(.*)$/;
            $name = $1; $val = $2;
            $name =~ s/^s //g; $name =~ s/s $//g;
            $val =~ s/^s //g; $val =~ s/s $//g;
            $rv{$name} = $val;
            }
        close(CONF);
        return %rv;
    } else {
        print("COULD NOT FIND CONFIG FILE");
        die;
    }
}
  

сценарий запуска

 #!/bin/sh
echo Starting reliand server in /usr/libexec/reliand
trap '' 1
LANG=
export LANG
#PERLIO=:raw
unset PERLIO
export PERLIO
PERLLIB=/usr/libexec/reliand
export PERLLIB
exec '/usr/libexec/reliand/miniserv.pl' /etc/reliand/miniserv.conf
  

скрипт init.d

 #!/bin/sh
# chkconfig: 235 99 10
# description: Start or stop the reliand server
#
### BEGIN INIT INFO
# Provides: reliand
# Required-Start: $network $syslog
# Required-Stop: $network
# Default-Start: 2 3 5
# Default-Stop: 0 1 6
# Description: Start or stop the reliand server
### END INIT INFO

start=/etc/reliand/start
stop=/etc/reliand/stop
lockfile=/var/lock/subsys/reliand
confFile=/etc/reliand/miniserv.conf
pidFile=/var/reliand/miniserv.pid
name='reliand'

case "$1" in
'start')
    $start >/dev/null 2>amp;1 </dev/null
    RETVAL=$?
    if [ "$RETVAL" = "0" ]; then
        touch $lockfile >/dev/null 2>amp;1
    fi
    ;;
'stop')
    $stop
    RETVAL=$?
    if [ "$RETVAL" = "0" ]; then
        rm -f $lockfile
    fi
    pidfile=`grep "^pidfile=" $confFile | sed -e 's/pidfile=//g'`
    if [ "$pidfile" = "" ]; then
        pidfile=$pidFile
    fi
    rm -f $pidfile
    ;;
'status')
    pidfile=`grep "^pidfile=" $confFile | sed -e 's/pidfile=//g'`
    if [ "$pidfile" = "" ]; then
        pidfile=$pidFile
    fi
    if [ -s $pidfile ]; then
        pid=`cat $pidfile`
        kill -0 $pid >/dev/null 2>amp;1
        if [ "$?" = "0" ]; then
            echo "$name (pid $pid) is running"
            RETVAL=0
        else
            echo "$name is stopped"
            RETVAL=1
        fi
    else
        echo "$name is stopped"
        RETVAL=1
    fi
    ;;
'restart')
    $stop ; $start
    RETVAL=$?
    ;;
*)
    echo "Usage: $0 { start | stop | restart }"
    RETVAL=1
    ;;
esac
exit $RETVAL
  

Комментарии:

1. Попробуйте это здесь: codereview.stackexchange.com

Ответ №1:

Скрипт предоставит вам новый PID.

Что касается файла кэша, то в нем хранятся стандартные потоки ввода-вывода; это нормально для Bash, поэтому скрипту не приходится постоянно создавать новые потоки каждый раз, когда он инициализирует демона.

Комментарии:

1. каким-то образом мой сервер потребляет много памяти, теперь, когда я смотрю в процессы, мой скрипт почти ничего не использует, он где-то протекает? Вверху написано, что у меня есть 1 zombia, но я не знаю, откуда это взялось, может быть что-то другое….

2. Две мысли: это либо из-за разветвления демона, либо из-за внешнего процесса. Я бы доверился диагностике sysmem и поискал в другом месте.

3. что вы имеете в виду, говоря «искать в другом месте»? то есть это не в моем скрипте, а где-то еще в системе? спасибо за помощь, кстати!

4. Да, как в: вероятно, это в другом месте.