MPI cannot execute with machine file or hosts from SSH using JSch exec channel [duplicate] - ssh

I have a piece of code which connects to a Unix server and executes commands.
I have been trying with simple commands and they work fine.
I am able to login and get the output of the commands.
I need to run an Ab-initio graph through Java.
I am using the air sandbox run graph command for this.
It runs fine, when I login using SSH client and run the command. I am able to run the graph. However, when I try to run the command through Java it gives me a "air not found" error.
Is there any kind of limit on what kind of Unix commands JSch supports?
Any idea why I'm not able to run the command through my Java code?
Here's the code:
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;
}
}

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:
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.
Fix your startup scripts to set the PATH the same for both interactive and non-interactive sessions.
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>"
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>";
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"

you could try to find out where "air" resides with
whereis air
and then use this outcome.
something like
/usr/bin/air sandbox run graph

You can use an ~/.ssh/environment file to set your AB_HOME and PATH variables.

Related

Is the below code correct to connect to a remote Linux host and get few tasks done using Apache Mina?

I want to switch from Jsch to Apache Mina to query remote Linux hosts and to get the few tasks done.
I need to achieve things like list files of a remote host, change directory, get file contents, put a file into the remote host etc.,
I am able to successfully connect and execute a few shell commands using session.executeRemoteCommand().
public byte[] getRemoteFileContent(String argDirectory, String fileName)
throws SftpException, IOException {
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
StringBuilder cmdBuilder = new StringBuilder("cat" + SPACE + remoteHomeDirectory);
cmdBuilder.append(argDirectory);
cmdBuilder.append(fileName);
_session.executeRemoteCommand(cmdBuilder.toString(), stdout, null, null);
return stdout.toByteArray();
}
public void connect()
throws IOException {
_client = SshClient.setUpDefaultClient();
_client.start();
ConnectFuture connectFuture = _client.connect(_username, _host, portNumber);
connectFuture.await();
_session = connectFuture.getSession();
shellChannel = _session.createShellChannel();
_session.addPasswordIdentity(_password);
// TODO : fix timeout
_session.auth().verify(Integer.MAX_VALUE);
_channel.waitFor(ccEvents, 200);
}
I have the following questions,
How can I send a ZIP file to a remote host much easily in API level (not the Shell commands level)? And all other operations in API level.
Can I secure a connection between my localhost and remote through a certificate?
As of now, I am using SSHD-CORE and SSHD-COMMON version 2.2.0. Are these libraries enough or do I need to include any other libraries?
executeRemoteCommand() is stateless how can I maintain a state?
I needed sshd-sftp and its APIs to get the file transfer work.
Below code gets the proper API,
sftpClient = SftpClientFactory.instance().createSftpClient(clientSession);
On sftpClinet I called read() and write() methods get the task done. This answers my question fully.

Issue with SSH.NET UWP

I am having issues using SSh.net in a UWP App. This app will run on Win10.
I get the following error:
An attempt was made to access a socket in a way forbidden by its access permissions. I have looked online and there is no one actually dealing with this.The exact same code works in a standard Desktop App (WPF)
The key is the key string and I had to replace \r with \n because the PrivateKeyFile creation gave an error message and I tracked this down to carriage return placed instead of new line (by the textbox).
key = key.Replace("\r", "\n");
PrivateKeyFile(stringToStream(key));
client = new SshClient(ip, port, username, pkf);
if (!client.IsConnected)
{
try
{
client.Connect();
connected = true;
}
catch (Exception ex)
{
exception = ex.Message.ToString();
connected = false;
}
}
Finally resolved this issue - Look here: An attempt was made to access a socket in a way forbidden by its access permissions
Go down to the following line:
If you're getting the same error in Windows 8 development, it could be that you haven't enabled access over Private Networks in your Package.appxmanifest file:
Select the Private Networks (Client & Server) option as shown on the image.
Click here for the image

Selenium+AutoIt - send commands to execute in Remote Desktop

I am trying to automate non-browser based functionality (thick client application - Delphi based), web-based application(new java application) and opted to use Selenium + AutoIt for this. I need to compare data displayed in both applications for one particular user.
To access the thick client application, I need to use Remote Desktop Connection. I was able to connect to the remote desktop through selenium+autoit but not able to send any commands to the remote machine. If anyone is aware of the solution please help.
Following is the code I used.
import java.io.File;
import autoitx4java.AutoItX;
import com.jacob.com.LibraryLoader;
public class sampleTest {
  static String rdcPwd = "password";
  static String remoteComputerName = "computername";
  
  public static void main(String[] args) throws InterruptedException {
    String jacobDllVersionToUse;
    jacobDllVersionToUse = "jacob-1.18-x64.dll";
    File file = new File("lib", jacobDllVersionToUse);
    System.setProperty(LibraryLoader.JACOB_DLL_PATH, file.getAbsolutePath());
    AutoItX x = new AutoItX();
    x.run("MSTSC.EXE");
    x.winActivate("Remote Desktop Connection");
    x.winWaitActive("Remote Desktop Connection");
    x.controlClick("Remote Desktop Connection", "Co&nnect", "1");
    Thread.sleep(15000);
    x.send(rdcPwd);
    Thread.sleep(3000);
    x.controlClick("Windows Security", "", "[CLASS:Button; INSTANCE:2;]");
    Thread.sleep(10000);
    x.send("#r");      // Not Working
    x.run("explorer.exe");  //Not Working
  }
}
Thanks,
Madhu.

"USERAUTH fail" using gradle-ssh-plugin with identity

I can't connect to a SSH host using the Gradle SSH Plugin with my private key.
Specifying the password in the build.gradle works fine:
remotes {
webServer {
host = '<IP>'
user = '<USER>'
password = '<PASSWORD>'
}
}
But to avoid writing my password in the build file, I've set my environment to connect using my private key without entering the password from shell:
ssh <user>#<ip>
This command works from the shell but I can't achieve this with the Gradle plugin. This is my configuration:
remotes {
webServer {
host = '<IP>'
user = '<USER>'
identity = file("${System.getProperty('user.home')}/.ssh/id_rsa")
}
}
The error is:
Caused by: com.jcraft.jsch.JSchException: USERAUTH fail at com.jcraft.jsch.UserAuthPublicKey.start(UserAuthPublicKey.java:119)
Since I'm able to connect from the shell, what's wrong with my configuration?
I fixed this by adding the agent = true property:
remotes {
webServer {
host = '54.233.77.171'
user = 'denis'
agent = true
identity = file("${System.getProperty('user.home')}/.ssh/id_rsa")
}
}
agent - If this is set, Putty Agent or ssh-agent will be used on
authentication
For more information: Connections settings
I tried this property after analyzing the class UserAuthPublicKey:
if(userinfo==null) throw new JSchException("USERAUTH fail");
I think JCraft only supports PEM keys - when generating the keys, you need to specify the format:
ssh-keygen -t rsa -m PEM

Problem Loading SSIS Custom Connection Manager/Type

I'm currently trying to build a custom connection manager and custom data flow source for a proprietary system at work, and I'm running into an odd problem when I attempt to execute a task containing my custom manager (from BIDS, DTEXEC, or the agent)
Error: 0xC0014005 at : The connection
type "AF" specified for connection
manager "AFConnection" is not
recognized as a valid connection
manager type. This error is returned
when an attempt is made to create a
connection manager for an unknown
connection type. Check the spelling in
the connection type name. Error:
0xC0010018 at : Error loading value
"<DTS:ConnectionManager
xmlns:DTS="www.microsoft.com/SqlServer/Dts"><DTS:Property
DTS:Name="DelayValidation">0</DTS:Property><DTS:Property
DTS:Name="ObjectName">AFConnection</DTS:Property><DTS:Property
DTS:Name="DTSID">{43304F2E-0C3F-4C00-9221-BD88C50EDDFC}"
from node "DTS:ConnectionManager".
I have the relevant DLLs in the GAC as well as the \90\DTS\Connections folder. All other connection managers work fine.
Here is the connection manager boilerplate:
[DtsConnection(ConnectionType="AF", Description="Connection manager for AF2", DisplayName="AF Connection"
, UITypeName = "AnalysisFrameworkCustomTask.AFConnectionManagerUI,AnalysisFrameworkCustomTask,Version=1.0.0.0,Culture=neutral,PublicKeyToken=e11db2e10378dc29")]
public class AFConnectionManager : ConnectionManagerBase
{
#region Overrides
public override DTSExecResult Validate(IDTSInfoEvents infoEvents)
{
// Code omitted that determines success or failure
return DTSExecResult.Success;
}
public override object AcquireConnection(object txn)
{
// Code ommitted to return new connection; works fine when debugged
// in the development environment
}
public override void ReleaseConnection(object connection)
{
// Code ommitted to release connection; works fine when debugged
// in the development environment
}
#endregion
}
Has anyone seen this before and have any idea how to move forward?
Try restarting the SSIS service.