2016年10月6日 星期四

[Embedded] 取出背景行程的 STDOUT 訊息

在 linux 系統,若需要觀察系統中某行程的輸出訊息 (stdout, stderr),常見的做法是在執行檔案時直接將輸出導入至某個檔案。如下:
1. 分別導出 stdout 與 stderr
executable_file > stdout.txt 2> stderr.txt
2. 將 stdout 與 stderr 導出至同一檔案
executable > output.txt 2>&1
如果是目前已經在執行的行程,要如何在不重啟的情況之下,將 stdout, stderr 轉導向其他檔案呢?比方說某個正在執行的 CGI 程式,如何知道其輸出訊息?
以下以 lighttpd為例,說明作法

1. 確認 process 的 STDOUT/STDERR 對應的 file descriptor
$ ls -l /proc/$(pidof lighttpd)/fd
lrwx------ 1 root root 64 Oct 6 14:13 0 -> /dev/null
lrwx------ 1 root root 64 Oct 6 14:13 1 -> /dev/null
lrwx------ 1 root root 64 Oct 6 14:13 2 -> /dev/null 

2. 關閉原本的tty, 並重新開啟tty 指定到某個檔案
# gdb -p $(pidof lighttpd)
(gdb) p close(1)
(gdb) p dup2(open("/tmp/httplog ",2),1)
(gdb) detach
(gdb) quit
$ ls -l /proc/$(pidof lighttpd)/fd
lrwx------ 1 root root 64 Oct 6 14:13 0 -> /dev/null
lrwx------ 1 root root 64 Oct 6 14:13 1 -> /tmp/httplog
lrwx------ 1 root root 64 Oct 6 14:13 2 -> /dev/null

3. 假設要直接導向目前視窗,先確認目前tty之後,再更換輸出即可
# tty
   /dev/pts/0 
# gdb -p $(pidof lighttpd)
(gdb) p close(1)
(gdb) p dup2(open("/dev/pts/0",2),1)

4. 若是想要直接看到 console 出現的錯誤訊息呢?
a. 開啟兩個 telnet session
# who
root            pts/0           00:00   Oct  7 08:49:55  [::ffff:192.168.0.101]:31109
root            pts/1           00:01   Oct  7 08:53:55  [::ffff:192.168.0.101]:31133
b. 在 pts/0 畫面輸入指令 "tail -f /var/adm/messages > /dev/pts/1 &",接著便可以在 pts/1 畫面看到與 console 相同的除錯訊息。

參考資料:
  1. http://stackoverflow.com/questions/593724/redirect-stderr-stdout-of-a-process-after-its-been-started-using-command-lin/593764#593764