0

リモートの Linux マシンでログ ファイルを追跡し、それをブラウザーに継続的に出力する必要があります。私はJSchを使用してそれを尾行することができました。現在、出力をシステム出力として出力しています。私は現在、これにサーブレットを使用しています (ただし、クライアントは jsp のみを使用するように求めています)。問題は、ブラウザーで末尾のストリームを印刷しようとするとすぐに、ブラウザーが何かを継続的にロードしているかのようにフリーズ状態になることです (これはそうです!!)。sysout ログは、ブラウザーがフリーズしている間、テール ストリームをコンソールに問題なく出力します。ここに私のサーブレットがあります

package sshUploader;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Run several ssh commands in a single JSch session
 */
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.io.*;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Hashtable;

/**
 * Servlet implementation class TailLogServlet
 */
@WebServlet(description = "This servlet tails the remote logs", urlPatterns = { "/TailLogServlet" })
public class TailLogServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public TailLogServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        try{
            System.out.println("**************************ADI NEW*****************");
            JSch jsch = new JSch();
              String user = <user>;            //CHANGE ME
              String host = <host>; //CHANGE ME
              String passwd = <pwd>;      //CHANGE ME
              int port = 22;    
              Session session = jsch.getSession(user, host, port);
              session.setPassword(passwd);

              Hashtable<String, String> hashtable  = new Hashtable<String, String>();
              hashtable.put("StrictHostKeyChecking", "no");
              session.setConfig(hashtable);

              session.connect();

              Channel channel = session.openChannel("shell");
              OutputStream ops = channel.getOutputStream();
              PrintStream ps = new PrintStream(ops, true);

              channel.connect();
              InputStream input = channel.getInputStream();

              ps.println("tail -f /home/LogFile.log");
              ps.close();

             // response.setIntHeader("Refresh", 1);
              response.setContentType("text/html");

              /*Calendar calendar = new GregorianCalendar();
              String am_pm;
              int hour = calendar.get(Calendar.HOUR);
              int minute = calendar.get(Calendar.MINUTE);
              int second = calendar.get(Calendar.SECOND);
              if(calendar.get(Calendar.AM_PM) == 0)
                am_pm = "AM";
              else
                am_pm = "PM";

              String CT = hour+":"+ minute +":"+ second +" "+ am_pm;*/

              PrintWriter out = new PrintWriter (response.getOutputStream());//.getWriter();
              out.println("<html><head><title>GuestBookServlet</title></head>");
              out.println("<body>********************");

              int SIZE = 1024;
              byte[] tmp = new byte[SIZE];
              while (true)
              {
                 while (input.available() > 0)
                 {
                    int i = input.read(tmp, 0, SIZE);
                    if(i < 0)
                       break;
                     System.out.print(new String(tmp, 0, i)); // use document.write(new String(tmp, 0, i));
                   // System.out.println("******Adi i :"+i);
                    //out.println("Out by Adi i :"+i);
                   out.println(new String(tmp, 0, i));
                 }
                 if(!channel.isConnected())
                 {
                    System.out.println("exit-status: " + channel.getExitStatus());
                    break;
                 }
                 try
                 {
                    Thread.sleep(300);
                 }
                 catch (Exception ee)
                 {
                 }
             }
              out.println("</body></html>");
              out.close();


              channel.disconnect();
              session.disconnect();
        }catch(Exception e){
            e.printStackTrace();

        }
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
    }

}

これは、ストリームの印刷でのみスタックします。継続的に更新して現在の時刻を印刷しようとすると、印刷できます。ブラウザにバッチリ反映されます。私に抜け道はありますか?

編集: わかりました、私はに絞り込みました

根本的な原因

. それは

無限ループ

こちらで募集しています。このループは、リモートからの入力ストリームに何かがあるかどうかを継続的にチェックします。そのため、sysout は正しく出力されますが、out.write はそうではありません。無限 while ループを削除すると、リモート入力ストリームで唯一のものであるため、1 行が出力されます。無限 while ループ内でブラウザーで出力を取得する方法についてのアイデアはありますか?

4

1 に答える 1

2

わかりました、私はしばらく時間をかけてようやくそれをやりました。クライアントの配信で忙しかったため、ここでの更新が遅くなりました。手順は次のとおりです。
リモートログを追跡するコードを持つ TailLogServlet.java という名前のサーブレットを用意しました。2 秒ごとに ajax を介してこのサーブレットを呼び出し、ブラウザーに応答を出力する showTailLogs.jsp という jsp を準備しました。この呼び出しは、jspの本体 onLoad関数で行われます。
サーブレットと JSP は次のとおりです:

showTailLogs.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
        <head>
                <link rel="stylesheet" type="text/css" href="css/myStyle.css">
                <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script type="text/javascript" src="jquery.js"></script>
                <title>Show Tail Logs</title>
                <script>
                        var binDone = false;
                        var lastUpdate = "Starting logs";
                        function tail2() {
                                if (!binDone) {
                                        $.post("/<<Context>>/TailLogServlet",
                                          {
                                                logUID:"<%= request.getParameter("logUID")%>",
                                                logPwd:"<%= request.getParameter("logPwd")%>",
                                                host:"<%= request.getParameter("host")%>",
                                                logFileName:"<%= request.getParameter("logFileName")%>"
                                          },
                                          function(data,status){
                                                $("#thePlace").append(data);
                                                if (data.indexOf(lastUpdate)>-1) {
                                                        binDone = true;
                                                }
                                          });
                                }
                        }
                </script>
        </head>
    <body onLoad='tail2(); setInterval("tail2()", 2000)'>
        <div id="wrapper" class="radius">
                <div id="imageContainer">
                        <img alt="my Image" class="myLogo" src="myLogo.jpg" />
                        <h1>Show Tail Logs</h1>
                </div>
                <div id="navContainer" style="color:white">
                        Logs Update automatically. Please don't press refresh button...
                </div>
                        <div>
                                <div id="thePlace"></div>
                        </div>
                </body>
        </div>
</html> 



TailLogServlet.java

package sshUploader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Run several ssh commands in a single JSch session
 */
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.io.*;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Hashtable;

/**
 * Servlet implementation class TailLogServlet
 */
@WebServlet(description = "This servlet tails the remote logs", urlPatterns = { "/TailLogServlet" })
public class TailLogServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public TailLogServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try  
        {  
            //System.out.println("*************GETTT TailLogServlet Hit. logFileName :"+request.getParameter("logFileName"));

          PrintWriter pw=response.getWriter();  
          response.setContentType("text/html"); 
          response.setHeader("Cache-Control", "no-cache");

          JSch jsch = new JSch();
          String user = request.getParameter("logUID");            //CHANGE ME
          String host = request.getParameter("host");//CHANGE ME
          String passwd = request.getParameter("logPwd");      //CHANGE ME
          int port = 22;    
          Session session = jsch.getSession(user, host, port);
          session.setPassword(passwd);

          Hashtable<String, String> hashtable  = new Hashtable<String, String>();
          hashtable.put("StrictHostKeyChecking", "no");
          session.setConfig(hashtable);

          session.connect();

          Channel channel = session.openChannel("shell");
          OutputStream ops = channel.getOutputStream();
          PrintStream ps = new PrintStream(ops, true);

          channel.connect();
          InputStream input = channel.getInputStream();

           ps.println("tail -f "+request.getParameter("logFileName"));
          ps.close();

          int SIZE = 1024;
          byte[] tmp = new byte[SIZE];
          long startTime = System.currentTimeMillis();
          while ((System.currentTimeMillis()-startTime)< 3*1000){
             while (input.available() > 0)
             {
                int i = input.read(tmp, 0, SIZE);
                if(i < 0)
                   break;
                 System.out.println(new String(tmp, 0, i)); 
                 pw.println(new String(tmp, 0, i));
             }          
             pw.flush();             
         }


        }catch(Exception e)  
        {  
             e.printStackTrace();  
        } 
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        //System.out.println("*************POSTTTTT TailLogServlet Hit. logFileName :"+request.getParameter("logFileName"));
        doGet(request, response);
    }
}

まだクリーニングを行っていないため、コードに不要なインポートが含まれている可能性があります。

于 2013-11-06T15:54:36.087 に答える