我正在监视一组远程服务器上的错误日志。为此,我正在监视在一段时间内修改的日志。

我正在使用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程序,并且希望在每个远程主机上运行此脚本。

下面是我目前使用ChannelExec的代码
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上并在远程主机上执行。

但是,是否有一些简单的解决方案,即使不编写脚本,而仅在远程服务器上执行命令或执行脚本,也可以通过该解决方案获得相同的结果。

感谢帮助

最佳答案

您不能在服务器上执行本地脚本。

您有两个选择(显然您知道):

  • 上载脚本并执行(然后根据需要删除)。
  • 执行脚本的内容。如您所知,只需将所有行与;串联即可。

    虽然要注意forif;do之后不应有then

    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,“echo`pwd`”和“echo`hostname`”没有任何意义。直接使用“pwd”和“主机名”。

    09-11 16:27
    查看更多