2017-04-12 137 views
1

我正在監視一組遠程服務器上的錯誤的日誌。爲此,我正在監視在一段時間內被修改的日誌。通過Java JSch庫在遠程計算機上執行本地腳本

我使用Jsch Java library來製作SSH connection並執行命令。正如我所搜索的,多個命令可以通過將不同命令分開的遠程機器通過;

爲此我有一個文本文件,其中包含我在其上建立連接的遠程主機上的列表。我意識到,我可以通過下面的命令

find . -mmin -60 -type f -exec ls {} + 

不,我可以遍歷文件和grep for the Error修改的所有文件的列表。爲此,我寫了下面的腳本

logTestScript.sh

#!/bin/bash 

cd /log 
searchString='<Error ErrorCode="java.sql.SQLException"' 
files=`find . -mmin -60 -type f -exec ls {} +` 
pwd 
hostname 
echo ${files} 
for file in ${files[@]} 
do 
     if grep -Fq "$searchString" $file 
     then 
       echo "String found in $file" 
     fi 
done 

現在這個腳本會在當前包從我運行一個Java程序,我想運行在每個這個腳本的遠程主機。

下面是我當前的代碼利用的

private void getSSHConnection() throws IOException, JSchException { 

     username = props.getProperty("host_username"); 
     password = props.getProperty("host_password"); 
     log_traceback_interval = props.getProperty("fetch_logs_interval_minutes"); 
     errorString = props.getProperty("error_message_log"); 

     System.out.println(username + " " + password + " " + errorString); 

     // Get the hostnames resource file 
     String hostnameResourcePath = envObj.getAgentHostnamesConfig(TargetEnvironment, ManagementSystem); 
     InputStream hostInpStream = this.getClass().getResourceAsStream(hostnameResourcePath); 
     BufferedReader hostnameReader = new BufferedReader(new InputStreamReader(hostInpStream)); 

     String host = null; 

     while((host = hostnameReader.readLine()) != null) { 

      System.out.println(host); 

      // get a JSch connection object 
      JSch jschObj = new JSch(); 
      Session session = jschObj.getSession(username, host); 

      // Disable StrictHost key checking 
      Properties config = new Properties(); 
      config.put("StrictHostKeyChecking", "no"); 
      session.setConfig(config); 

      session.setPassword(password); 
      session.connect(); 

      //Execute channel instance 
      ChannelExec channelExec = (ChannelExec)session.openChannel("exec"); 
      InputStream in = channelExec.getInputStream(); 

      //Bash script command with arguments 
      StringBuilder sb = new StringBuilder(); 
      String command = sb.append("cd /log").append(";") 
           .append("echo `find . -mmin -60 -type f -exec ls {} +`").append(";") 
           .toString(); 

      System.out.println(command); 

      //Run the script on host 
      channelExec.setCommand(command); //I want to run the script here instead of each command as it uses for loop 

      channelExec.setInputStream(null); 

      channelExec.setErrStream(System.err); 

      InputStream monitorLogs = channelExec.getInputStream(); 

      channelExec.connect(); 

      //Read the logs 
      BufferedReader logReader = new BufferedReader(new InputStreamReader(monitorLogs)); 
      String logLine; 

      while((logLine = logReader.readLine()) != null) { 

       System.out.println(logLine); 
      } 

      //Close the connections 
      channelExec.disconnect(); 
      session.disconnect(); 
     } 




    } 

一個解決方案,我可以到遠程主機想如果到SCP的腳本,然後執行它。

但是有沒有一些簡單的解決方案,即使沒有編寫腳本,只執行命令或在遠程服務器上執行腳本,我也可以獲得相同的結果。

感謝您的幫助

+0

https://www.ibm.com/developerworks/community/blogs/738b7897-cd38-4f24-9f05-48dd69116837/entry/programmatically_connecting_to_remote_systems2?lang=en – RajatJ

回答

1

您無法在服務器上執行本地腳本。

你有兩個選擇(你是顯然知道):

  • 上傳腳本並執行它(和刪除後,如果需要的話)。
  • 執行腳本的內容。如您所知,只需將所有行與;連接即可。

    雖然要小心forif。在dothen之後應該沒有;

    cd /log ; searchString='<Error ErrorCode="java.sql.SQLException"' ; files=`find . -mmin -60 -type f -exec ls {} +` ; echo `pwd` ; echo `hostname` ; echo ${files} ; for file in ${files[@]} ; do if grep -Fq "$searchString" $file ; then echo "String found in $file" ; fi ; done 
    
  • 類似於之前的方法,您可以執行bash -s和寫劇本的內容(命令),以它的輸入。

    ChannelExec channelExec = (ChannelExec)session.openChannel("exec"); 
    channelExec.setCommand("bash -s"); 
    channelExec.connect(); 
    OutputStream out = channel.getOutputStream(); 
    FileInputStream fis = new FileInputStream("testScript.sh"); 
    byte[] buf = new byte[1024]; 
    while (true) 
    { 
        int len = fis.read(buf, 0, buf.length); 
        if (len <= 0) break; 
        out.write(buf, 0, len); 
    } 
    

    以上基本上是從看似無關的SCP upload example複製 - 這個例子實際上提要本地的文件到遠程scp過程 - 因此,它實際上是非常相關的。


的Ntb, 「回聲`pwd`」 和 「回聲`hostname`」 是沒有意義的。直接使用「pwd」和「主機名」。

+0

循環和if-else是執行時的主要問題腳本的內容。這就是說我需要將某些參數傳遞給腳本,我想這可以在創建字符串命令時完成。 我只是想知道JSch是否提供了執行下面這個命令的選項,就像我們爲命令'ssh username @ hostname'bash -s'

+0

查看我更新的答案。 –

+0

你能否詳細說明一下。我會盡力接近。 –

-1

爲了在遠程服務器上執行腳本script.sh,您可以使用下面的代碼 -

#!/usr/bin/expect 
export PASSD="[email protected]" 
expect -c 'spawn sftp [email protected]; 
expect "*Password: "; 
send "$env(PASSD)\r"; 
expect "ssh>"; 
send "cd /home/user \r"; 
expect "ssh>"; 
send "sh -x script.sh \r"; 
expect "ssh>"; 
send "exit \r"' 

你可以把上面的代碼中的腳本,然後你如果循環的成功條件之後添加。

+0

問題是關於在** remote **服務器上執行** local **腳本+這是關於JSch庫。 –

+0

@MartinPrikryl - 是的,你是對的,但這是一個替代解決方案。 –

相關問題