2012-06-28 37 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