2012-06-28 33 views
2

我有一个Perl脚本,它作为电子邮件服务器上的后台进程运行,并尝试通过对队列和日志文件进行各种检查来检测受感染的电子邮件帐户。我为USR1信号添加了一个处理程序,它使脚本在运行时输出关于它自己的一些信息。如果我在后台启动脚本,然后发送USR1信号,像这样这个伟大的工程:获取以Perl发送信号的TTY

 
./myscript.pl & 
kill -USR1 (PID) 

的问题是,如果我退出该shell会话,然后重新连接在,我不能得到任何输出当我使用kill -USR1命令时,因为与脚本的STDOUT相关的TTY消失了。

所以,我想知道是否有一种方法来获得发送Perl信号的用户或shell进程的TTY,然后直接输出回到TTY而不是STDOUT。我尝试在信号处理程序中使用POSIX::ttyname(1),但它会返回脚本STDOUT的TTY(在这种情况下为空值),而不是发送USR1信号的用户的TTY。

我在Perldoc中看到POSIX指出POSIX::sigaction会给出生成信号的进程的PID和UID,但我不知道是否有一种很好的方法可以从Perl中得到TTY名称。

任何帮助将不胜感激!谢谢!

+4

为什么不使用某种日志文件来捕获脚本的输出:'./myscript.pl> some.log&',然后使用任何你喜欢的TTY中的'tail -f some.log'命令来监视它? – nab

+0

这实际上是我的备用计划。让信号处理程序将信息写入文件而不是TTY。我想从中得到的信息就像是正常运行时间,处理的消息数量等等,所以如果我可以根据需要获取这些信息,而不是让脚本在某个时间间隔定期记录它,那将会更好。我想我可能需要编写一个shell脚本来发送USR1信号,然后'cat'输出文件,然后再删除它。 – Dave

回答

1

si最简单的解决方案是由nab在您的问题的评论中提出的解决方案:只需将您的输出记录到文件(可能位于您的$ SIG {USR1}处理程序中),然后对其进行监控。每次获得SIGUSR1时,甚至可以覆盖它。

我正在运行的另一个解决方案是创建一个套接字处理程序。这会变得更加复杂,除非你愿意使用一堆模块。我的解决方案是使用AnyEvent + Coro。我把主要的工作在一个线程科罗,开始了我的AnyEvent::Socket :: tcp_server(S)(插座和/或TCP端口号),并连接上,做我需要做的(在我的情况下,创造了一堆线程,在你的情况下只需输出你在$ SIG {USR1}处理程序中做的细节,然后关闭连接)。

真正的代码:

AnyEvent::Socket::tcp_server "unix/", "/tmp/cbstats.sock", sub { 
    my $fh = shift; 
    $fh->binmode(':utf8'); 
    $fh = unblock $fh; 

    $self->handle_connection($fh, @_); 

}; 

然后,因为我的是互动的,我跑socat readline /tmp/cbstats.sock。在你的情况下,只要你想要输出就可以做socat stdout /tmp/your.socket。 (使用文件系统权限来限制/允许谁可以看到这些数据。)

这里有一点需要关注 - 您需要停止使用sleep()(或使用Coro版本),以便您可以接收请求在套接字上。但是,说实话,它一直是最小的。不过,我已将服务器切换到使用AnyEvent定时器,然后我甚至不需要担心睡眠。在那之后,我在自己的计时器上共享了多台服务器,并且它们都运行得很好。

祝你好运。

+0

我认为输出文件解决方案就是我最终使用的解决方案。我将让信号处理程序将输出写入文件,然后我只需编写一个shell脚本来发送USR1信号并将文件内容转储给用户。谢谢。 – Dave

1

什么是您的操作系统? ps(1)可以输出任何进程ID的控制tty。在Linux上,/proc/<pid>/fd/1/proc/<pid>/fd/2是到终端或进程的输出流连接到的文件的符号链接。

+0

对不起,我应该提到操作系统是Solaris 10(SPARC)。我尝试使用'POSIX :: sigaction'并在相应的'SigAction'对象上设置了SA_SIGINFO标志,但Solaris不会将pid和uid(或任何其他)传递给处理程序,即使设置了SA_SIGINFO标志也是如此。 – Dave

2

与你问的两个主要问题是

  1. 的TTY不见了/删除一旦调用shell终止
    在我的Linux系统,其效果类似于如果打开会发生什么/将STDOUT重定向到一个文件,然后取消链接该文件。你没有得到的是输出设备后面,除非你在/proc

  2. 信号发挥可怕,可怕的招数不携带发送者的TTY
    无论是通过minimal specification也不由implementations which extend the spec

所以,我'd建议您在终端多路复用器(如tmuxGNU screen)下运行该实用程序,或将STDOUT重定向到某些其他输出,您可以从另一个终端检查该文件,如文件或系统日志或数据库等。

+0

谢谢。我希望避免使用屏幕等,使其更像一个守护进程,看起来更“原生”(如果这是有道理的)。不过,我可能需要探索这个选项。 – Dave

+0

@Dave,守护进程经常登录到日志记录子系统FWIW。 – pilcrow