0

I am trying to run a series of unix commands through Java. Basically, whatever I do over Putty, I want to do it over java program.

I have written 2 classes.

  1. Connects to the server and executes the Unix Command.
  2. Sends the unix commands to Class1 in a list.

I am able to connect to server and execute, if there is only 1 value present at the list of Class2. However, when there are multiple values present in the list, the code executes only the latest command (value from the list) and skips all the other values.

I want to execute each value (unix command) present on the list of Class2. Please help. I am using JCraft's JSch classes.

Class1

package package1;

import java.io.InputStream;
import java.util.List;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;


public class ConnExec 
{
    static InputStream in;
    static byte[] tmp;
    static int flag = 0;
    public void connExec(List<String> commandLst)
    {
        String host="serverName.host.dev";
        String user="UserName";
        String password="PWD";

        try
        {
            java.util.Properties config = new java.util.Properties(); 
            config.put("StrictHostKeyChecking", "no");
            JSch jsch = new JSch();
            Session session=jsch.getSession(user, host, 22);
            session.setPassword(password);
            session.setConfig(config);
            session.connect();
            System.out.println("Connected to the server.....\n");

            Channel channel=session.openChannel("exec");
            channel.setInputStream(null);

            for (int x = 0; x < commandLst.size();x++)
            {
                ((ChannelExec)channel).setCommand(commandLst.get(x));

                in=channel.getInputStream();
                channel.connect();
                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));
                        System.out.println("\nExecuted.....");
                    }

                    if(channel.isClosed())
                    {
                        break;
                    }
               }
            }

            channel.disconnect();
            session.disconnect();
            System.out.println("Terminated.....\n");
            flag = 1;
        }
        catch(Exception e)
        {
            e.printStackTrace();
            flag = 1;
        }

    }

}

Class2

package package1;

import java.util.ArrayList;
import java.util.List;

public class ReadCommands 
{


    public static void main(String a[])
    {
        List<String> lst = new ArrayList<String>();

        String command1="ls /local/dev/source/folder";
        String command2="ls /local/dev/source/folder/inbound";

        lst.add(command1);
        lst.add(command2);

        ConnExec ce = new ConnExec();
        ce.connExec(lst);
    }

}
Shreyas SG
  • 368
  • 3
  • 6
  • 21
  • As the [answer by @Paŭlo Ebermann](http://stackoverflow.com/a/5843935/850848) says, you have to execute each command in its own "exec" channel. So just move the `Channel channel=session.openChannel("exec"); channel.setInputStream(null);` and the `channel.disconnect();` to the `for` loop. – Martin Prikryl Oct 20 '16 at 12:31
  • @MartinPrikryl Tried - Didn't work. – Shreyas SG Oct 20 '16 at 14:54
  • I am getting the same results as my above code. Nevertheless, I am now creating a new instance variable for each unix command and am getting the desired result. Thanks for your help though :) – Shreyas SG Oct 20 '16 at 15:20

2 Answers2

0

If you are planning to run the commands one by one you can use the "&&" over multiple commands with openChannel("shell") instead of exec .Then each command will work after the previous one completes.

Channel channel=session.openChannel("shell");
OutputStream ops = channel.getOutputStream();
PrintStream ps = new PrintStream(ops, true);

channel.connect();
ps.println("cd /abc/def" + "&&" + "ls -lrt");
GhostCat
  • 137,827
  • 25
  • 176
  • 248
Sshastry
  • 57
  • 1
  • 8
  • Actually the `&&` is useful for the **exec** channel. For **shell** channel, you can send the commands simply using multiple `println` calls. – Martin Prikryl Jul 21 '17 at 10:13
-1

At Class2, I am now creating a new instance variable for each unix command. It works well.

for(String cmd:lst)
{
    new ConnExec().connExec(cmd);
}
Shreyas SG
  • 368
  • 3
  • 6
  • 21