jwb*_*ley 302 bash process io-redirection
当我在本地工作时,我已经在远程机器上运行了一个脚本。我可以以同一用户身份通过 SSH 连接到机器,并查看在ps.
$ ps aux | grep ipcheck
myuser 18386 0.0 0.0 18460 3476 pts/0 S+ Dec14 1:11 /bin/bash ./ipchecker.sh
Run Code Online (Sandbox Code Playgroud)
它只是在本地会话上输出到标准输出(我从./ipchecker.sh本地终端窗口运行,没有重定向,没有使用screen等)。
无论如何,我可以从 SSH 会话中查看此运行命令的输出(不停止它)吗?
到目前为止,我发现的最好的方法是使用,strace -p 18386但我在屏幕上看到成群的文本,它太详细了。我可以停下来strace,然后筛选输出,发现文本带打印到标准输出,但它非常长且令人困惑,很明显,当它停止时,我可能会错过一些东西。我想找到一种方法来实时查看脚本输出,就像我在本地工作一样。
任何人都可以改进吗?显而易见的答案是通过重定向或在screen会话等中重新启动脚本,这不是关键任务脚本,所以我可以这样做。相反,我认为这是一个有趣的学习练习。
Gil*_*il' 248
如果您只想监视现有进程,则可以使用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 将后续输出转移到当前终端或新屏幕会话。请参阅如何否认正在运行的进程并将其关联到新的屏幕外壳?和其他链接线程。
请注意,根据您系统的设置方式,您可能需要以straceroot身份运行所有这些命令,即使该进程在您的用户下运行而没有额外权限。(如果进程以不同的用户身份运行,或者是 setuid 或 setgid,则需要以straceroot身份运行。)大多数发行版只允许进程跟踪其子进程(这提供了适度的安全优势——它可以防止一些直接的恶意软件注入,但不会通过修改文件来防止间接注入)。这是由kernel.yama.ptrace_scomesysctl控制的。
tvl*_*ooy 242
您可以通过proc文件系统访问输出。
tail -f /proc/<pid>/fd/1
Run Code Online (Sandbox Code Playgroud)
1= 标准输出,2= 标准错误
ken*_*orb 15
在 BSD 中,您可以使用watchwhich 监听给定的 tty,例如
watch /dev/pts/0
Run Code Online (Sandbox Code Playgroud)
在 Linux 中,如果进程没有在screen或之前在多路复用器下运行,则不可能tmux。另请参阅:Reptyr:将正在运行的进程附加到新终端
看来唯一的办法是调试过程中(例如strace,dtrace/ dtruss,gdb,lldb,等)。
由于您已经使用strace, 来获取任何有意义的输出,您需要通过限定表达式(例如file)进行过滤,然后解析输出。这是示例:
strace -e trace=write -s1000 -fp 18386 2>&1 | grep -o '".\+[^"]"'
Run Code Online (Sandbox Code Playgroud)
它的作用是打印由 PID 指定的进程(长度为 1000)的写操作(用于pgrep按名称查找),将标准错误重定向到输出(要过滤),并打印双引号字符串。
如果您正在处理二进制输出,则可以使用read(with -r) 和printf (with %b)来解析转义序列字符,例如
while read -r -t1 line; do printf "%b" $line; done
Run Code Online (Sandbox Code Playgroud)
检查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
Run Code Online (Sandbox Code Playgroud)
有关使用任何进程的示例,请检查:如何将 shell 中的 strace 解析为纯文本?在计算器溢出
小智 8
如果你想获得 stderr 和 stdout 你可以运行这个:
tail -f /proc/<pid>/fd/*
Run Code Online (Sandbox Code Playgroud)
解析strace的输出:
我使用了最佳答案(我的进程 ID 为 28223)...
> sudo strace -p28223 -s9999 -e write
...
write(9, "Info\nI\nCare\nabout", 55) = 55
...
Run Code Online (Sandbox Code Playgroud)
确定我在乎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 $1.split('\x').map { |s| s.to_i(16).chr }.join()
end
}
Run Code Online (Sandbox Code Playgroud)
不要忘记 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'
Run Code Online (Sandbox Code Playgroud)
而且,瞧,它输出进程的原始标准输出、换行符、颜色等等!
小智 6
您始终可以使用nohup和&启动进程
nohup rsync source_file dest_file &
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用以下命令从任何 tty 检查进度:
tail -f nohup.out
Run Code Online (Sandbox Code Playgroud)
这对我来说效果很好。
我建议创建一个命名管道(mkfifo),然后写入该文件。然后,从中阅读。您始终可以使用tail, 等方法来最小化输出等。每当您清除管道(从中读取)时,它都会被清除,因此不会保留输出。
另一种选择是将所有内容写入文件(很像日志文件),然后随时对其进行分析。如果您想保留所有输出,这将是首选操作。