java 使用 JSch sudo 示例和 Channel.setPty 在远程主机上运行 sudo 命令
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11968805/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Use JSch sudo example and Channel.setPty for running sudo command on remote host
提问by waqas
I have used JSch Sudo example under following link:
我在以下链接下使用了 JSch Sudo 示例:
http://www.jcraft.com/jsch/examples/Sudo.java.html
http://www.jcraft.com/jsch/examples/Sudo.java.html
And changed it a bit and get rid of all the dialogs as I have to use it for EC2 instances using PuTTY.
并对其进行了一些更改并摆脱了所有对话框,因为我必须将它用于使用 PuTTY 的 EC2 实例。
Now my code looks like this:
现在我的代码如下所示:
import com.jcraft.jsch.*;
import java.awt.*;
import javax.swing.*;
import java.io.*;
public class sudo{
public static void main(String[] arg){
try{
JSch jsch=new JSch();
String host=null;
if(arg.length>0){
host=arg[0];
}
String privateKey = "my private key.pem";
jsch.addIdentity(privateKey, "");
Session session=jsch.getSession("ec2-user", "xx.xx.xx.xx", 22);
session.setPassword("");
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
String command="sudo mkdir /data";
String sudo_pass="";
Channel channel=session.openChannel("exec");
// man sudo
// -S The -S (stdin) option causes sudo to read the password from the
// standard input instead of the terminal device.
// -p The -p (prompt) option allows you to override the default
// password prompt and use a custom one.
((ChannelExec)channel).setCommand("sudo -S -p '' "+command);
InputStream in=channel.getInputStream();
OutputStream out=channel.getOutputStream();
((ChannelExec)channel).setErrStream(System.err);
channel.connect();
out.write((sudo_pass+"\n").getBytes());
out.flush();
byte[] tmp=new byte[1024];
while(true){
while(in.available()>0){
int i=in.read(tmp, 0, 1024);
if(i<0)break;
System.out.print(new String(tmp, 0, i));
}
if(channel.isClosed()){
System.out.println("exit-status: "+channel.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
channel.disconnect();
session.disconnect();
}
catch(Exception e){
System.out.println(e);
}
}
}
But I am getting the error
但我收到错误
sorry you must have a tty to run sudo
抱歉,您必须有一个 tty 才能运行 sudo
I also tried to use ((ChannelExec) channel).setPty(true)
but I can run the program once but next time, for same EC2 instance, I get the following error but for new instance it works fine for first time again.
我也尝试使用,((ChannelExec) channel).setPty(true)
但我可以运行该程序一次,但下一次,对于同一个 EC2 实例,我收到以下错误,但对于新实例,它第一次再次正常工作。
com.jcraft.jsch.JSchException: Session.connect: java.io.IOException: End of IO Stream Read
sudo mkdir /data
Exception in thread "main" com.jcraft.jsch.JSchException: session is down
at com.jcraft.jsch.Session.openChannel(Session.java:791)
And then also I could not ssh the remote host from command line as well.
然后我也无法从命令行 ssh 远程主机。
Can someone please guide me that what I need to do to run sudo
command on remote host.
有人可以指导我sudo
在远程主机上运行命令需要做什么。
回答by BlueRebel
I have similar code in a project I am working on, and was getting the same error. I resolved this using the setPty(true)
as you did.
我正在处理的项目中有类似的代码,但遇到了同样的错误。我setPty(true)
像你一样使用 解决了这个问题。
I think you're getting this error because you don't close out the streams in your code. If you are using Java 1.7, you can use a resource block as follows:
我认为您收到此错误是因为您没有关闭代码中的流。如果您使用的是 Java 1.7,则可以按如下方式使用资源块:
try( InputStream in=channel.getInputStream() ) {
try( OutputStream out = channel.getOutputStream() ) {
...
}
}
or the try...finally block pattern from past versions.
或者 try...finally 阻止过去版本的模式。
回答by Jeevan Pingali
After setting
设置后
((ChannelExec) channel).setPty(true)
the reported problem have in my code got solved.
我的代码中报告的问题得到了解决。
回答by nav3916872
By default, SUDO is configured to require a TTY. That is, SUDO is expected to be run from a login shell.
默认情况下,SUDO 配置为需要 TTY。也就是说,SUDO 应该从登录 shell 运行。
That's probably because your /etc/sudoers file (or any file it includes) has:
这可能是因为您的 /etc/sudoers 文件(或它包含的任何文件)具有:
Defaults requiretty
But the option -S in sudo will make it read from Standard input.
但是 sudo 中的选项 -S 将使其从标准输入中读取。
-S The -S (stdin) option causes sudo to read the password from
the standard input instead of the terminal device. The pass-
word must be followed by a newline character.
Jsch exploits the same and tries to send the password. If you want to Jsch to work without prompting the password , you need to disable the requiretty from the sudoers file...using visudo command as follows
Jsch 利用相同的方法并尝试发送密码。如果你想让 Jsch 在不提示密码的情况下工作,你需要从 sudoers 文件中禁用 requiretty...使用 visudo 命令如下
Defaults !requiretty
or
或者
#Defaults requiretty