This is doable, with some hacking and limitations (you need root privileges).
First find what file descriptor is using the application to write the log file then create a symbolic link in the previous log file location and pointing to the file /proc entry, eg:
ln -s /var/tmp/file.log /proc/12345/fd/3
The first limitation is that if the file was only open for writing by the process, its permission won't allow an unprivileged user to read its content. However, root and users with the file_dac_read privilege won't be affected. Alternatively, you can use a process to copy the file contents with tail
like Gilles is suggesting in his comment. eg:
tail -c +1 -f /proc/12345/fd/5 > /var/tmp/file.log
The second issue is that the whole file content will be lost (ln -s
) or part of it (tail -c 1 -f
) when the process either closes it or exits.
A workaround is to use a program that monitors this event and backup the file before close is actually called.
Likely tools to do the job are dtrace, truss, mdb, or dbx.
Here is a proof of concept using dtrace on Solaris 10.
#!/bin/ksh
#
# This dtrace script is monitoring a file descriptor for a given process
# and copy its content to the given path when the file is closed.
#
pid=${1:?"$0: Usage: pid fd path"}
fd=${2:?}
path=${3:?}
[[ -f $path ]] && { echo "$path exists"; exit 1; }
dtrace -w -n '
syscall::close:entry
/pid=='$pid' && arg0=='$fd'/
{
stop();
system("cp /proc/%d/fd/%d %s",pid,arg0,"'"$path"'");
system("prun %d",pid);
exit(0);
}'
tail -c +1 -f /proc/pid/fd/num > /logfile
to keep the original file (name) in sync with is active file descriptor data. The issue with this solution is that, especially with buffered output but not only, you'll likely miss the last lines when the original writing process dies. – jlliagre Apr 7 '12 at 13:01