bax*_*ear 39 linux zsh python logging tmux
不小心删除了正在运行的进程的日志文件python something.py 2>&1 | tee .log。该脚本在 zsh 上的 tmux 窗格中运行。该进程仍在运行,但不记录日志。输出本身溢出 tmux-scrollback-buffer。我可以以某种方式(管理员/sudo 权限)再次启动日志记录过程而不重新启动该过程吗?
通常,我的尝试不会出现问题,并且代码与安全或任何类型的生产无关,而只是复杂的数学计算。所以,这样的尝试始终是足够的。
在我目前的情况下,如果我可以在不重新启动进程的情况下再次开始日志记录,那就太好了。
use*_*686 68
只要tee进程持有打开的文件描述符,文件就会继续存在,并且所有内容仍然记录在那里。您可以通过 /proc 复制它们来恢复其当前内容:
查找“tee”进程的 PID。
\n使用lsfd -p <PID>或lsof -p <PID>或ls -l /proc/<PID>/fd查找与打开的文件对应的文件描述符号。(它甚至会在文件名旁边标记为“(已删除)”。)
对于诸如“tee”之类的简单程序,打开的第一个文件几乎总是 FD #3,因此本文中的所有示例也将使用3。
通过以下方式将文件的内容复制到新文件/proc:
cp /proc/<TEE_PID>/fd/3 old.log\nRun Code Online (Sandbox Code Playgroud)\n(/proc/PID/fd 中的符号链接是特殊的 \xe2\x80\x93,打开它们仍然可以解析为正确的文件,即使符号链接看起来已损坏,或者即使它指向的东西甚至不是真正的文件。)
\n也可以让 'tee' 开始写入新文件:
\n将gdb调试器附加到进程:
$ sudo gdb -p <TEE_PID>\nRun Code Online (Sandbox Code Playgroud)\n这将暂停“tee”。如果 Python 程序产生足够的日志输出来填充管道缓冲区,它也可能会暂停(否则它不会注意到)。
\n如果您还没有 \xe2\x80\x93 使用 /proc 技巧来恢复旧的日志文件(通过另一个 shell,而不是从 gdb 内):
\n$ cp /proc/<TEE_PID>/fd/3 old.log\nRun Code Online (Sandbox Code Playgroud)\n通过在附加 gdb之后(即当“tee”挂起时)执行此操作,您可以避免在“cp”和 open() 之间的间隙丢失消息。
\n现在使用 gdb 关闭 'tee' 并重新打开文件:
\n(gdb) p (int) close(3)\n$1 = 0\n\n(gdb) p (int) open("new.log", 01|0100|02000, 0666)\n$2 = 3\n\n(gdb) q\nDetach? y\nRun Code Online (Sandbox Code Playgroud)\n(这些值01|0100|02000等于fcntl.hO_WRONLY|O_CREAT|O_APPEND中的值,这使得 open() 调用的行为类似于shell 运算符。)>>
对于诸如“tee”之类的简单情况,open() 极不可能为您提供除原始#3 之外的任何其他文件描述符,因为这是最低的可用 FD。但在某些情况下,程序更复杂(如果存在编号间隙),可能需要调用dup2($2, 3)并close($2)手动将新打开的文件移动到所需的 FD。
旧文件现在将完全消失(因为它已被删除并且最后一个文件句柄已关闭),但“tee”将写入新文件而不会注意到任何事情。
\n注意:除了打开新文件之外,还可以使用linkat()在不中断任何内容的情况下使原始日志文件存在,但我还没有对此进行测试。(编辑:不幸的是,根据 linkat() 文档,这对于完全取消链接的文件不起作用。)
| 归档时间: |
|
| 查看次数: |
3143 次 |
| 最近记录: |