I am trying to run commands which uses local Linux logical paths like cat $test_dir/test.dat
, but the logical path $test_dir
(which is a user environment variable) is not available via ChannelExec
. But when I use interactive ChannelShell
, I am able to see the user variables and the commands run fine on the interactive session. I can view system level environment variable only from “exec” session. Is that even possible using JSch library, if yes then how shall I achieve it and if not what library shall I use to achieve this?
Adding my class code below:
private static final Logger logger = LogManager.getLogger(SecureShell.class); private String uName; private String pWord; private String hName; private int port; private Session session = null; private Channel channel = null; /**Create an instance to start and stop the remote shell and execute commands * remotely via java. * * @param uName * host username * @param pWord * host password * @param hName * host name * @param port * host port number */ public SecureShell(String uName, String pWord, String hName, int port) { this.uName = uName; this.pWord = pWord; this.hName = hName; this.port = port; } /**Create an instance to start and stop the remote shell and execute commands * remotely via java. * *@param uName * host username * @param pWord * host password * @param hName * host name */ public SecureShell(String uName, String pWord, String hName) { this.uName = uName; this.pWord = pWord; this.hName = hName; this.port = 22; } /**Start the session with the host. * @return * true if the session started successfully, false otherwise */ public boolean startSession() { JSch jsch = new JSch(); try { session = jsch.getSession(uName, hName, port); java.util.Properties config = new java.util.Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); session.setPassword(pWord); session.connect(); } catch (JSchException jsche) { logger.error(jsche.getMessage()); return false; } return true; } /** Execute commands on the host; * @param command * command to be executed on the host. * @return * status of the execution */ public int execute(String command) { int status = -1; if(session != null && session.isConnected()) { try { channel = session.openChannel("exec"); //((ChannelExec)channel).setEnv("LC_XXX", "xxxxxxx"); ((ChannelExec)channel).setPty(true); ((ChannelExec) channel).setCommand(command); InputStream in = channel.getInputStream(); channel.connect(); byte[] buffer = new byte[1024]; while(true){ while(in.available()>0){ int i=in.read(buffer, 0, 1024); System.out.print(new String(buffer, 0, i)); if(i<0) break; } if(channel.isClosed()){ if(in.available()>0) continue; status = channel.getExitStatus(); break; } } } catch (JSchException jsche) { logger.error(jsche.getMessage()); } catch (IOException ioe) { logger.error(ioe.getMessage()); } finally { if(channel!=null && channel.isConnected()) channel.disconnect(); } } return status; } /**Stop the session with the remote. * */ public void stopSession() { if(session!=null && session.isConnected()) session.disconnect(); } public static void main(String[] args) { SecureShell ssh = new SecureShell("user", "password", "hostname"); ssh.startSession(); System.out.println(ssh.execute("env")); ssh.stopSession(); } }
Advertisement
Answer
Since you’re not opening up an interactive shell, your environment variables won’t be set. However, you can use the bash command with –login (man bash for more details) to get the results you want
bash --login -c 'command arg1 ...'"