I was trying to use the SSH.NET NuGet package to remotely execute a command to grab an app version that is installed on one iPhone connected to a Mac.
If executed on the Mac itself with below command, will get me its version:
ideviceinstaller -l|grep <bundleIdOfMyAppPackage>
So I build a small utility in C# with this package, hoping that I would leverage it. However, all I get is just an empty string. Would anyone let me know what I could do to get the result I want ? Thank you !
var host = "myhost";
var username = "username";
var password = "password";
using (var client = new SshClient(host, username, password))
{
client.HostKeyReceived += delegate(object sender, HostKeyEventArgs e) { e.CanTrust = true; };
client.Connect();
var command = client.CreateCommand("ideviceinstaller -l|grep <bundleIdOfMyAppPackage>");
command.Execute();
var result = command.Result;
Console.WriteLine(result);
client.Disconnect();
}
The error that I've got from command.Error is
zsh1: command not found ideviceinstaller`
which is weird because I can see ideviceinstaller inside that folder if I browse to there.
I've got it working thanks to @Martin Prikryl by changing the command to:
/usr/local/bin/ideviceinstaller -l|grep <myAppBundleId>
The SSH.NET SshClient.CreateCommand (or SshClient.RunCommand) does not run shell in "login" mode and does not allocate a pseudo terminal 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), than in your regular interactive SSH session. And/or different branches in the scripts are taken, based on an absence/presence of TERM environment variable.
Possible solutions (in preference order):
Fix the command not to rely on a specific environment. Use a full path to ideviceinstaller in the command. E.g.:
/path/to/ideviceinstaller ...
If you do not know the full path, on common *nix systems, you can use which ideviceinstaller 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 "ideviceinstaller ..."
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:
PATH="$PATH;/path/to/ideviceinstaller" && ideviceinstaller ...
Another (not recommended) is to use "shell" channel to execute the command via SshClient.CreateShellStream or SshClient.CreateShell as these allocate pseudo terminal
ShellStream shellStream = client.CreateShellStream(string.Empty, 0, 0, 0, 0, 0);
shellStream.Write("ideviceinstaller\n");
while (true)
{
string s = shellStream.Read();
Console.Write(s);
}
Using the shell and pseudo terminal to automate a command execution can bring you nasty side effects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With