Certain Unix Commands Fail with "... Not Found", When Executed Through Java Using Jsch

Certain Unix commands fail with ... not found , when executed through Java using JSch

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 (particularly for non-interactive sessions, .bash_profile is not sourced). 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.

So, in your case, the PATH is probably set differently; and consequently the air executable cannot be found.

To verify that this is the root cause, disable the pseudo terminal allocation in your SSH client. For example in PuTTY, it's Connection > SSH > TTY > Don't allocate a pseudo terminal. Then, go to Connection > SSH > Remote command and enter your air ... command. Check Session > Close window on exit > Never and open the session. You should get the same "air not found" error.


Ways to fix this, in preference order:

  1. Fix the command not to rely on a specific environment. Use a full path to air in the command. E.g.:

    /bin/air sandbox run <graph-path>

    If you do not know the full path, on common *nix systems, you can use which air command in your interactive SSH session.

  2. Fix your startup scripts to set the PATH the same for both interactive and non-interactive sessions.

  3. Try running the script explicitly via login shell (use --login switch with common *nix shells):

    bash --login -c "air sandbox run sandbox run <graph-path>"
  4. If the command itself relies on a specific environment setup and you cannot fix the startup scripts, you can change the environment in the command itself. Syntax for that depends on the remote system and/or the shell. In common *nix systems, this works:

    String command="PATH=\"$PATH;/path/to/air\" && air sandbox run <graph-path>";
  5. Another (not recommended) approach is to 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?


For a similar issues, see

  • Certain Unix commands fail with "... not found", when executed through Java using JSch even with setPty enabled
  • Commands executed using JSch behaves differently than in SSH terminal (bypasses confirm prompt message of "yes/"no")
  • JSch: Is there a way to expose user environment variables to "exec" channel?
  • Command (.4gl) executed with SSH.NET SshClient.RunCommand fails with "No such file or directory"

Certain Unix commands fail with ... not found , when executed through Java using JSch even with setPty enabled

Your server/shell is misconfigured somehow. It does not set the PATH correctly, when a shell session is not started. That's, why the ifconfig/iwconfig binaries cannot be found.

Either fix your startup scripts to set the PATH correctly for all situations. Or use a full path to the ifconfig/iwconfig.

To find the full path, open a regular shell session using your SSH client and type:

which ifconfig

For a similar issue, see Certain Unix commands fail with "... not found", when executed through Java using JSch.

Commands executed using JSch behaves differently than in SSH terminal (bypasses confirm prompt message of yes/ no )

By default the JSch does not request PTY (pseudo-terminal).

That can cause some commands to behave differently than in an interactive SSH terminal.

You can override this using the ChannelSession.setPty.


If the above does not help, see also similar questions:

  • Certain Unix commands fail with "... not found", when executed through Java using JSch
  • Certain Unix commands fail with "... not found", when executed through Java using JSch even with setPty enabled

Running KornShell Script with JSCH

The user you're logging in as with JSCH does not have sqlplus in it's path, so the shell is unable to locate the binary.

It's not a Korn Shell problem, it's an environment problem. Either you must run sqlplus by specifying it's full path on disk, such as /path/to/sqlplus <arguments> or add sqlplus to the environment variable $PATH for the user you're logging in as.

If your script should be portable, then it's common practice to not hard-code the binary path, but rather run through a series of tests to see where the binary is located, checking all common locations for the binary as well as seeing if it's on the path. Once found, set that absolute path to some variable, then use that variable whenever you need to run that binary in your script.

Execute remote ssh command which java (JSch java)

Enabling the pseudo-terminal mode the command is executed correctly.

My JSch session doesn't execute command

I assume the problem is that you close the connection before the command is even started.

All the examples your pointed to read a command output, until the end (hence until the command finishes). You do not read the output so you fail to wait for the command to finish.

Either consume the command output as the other examples do. Or (if you are not interested in the output) wait until channel.isClosed() is true before exiting.

How to set Java home in JSch to execute a command?

ChannelExec.setEnv on JSch side probably works. But assuming you are connecting to an OpenSSH server, the server must be explicitly configured to allow you to set the LANG and JAVA_HOME environment variables using the AcceptEnv directive. What it probably is not.

You can try the same using PuTTY (Connection > Data > Environment variables). You will probably get "Server refused to set environment variables" message back.

See also How can I set environment variables when I ssh login to my Unix box by passing custom arguments?


Anyway, the correct solution is to fix your server configuration to set the environment correctly even for non-interactive sessions.

Or as a dirty workaround you can set the variables directly in your command:

JAVA_HOME=/blah/java/J8.0_64/; java ...

See also Certain Unix commands fail with "... not found", when executed through Java using JSch.



Related Topics



Leave a reply



Submit