当我在本地工作时,我留下了一个在远程计算机上运行的脚本。我可以通过 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_scome
sysctl 控制的。
答案3
在 BSD 中,您可以使用watch
它监听给定的 tty,例如
watch /dev/pts/0
screen
在Linux中,如果进程之前没有在多路复用器下运行,例如或 ,则不可能tmux
。也可以看看:Reptyr:将正在运行的进程附加到新终端
似乎唯一的方法是调试进程(例如strace
,dtrace
/ dtruss
,gdb
,lldb
, 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/*