首页 > 解决方案 > 在 C# 中使用 SSH.NET CreateCommand 执行命令失败并显示“<command> not found”

问题描述

我试图使用SSH.NET NuGet 包远程执行命令以获取安装在连接到 Mac 的 iPhone 上的应用程序版本。

如果使用以下命令在 Mac 上执行,我会得到它的版本:

ideviceinstaller -l|grep <bundleIdOfMyAppPackage>

所以我用这个包在 C# 中构建了一个小实用程序,希望我能利用它。但是,我得到的只是一个空字符串。谁能让我知道我能做些什么来得到我想要的结果?谢谢 !

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();
}

我得到的错误command.Error

zsh1:找不到命令 ideviceinstaller`

这很奇怪,因为ideviceinstaller如果我浏览到那里,我可以看到该文件夹​​的内部。


感谢@Martin Prikryl,我通过将命令更改为:

/usr/local/bin/ideviceinstaller -l|grep <myAppBundleId>

标签: c#.netshellsshssh.net

解决方案


SSH.NET SshClient.CreateCommand(或SshClient.RunCommand)不会在“登录”模式下运行 shell,也不会为会话分配伪终端。因此,与常规交互式 SSH 会话相比,(可能)获取了一组不同的启动脚本(特别是对于非交互式会话,.bash_profile没有获取源)。和/或脚本中的不同分支基于TERM环境变量的缺失/存在而被采用。

可能的解决方案(按优先顺序):

  1. 修复命令不依赖于特定环境。ideviceinstaller在命令中使用完整路径。例如:

     /path/to/ideviceinstaller ...
    

    如果您不知道完整路径,在常见的 *nix 系统上,您可以which ideviceinstaller在交互式 SSH 会话中使用命令。

  2. 修复您的启动脚本,PATH为交互式和非交互式会话设置相同的设置。

  3. 尝试通过登录 shell 显式运行脚本(使用--login带有常见 *nix shell 的 switch):

     bash --login -c "ideviceinstaller ..."
    
  4. 如果命令本身依赖于特定的环境设置并且您无法修复启动脚本,则可以在命令本身中更改环境。其语法取决于远程系统和/或 shell。在常见的 *nix 系统中,这是有效的:

     PATH="$PATH;/path/to/ideviceinstaller" && ideviceinstaller ...
    
  5. 另一个(不推荐)是使用“shell”通道通过SshClient.CreateShellStreamSshClient.CreateShell作为这些分配伪终端执行命令

     ShellStream shellStream = client.CreateShellStream(string.Empty, 0, 0, 0, 0, 0);
     shellStream.Write("ideviceinstaller\n");
    
     while (true)
     {
         string s = shellStream.Read();
         Console.Write(s);
     }
    

    使用 shell 和伪终端自动执行命令会给您带来讨厌的副作用。


推荐阅读