JSch:有没有办法将用户环境变量公开给 "exec" 频道?
JSch: Is there a way to expose user environment variables to "exec" channel?
我正在尝试 运行 使用本地 Linux 逻辑路径的命令,例如 cat $test_dir/test.dat
,但逻辑路径 $test_dir
(这是一个用户环境变量)是无法通过 ChannelExec
获得。但是当我使用交互式 ChannelShell
时,我能够在交互式会话中看到用户变量和命令 运行。我只能从“exec”会话中查看系统级环境变量。这甚至可以使用 JSch 库吗?如果是,我该如何实现它,如果不能,我应该使用什么库来实现它?
在下面添加我的 class 代码:
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();
}
}
默认情况下,JSch 中的 "exec" 通道(理所当然地)不会为会话分配伪终端 (PTY)。因此,(可能)获得了一组不同的启动脚本。 And/or 根据 TERM
环境变量的 absence/presence,采用脚本中的不同分支。因此环境可能不同于交互式 JSch "shell" 会话或当您使用 SSH 客户端时。
解决此问题的方法:
修复您的启动脚本,为交互式和非交互式会话设置相同的环境变量。
另一种(不推荐)方法是使用.setPty
方法强制为"exec"频道分配伪终端:
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setPty(true);
使用伪终端自动执行命令会给您带来严重的副作用。参见示例
- Remove of unwanted characters when i am using jsch to run command
- Removing shell stuff (like prompts) from command output in JSch
对于类似的问题,请参阅
由于您没有打开交互式 shell,因此不会设置您的环境变量。但是,您可以将 bash 命令与 --login (man bash 以获得更多详细信息)一起使用以获得您想要的结果
bash --login -c 'command arg1 ...'"
我能够通过在 .bashrc 文件中设置环境变量来解决这个问题。通过 setEnv 方法设置环境变量对我没有帮助。
我正在尝试 运行 使用本地 Linux 逻辑路径的命令,例如 cat $test_dir/test.dat
,但逻辑路径 $test_dir
(这是一个用户环境变量)是无法通过 ChannelExec
获得。但是当我使用交互式 ChannelShell
时,我能够在交互式会话中看到用户变量和命令 运行。我只能从“exec”会话中查看系统级环境变量。这甚至可以使用 JSch 库吗?如果是,我该如何实现它,如果不能,我应该使用什么库来实现它?
在下面添加我的 class 代码:
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();
}
}
默认情况下,JSch 中的 "exec" 通道(理所当然地)不会为会话分配伪终端 (PTY)。因此,(可能)获得了一组不同的启动脚本。 And/or 根据 TERM
环境变量的 absence/presence,采用脚本中的不同分支。因此环境可能不同于交互式 JSch "shell" 会话或当您使用 SSH 客户端时。
解决此问题的方法:
修复您的启动脚本,为交互式和非交互式会话设置相同的环境变量。
另一种(不推荐)方法是使用
.setPty
方法强制为"exec"频道分配伪终端:Channel channel=session.openChannel("exec"); ((ChannelExec)channel).setPty(true);
使用伪终端自动执行命令会给您带来严重的副作用。参见示例
- Remove of unwanted characters when i am using jsch to run command
- Removing shell stuff (like prompts) from command output in JSch
对于类似的问题,请参阅
由于您没有打开交互式 shell,因此不会设置您的环境变量。但是,您可以将 bash 命令与 --login (man bash 以获得更多详细信息)一起使用以获得您想要的结果
bash --login -c 'command arg1 ...'"
我能够通过在 .bashrc 文件中设置环境变量来解决这个问题。通过 setEnv 方法设置环境变量对我没有帮助。