如何在初始化脚本中获取 perl 守护进程的 PID?
How to get PID of perl daemon in init script?
我有以下 perl 脚本:
#!/usr/bin/perl
use strict;
use warnings;
use Proc::Daemon;
Proc::Daemon::Init;
my $continue = 1;
$SIG{TERM} = sub { $continue = 0 };
while ($continue) {
# stuff
}
我的初始化脚本中有以下内容:
DAEMON='/path/to/perl/script.pl'
start() {
PID=`$DAEMON > /dev/null 2>&1 & echo $!`
echo $PID > /var/run/mem-monitor.pid
}
问题是,这个returns错误的PID!这 returns 守护进程为 运行 时启动的父进程的 PID,但该进程立即被终止。我需要获取子进程的PID!
Proc::Daemon does the following:
...
9. The first child transfers the PID of the second child (daemon) to the parent. Additionally the PID of the daemon process can be written into a file if 'pid_file' is defined. Then the first child exits.
然后在 new ( %ARGS )
下
pid_file
Defines the path to a file (owned by the parent user) where the PID of the daemon process will be stored. Defaults to undef (= write no file).
另请参阅 Init()
方法说明。这一切都意味着您可能想先使用 new
。
关键是 grand-child 进程是守护进程。然而,childr 传递 pid 并且它可供父级使用。如果在构造函数(守护进程的)中设置了 pid_file => $file_name
,则将 pid 写入该文件。
一条评论要求不要让 shell 脚本依赖于另一个脚本编写的文件。
我可以看到两种方法。
打印由 $daemon->Init()
从父级返回的 pid,并在 shell 中获取它。这被问题中的重定向打败了,但我不知道为什么需要它们。父子关系在所有设置完成后立即退出,而守护进程与一切分离。
Shell 脚本可以使用所需的 log-file 名称作为参数启动 Perl 脚本,让它通过上述过程将守护程序 pid 写入该文件。该文件仍然由 Perl 输出,但重要的是它由 shell 脚本决定。
我想在下面的评论中包含一个声明。我认为这些优于想到的其他两件事:从 shell 保存的 config-style 文件中选取文件名更复杂,而解析过程 table 可能不可靠。
感谢 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 }'`
echo $PID > /var/run/mem-monitor.pid
}
这有效并满足了我的强迫症!请注意 grep "$DAEMON"
.
中“$DAEMON”周围的双引号
我以前见过这个,不得不求助于使用 STDERR 将子 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 脚本确实(在这种情况下)很早就退出了。
我有以下 perl 脚本:
#!/usr/bin/perl
use strict;
use warnings;
use Proc::Daemon;
Proc::Daemon::Init;
my $continue = 1;
$SIG{TERM} = sub { $continue = 0 };
while ($continue) {
# stuff
}
我的初始化脚本中有以下内容:
DAEMON='/path/to/perl/script.pl'
start() {
PID=`$DAEMON > /dev/null 2>&1 & echo $!`
echo $PID > /var/run/mem-monitor.pid
}
问题是,这个returns错误的PID!这 returns 守护进程为 运行 时启动的父进程的 PID,但该进程立即被终止。我需要获取子进程的PID!
Proc::Daemon does the following:
...
9. The first child transfers the PID of the second child (daemon) to the parent. Additionally the PID of the daemon process can be written into a file if 'pid_file' is defined. Then the first child exits.
然后在 new ( %ARGS )
pid_file
Defines the path to a file (owned by the parent user) where the PID of the daemon process will be stored. Defaults to undef (= write no file).
另请参阅 Init()
方法说明。这一切都意味着您可能想先使用 new
。
关键是 grand-child 进程是守护进程。然而,childr 传递 pid 并且它可供父级使用。如果在构造函数(守护进程的)中设置了 pid_file => $file_name
,则将 pid 写入该文件。
一条评论要求不要让 shell 脚本依赖于另一个脚本编写的文件。
我可以看到两种方法。
打印由
$daemon->Init()
从父级返回的 pid,并在 shell 中获取它。这被问题中的重定向打败了,但我不知道为什么需要它们。父子关系在所有设置完成后立即退出,而守护进程与一切分离。Shell 脚本可以使用所需的 log-file 名称作为参数启动 Perl 脚本,让它通过上述过程将守护程序 pid 写入该文件。该文件仍然由 Perl 输出,但重要的是它由 shell 脚本决定。
我想在下面的评论中包含一个声明。我认为这些优于想到的其他两件事:从 shell 保存的 config-style 文件中选取文件名更复杂,而解析过程 table 可能不可靠。
感谢 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 }'`
echo $PID > /var/run/mem-monitor.pid
}
这有效并满足了我的强迫症!请注意 grep "$DAEMON"
.
我以前见过这个,不得不求助于使用 STDERR 将子 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 脚本确实(在这种情况下)很早就退出了。