如何在init脚本中获得perl守护进程的PID?
我有以下perl脚本:如何在init脚本中获得perl守护进程的PID?
#!/usr/bin/perl
use strict;
use warnings;
use Proc::Daemon;
Proc::Daemon::Init;
my $continue = 1;
$SIG{TERM} = sub { $continue = 0 };
while ($continue) {
# stuff
}
我有我的init脚本如下:
DAEMON='/path/to/perl/script.pl'
start() {
PID=`$DAEMON > /dev/null 2>&1 & echo $!`
echo $PID > /var/run/mem-monitor.pid
}
的问题是,这个返回错误的PID!这将返回守护进程运行时启动的父进程的PID,但该进程立即停止。我需要获得子进程的PID!
谢谢zdim和Hakon的建议。他们肯定是可行的,并让我走上正轨,但最终我走了另一条路。而不是依靠$!
,我用ps
和awk
得到PID,如下所示:
DAEMON='/path/to/perl/script.pl'
start() {
$DAEMON > /dev/null 2>&1
PID=`ps aux | grep -v 'grep' | grep "$DAEMON" | awk '{print $2}'`
echo $PID > /var/run/mem-monitor.pid
}
这工作,并满足我的强迫症!请注意0中“$ DAEMON”的双引号。
PROC ::守护程序将执行以下操作:
...
9.第一个孩子转的第二个孩子(守护进程)父的PID。另外,如果定义了'pid_file',守护进程的PID可以写入文件中。然后第一个孩子退出。
再后来,下new (%ARGS)
pid_file
路径定义要在守护进程的PID将被存储在一个文件(由父用户拥有)。默认为undef(=写入没有文件)。
另请参见Init()
方法说明。这一切都意味着你可能首先要使用new
。
重点是它是守护进程的大孩子进程。但是,childr将该pid传递给父级,并可供父级使用。如果在构造函数中设置了pid_file => $file_name
(守护进程),则pid将写入该文件。
评论要求没有shell脚本依赖于另一个脚本编写的文件。
我可以看到两种方法来做到这一点。
从父母打印由
$daemon->Init()
返回的pid,并将其从外壳中拾取。这被问题中的重定向击败,但我不知道为什么他们需要。所有设置都会让父母和孩子退出,而守护进程则与所有事物分离。Shell脚本可以用所需的日志文件名作为参数启动Perl脚本,让它通过上述过程将守护程序pid写入该文件。该文件仍然由Perl输出,但重要的是由shell脚本决定的。
我想在下面的评论中添加一条语句。我认为这些优于其他两件事情:从shell保存的配置风格文件中选择文件名比较复杂,而解析进程表可能不可靠。
我以前见过这种情况,不得不求助于使用STDERR将childs PID发送回调用shell脚本。我一直认为这是由于所提到的退出代码的不可靠性 - 但文档中的细节不清楚。请尝试是这样的:
#!/usr/bin/perl
use strict;
use warnings;
use Proc::Daemon;
if(my $pid = Proc::Daemon::Init()) {
print STDERR $pid;
exit;
}
my $continue = 1;
$SIG{TERM} = sub { $continue = 0 };
while ($continue) {
sleep(20);
exit;
}
与调用的脚本是这样的:
#!/bin/bash
DAEMON='./script.pl'
start() {
PID=$($DAEMON 2>&1 >/dev/null)
echo $PID > ./mem-monitor.pid
}
start;
当bash脚本是跑,它会捕捉到STDERR输出(含正确的PID),并将其存储在文件中。 Perl脚本产生的任何STDOUT都会被发送到/ dev/null - 尽管这不太可能,因为第一级Perl脚本(在这种情况下)很早就退出了。
查看['Proc :: Daemon']的文档(https://metacpan.org/pod/Proc::Daemon)。有一个选项叫做'pid_file'。 PID将被写入该文件。 –
是的,我知道我可以在Perl中使用这个选项。但是,我想在init脚本中保留这样的功能(创建,删除PID文件),而不是在perl中完成1/2,在init脚本中完成1/2。 – Bintz
您可以尝试在命令行上将shell脚本的文件名传递给Perl脚本,例如'$ DAEMON $ pid_file>/dev/null 2>&1 ....'然后Perl脚本可以使用这个文件名'$ pid_file'来创建pid文件 –