在另一个bash会话中查看运行过程的输出
1. 概述
我们偶尔会运行命令或脚本,我们需要实时观察它们的输出。但是,该输出可能没有被定向到我们当前的终端。 在本教程中,我们将了解如何在另一个 Bash 会话中查看命令输出。我们将在不中断流程的情况下执行此操作。
2. 长时间运行脚本示例
想象一下,我们有一个名为Blogdemo_Categorization.sh的脚本,它根据主题将 Blogdemo 文章组织到目录中:
#!/bin/bash
grep -riH 'java' ~/articles/* >> Java
grep -riH 'kotln' ~/articles/* >> Kotlin
grep -riH 'scala' ~/articles/* >> Scala
grep -riH 'computer science' ~/articles/* >> Computer_Science
grep -riH 'linux' ~/articles/* >> Linux
鉴于 Blogdemo 档案中的文章数量,这个过程可能会运行相当长的一段时间。运行脚本 ( $ ./Blogdemo_Categorization.sh ) 不会向我们的终端显示任何输出。 我们如何观察脚本的进度?
3. 在输出文件上使用tail或cat
使用这种方法,我们将脚本的输出重定向到一个文件:
$ ./Blogdemo_Categorization.sh > file1
接下来,在新的 Bash 会话中,我们对该输出文件运行tail 命令:
$ tail -f file1
我们应该看到运行命令的输出流。 让我们尝试用cat替换 tail:
$ cat file1
与tail不同,** cat不会在所有数据到达时对所有数据进行流式传输,而是会打印出到目前为止的进度,然后结束**。当我们主要对**正在运行的进程输出的快照感兴趣时,cat很有用。**相反,tail -f会跟随正在运行的进程,直到我们按下 CTRL-C 来停止它。
4. 使用strace
在单独的 Bash 会话中,我们必须首先运行ps 以列出正在运行的进程:
$ ps -ef
从这里,我们找到正在运行的命令的进程 ID。这将位于命令语句记录的PID列下:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 12754 0.0 0.0 48304 1344 pts/0 S+ 17:12 0:00 Blogdemo_Categorization.sh
strace 然后跟踪系统调用和信号:
$ sudo strace -p12754 -s9999 -e write
使用此命令,我们将其*-p选项用于进程 ID。我们还使用-s9999选项无限扩展字符串大小输出。默认字符串大小为 32 个字符。最后,我们使用-e write选项来允许ASCII和十六进制*字符。
这种方法比较常用,因为我们不需要对文件设置任何重定向,我们可以选择在进程启动后进行。
5. 使用nohup
nohup 使我们能够在没有挂断的情况下运行命令,并将输出发布到non-tty:
$ sudo nohup Blogdemo_Categorization.sh
接下来,在新的 Bash 会话中,我们可以在nohup.out上使用tail 。这是一个包含命令语句输出的文件:
$ tail -f nohup.out
这会产生一个运行命令的输出流。 正如我们在第 3 节中观察到的,我们也可以用cat替换tail。
6. 通过*/proc*观察输出
我们可以使用 Linux /proc目录查看输出。如果进程本身已经在其核心操作中重定向到文件,我们可以使用此方法:
$ ./Blogdemo_Categorization.sh > file1
接下来,我们使用tail命令显示文件增长时进程的输出。
$ sudo tail -f /proc/12754/fd/1
进程输出的恒定流将出现在我们的新 Bash 会话中。
此方法之所以有效,是因为/proc 文件夹托管子目录,其中包含每个正在运行的进程的虚拟流。子目录以进程 ID 命名。进程 ID 后面的*/fd文件夹是文件描述符。它**记录进程的流,即stdout*、stderr和其他输出**。stdout是我们感兴趣的输出流,即*/fd* 文件 1。
和前面的部分一样,我们可以用cat替换tail。
7. 使用watch(BSD特有)
如果我们运行的是BSD平台,我们可以使用watch 命令来观察脚本的输出。因此,在一个会话中运行脚本后,在新会话中,我们可以运行watch:
$ watch /dev/pts/0
/pts 代表伪终端从机。这是内核生成的一个文件夹,用于列出正在运行的进程的内容。在该*/dev/pts文件夹中,文件0*是具有脚本虚拟流的文件。