控制台和Cocoa应用程序中的$PATH不同?

3

好的,我一定错过了什么非常简单的东西,下面是内容:

  • 如果我在终端中输入echo $PATH,我得到的是/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/drkameleon,这是正确的。

  • 现在,如果我运行一个NSTask并尝试执行一个简单的bash脚本(/usr/bin/env bash myscript.sh)来输出$PATH,它打印出的是/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin

(我甚至已经尝试使用getenv,或者打印整个[[NSProcessInfo processInfo] environment]字典,但是PATH变量简直是......错误的)

发生了什么?我怎样才能访问在终端中看到的真正的$PATH


1
如果您尝试使用 bash -l 使其运行像登录 shell,会发生什么?$PATH 的内容通常在 .bashrc 文件中被修改。 - Lev Landau
2
请查看 https://dev59.com/n3RC5IYBdhLWcg3wK92V 上的答案,您会在那里找到您的答案。 - Mehul Thakkar
@LevLandau 我几乎是在你发表评论的同时发现了它。非常感谢! :-) - Dr.Kameleon
@MehulThakkar 是的,就是这样。谢谢! :-) - Dr.Kameleon
1个回答

5
当通过NSTask执行命令时,不会启动您使用的bash、zshell或其他类型的shell。因此,当在终端中回显环境变量时,PATH(和其他环境变量)与您的环境变量不同。
原因:NSTask使用fork()和exec()进行命令执行。
我认为,有两种可能的解决方案。
1. 您可以通过NSTask的setEnvironment: 方法设置所需的PATH。
以下是一些未经测试的示例代码,应该能解决问题:
NSTask *task = //Configure your task
NSDictionary* env = [task environment];
NSString* currentPATH = env["PATH"];
NSString* yourPathExtension = @"/your/path";
env["PATH"] = (currentPATH != nil) ? [yourPath stringByAppendingFormat:@":%@", currentPATH] : yourPathExtension;
[task setEnvironment:env];

这将在NSTask中当前的PATH后添加:<old-PATH>

2. 您可以在NSTask内启动/bin/bash

task setLaunchPath:@"/bin/bash"];
NSArray *args = [NSArray arrayWithObjects:@"-l",
                 @"-c",
                 @"<your command here>",
                 nil];
[task setArguments: args];

这个任务将使用通过~/.bashrc等配置的PATH启动/bin/bash,并在bash中执行命令。

优点:您的命令具有bash的所有常规环境变量。

缺点:您依赖用户的PATH变量,可能与您的变量非常不同,这可能导致意外行为。

哪种解决方案最适合您取决于您的使用情况。在您提供的示例中,这两种方法都应该可以正常工作。

通常情况下,根据NSTask和NSProcessInfo文档,环境变量等于从中启动应用程序的进程的变量。因此,当从bash启动应用程序时,您可能会解决问题。


我已经解决了这个问题。但是这个答案非常棒,是处理相同问题的人们的很好的参考。非常感谢! :-) - Dr.Kameleon
NSTask现在可能使用posix_spawn()而不是fork()/exec()。 - Greg Parker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接