seventy70 seventy70 - 3 months ago 33
Linux Question

Need to automate SSH commands to router

I need to find a way to automate ssh commands to my router. My goal is to make the router restart whenever I run the script from my Java program. I'm having some issues though.

First of all, this is the sequence of output I get from my router's ssh:
First I do:

ssh root@192.168.100.1


which returns:

root@192.168.100.1's password:


I enter the password, "admin". It then goes to this prompt:

Welcome Visiting Huawei Home Gateway
Copyright by Huawei Technologies Co., Ltd.

Password is default value, please modify it!
WAP>


Now, I input "reset" and it restarts the router.

I've tried Tcl with Expect and while I can get it working on Windows, it doesn't work on Linux. Here's my code for the Tcl script:

#!/bin/sh
# \ exec tclsh "$0" ${1+"$@"}
package require Expect
spawn ssh root@192.168.100.1
send "admin\r"
send "reset\r"
after 3000
exit


Whenever I try to execute it, Tcl8.6 runs through it and terminates without actually doing anything. However, if I manually input all of these commands while running Tcl8.6, it works just fine

I've also tried the JSch Java library. With that, I can get the Java program to connect and output the shell of the router, but any command that I try to send does nothing. Here's the code from that:

...
JSch jsch = new JSch();

Session session = jsch.getSession("root", "192.168.100.1", 22);

Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);

// Skip prompting for the password info and go direct...
session.setPassword("admin");
session.connect();

String command = "reset\r";

Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);

((ChannelExec) channel).setErrStream(System.err);

InputStream in = channel.getInputStream();

System.out.println("Connect to session...");
channel.connect();


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();
System.out.println("disconnected");


This is the output that I get:

Connect to session...

Welcome Visiting Huawei Home Gateway
Copyright by Huawei Technologies Co., Ltd.

Password is default value, please modify it!
WAP>


It just stays here until I exit. The router doesn't restart. I've also tried:

String command = "reset";


but it does the same thing. Anybody know of any other ways I could do this?

Answer

Try interacting with the device using shell instead of exec.

Here is a quick-and-dirty code I used to do so, you can adjust it to suit your needs:

private static final String PROMPT = ">";

public static void main(String[] args) throws Exception {

    Session session = null;
    ChannelShell channel = null;

    try {

        JSch jsch = new JSch();
        session = jsch.getSession("root", "192.168.100.1", 22);
        session.setConfig("StrictHostKeyChecking", "no");
        session.setPassword("admin");
        session.connect();

        channel = (ChannelShell) session.openChannel("shell");

        PipedOutputStream reply = new PipedOutputStream();
        PipedInputStream input = new PipedInputStream(reply);
        ByteArrayOutputStream output = new ByteArrayOutputStream();

        channel.setInputStream(input, true);
        channel.setOutputStream(output, true);

        channel.connect();

        getPrompt(channel, output);
        writeCommand(reply, "reset");
        getPrompt(channel, output);

    } finally {

        if (channel != null) {
            channel.disconnect();
        }

        if (session != null) {
            session.disconnect();
        }
    }
}

private static void writeCommand(PipedOutputStream reply, String command) throws IOException {
    System.out.println("Command: " + command);
    reply.write(command.getBytes());
    reply.write("\n".getBytes());
}

private static void getPrompt(ChannelShell channel, ByteArrayOutputStream output)
        throws UnsupportedEncodingException, InterruptedException {

    while (!channel.isClosed()) {

        String response = new String(output.toByteArray(), "UTF-8");
        System.out.println(response);
        if (response.trim().endsWith(PROMPT)) {
            output.reset();
            return;
        }

        Thread.sleep(100);
    }
}

UPDATE: I have noticed that the command you send via SSH ends with \r. Try \n instead and see if it works for you.

Comments