title: Use JSch sudo example and Channel.setPty for running sudo command on remote host
body: <p>I have used JSch Sudo example under following link:</p>
  
  <p><a href="http://www.jcraft.com/jsch/examples/Sudo.java.html" rel="nofollow noreferrer">http://www.jcraft.com/jsch/examples/Sudo.java.html</a></p>
  
  <p>And changed it a bit and get rid of all the dialogs as I have to use it for EC2 instances using PuTTY.</p>
  
  <p>Now my code looks like this:</p>
  
  <pre><code>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&gt;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()&gt;0){
            int i=in.read(tmp, 0, 1024);
            if(i&lt;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);
      }
    }
  }
  </code></pre>
  
  <p>But I am getting the error </p>
  
  <blockquote>
    <p>sorry you must have a tty to run sudo</p>
  </blockquote>
  
  <p>I also tried to use <code>((ChannelExec) channel).setPty(true)</code> 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.</p>
  
  <pre class="lang-none prettyprint-override"><code>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)
  </code></pre>
  
  <p>And then also I could not ssh the remote host from command line as well.        </p>
  
  <p>Can someone please guide me that what I need to do to run <code>sudo</code> command on remote host.</p>