#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. Да, как в: вероятно, это в другом месте.