9

在我的 Cocoa 应用程序中,我尝试使用它NSTask来运行一些基本的 Git 命令。每当我运行需要权限(SSH 密钥)才能访问远程(例如git pushgit pull)的命令时,它都会失败并出现以下错误:

权限被拒绝(公钥)。远端意外挂断

从终端运行相同的命令工作得很好,所以我认为这可能是一个问题,NSTask因为没有设置将在访问 ssh 密钥过程中某处使用的环境变量。我尝试像这样手动设置HOMEUSER环境变量:

[task setEnvironment:[NSDictionary dictionaryWithObjectsAndKeys:NSHomeDirectory(), @"HOME", NSUserName(), @"USER", nil]];

但这没有效果。我必须设置任何特定的环境变量NSTask才能正常工作吗?

编辑:多亏了达斯汀的提示,我在弄清楚这一点上又进了一点。我使用该env命令列出了当前会话的环境变量,我发现了这个:

SSH_AUTH_SOCK=/tmp/launch-DMQopt/Listeners

为了测试,我复制了该路径并将其设置为环境变量NSTask并再次运行代码,这一次成功了!也就是说,我确信SSH_AUTH_SOCK每个会话都会发生变化,所以我不能只是硬编码它。如何动态生成/检索此变量?

4

1 回答 1

4

您可以尝试按照教程“ Wrapping rsync or SSH in an NSTask ”(来自Ira),其中确实提到了SSH_AUTH_SOCK变量:

自从写了这篇文章后,我意识到我在为 NSTask 设置环境变量时省略了一个重要的额外步骤。
为了使无密码的基于密钥的身份验证工作,有必要SSH_AUTH_SOCK从用户的环境中获取变量并将其包含在 NSTask 的环境中
因此,例如在设置环境变量时;

NSTask *task;
NSDictionary *environmentDict = [[NSProcessInfo processInfo] environment];
// Environment variables needed for password based authentication 
NSMutableDictionary *env = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                         @"NONE", @"DISPLAY",                           askPassPath, @"SSH_ASKPASS",
                         userName,@"AUTH_USERNAME",
                         hostName,@"AUTH_HOSTNAME",
                         nil];

// Environment variable needed for key based authentication
[env setObject:[environmentDict objectForKey:@"SSH_AUTH_SOCK"] forKey:@"SSH_AUTH_SOCK"];

// Setting the task's environment
[task setEnvironment:env];

然而,OP indragie评论:

我之前尝试过这个,但是因为它是用 XCode 调用的,SSH_AUTH_SOCKenv var。没有被传递给它。
从 Finder 打开应用程序可以解决此问题



作为askPassPath Askpass 可执行文件的路径,它包含在应用程序的主包中。(为此,在 xcode 中的“Products”下找到可执行文件,然后将其拖到主应用程序目标上的“Copy Bundle Resources”中。)

// Get the path of the Askpass program, which is
// setup to be included as part of the main application bundle
NSString *askPassPath = [NSBundle pathForResource:@"Askpass"
              ofType:@"" 
              inDirectory:[[NSBundle mainBundle] bundlePath]];
于 2011-06-03T07:16:19.337 回答