2011-06-03 165 views
8

在我的Cocoa应用程序中,我试图使用NSTask来运行一些基本的Git命令。每当我运行需要的权限(SSH密钥)命令来访问远程(例如git pushgit pull)时,出现以下错误:NSTask和Git - 权限问题

Permission denied (publickey). The remote end hung up unexpectedly

运行相同的命令,从终端工作得很好,所以我m认为这可能是一个问题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每个会话都有变化,所以我不能对它进行硬编码。我如何动态生成/检索这个变量?

+1

尝试另一种方式,在命令行中使用'env -i'并查看在需要加载之前需要添加多少。 – Dustin 2011-06-03 04:25:25

+0

得到了一点进一步感谢您的提示,阅读我编辑过的文章:) – indragie 2011-06-03 04:49:49

回答

4

你可以尝试,并按照教程 “Wrapping rsync or SSH in an NSTask”(从Ira),这确实提到SSH_AUTH_SOCK变量:

Since writing this post I've realised that I omitted an important additional step in setting up the environment variables for the NSTask.
In order to make passwordless key-based authentication work it's necessary to grab the SSH_AUTH_SOCK variable from the user's environment and include this in the NSTask's environment.
So, when setting environment variables for example;

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评论:

I had tried this earlier but since it was being invoked with XCode, the SSH_AUTH_SOCK env var. wasn't being passed to it.
Opening the app from Finder corrects this issue.



With askPassPath being the path for the Askpass executable, which is included as part of the application’s main bundle. (In order to do this, find the executable under “Products” in xcode, and then drag it into “Copy Bundle Resources” on the main application’s target.)

// 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]]; 
+1

我曾尝试过这一点,但因为它是与Xcode调用SSH_AUTH_SOCK环境变种。没有被传递给它。从Finder打开应用程序可以解决这个问题。谢谢! – indragie 2011-06-03 13:35:26

+0

@indragie:很好。我已将您的评论纳入答案中,以获得更多的知名度。 – VonC 2011-06-03 14:59:11

+0

@VonC你能告诉我askPassPath是什么变量吗? – 2013-05-16 21:53:17