【问题标题】:Issue launching X11 app via NSTask通过 NSTask 启动 X11 应用程序的问题
【发布时间】:2013-03-17 00:29:38
【问题描述】:

我的应用使用 NSTask 执行 shell 脚本,其中一个脚本启动 X11 应用(特别是 meld)。

我原以为这会起作用:

#!/bin/bash
source ~/.profile                      # setup $PATH/etc
meld .

但它失败了:

gtk.icon_theme_get_default().append_search_path(meld.paths.icon_dir())
Traceback (most recent call last):
  File "/usr/local/bin/meld", line 132, in <module>
    gtk.icon_theme_get_default().append_search_path(meld.paths.icon_dir())
AttributeError: 'NoneType' object has no attribute 'append_search_path'

作为概念证明,我将脚本更改为这样,效果很好:

#!/usr/bin/ruby

exec 'osascript -e \'tell app "Terminal" to do script "meld ' + Dir.pwd + '" in front window\''

有没有人是什么导致了这个问题?这是我执行 shell 脚本的代码:

NSTask *task = [[NSTask alloc] init];
task.launchPath = self.scriptURL.path;
task.standardOutput = [NSPipe pipe];
task.currentDirectoryPath = workingDirectoryURL.path;

[task launch];

【问题讨论】:

    标签: objective-c macos unix pygtk


    【解决方案1】:

    更改您的脚本以喷出环境变量并将“工作”与“不工作”进行比较。

    在不同的执行模型中,shell 的初始化方式存在细微差别。几乎可以肯定,环境是问题的根源。

    【讨论】:

    • 谢谢!我需要这个:export DISPLAY=/tmp/launch-e6qXkg/org.macosforge.xquartz:0。但是,看起来每次重新启动时值都会发生变化,所以我需要进一步研究它......
    • X11 环境中应该有一些东西一旦启动就会喷出 DISPLAY 变量,因为它是动态设置的。 (我已经很久没有搞砸 w/X 了)。
    【解决方案2】:

    看看man launchctl

    launchctl submit ... -p /usr/local/bin/meld -- .

    已经启动了任务;这将为您设置某些环境变量,这些变量是每个用户会话的一部分。

    【讨论】:

      【解决方案3】:

      X11 应用使用 DISPLAY 环境变量了解显示服务器的地址。

      在 OS X 上,出于安全原因,DISPLAY 值是随机的,因此您无法对其进行硬编码,正如您所注意到的。相反,有一个 launchd 代理告诉 launchd 在启动进程时设置 DISPLAY。

      在launchd 和meld 之间的某个地方,DISPLAY 的值被丢弃或覆盖。你的工作是找出在哪里。

      1. 确保已启动的代理正在运行。运行 launchctl list 并查找 org.macosforge.xquartz.startx。由于meld 在 Terminal.app 中工作,这部分可能是正确的。
      2. 确保在您的应用程序中设置了显示。它应该列在[NSProcessInfo processInfo].environment
      3. 确保在您启动的 NSTask 中设置了 DISPLAY。尝试使用 NSTask 运行 /usr/bin/env,并确保 DISPLAY 出现在其输出中。
      4. 确保在您运行的脚本中设置了 DISPLAY。在采购〜/ .profile之前和之后尝试echo $DISPLAY。 (有时 .profile 本身会将 DISPLAY 覆盖为不正确的值,因为有时在其他操作系统上这样做是正确的。)

      编辑:这是我用来将 DISPLAY 从我的 GUI 应用程序复制到 shell 脚本的代码:

      NSTask *task = ...
      task.environment = [NSProcessInfo processInfo].environment;
      [task.launch];
      

      【讨论】:

      • 列表中的第 2 项是问题所在。我不得不手动将 ENV 从我的 GUI 应用程序复制到它正在启动的 shell 脚本中。也许这通常会自动完成,但我正在设置其他环境变量,这可能会踩到它。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-04
      • 2012-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多