如何在另一个 bash 会话中查看正在运行的进程的输出?

如何在另一个 bash 会话中查看正在运行的进程的输出?

当我在本地工作时,我留下了一个在远程计算机上运行的脚本。我可以通过 SSH 以同一用户身份连接到计算机,并查看在ps.

$ ps aux | grep ipcheck
myuser  18386  0.0  0.0  18460  3476 pts/0    S+   Dec14   1:11 /bin/bash ./ipchecker.sh

它只是在本地会话上输出到标准输出(我./ipchecker.sh从本地终端窗口运行,没有重定向,没有使用screen等)。

无论如何,我可以从 SSH 会话中查看此运行命令的输出(无需停止它)吗?

到目前为止,我发现的最好的方法是使用,strace -p 18386但我看到大量的文本在屏幕上飞舞,它太详细了。我可以停下来strace,然后筛选输出,找到打印到标准输出的文本,但它非常长且令人困惑,显然,当它停止时,我可能会错过一些东西。我想找到一种方法来实时查看脚本输出,就像我在本地工作一样。

有人可以对此进行改进吗?明显的答案是通过重定向或在会话等中重新启动脚本screen,这不是关键任务脚本,所以我可以这样做。相反,我认为这是一个有趣的学习练习。

答案1

您可以通过文件系统访问输出proc

tail -f /proc/<pid>/fd/1

1= 标准输出,2= 标准错误

(或者像 @jmhostalet 说的:cat /proc/<pid>/fd/1如果 tail 不起作用)

答案2

如果您只想监视现有进程,则可以使用strace -p1234 -s9999 -e write其中 1234 是进程 ID。 (-s9999避免将字符串截断为 32 个字符,以及write生成输出的系统调用。)如果您只想查看写入特定文件描述符的数据,您可以使用类似于strace -p1234 -e trace= -e write=3仅查看写入文件描述符 3 的数据(-e trace=防止系统呼叫被记录)。这不会给你已经产生的输出。

如果输出滚动得太快,您可以将其通过管道传输到寻呼机,例如less,或将其发送到带有strace -o trace.log ….

对于许多程序,您可以使用 ptrace hack 将后续输出转移到当前终端或新的屏幕会话。看如何否认正在运行的进程并将其关联到新的屏幕外壳?和其他链接的线程。

请注意,根据您的系统设置方式,您可能需要strace以 root 身份运行所有这些命令,即使该进程在您的用户下运行且没有额外的权限。 (如果进程以不同用户身份运行或者是 setuid 或 setgid,则您需要strace以 root 身份运行。)大多数发行版只允许进程追踪其子进程(这提供了适度的安全优势 - 它可以防止一些直接的恶意软件注入,但不能防止通过修改文件进行间接注入)。这是由kernel.yama.ptrace_scomesysctl 控制的。

答案3

在 BSD 中,您可以使用watch它监听给定的 tty,例如

watch /dev/pts/0

screen在Linux中,如果进程之前没有在多路复用器下运行,例如或 ,则不可能tmux。也可以看看:Reptyr:将正在运行的进程附加到新终端

似乎唯一的方法是调试进程(例如stracedtrace/ dtrussgdblldb, ETC。)。

由于您已经使用strace, 来获取任何有意义的输出,因此您需要按限定表达式(例如file)进行过滤,然后解析输出。这是示例:

strace -e trace=write -s1000 -fp 18386 2>&1 | grep -o '".\+[^"]"'

它的作用是打印由 PID 指定的进程(长度为 1000)的写入操作(用于pgrep按名称查找),将标准错误重定向到输出(进行过滤),并打印双引号字符串。

如果您正在处理二进制输出,您可以使用read(with -r) 和printf (with %b) 来解析转义序列字符,例如

while read -r -t1 line; do printf "%b" $line; done

检查help read更多参数(例如,-n在一定数量的字符后打印,而不是换行)。

这是更完整的示例:

strace -e trace=write -s1000 -fp 18386 2>&1 \
| grep --line-buffered -o '".\+[^"]"' \
| grep --line-buffered -o '[^"]\+[^"]' \
| while read -r line; do
  printf "%b" $line;
done

有关使用任何流程的示例,请检查:如何将shell中的strace解析为纯文本?在堆栈溢出

答案4

如果你想获得 stderr 和 stdout 你可以运行这个:

tail -f /proc/<pid>/fd/*

相关内容