user3221714 user3221714 - 27 days ago 8
Java Question

JSch: Is there a way to expose user environment variables to "exec" channel?

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:
`public class SecureShell {

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();
}


}`

Answer Source

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 ...'"