正在运行的脚本可以识别日志记录上下文吗?

正在运行的脚本可以识别日志记录上下文吗?

假设我将程序的 重定向到文件STDOUTSTDERR

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

正在运行的程序能否发现这一点,即知道这些文件的路径吗?

答案1

{ 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

答案2

您可以致电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

答案3

在您的情况下,STDOUT将保存到 fileoutput.log并将STDERR保存到 file error.log。两个文件都保存在同一目录中script.sh

如果你想让你的程序“知道这些文件的路径”,你必须使用绝对路径:

./script.sh > /path/to/output.log 2> /path/to/error.log

答案4

output.log和文件error.log在当前目录(即变量值)中创建$PWD。如果您希望程序稍后使用这些文件,只需在运行脚本之前将其目录保存在变量中即可。这是一个例子:

OUTDIR=$PWD
./script.sh 1> output.log 2> error.log
# Whatever you want to do else ...
echo The output file : =======
cat $OUTDIR/output.log
echo =========================
echo 
echo The errors file : =======
cat $OUTDIR/error.log
echo =========================

相关内容