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