我正在监视一组远程服务器上的错误日志。为此,我正在监视在一段时间内修改的日志。
我正在使用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上并在远程主机上执行。
但是,是否有一些简单的解决方案,即使不编写脚本,而仅在远程服务器上执行命令或执行脚本,也可以通过该解决方案获得相同的结果。
感谢帮助
最佳答案
您不能在服务器上执行本地脚本。
您有两个选择(显然您知道):
;
串联即可。虽然要注意
for
和if
。 ;
和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”和“主机名”。