我使用的是Jsch,我的任务是登录到服务器,并运行以下命令。
sudo "command"
使用下面的代码,我能够成功地连接并执行命令(没有出现错误)。"sudo: sorry, you must have a tty")
public String runSudo(RemoteHost remoteHost, String[] commands, OperationData operationData, String known_hosts, String id_rsa) {
String result = "";
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
JSch jsch = new JSch();
// Create a JSch session to connect to the server
Session session = null;
try {
session = jsch.getSession(remoteHost.getUsername(), remoteHost.getHost(), remoteHost.getPort());
if (remoteHost.getPassword() != null)
session.setPassword(remoteHost.getPassword());
else{
session.setConfig("PreferredAuthentications", "publickey");
jsch.setKnownHosts(known_hosts);
jsch.addIdentity(id_rsa);
}
session.setConfig(config);
// Establish the connection
session.connect();
logger.debug("Connected...");
for (int k = 0; k < commands.length; k++) {
ChannelExec channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(commands[k]);
OutputStream outputStreamStdErr = new ByteArrayOutputStream();
channel.setErrStream(outputStreamStdErr, true);
channel.setPty(true);
InputStream in = channel.getInputStream();
channel.connect();
byte[] tmp = new byte[1024];
while (true) {
while (in.available() > 0) {
int i = in.read(tmp, 0, 1024);
if (i < 0) {
break;
}
result = result + new String(tmp, 0, i);
}
if (channel.isClosed()) {
this.exitStatus += channel.getExitStatus();
break;
}
Thread.sleep(1000);
}
String errors = readInputStream(outputstream2inputstream(outputStreamStdErr));
if (!errors.equals("")) {
operationData.setErrorMessage(errors);
}
channel.getErrStream().close();
channel.disconnect();
}
session.disconnect();
} catch (JSchException e) {
operationData.setErrorMessage(e.getMessage());
logger.error(e.getMessage());
return result;
} catch (IOException e) {
operationData.setErrorMessage(e.getMessage());
logger.error(e.getMessage());
return result;
} catch (InterruptedException e) {
operationData.setErrorMessage(e.getMessage());
logger.error(e.getMessage());
return result;
} finally {
return result;
}
}
但使用属性 channel.setPty(true);
我无法读取错误流,因为它是 null
和错误显示在命令的输出中.相反,如果我不使用属性 channel.setPty(true);
我可以读取错误流,但该方法返回错误 "sudo: sorry, you must have a tty" 我想避免的。
谁能帮助我使用错误流和属性--------。channel.setPty(true);
在相同的代码中?
这是标准的SSH行为(至少在Linux上是这样),当终端仿真被启用时,所有的输出都会进入SSH连接中的一个流。这与你的JavaJSch代码无关。
不要使用PTY来实现命令自动化。PTY的目的是为了实现一个交互式终端,供人使用。
你可以配置 sudo
不要求PTY。
也有其他选择。见允许在Linux上使用SSH以root身份自动执行命令。.
另一个变通方法是将stdout和stderr重定向到服务器上的临时文件。然后分别打印这些文件到终端输出。
憨厚的实现方式可以是这样的。
sudo ... > /tmp/my_stdout 2> /tmp/my_stderr ; echo "stdout:" ; cat /tmp/my_stdout ; echo "stderr:" ; cat /tmp/my_stderr