java shell unix ssh jsch

Ciertos comandos de Unix fallan con "... no encontrado", cuando se ejecuta a través de Java usando JSch



shell ssh (3)

Tengo un código que se conecta a un servidor Unix y ejecuta comandos.

He estado intentando con comandos simples y funcionan bien.

Puedo iniciar sesión y obtener la salida de los comandos.

Necesito ejecutar un gráfico Ab-initio a través de Java.

Estoy usando el comando air sandbox run graph para esto.

Funciona bien, cuando inicio sesión con el cliente SSH y ejecuto el comando. Soy capaz de ejecutar el gráfico. Sin embargo, cuando trato de ejecutar el comando a través de Java me da un error "aire no encontrado" .

¿Hay algún tipo de límite sobre qué tipo de comandos de Unix admite JSch?

¿Alguna idea de por qué no puedo ejecutar el comando a través de mi código Java?

Aquí está el código:

public static void connect(){ try{ JSch jsch=new JSch(); String host="*****"; String user="*****"; String config = "Host foo/n"+ " User "+user+"/n"+ " Hostname "+host+"/n"; ConfigRepository configRepository = com.jcraft.jsch.OpenSSHConfig.parse(config); jsch.setConfigRepository(configRepository); Session session=jsch.getSession("foo"); String passwd ="*****"; session.setPassword(passwd); UserInfo ui = new MyUserInfo(){ public boolean promptYesNo(String message){ int foo = 0; return foo==0; } }; session.setUserInfo(ui); session.connect(); String command="air sandbox run <graph-path>"; Channel channel=session.openChannel("exec"); ((ChannelExec)channel).setCommand(command); channel.setInputStream(null); ((ChannelExec)channel).setErrStream(System.err); InputStream in=channel.getInputStream(); channel.connect(); byte[] tmp=new byte[1024]; while(true){ while(in.available()>0){ int i=in.read(tmp, 0, 1024); if(i<0)break; page_message=new String(tmp, 0, i); System.out.print(page_message); } if(channel.isClosed()){ if(in.available()>0) continue; System.out.println("exit-status: "+channel.getExitStatus()); break; } try{Thread.sleep(1000);}catch(Exception ee){} } channel.disconnect(); session.disconnect(); } catch(Exception e){ System.out.println(e); } } public static void main(String arg[]){ connect(); } public String return_message(){ String ret_message=page_message; return ret_message; } public static abstract class MyUserInfo implements UserInfo, UIKeyboardInteractive{ public String getPassword(){ return null; } public boolean promptYesNo(String str){ return false; } public String getPassphrase(){ return null; } public boolean promptPassphrase(String message){ return false; } public boolean promptPassword(String message){ return false; } public void showMessage(String message){ } public String[] promptKeyboardInteractive(String destination, String name, String instruction, String[] prompt, boolean[] echo){ return null; } }


El canal "exec" en el JSch (legítimamente) no asigna un pseudo terminal (PTY) para la sesión. Como consecuencia, se obtiene (podría ser) un conjunto diferente de scripts de inicio (particularmente para sesiones no interactivas, no se obtiene .bash_profile ). Y / o se toman diferentes ramas en los scripts, en base a la ausencia / presencia de la variable de entorno TERM . Por lo tanto, el entorno puede diferir de la sesión interactiva que utiliza con su cliente SSH.

Entonces, en su caso, la PATH probablemente esté configurada de manera diferente; y, por consiguiente, no se puede encontrar el ejecutable air .

Para verificar que esta es la causa raíz, desactive la asignación de pseudo terminal en su cliente SSH. Por ejemplo, en PuTTY, es Conexión> SSH> TTY> No asignar un pseudo terminal . Luego, vaya a Conexión> SSH> Comando remoto e ingrese su comando air ... Verifique Sesión> Cerrar ventana al salir> Nunca y abra la sesión. Debería obtener el mismo error "aire no encontrado" .

Formas de arreglar esto, en orden de preferencia:

  1. Arregle el comando de no confiar en un entorno específico. Use una ruta completa para air en el comando. P.ej:

    /bin/air sandbox run <graph-path>

    Si no conoce la ruta completa, en los sistemas comunes * nix, puede usar which air comando which air en su sesión SSH interactiva.

  2. Arregle sus secuencias de comandos de inicio para establecer la PATH la misma manera para las sesiones interactivas y no interactivas.

  3. Intente ejecutar el script explícitamente a través del shell de inicio de sesión (use el interruptor --login con shells comunes * nix):

    bash --login -c "air sandbox run sandbox run <graph-path>"

  4. Si el comando en sí se basa en una configuración de entorno específica y no puede corregir los scripts de inicio, puede cambiar el entorno en el comando en sí. La sintaxis para eso depende del sistema remoto y / o del shell. En los sistemas * nix comunes, esto funciona:

    String command="PATH=/"$PATH;/path/to/air/" && air sandbox run <graph-path>";

  5. Otro enfoque (no recomendado) es forzar la asignación de pseudo terminal para el canal "exec" utilizando el método .setPty :

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

    Usar el pseudo terminal para automatizar la ejecución de un comando puede traerle efectos secundarios desagradables. Vea, por ejemplo, ¿Hay una manera simple de deshacerse de los valores basura que aparecen cuando utiliza SSH utilizando la biblioteca Paramiko de Python y obtiene la salida de la CLI de una máquina remota?

Para problemas similares, vea

  • Ciertos comandos de Unix fallan con "... no encontrado", cuando se ejecuta a través de Java usando JSch incluso con setPty habilitado
  • Los comandos ejecutados usando JSch se comportan de manera diferente que en el terminal SSH (omite el mensaje de confirmación de "sí /" no ")
  • JSch: ¿Hay alguna manera de exponer las variables de entorno del usuario al canal "exec"?
  • El comando (.4gl) ejecutado con SSH.NET SshClient.RunCommand falla con "No existe tal archivo o directorio"

Puede usar un archivo ~ / .ssh / environment para configurar sus variables AB_HOME y PATH.


podrías intentar averiguar dónde reside el "aire"

whereis air

y luego usa este resultado.

algo como

/usr/bin/air sandbox run graph