Calling a shell script using SSH exec channel, but it ignores calls to other shell scripts

只谈情不闲聊 提交于 2019-12-01 06:39:06

问题


I am managing to execute a shell script on a remote server using JSch exec using the helpful examples provided here. I can see the echoes being returned from the script and the exit status at the end is 0 - so all looks good at first glance.

However, the problem is that the script itself calls out to other scripts, and these appear to be completely ignored, just skipped over.

The script calls other scripts directly. i.e. the first line of the script is something like:

script_two.sh

Could anyone advise of any way to overcome this? I did start to look into the "shell" channel instead of "exec", but this may be tricky in my case because before giving the user access to the system, the server presents a form to fill in (name, number, why are you logging in, etc) - I haven't yet been able to to programmatically fill in and submit this form, so I would like to stick with exec if possible.

I am new to all this, so any help/advice would be most welcome!

Code snippet below. As I said, this appears to work, but the sh script represented by "scriptFileName" int he code calls other sh scripts, and these are not executed.

Many thanks in advance for any help, J

JSch jsch = new JSch();
JSch.setConfig(FileTransferConstants.STRICT_HOST_KEY_CHECKING, "no");

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

//create the execution channel over the session
ChannelExec channelExec = (ChannelExec)session.openChannel("exec");

channelExec.setCommand(scriptFileName);
channelExec.connect();

回答1:


I assume the script looks like:

script_one.sh
script_two.sh

I.e. the script relies on the . (the current path) being in the PATH environment variable, what is not a default.

So for the script to ever work, the . has to be added to the PATH in some startup script. It's quite probable that the addition occurs (probably unintentionally incorrectly) only for interactive sessions. Probably because the addition is done in a startup script that is executed (sourced) for the the interactive sessions only.

The "exec" channel in the JSch (rightfully) does not allocate a pseudo terminal (PTY) for the session. As a consequence a different set of startup scripts is (might be) sourced than, when you login with an SSH client. And/or different branches in the scripts are taken, based on absence/presence of the TERM environment variable. So the environment might differ from the interactive session you use with your SSH client.


Solutions are (in preferred order):

  • Correct the script not to rely on non-default settings of having the . in PATH. Call the sub-scripts with an explicit path:

    ./script_one.sh
    ./script_two.sh
    
  • Correct the startup scripts to add the . to the PATH unconditionally (even for non-interactive sessions).

  • (not recommended) Force the pseudo terminal allocation for the "exec" channel using the .setPty method:

    Channel channel=session.openChannel("exec");
    ((ChannelExec)channel).setPty(true);
    

    Using the pseudo terminal to automate a command execution can bring you nasty side effects. See for example Is there a simple way to get rid of junk values that come when you SSH using Python's Paramiko library and fetch output from CLI of a remote machine?


See also a related question Shell ping command with source option is failing when executed using JSch setCommand.



来源:https://stackoverflow.com/questions/38073260/calling-a-shell-script-using-ssh-exec-channel-but-it-ignores-calls-to-other-she

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!