无法连续读取/监控远程文件

时间:2015-07-06 12:59:03

标签: java sftp jsch

我正在使用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);
    }
}

4 个答案:

答案 0 :(得分:2)

您可以看到Jsch的{​​{1}} here的源代码。获取远程文件时InputStream returned by jsch在读取远程文件末尾时设置标志。继续尝试从流中读取将只返回缓存的EOF指示。

Jsch有a stat() method to retrieve information about a remote file,包括其大小和上次修改的时间戳。 Jsch还有a version of the get method,可以跳过远程文件的第一部分。您可以定期调用stat()来检测文件是否已更改,然后使用get()跳过您已阅读过的文件部分,并阅读新内容。

您可能还想考虑使用其他SSH客户端库。 SFTP protocol包含用于打开远程文件以及读取或写入文件的任意部分的低级命令。但是,Jsch没有通过ChannelSftp公开这一全部功能。还有其他java SFTP客户端库,它们提供对SFTP协议的低级访问。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

只是添加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);
        }
    }
}

答案 3 :(得分:0)

就我而言,我必须连续读取日志,但是只能通过sftp访问它,正如@Kenster提到的那样,我通过调用stat()检查文件的大小是否已更改然后使用get( String src, String dst, SftpProgressMonitor monitor, int mode),它的作用是在我的目录中生成一个新文件,并在RESUME中使用mode参数,它仅获取最新内容。

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);
    }
}