Shell

正在執行的腳本可以辨識日誌記錄上下文嗎?

  • April 7, 2014

假設我將程序的STDOUT,重定向STDERR到文件。

./script.sh 1> output.log 2> error.log

正在執行的程序能否發現這一點,即知道這些文件的路徑?

您可以呼叫lsof列出 shell 程序的打開文件。用於-a -p $$將輸出限制為 shell 程序 ( $$),-d 1將輸出限制為文件描述符 1(例如),並-F n以可解析的形式列印輸出。這是一個處理文件名中任意字元的 shell 片段:

output_file=$(lsof -a -p $$ -d 1 -F pn; echo .)
output_file=${output_file%.}
output_file=${output_file#n}

如果文件名不包含換行符,您將能夠擺脫output_file=$(lsof -a -p $$ -d 1 -F pn | sed -n '2s/.//p').

請注意,文件名可能並不總是存在,尤其是在文件已被刪除的情況下。

在 Linux 下,訪問文件名的另一種方法是通過/proc/$$/fd:/proc/$$/fd/1是一個稍微神奇的符號連結,指向 shell 在文件描述符 1 上打開的文件(即使返回的文件名readlink不存在,該連結也有效,例如在刪除文件的情況)。

利用這種方式獲得的資訊通常是一個非常糟糕的主意。如果有人呼叫您的腳本並將輸出重定向到文件,如果您因文件的位置而表現不同,或者以附加到文件以外的方式影響文件,他們將不會喜歡它。有一個例外:您可能希望根據您是在寫入終端還是其他東西(管道、套接字、文件)做出不同的反應,例如在終端上顯示顏色或進度指示器。有一個特定的測試來確定文件描述符是否連接到終端:

if [ -t 2 ]; then
 # stderr is a terminal
 printf 1>&2 '\e[31mError: widget not found\e[0m'
else
 # stderr is not a terminal
 echo 1>&2 'Error: widget not found'
fi
{ readlink /dev/fd/[1,2] ; echo "out" ; } >./file 2>./error    
{ readlink /dev/fd/0 ; cat ; } <./file

輸出:

/home/mikeserv/file
/home/mikeserv/file
/home/mikeserv/error
out

{ readlink /proc/$$/fd/[1,2] ; echo out ; } >./file 2>./error
{ readlink /proc/$$/fd/0 ; cat ; } <./file

輸出:

/home/mikeserv/file
/home/mikeserv/file
/home/mikeserv/error    
out

引用自:https://unix.stackexchange.com/questions/123492