我正在监视一组远程服务器上的错误的日志。为此,我正在监视在一段时间内被修改的日志。通过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的脚本,然后执行它。
但是有没有一些简单的解决方案,即使没有编写脚本,只执行命令或在远程服务器上执行脚本,我也可以获得相同的结果。
感谢您的帮助
===========解决方案如下:
您无法在服务器上执行本地脚本。
你有两个选择(你是显然知道):
- 上传脚本并执行它(和删除后,如果需要的话)。
-
执行脚本的内容。如您所知,只需将所有行与
;
连接即可。虽然要小心
for
和if
。在do
和then
之后应该没有;
。<code class="prettyprint-override">cd /log ; searchString='<Error ErrorCode="<a href="http://www.fixbbs.com/p/tag/java" title="查看更多关于java的文章" target="_blank">java</a>.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 </code>
-
类似于之前的方法,您可以执行
bash -s
和写剧本的内容(命令),以它的输入。<code class="prettyprint-override">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); } </code>
以上基本上是从看似无关的SCP upload example复制 – 这个例子实际上提要本地的文件到远程
scp
过程 – 因此,它实际上是非常相关的。
的Ntb, “回声`pwd`” 和 “回声`hostname`” 是没有意义的。直接使用“pwd”和“主机名”。