2017-02-17 113 views
0

我有以下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!

+1

查看['Proc :: Daemon']的文档(https://metacpan.org/pod/Proc::Daemon)。有一个选项叫做'pid_file'。 PID将被写入该文件。 –

+0

是的,我知道我可以在Perl中使用这个选项。但是,我想在init脚本中保留这样的功能(创建,删除PID文件),而不是在perl中完成1/2,在init脚本中完成1/2。 – Bintz

+0

您可以尝试在命令行上将shell脚本的文件名传递给Perl脚本,例如'$ DAEMON $ pid_file>/dev/null 2>&1 ....'然后Perl脚本可以使用这个文件名'$ pid_file'来创建pid文件 –

回答

0

谢谢zdim和Hakon的建议。他们肯定是可行的,并让我走上正轨,但最终我走了另一条路。而不是依靠$!,我用psawk得到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”的双引号。

2

Proc::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保存的配置风格文件中选择文件名比较复杂,而解析进程表可能不可靠。

+0

谢谢你的解释。有没有办法从shell中访问大孩子的PID?正如我在对原始问题的评论中指出的那样,我宁愿避免在Perl脚本中创建PID文件。这对我来说不算什么,因为init脚本将不得不依赖Perl脚本创建的文件。 – Bintz

+0

@Bintz我认为这是合理的。我添加了两个我可以看到的帖子。我能想到的另外两个看起来不太好 - (1)Perl脚本从文件夹中保存的某种配置文件中获取文件名。这会比将脚本文件传递给脚本更加复杂并且没有更好,如答案(2)Shell通过跟踪和分析进程表来找到pid。那会非常麻烦和不可靠。 //我还没有看到其他方法。 – zdim

1

我以前见过这种情况,不得不求助于使用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脚本(在这种情况下)很早就退出了。

相关问题