我使用jcraft.jsch频道在ssh上运行了几个命令,我看到每当我使用一些复杂的命令(使用regexp或使用管道)时,命令的输出都有一个意外的'前缀&#39 ;从命令的片段或整个命令组合成碎片,分成多个空格分隔的小片,并与''<&#人物到处......
示例1:
#ls /opt/qb/data2/oscar/process-manager-helper/*/var/core-dump/{2089,2090,2091,2092,2093,2094,2095}.*
ger-helper/*/var/core-dump/{20
<2/oscar/process-manager-helper/*/var/core-dump/{208 9,2090,2091,2092,ls: cannot access /opt/qb/data2/oscar/process-manager-helper/*/var/core-dump/2090.*: No such file or directory
ls: cannot access /opt/qb/data2/oscar/process-manager-helper/*/var/core-dump/2092.*: No such file or directory
ls: cannot access /opt/qb/data2/oscar/process-manager-helper/*/var/core-dump/2094.*: No such file or directory
ls: cannot access /opt/data2/oscar/process-manager-helper/*/var/core-dump/2095.*: No such file or directory
/opt/qb/data2/oscar/process-manager-helper/0/var/core-dump/2089.20141126-195527.213-00000000-opt.dell.srvadmin.bin.idracadm7.idracadm7.core.gz
/opt/qb/data2/oscar/process-manager-helper/0/var/core-dump/2091.20141126-201557.530-00000000-opt.dell.srvadmin.bin.idracadm7.idracadm7.core.gz
/opt/qb/data2/oscar/process-manager-helper/0/var/core-dump/2093.20141126-202822.524-00000000-opt.dell.srvadmin.bin.idracadm7.idracadm7.core.gz
示例2:
#du -s --block-size=1 /opt/qb/data2/oscar/process-manager-helper/0/var/core-dump/2089.20141126-195527.213-00000000-opt.dell.srvadmin.bin.idracadm7.idracadm7.core.gz | awk { print $1; }
rvadmin.bin.idracad
<-195527.213-00000000-opt.dell.srvadmin.bin.idracadm 7.idracadwk
<ell.srvadmin.bin.idracadm7.idracadm7.core.gz | awk { print $1; }
86016
这是一个重现它的示例代码(至少在我的设置中):
public static void main(String[] args) throws Exception
{
JSch myConnection = new JSch();
myConnection.setKnownHosts("/dev/null");
Session mySession = myConnection.getSession("root", "my-host.my-lab.com", 2222);
mySession.setPassword("password123");
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
mySession.setConfig(config);
mySession.connect(15000);
Channel myChannel = mySession.openChannel("shell");
((ChannelShell) myChannel).setPtyType("exec");
InputStream fromServer = myChannel.getInputStream();
OutputStream toServer = myChannel.getOutputStream();
myChannel.connect();
String commandString = "du -s --block-size=1 /opt/base/dir/eventLog | awk '{ print $1; }'";
toServer.write((commandString + "\n").getBytes());
toServer.flush();
Thread.sleep(5000);
StringBuffer result = new StringBuffer();
while (true)
{
int avail = fromServer.available();
if (avail > 0)
{
while (avail > 0)
{
byte[] buf = new byte[avail];
int bytesRead = 0;
if ((bytesRead = fromServer.read(buf)) < 0)
{
throw new IOException("connection is probably closed (can't read " + avail + " from server) - return value is " + bytesRead);
}
for (int i = 0; i < bytesRead; i++)
{
if (buf[i] >= 127 || buf[i] < 9 || (buf[i] >= 14 && buf[i] <= 31) || buf[i] == 11 || buf[i] == 12 || buf[i] == 8)
{
continue;
}
result.append((char) buf[i]);
}
avail = fromServer.available();
}
if (result.toString().trim().endsWith("#"))
{
System.out.println(result);
break;
}
}
}
}
请告知
答案 0 :(得分:0)
Channel myChannel = mySession.openChannel("shell");
((ChannelShell) myChannel).setPtyType("exec");
[...]
String commandString = "du ...";
toServer.write((commandString + "\n").getBytes());
您正在打开一个shell频道,该频道通常用于互动会话。然后,您将命令字符串写入通道的输入流,该输入流模拟键入命令的字符。这种运行命令的方式可行,但远程系统的行为就好像这是一个交互式终端会话。特别是,远程shell可以打印命令提示,远程PTY可以回显你的程序所在的文本&#34;输入&#34;。我认为发生了什么 - 你正在运行的命令的输出与命令提示和字符回声混合在一起。
您应该考虑使用ChannelExec
来运行远程命令而不是ChannelShell
。使用ChannelExec,远程系统直接调用您的命令(而不是调用shell并让您将命令提供给shell的输入)。当命令退出时,通道关闭,你不应该受到字符回显或命令提示的困扰。
Jsch有ChannelExec example。您的代码看起来像这样:
ChannelExec chan = mySession.openChannel("exec");
chan.setCommand("du ... | awk ...");
// Set input and output streams
// Request a PTY if you think you need one
chan.connect();
chan.connect()
将打开频道并在远程系统上启动命令。可以从getInputStream()
返回的输入流中读取远程命令的标准输出,并且可以从getErrStream()
返回的流中读取命令的标准错误。或者你可以用这些流做其他事情;看到例子。