首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Mac中的top命令被截断

Mac中的top命令被截断
EN

Stack Overflow用户
提问于 2013-01-16 21:37:28
回答 1查看 1.4K关注 0票数 2

我试图使用MacOS X中的"top“命令来确定哪个应用程序正在使用这些资源。当我这么做时:

顶级-stats "pid,命令“

如果进程名太长,命令列将被截断。

如果您查看活动监视器,进程名称将正确显示(全名)+图标。我的问题是:

  1. 如何获得完整的进程名称?
  2. 有时应用图标显示在进程名旁边,是否有使用objective来做类似的事情?我应该简单地导航到应用程序内容文件夹并抓取icns图像吗?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-01-16 21:56:00

首先,如果您试图以编程方式获取数据,那么驱动top几乎肯定不是您想要做的事情。

但是,要回答你的直接问题:

如何获得完整的进程名称?

无法控制命令的截断。您可以使用-ncols参数来设置非交互式输出的输出宽度,但如果top想要的话,这并不能阻止它截断输出。

有时应用图标显示在进程名旁边,是否有使用objective来做类似的事情?我应该简单地导航到应用程序内容文件夹并抓取icns图像吗?

不是的。您将如何处理具有多个.icns文件的应用程序,例如文档图标?(例如,用iTunes试试。如果选择第一个.icns,就会得到AIFF文档图标;如果选择最后一个,则会得到内部使用最近电视节目的图标。)

正确的方法是为应用程序获取NSBundle,然后执行如下操作:

代码语言:javascript
运行
复制
NSString *iconFile = [bundle objectForInfoDictionaryKey:@"CFBundleIconFile"];
if (iconFile) {
    NSString *iconPath = [bundle pathForResource:iconFile ofType:@"icns"];
    // load and display the icon
}

那么,如果不是通过驱动top,您想要如何做到这一点呢?

好吧,你要求的其实不是一个明确的东西。OS有四个不同的任务/进程/程序/应用程序的概念,它们不对应于1-1,如果您想要编写两个使用不同概念的程序的混搭(例如,在BSD进程中使用top处理,而活动监视器在OS应用程序中处理),这会使生活变得困难。

如果您真正想要的是top使用的相同的列表,那么它是开源的,所以您可以使用读一读并做同样的事情。

但是获取BSD进程列表的最简单方法可能是libproc.h中的接口,特别是proc_listallpidsproc_pidinfo。例如:

代码语言:javascript
运行
复制
int dump_proc_names() {
  int buf[16384];
  int count = proc_listallpids(&buf, 16384*sizeof(int));
  for (int i = 0; i != count; ++i) {
    int pid = buf[i];
    char path[MAXPATHLEN+1] = {0};
    int ret = proc_pidinfo(pid, PROC_PIDPATHINFO, 0,
                           &path, sizeof(path));
    if (ret < 0) {
      printf("%d: error %s (%d)\n", pid, strerror(errno), errno);
    } else {
      printf("%d: %s\n", pid, path);
    }
  }
}

显然,在实际代码中,您需要动态分配缓冲区,返回值,而不是仅仅转储它们,获得的不仅仅是路径,等等。但这足以给您提供基本的想法。(当您要获取其他信息时,请注意,如果您要求任何结构,除非您有权查看该结构的每个成员,否则您将得到EPERM错误。所以,如果你只想要PROC_PIDTASKALLINFO,就不要去问PROC_PIDT_SHORTBSDINFO

无论如何,由于这个API处理的是BSD进程(和Mach任务),而不是应用程序,所以它不会直接帮助您获得您想要提供活动监视器样式特性的NSBundle

没有办法做到这一点是完全正确的,但您可能可以逃脱这样的事情:

代码语言:javascript
运行
复制
NSString *path = processPath;
while (path && ![path isEqualTo:@"/"]) {
    NSBundle *bundle = [NSBundle bundleWithPath:path];
    if (bundle) {
        if ([bundle executablePath != processPath]) return nil;
        return bundle;
    }
    path = [path stringByDeletingLastPathComponent];
}

要做到这一点,可能有其他的方法,每种方法都有不同的权衡。例如,使用-[NSWorkspace runningApplications]将结果存储在字典中,将包可执行路径映射到包,并使用它查找每个进程,但它似乎只对当前用户(可能在当前会话中)拥有的应用程序有用。另一方面,枚举系统上的所有包,或者询问Spotlight或类似的程序,可能太慢了,但如果在第一次运行时缓存它们,就会过时。

替代libproc的另一个选项是使用libtop

不幸的是,苹果并没有提供这种服务。他们确实有一个libtop实现,用于他们的top工具,但它实际上是嵌入到top源代码中的,不能从外部获得。您可以找到源代码(在上面的链接中),并以top本身的方式将其嵌入到程序中。

或者,GNU和BSD进程实用程序都有Mac端口(尽管知道在Homebrew/MacPorts/Google中使用哪个名称并不总是容易的…),这样你就可以建造其中之一并使用它。

但是,除非您试图编写跨平台软件(或者已经知道如何为linux或FreeBSD或其他什么编写此代码),否则我认为这只会增加额外的复杂性。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14368319

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档