无法连续 read/monitor 远程文件

Can't continously read/monitor remote file

我正在使用 JSCH 尝试读取不断更新的单独服务器上的日志文件。我可以很好地获取文件中当前的任何内容,但是一旦我到达文件末尾,我的延迟就会发生但没有新行被获取并且我的延迟打印语句继续循环(我通过 运行 验证我的程序旁边的日志尾巴)。如果有人能指出我的代码中可能有误或遗漏的地方,或者可能提出更好的方法,我将不胜感激。

InputStream stream = sftpClient.get(filename);
BufferedReader br = new BufferedReader(new InputStreamReader(stream));
String line;
while (true)
{
    try
    {
        line = br.readLine();
        if (line == null)
        {
            System.out.println("End of file reached. Sleeping..");
            Thread.sleep(sleepTime);
            System.out.println("Retrying for more data..");
        }
        else
        {
            //do something with line, print for now.
            System.out.println(line);
        }
    }
    catch (Exception e)
    {
        System.out.println("Something went wrong: " + e);
    }
}

我认为您应该在结束时重新打开文件。 如果是用于生产目的,请尝试使用 Apache tailer https://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/input/Tailer.html

补充一下 crv 提到的内容,这里有一个关于如何使用 Apache 的示例 Tailor

import java.io.File;

import org.apache.commons.io.input.Tailer;
import org.apache.commons.io.input.TailerListener;
import org.apache.commons.io.input.TailerListenerAdapter;

public class FileTailor {

    private static final int SLEEP = 500;

    public static void main(String[] args) throws Exception {
        FileTailor fileTailor = new FileTailor();
        fileTailor.run("log_file.log");
    }

    private void run(String path) throws InterruptedException {
        TailerListener listener = new LogFileListener();
        Tailer tailer = Tailer.create(new File(path), listener, SLEEP);
        tailer.run();
    }

    public class LogFileListener extends TailerListenerAdapter {
        @Override
        public void handle(String line) {
            //do something with line, print for now.
            System.out.println(line);
        }
    }
}

您可以查看 Jsch 的源代码 ChannelSftp here. The InputStream returned by jsch 当您获取远程文件时,您会在读取到远程文件末尾时设置一个标志。继续尝试从流中读取只会 return 缓存的 EOF 指示。

Jsch 有 a stat() method to retrieve information about a remote file, including its size and last-modified timestamp. Jsch also has a version of the get method 可以让你跳过远程文件的第一部分。您可以定期调用 stat() 来检测文件是否已更改,然后使用 get() 跳过您已经阅读的文件部分,只阅读新内容。

您可能还想考虑使用不同的 SSH 客户端库。 SFTP protocol 包含打开远程文件和读取或写入文件任意部分的低级命令。然而,Jsch 并未通过 ChannelSftp 公开此功能的全部范围。还有其他 java SFTP 客户端库,可提供对 SFTP 协议的较低级别访问。

我正在尝试这个,在我的情况下,我必须连续读取日志,但我只能通过 sftp 访问它,正如@Kenster 提到的,我通过调用 [=11 检查文件大小是否发生了变化=] 然后使用 get( String src, String dst, SftpProgressMonitor monitor, int mode),它所做的是在我的目录中生成一个新文件,并在 RESUME 中使用模式参数,它只获取最新的内容。

long remotepointer = 0;
SftpATTRS atrr = null;
Strinf remoteFile = "log.txt"
Strinf tempFile = "/tmp/data/log.txt"
while (true){
    try {  
      atrr =  channelSftp.stat(remoteFile);
      if(atrr.getSize() > remotepointer){
        remotepointer = atrr.getSize();
        channelSftp.get(remoteFile, tempFile,null,ChannelSftp.RESUME);
      }
    }catch (Exception e){
        System.out.println("Something went wrong: " + e);
    }
}