Search code examples
javalinuxbashaliasjsch

How to use an alias on server with JSch?


I want to use an alias in my JSch-connection. I successfully built a connection to the Linux-Server.

In the Linux-Server there's an alias for ls -l called ll. When I type the alias in PuTTY I have no problems, but through JSch I get the following Error:

bash: ll: command not found

What the hell is wrong here? Here's a preview of my code:

package test;

import java.io.InputStream;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UIKeyboardInteractive;
import com.jcraft.jsch.UserInfo;

public class SSHConnection {
    private static String host = "", username = "", password = "";
    private static int port = 22;
    private static String[] commands = {"ll /", "df -h"};

    public static void main(String[] arg) {
        try {
            JSch jsch = new JSch();

            Session session = jsch.getSession(username, host, port);
            session.setPassword(password);

            UserInfo ui = new MyUserInfo() {
                public void showMessage(String message) {}
                public boolean promptYesNo(String message) {
                    return true;
                }
            };

            session.setUserInfo(ui);
            session.connect();

            for (String command : commands) {
                Channel channel = session.openChannel("exec");  // runs commands 
                ((ChannelExec) channel).setCommand(command);    // setting command

                channel.setInputStream(null);
                ((ChannelExec) channel).setErrStream(System.err);   // Error input
                InputStream in = channel.getInputStream();

                channel.connect();

                byte[] temp = new byte[1024]; //temporary savings

                System.out.println("Hostname:\t" + host + "\nCommand:\t" + 
                command + "\n\nResult:\n----------");

                while (true) {
                    // reads while the inputStream contains strings
                    while (in.available() > 0) {
                        int i = in.read(temp, 0, temp.length);
                        if (i < 0) break;
                        System.out.print(new String(temp, 0, i));
                    }
                    if (channel.isClosed()) {
                        if (in.available() > 0) continue;
                        if (channel.getExitStatus() != 0) { // Error-Check
                            System.out.println("----------\nExit-status: " + 
                            channel.getExitStatus() + "\n\n");
                        } else {
                            System.out.println("\n\n");
                        }
                        break;
                    }
                    // pauses the code for 1 s
                    try { Thread.sleep(1000); } catch (Exception e) {}
                }
                channel.disconnect();
                in.close();
            }

            session.disconnect();
        } catch (Exception a) {
            a.printStackTrace();
        }
    }

    public static abstract class MyUserInfo implements UserInfo, UIKeyboardInteractive {
        public String getPassword() { return null; }
        public boolean promptYesNo(String str) { return false; }
        public String getPassphrase() { return null; }
        public boolean promptPassphrase(String message) { return false; }
        public boolean promptPassword(String message) { return false; }
        public void showMessage() { }
        public String [] promptKeyboardInteractive(String destination,
                                                   String name,
                                                   String instruction,
                                                   String[] prompt,
                                                   boolean[] echo) {
            return null;
        }
    }
}

Thank you very much for your help in advance!

EDIT : I forgot to tell you, that I have no problems with the login and the command df -h.


Solution

  • The correct solution is really to not use aliases at all; they are intended as a convenience for interactive use. If you have a complex alias which you would like to use noninteractively, convert it to a regular shell script, save the file in your $PATH, and mark it as executable. Or convert it to a function. Even for interactive use, functions are actually superior to aliases, and work in noninteractive shells, too.

    Having said that, you can always wing it. The command you execute could be, for example,

     private static String[] commands = {"bash -O expand_aliases -c 'll /'", "df -h"};
    

    You may need to smuggle a newline into that command line if you need to explicitly source the alias definition before you can use it; there is a caveat in the manual about this. (Do read all of it, and especially the last sentence.)

    Of course, for something this simple, the proper solution is to just run the standard command ls -l and forget about the alias. It's better for portability, too; while many sites have this alias, it's by no means guaranteed to exist. (Personally, the first thing I do when I set up an account is remove these "de facto standard" aliases.)