问题
I am having problems with using sudo su in jsch, below is my post(exec.java):
package com.test;
import com.jcraft.jsch.*;
import java.awt.*;
import javax.swing.*;
import java.io.*;
public class Exec{
public static void main(String[] arg){
try{
JSch jsch=new JSch();
String host=null;
if(arg.length>0){
host=arg[0];
}
else{
host=JOptionPane.showInputDialog("Enter username@hostname",
"username"+
"@hostName");
}
String user=host.substring(0, host.indexOf('@'));
host=host.substring(host.indexOf('@')+1);
Session session=jsch.getSession(user, host, 22);
/*
String xhost="127.0.0.1";
int xport=0;
String display=JOptionPane.showInputDialog("Enter display name",
xhost+":"+xport);
xhost=display.substring(0, display.indexOf(':'));
xport=Integer.parseInt(display.substring(display.indexOf(':')+1));
session.setX11Host(xhost);
session.setX11Port(xport+6000);
*/
// username and password will be given via UserInfo interface.
UserInfo ui=new MyUserInfo();
session.setUserInfo(ui);
session.connect();
String command = "cd bin";
System.out.println(command);
Channel channel=session.openChannel("exec");
channel.setInputStream(null);
((ChannelExec)channel).setErrStream(System.err);
InputStream in=channel.getInputStream();
channel.connect();
((ChannelExec)channel).setCommand("sudo su - user -");
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){}
System.out.println("te");
}
channel.disconnect();
session.disconnect();
}
catch(Exception e){
System.out.println(e);
}
}
public static class MyUserInfo implements UserInfo, UIKeyboardInteractive{
public String getPassword(){ return passwd; }
public boolean promptYesNo(String str){
Object[] options={ "yes", "no" };
int foo=JOptionPane.showOptionDialog(null,
str,
"Warning",
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
null, options, options[0]);
return foo==0;
}
String passwd;
JTextField passwordField=(JTextField)new JPasswordField(20);
public String getPassphrase(){ return null; }
public boolean promptPassphrase(String message){ return true; }
public boolean promptPassword(String message){
Object[] ob={passwordField};
int result=
JOptionPane.showConfirmDialog(null, ob, message,
JOptionPane.OK_CANCEL_OPTION);
if(result==JOptionPane.OK_OPTION){
passwd=passwordField.getText();
return true;
}
else{
return false;
}
}
public void showMessage(String message){
JOptionPane.showMessageDialog(null, message);
}
final GridBagConstraints gbc =
new GridBagConstraints(0,0,1,1,1,1,
GridBagConstraints.NORTHWEST,
GridBagConstraints.NONE,
new Insets(0,0,0,0),0,0);
private Container panel;
public String[] promptKeyboardInteractive(String destination,
String name,
String instruction,
String[] prompt,
boolean[] echo){
panel = new JPanel();
panel.setLayout(new GridBagLayout());
gbc.weightx = 1.0;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridx = 0;
panel.add(new JLabel(instruction), gbc);
gbc.gridy++;
gbc.gridwidth = GridBagConstraints.RELATIVE;
JTextField[] texts=new JTextField[prompt.length];
for(int i=0; i<prompt.length; i++){
gbc.fill = GridBagConstraints.NONE;
gbc.gridx = 0;
gbc.weightx = 1;
panel.add(new JLabel(prompt[i]),gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weighty = 1;
if(echo[i]){
texts[i]=new JTextField(20);
}
else{
texts[i]=new JPasswordField(20);
}
panel.add(texts[i], gbc);
gbc.gridy++;
}
if(JOptionPane.showConfirmDialog(null, panel,
destination+": "+name,
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE)
==JOptionPane.OK_OPTION){
String[] response=new String[prompt.length];
for(int i=0; i<prompt.length; i++){
response[i]=texts[i].getText();
}
return response;
}
else{
return null; // cancel
}
}
}
}
Normal sudo su is good but I want to run multiple commands after sudo su, some of the points which might be informative.
- login to server and sudo with user
- sudo su - user - is without password
- perform some commands
regards,
icr
回答1:
second way is that you need to redirect providing second password.
Try to use sudo -S -p
.
In the past I had the same problem but solved. To save your time here is my code:
SudoExec class
public abstract class SudoExec {
private String mHost;
private static String passwd;
private SSHObserverItf mObserver = null;
protected boolean isForceStop = false;
protected boolean isAsIs = false;
protected Timer mTimer = null;
//default constructor
public SudoExec(String hostName,String userName,String password){
setHost(userName+"@"+hostName);
setPassword(password);
}
public void init(int timeToWait) {
mTimer = new Timer();
new Thread(){
public void run(){
execCMD();
}
}.start();
mTimer.doWait(timeToWait);
isForceStop = true;
}
private void execCMD (){
isForceStop = false;
try{
JSch jsch=new JSch();
String host=getHost();
String user=host.substring(0, host.indexOf('@'));
host=host.substring(host.indexOf('@')+1);
Session session=jsch.getSession(user, host, 22);
// username and password will be given via UserInfo interface.
UserInfo ui=new MyUserInfo();
session.setUserInfo(ui);
session.connect();
String command=getCmd();
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setPty(true);
if(isAsIs == true){
((ChannelExec)channel).setCommand(command);
}
else{
((ChannelExec)channel).setCommand("sudo -S -p '' " + command);
}
InputStream in=channel.getInputStream();
OutputStream out=channel.getOutputStream();
((ChannelExec)channel).setErrStream(System.err);
channel.connect();
out.write((passwd+"\n").getBytes());
out.flush();
byte[] tmp=new byte[1024];
while( isForceStop == false ){
while(in.available()>0 ){
int i=in.read(tmp, 0, 1024);
if(i<0)break;
mObserver.onResponse((new String(tmp, 0, i)));
}
if(channel.isClosed()){
mObserver.onResponse("exit-status: "+channel.getExitStatus());
mTimer.doNotify();
break;
}
try{Thread.sleep(100);}catch(Exception ee){}
}
mObserver.onResponse("close channel ... ");
channel.disconnect();
mObserver.onResponse("close session ... ");
session.disconnect();
}
catch(Exception e){
System.out.println(e);
mObserver.onErrorResponse(e.getMessage());
}
}
public static class MyUserInfo implements UserInfo, UIKeyboardInteractive{
public String getPassword(){
return passwd;
}
public boolean promptYesNo(String str){
return true;
}
public String getPassphrase(){ return null; }
public boolean promptPassphrase(String message){ return true; }
public boolean promptPassword(String message){
return true;
}
public void showMessage(String message){
}
@Override
public String[] promptKeyboardInteractive(String arg0, String arg1,
String arg2, String[] arg3, boolean[] arg4) {
return null;
}
}
public void setPassword(String password){
passwd=password;
}
public void setHost(String hostname){
mHost=hostname;
}
public String getPassword(){
return passwd;
}
public String getHost(){
return mHost;
}
protected abstract String getCmd();
public void setObserver(SSHObserverItf observer) {
mObserver = observer;
}
}
SSHObserverItf interface
public interface SSHObserverItf {
public void onResponse(String line);
public void onErrorResponse(String line);
}
SomeTask
public class SomeTask extends SudoExec implements SSHObserverItf{
private static String command = "";
private static String hostname = "";
private static String user = "";
private static String pass = "";
private static Boolean isError=false;
private static String wait = "300";
static public void main(String args[]) throws IOException, ParseException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
new SomeTask(hostname,user,pass);
if (isError == true){
System.out.println("Test failed");
}
else{
System.out.println("\nSucceeded to invoke command : " + command);
}
}
public CopyPeriodMergeToExternal(String hostName, String userName, String password) throws IOException, ParseException {
super(hostName, userName, password);
SSHObserverItf observer = this;
super.setObserver(observer);
super.init(Integer.parseInt(wait) * 1000);
}
@Override
protected String getCmd() {
isAsIs = true;
command="rm -f somescript.sh";
System.out.println("Run followed command : " + command);
return command;
}
@Override
public void onResponse(String line) {
System.out.println(line);
}
@Override
public void onErrorResponse(String line) {
System.out.println(line);
System.out.println("Error has occured");
isError = true;
}
}
The main part in SudoExec
class is:
public static class MyUserInfo implements UserInfo, UIKeyboardInteractive{
public String getPassword(){ // <---
return passwd;
}
public boolean promptYesNo(String str){
return true; // <---
}
Hope it will solve your problem
[EDIT]
After you got first response, you close the session.
Therefore next command starts as not super user.
My suggestion is to do not create session but run each command with sudo
preffix
回答2:
I also have to ssh on a remote server, then sudo with diffrent user and finally execute a command, what I did is:
package oracle.idaas.changelog.util;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
public class Test {
final static Logger logger = Logger.getLogger(Test.class);
public static void main(String[] args) {
try {
JSch jsch = new JSch();
String user = "opc";
String host = "101.252.109.112";
String password = "NotMyPassword"
int port = 22;
Session session = jsch.getSession(user, host, port);
System.out.println("session created.");
session.setConfig("StrictHostKeyChecking", "no");
session.setPassword(password);
session.connect();
ChannelExec channel=(ChannelExec) session.openChannel("exec");
BufferedReader in=new BufferedReader(new InputStreamReader(channel.getInputStream()));
channel.setCommand("sudo su - oracle -c \"pwd\";");
channel.connect();
String msg=null;
List<String> lines = new ArrayList<>();
while((msg=in.readLine())!=null){
System.out.println(msg);
lines.add(msg);
}
channel.disconnect();
session.disconnect();
} catch(Exception e){
logger.fatal("Remote BTU Process FAILED" + e);
}
}
}
If you see sudo su - oracle -c "your-command" will solve your problem.
来源:https://stackoverflow.com/questions/18534922/idea-regarding-sudo-su-user-in-jsch