0

In order to realize a small supervisor of a server, I would like to know how to relaunch the ask(...) method in my code below. The goal is to query the server via SSH with the JSch library, and to return the result, in the JTextArea every x minutes.

The code works fine for me, I want just add the refresh option in the JTextArea, which receives the result via SSH every x minutes.

public class Test1 {
    public static void main(String args[]) throws Exception {
        final JFrame frame = new JFrame("Superviser SRV");
        frame.setLayout(new FlowLayout());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 500);

        JLabel label1 = new JLabel("Informations of SRV",JLabel.CENTER);            
        frame.getContentPane().add(label1);
        
        JTextArea ta11 = new JTextArea(1,50);
        JScrollPane sp11 = new JScrollPane(ta11);

        Border border = BorderFactory.createLineBorder(Color.BLACK);
        ta11.setBorder(BorderFactory.createCompoundBorder(border,
                BorderFactory.createEmptyBorder(10, 10, 10, 10)));

        frame.getContentPane().add(sp11);
        frame.setVisible(true);   
    
        int Port=22;
        String usernam ="usernam";
        String passwd ="passwd";
        String host ="192.168.10.1";      
        String msg = " Check Procs = ";     
        String com = " /usr/local/nagios/libexec/check_procs -w 200 -c 300 && exit \n";
        ask(ta11, Port, usernam, host, passwd, msg, com);
    }

    public static void ask(JTextArea ta, int port, String name, String ip, String password, String msg, String com)
            throws JSchException, IOException {
        JSch jsch = new JSch();
        Session session = jsch.getSession(name, ip, port);
        session.setPassword(password);
        session.setConfig("StrictHostKeyChecking", "no");
        System.out.println("Establishing Connection...");
        session.connect();
        System.out.println("Connection established.");

        ChannelExec channelExec = (ChannelExec)session.openChannel("exec");
        InputStream in = channelExec.getInputStream();
        channelExec.setCommand("sudo su - root");     
        channelExec.connect();
        OutputStream out = channelExec.getOutputStream();   
        out.write((com).getBytes());
        out.flush();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String line= reader.readLine();  
        ta.append(msg+" = "+line);

        out.close();
        reader.close();
        channelExec.disconnect();
        session.disconnect();
    } 
}
You
  • 19
  • 3
  • Do you have any **specific** question about this problem? Also, please add tags for the programming language you are using – Nico Haase Mar 10 '23 at 08:56
  • Thank you @NicoHaase for your your help, My question is how to refresh the textArea which receives the result via ssh every x minutes ? – You Mar 10 '23 at 09:05
  • Please add all clarification to your question by editing it. What is currently working with the code? What is missing? – Nico Haase Mar 10 '23 at 09:11
  • Thank you again @NicoHaase , the code works fine for me, I want just to add this refresh option in my JTextArea. – You Mar 10 '23 at 10:13

2 Answers2

1

You can use a timer to run the task every so many minutes.

int minutes = 2;
Timer timer = new Timer("query timer", true);
//it is daemon so it doesn't prevent the app from exiting.

timer.schedule( 
    new TimerTask(){
        public void run(){
            ask(ta11, Port, usernam, host, passwd, msg, com);
        }
    }, minutes * 60 * 1000 );

That will run the code every 2 minutes.

This performs the work on a separate thread, so when you update your text area you should post it to the EDT.

EventQueue.invokeLater( () -> {
    ta.append(msg+" = "+line);
});

As a side note, I would set this up via linux/server to run the privileged task on cron that updates a file in an less secure area. Then just use ssh to access the file without ever needing to sudo/su with a password stored as plain text in a java program.

matt
  • 10,892
  • 3
  • 22
  • 34
  • Thank you @matt, I agree with you on the security aspect. But still, to connect to an external DMZ, you have to give the login and the password in clear text. – You Mar 10 '23 at 10:34
  • *Not* a Swing timer, actually. What you need is a timer that runs your background non-gui task but updates the gui *on the event dispatch thread*. There are various ways of doing this, but `SwingWorker` is probably the best and illustrates the niceties of what threads should do which tasks and how they interact with the gui. – g00se Mar 10 '23 at 10:41
  • @g00se true. I didn't really consider how long this task takes. If it is a fast task, then a swing time should suffice, but you're correct. Doing the work off of the EDT is probably the best. – matt Mar 10 '23 at 10:47
  • I found this solution in this link: [link]( https://stackoverflow.com/a/31324460/14110479) ` int MINUTES = 10; Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { // code here CLASSB.funcb(); } }, 0, 1000 * 60 * MINUTES); ` But there is an ugly refresh after deleting the JTextArea. And I tested the method of @matt, I find it elegant thank you. Can you confirm me if it's ok for the program load or time complexity, please, especially if I run every 15 minutes? – You Mar 10 '23 at 10:56
  • @g00se can you give me an example of your method please? where can I find the documentation, and especially examples please :) – You Mar 10 '23 at 10:58
  • [SwingWorker](https://docs.oracle.com/en/java/javase/18/docs/api/java.desktop/javax/swing/SwingWorker.html) is one of the best-documented classes in the API docs and you will find further examples if needed – g00se Mar 10 '23 at 11:57
  • @You Why would you delete the TextArea? The way I suggest is fine, provided your method is fast because the GUI will block while your method is running. I will update my answer to use the `java.util.Timer` that way it doesn't block the edt. – matt Mar 10 '23 at 12:12
  • @matt sorry, I meant with delete, but empty, to add the new result searched via ssh. – You Mar 10 '23 at 13:03
  • @matt's new code should be OK actually. For this simple use case, `SwingWorker` is probably *de trop* :) – g00se Mar 10 '23 at 13:10
  • I trust you ;) @g00se I am trying your approach, thank you again,I'll tell you what asap – You Mar 10 '23 at 13:22
-2

You may use a Thread and in the overridden method public void run() you can create a try-catch block which would call the method ask(...).

Then you can do Thread.currentThread().wait(int millis , int nanoseconds) to pause the thread for 1 minute, then you may fetch new data in 1 minute and then you can rerun the ask method.

NOTE: This can be implemented in a forever loop but taking into consideration,the wastage that may happen , you can run this entire thread in a for-loop. In this way you can run this ask(...) method for x hours(say) and refresh it each minute.

Hope this helps :)

  • Swing already has tools for this. That isn't how wait works or synchronized really. – matt Mar 10 '23 at 10:25
  • synchronized is for the Thread, but I proposed calling the entire ask method in a Thread. – Kiyotaka Ayanakoji Mar 10 '23 at 10:27
  • What you need is a thread that runs your background non-gui task but updates the gui *on the event dispatch thread*. There are various ways of doing this, but `SwingWorker` is probably the best and illustrates the niceties of what threads should do which tasks and how they interact with the gui. – g00se Mar 10 '23 at 10:43
  • Understood but i was hoping if we could integrate threads with GUI but since `SwingTimer` exists , it is pointless to disintegrate it to segregate code into gui and non-gui – Kiyotaka Ayanakoji Mar 10 '23 at 10:49
  • Yes, so if you want to use that code, look, for instance, at the `EventQueue` methods that could be used with it – g00se Mar 10 '23 at 10:55