我正在尝试tail
在多台远程计算机上记录日志文件并将输出转发到我的本地工作站。我希望在按Ctrl-时关闭连接C。
目前我有以下功能几乎按预期工作。
function dogfight_tail() {
logfile=/var/log/server.log
pids=""
for box in 02 03; do
ssh server-$box tail -f $logfile | grep $1 &
pids="$pids $!"
done
trap 'kill -9 $pids' SIGINT
trap wait
}
连接关闭,我收到来自 的输出tail
。但是,由于输出是分批进行的,所以会进行某种缓冲。
这是有趣的部分......
/var/log/server.log
当执行以下命令并将“test”附加到远程计算机上的文件 4-5 次时,我可以看到相同的缓冲行为......
ssh server-01 "tail -f /var/log/server.log | grep test"
...并找到了两种禁用它的方法...
将 -t 标志添加到 ssh。
ssh -t server-01 "tail -f /var/log/server.log | grep test"
从远程命令中删除引号。
ssh server-01 tail -f /var/log/server.log | grep test
然而,这些方法都不适用于上述在多台机器上执行的功能。
我尝试过 dsh,它在执行时具有相同的缓冲行为。
dsh -m server-01,server-02 -c "tail -f /var/log/server.log | grep test"
同样,如果我删除引号,缓冲就会消失,一切正常。
dsh -m server-01,server-02 -c tail -f /var/log/server.log | grep test
还尝试了parallel-ssh
与 完全相同的工作方式dsh
。有人可以解释一下这是怎么回事吗?
我该如何解决这个问题?如果可能的话,采用直道是理想的选择ssh
。
PS 我不想使用multitail
或类似的,因为我希望能够执行任意命令。
答案1
grep
您看到的是Glibc 提供的标准 stdout 缓冲区的效果。最好的解决方案是使用--line-buffered
(GNU grep,我不确定其他实现可能支持它或类似的东西)来禁用它。
至于为什么这仅在某些情况下发生:
ssh server "tail -f /var/log/server.log | grep test"
在服务器上运行引号中的整个命令 - 从而grep
等待填充其缓冲区。
ssh server tail -f /var/log/server.log | grep test
在本地计算机上运行通过 ssh 通道发送的grep
输出。tail
这里的关键部分是,grep
根据它是否stdin
是终端来调整其行为。当您运行时ssh -t
,远程命令正在使用控制终端运行,因此远程命令的grep
行为就像本地命令一样。
答案2
看一下这个:multitail
MultiTail 允许您在终端的多个窗口中监视日志文件和命令输出、着色、过滤和合并。
要跟踪多个服务器中的日志,请使用:
multitail -l 'ssh user@host1 "tail -f /path/to/log/file"' -l 'ssh user@host2 "tail -f /path/to/log/file"'
答案3
您可以在侧边日志中查看。
我创建的一个 Java 工具,能够使用 SSH 读取本地和远程日志文件。使用起来相当简单。
更多解释:https://github.com/pschweitz/insidelog/wiki
只需下载与您的操作系统相对应的版本,即您的 Java 运行时中的本机 jar 版本可执行文件(需要 java 8_40 或更高版本):
https://github.com/pschweitz/insidelog/releases
您可以找到完整的文档(也嵌入在 Github 的页面中)