从本地工作开始,我就已经在远程计算机上运行了一个脚本。我可以以同一用户的身份通过SSH连接到计算机,并查看ps中运行的脚本。

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


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

SSH会话中是否存在我可以查看此正在运行的命令的输出(而无需停止它)?

到目前为止,我发现最好的方法是使用strace -p 18386,但是我成群结队屏幕上飞扬的文字,其内容过于详尽。我可以停止strace,然后在输出中进行筛选,然后找到打印到stdout的文本,但是它很长且令人困惑,显然在停止时我可能会错过一些东西。我想找到一种方法来实时查看脚本输出,就像在本地工作一样。

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

评论

您的进程是在虚拟控制台中还是在类似GUI / xterm的环境中运行?

您可以将strace的输出限制为一个系统调用:strace -p 4232 -e write

@jippie这台机器正在运行完整的GUI(Linux Mynt 13,XFCE桌面),我启动了一个gnome终端。

这个网站上至少有十二个类似的问题。在此处查找reptyr可以找到其中的一些(和答案)。

#1 楼

如果您只想监视现有进程,则可以使用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 …发送到文件中。 br />
使用许多程序,您可以使用ptrace hack将后续输出转移到当前终端或新的屏幕会话。请参阅如何放弃正在运行的进程并将其关联到新的屏幕外壳?和其他链接的线程。

请注意,根据进程的系统设置,即使该进程在您的用户下运行且没有额外特权,您也可能需要以root用户身份运行所有这些strace命令。 (如果该进程以其他用户身份运行,或者是以setuid或setgid身份运行,则需要以root用户身份运行strace。)大多数发行版仅允许进程跟踪其子进程(这提供了中等的安全性好处-它防止了某些直接的恶意软件注入,但不能通过修改文件来防止间接注入)。这由kernel.yama.ptrace_scome sysctl控制。

评论


我不认为有办法将输出范围缩小到标准输出范围吗?

–乔纳
13年3月28日在0:33

你能解释所有论点吗?

–用户
15年3月16日在22:15

我从nodejs获得的很多输出中都有很多反斜杠和数字。关于它们可能采用哪种编码的任何线索?也有很多纯文本,这是我所需要的。

–雷神召唤师
15年7月16日在17:27

“你能解释所有论点吗?” @User:man strace

–手枪
2015年9月1日15:32

@RafaelMoni一个执行您要求的程序的程序称为调试器。

–吉尔斯'所以-不再是邪恶的'
15/12/22在12:12

#2 楼

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

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


1 = stdout,2 = stderr

评论


它给我:“无法打开/ proc / <我的pid> / fd / 1进行读取:没有这样的设备或地址”。

–雅罗斯拉夫·尼基琴科(Yaroslav Nikitenko)
16-10-27在13:36

是的应该是您的进程ID

–tvlooy
16年8月8日在14:10

如果输出将输出到tty(或重定向到/ dev / null),则此方法将不起作用-仅在将输出重定向到文件时才有效。

–mattdm
17年4月26日在18:19

在Ubuntu 16.04上测试过,它不起作用。在一个会话中,我执行以下操作:ping google.es,在另一个会话中以root身份运行:tail -f / proc /`pgrep ping` / fd / 2,但未显示任何内容。

– david.perez
18 Mar 2 '18 at 8:57



尾部对我不起作用,我改用sudo cat / proc / / fd / 1

– jmhostalet
19年2月11日在8:39

#3 楼

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

watch /dev/pts/0


在Linux中,如果该进程之前未在多路复用器下运行,则不可能例如screentmux。另请参阅:Reptyr:将正在运行的进程附加到新终端

似乎唯一的方法是调试该进程(例如stracedtrace / dtrussgdblldb等)。 >
由于使用了strace来获取任何有意义的输出,因此需要通过限定表达式(例如file)进行过滤,然后解析输出。这是示例:错误进入输出(将被过滤),并输出双引号字符串。

如果要处理二进制输出,则可以使用pgrep(带有read)和-r(带有printf),例如

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


检查%b是否有更多参数(例如help read在一定数量的字符后而不是换行符后打印)。这是更完整的示例:有关使用任何过程的示例,请检查:如何将shell中的strace解析为纯文本?在stackoverflow

#4 楼


您可以使用ssh localhost 'DISPLAY=:0.0 xwd -root' | xwud -scale窥视远程屏幕,其中localhost将替换为远程服务器登录凭据,并用GUI的显示号替换:0.0
使用x11vnc(这是VNC服务器)用于屏幕上的X会话。
在6个虚拟控制台之一上运行时,请尝试sudo setterm -dump 2 -file /dev/stdout,在其中用适当的vc替换2


#5 楼

我建议制作一个命名管道(mkfifo),然后写入该文件。然后,从中读取。您始终可以使用tail之类的方法来执行此操作,以最小化输出等。每当您清除管道(从管道读取)时,管道都会被清除,因此不会保留输出。

另一种选择是将所有内容都写入文件(非常类似于日志文件),然后随时对其进行分析。如果要保留所有输出,这将是首选操作。

#6 楼

解析strace的输出:

我使用了最高答案(我的进程ID为28223)...

> sudo strace -p28223 -s9999 -e write
...
write(9, "Info\nI\nCare\nabout", 55) = 55
...


确定我在乎write(9。 (下面使用了9,它可能是文件句柄,可能与您的过程有所不同。)然后,我编写了一个快速的Ruby脚本来解析和显示它们。

将以下内容粘贴到/usr/bin/parse_strace.rb

#!/usr/bin/ruby

num = ARGV[0]
STDIN.each { |line|
  if (line.match(/write\(#{ num },\s*"(.*?)"/)) then
    puts .split('\x').map { |s| s.to_i(16).chr }.join()
  end
}


别忘了chmod a+x /usr/bin/parse_strace.rb

我调用strace -xx(输出十六进制,因此正则表达式正确匹配),将(包括STDERR)管道到我的脚本9作为第一个参数。

sudo sh -c 'strace -xx -p28223 -s9999 -e write 2>&1 | parse_strace.rb 9'


,瞧,它输出过程的原始STDOUT,换行符,颜色以及所有内容!



#7 楼

您总是可以通过nohup和&

nohup rsync source_file dest_file &

启动进程,然后,您可以使用以下任何命令从tty检查进度:

tail -f nohup.out


对我来说很好。

评论


这个问题我想知道如何查看警报运行过程的输出,而不是如您的回答所示如何在后台运行过程

– jwbensley
17年4月26日在18:18

实际上,您的:nohup提法启发了我!谢谢!

– Nam G VU
18/12/13在15:55

#8 楼

获得输出的一个非常简单的方法是将输出捕获到一个文件中并尾随该文件。
如果这样做:
./ipcheck

INSTEAD做:在脚本所在的位置创建一个输出文件。然后,您可以从任何其他bash shell中简单地尾文件:
./ipcheck > [replacewithyourfilename]


评论


默认情况下,文件重定向倾向于使用基于块的缓冲(请参阅setbuf(3)),这可能会使尾部出现问题。

– thrig
17年4月26日在18:14

同样,这也无济于事,该问题是关于如何查看已运行的进程的输出,而不是有关如何为新进程重定向stdout的问题。

– jwbensley
17年4月26日在18:19

#9 楼

无法获取进程ID并与USR1进行通信,

$pgrep -l '^ipchecker.sh$'


打印脚本的PID,然后将其用于

$ kill -USR1 PID


我了解到USR1是一个“用户定义”信号,这意味着创建该程序的任何人都可以使用它来表示“关闭”或“转储日志”或“打印foo千次”。等等。

#10 楼

在bash 1中:
any_command_you_want > my_output.txt&

在bash 2中:
cat my_output.txt


评论


Pleas注意到OP表示“无论如何,SSH会话中都可以查看此正在运行的命令的输出(而无需停止它)?”。尽管您的方法不需要停止命令,但是它却无助于观察已经在运行的命令的输出(例如在OPs问题中)。另外,我至少会考虑使用tail -f而不是cat,以便可以实时跟踪输出。您可能希望查看OP对此答案的评论,该评论与您的​​评论基本相同。

– AdminBee
20年7月13日在9:19



#11 楼

如果要获取stderr和stdout,则可以运行以下命令:
 tail -f /proc/<pid>/fd/*