0

我在我的大学机器上运行了一个 python 程序,我意识到它需要的时间比我预期的要多。代码的一个循环打印一些输出。我想将此输出保存在一个文件中,并在后台发送当前正在运行的程序,因为我需要从系统中注销。

这(如何将已经运行的进程置于 nohup 下?)解释了如何将其发送到后台。有没有什么方法可以保存每秒显示在屏幕上的输出,例如通过使用tee

4

2 回答 2

2

我没有尝试过,但这个邪恶的黑客可能会奏效。

  1. 查找程序正在使用的文件描述符:

    ls -l /proc/<your-pid>/fd
    
  2. 将调试器附加到进程(可执行文件类似于/usr/bin/python):

    gdb --pid=<your-pid> <executable>
    
  3. O_CREAT打开您想要的新文件(您可能需要查找和的数值O_WRONLY):

    (gdb) set $newfd = open("myfile", O_CREAT | O_WRONLY)
    
  4. 将您在步骤 1 中找到的旧文件描述符替换为新文件描述符。

    (gdb) call dup2(<old-fd>, $newfd)
    (gdb) call close($newfd)
    
  5. 设置程序再次运行并断开调试器

    (gdb) detach
    (gdb) quit
    

这仅在程序中存在opendup2函数时才有效。

警告:这可能会导致您的程序崩溃!

于 2013-11-06T14:39:28.450 回答
1

如果程序已经启动,则需要修改(见下文)来重定向其输出。相反,您可以/应该事先采取预防措施。

我发现始终在屏幕会话中运行远程命令非常有用。这使您可以:

  1. 随意附加和分离会话,而不会干扰正在运行的程序。这意味着您可以分离会话,注销,然后稍后登录并在您离开它们时找到所有“窗口”和正在运行的程序(或者,希望完成计算)。这也适用于您的 ssh 连接意外断开,或者您需要同时从多个地方连接(例如,通过 ssh 从您自己的笔记本电脑/机器,以及直接从大学机器的终端);
  2. 在同一个 ssh 连接上运行多个(文本模式)“窗口”,并通过键盘快捷键在它们(及其输出)之间切换;
  3. 每个“窗口”都有一个回滚缓冲区,这样即使忘记使用tee,也可以向上滚动查看程序打印的内容;
  4. 设置会话密码,以便只有您可以重新附加到它。

关于黑客部分:

如果你被卡在运行一个很长很重要的程序,并且无法使用上述方法重新启动它,还是有希望的。

可以通过文件系统找到每个进程的打开文件描述符(包括其当前的标准输出)/proc。使用它,您可以交换文件描述符并让命令切换到即时输出其他地方。 该脚本 (fdswap.sh)使用 gdb 从正在运行的进程下换出文件描述符,并且有一篇文章解释了如何使用它。

简而言之:找到正在运行的进程的pid,然后运行ls -l /proc/$pid/fd/0查找其当前输出到哪里,然后使用上面的脚本将其换出:fdswap.sh /dev/pts/$vty /path/to/new/output $pid.

历史参考:http ://www.phrack.org/issues.html?issue=51&id=5

于 2013-11-06T14:35:41.013 回答