我正在尝试更改我的进程名称,因为它在运行时显示在ps
和Activity Monitor
中。我发现有几个注意事项没有可移植的方法(我不关心)。
这是我尝试过的。这些方法都不适合我。
argv[0]
(似乎是在某些Unix系统上运行的方式)[[NSProcessInfo processInfo] setProcessName:@"someName"]
setprogname
(调用getprogname
会返回我设置的名称,但这无关紧要)我还读到了一个名为setproctitle
的函数,如果它可用,应该在stdlib.h
中定义,但它不存在。
必须有办法实现这一目标,因为QTKitServer-- QuickTime Player X的无面解码器 - 在其进程名称中具有相应的QuickTime Player的PID。
有没有人知道如何做到这一点?我非常喜欢使用Core Foundation或POSIXy方法来实现Objective-C方法。
谢谢,
马
编辑:如果它有任何相关性,我使用的是Mac OS X 10.6.5和Xcode 3.2.5
答案 0 :(得分:11)
有充分的理由更改流程名称。 Java软件应该更改进程名称,因为在运行不同的java工具时,我想查看哪个java进程适用于哪个工具。
Chromium做到了:http://src.chromium.org/viewvc/chrome/trunk/src/base/mac/mac_util.mm。
Node.js使用相同的代码来实现Process.title = 'newtitle'
:https://github.com/joyent/node/blob/master/src/platform_darwin_proctitle.cc
注意:如果有人su
向其他未登录的用户执行此操作,则会失败:https://github.com/joyent/node/issues/1727
这里的源代码完全是复杂的荣耀。顺便说一下,有人告诉我它也适用于Mac OS X Lion,并且也失败了su
。
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
void SetProcessName(CFStringRef process_name) {
if (!process_name || CFStringGetLength(process_name) == 0) {
NOTREACHED() << "SetProcessName given bad name.";
return;
}
if (![NSThread isMainThread]) {
NOTREACHED() << "Should only set process name from main thread.";
return;
}
// Warning: here be dragons! This is SPI reverse-engineered from WebKit's
// plugin host, and could break at any time (although realistically it's only
// likely to break in a new major release).
// When 10.7 is available, check that this still works, and update this
// comment for 10.8.
// Private CFType used in these LaunchServices calls.
typedef CFTypeRef PrivateLSASN;
typedef PrivateLSASN (*LSGetCurrentApplicationASNType)();
typedef OSStatus (*LSSetApplicationInformationItemType)(int, PrivateLSASN,
CFStringRef,
CFStringRef,
CFDictionaryRef*);
static LSGetCurrentApplicationASNType ls_get_current_application_asn_func =
NULL;
static LSSetApplicationInformationItemType
ls_set_application_information_item_func = NULL;
static CFStringRef ls_display_name_key = NULL;
static bool did_symbol_lookup = false;
if (!did_symbol_lookup) {
did_symbol_lookup = true;
CFBundleRef launch_services_bundle =
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
if (!launch_services_bundle) {
LOG(ERROR) << "Failed to look up LaunchServices bundle";
return;
}
ls_get_current_application_asn_func =
reinterpret_cast<LSGetCurrentApplicationASNType>(
CFBundleGetFunctionPointerForName(
launch_services_bundle, CFSTR("_LSGetCurrentApplicationASN")));
if (!ls_get_current_application_asn_func)
LOG(ERROR) << "Could not find _LSGetCurrentApplicationASN";
ls_set_application_information_item_func =
reinterpret_cast<LSSetApplicationInformationItemType>(
CFBundleGetFunctionPointerForName(
launch_services_bundle,
CFSTR("_LSSetApplicationInformationItem")));
if (!ls_set_application_information_item_func)
LOG(ERROR) << "Could not find _LSSetApplicationInformationItem";
CFStringRef* key_pointer = reinterpret_cast<CFStringRef*>(
CFBundleGetDataPointerForName(launch_services_bundle,
CFSTR("_kLSDisplayNameKey")));
ls_display_name_key = key_pointer ? *key_pointer : NULL;
if (!ls_display_name_key)
LOG(ERROR) << "Could not find _kLSDisplayNameKey";
// Internally, this call relies on the Mach ports that are started up by the
// Carbon Process Manager. In debug builds this usually happens due to how
// the logging layers are started up; but in release, it isn't started in as
// much of a defined order. So if the symbols had to be loaded, go ahead
// and force a call to make sure the manager has been initialized and hence
// the ports are opened.
ProcessSerialNumber psn;
GetCurrentProcess(&psn);
}
if (!ls_get_current_application_asn_func ||
!ls_set_application_information_item_func ||
!ls_display_name_key) {
return;
}
PrivateLSASN asn = ls_get_current_application_asn_func();
// Constant used by WebKit; what exactly it means is unknown.
const int magic_session_constant = -2;
OSErr err =
ls_set_application_information_item_func(magic_session_constant, asn,
ls_display_name_key,
process_name,
NULL /* optional out param */);
LOG_IF(ERROR, err) << "Call to set process name failed, err " << err;
}
编辑:这是一个复杂且令人困惑的问题。
在OS X上没有setproctitle(3)。一个人必须写入argv数组(丑陋 并且有点危险,因为有可能用伪造的东西覆盖一些环境变量)。做得对,它的效果非常好。
此外,Apple拥有ActivityMonitor应用程序,类似于Windows下的任务管理器。上面的代码操纵ActivityMonitor,但Apple似乎并不鼓励这种操作(因此使用了未记录的函数)。
重要提示:ps和ActivityMonitor不会显示相同的信息。
同样重要的是:如果您没有GUI,则ActivityMonitor不可用。如果您进入远程Apple盒并且没有人通过GUI登录,则会发生这种情况。可悲的是,Apple IMO存在一个错误。只查询是否有GUI向stderr发送恼人的警告消息。
摘要:如果您需要更改ActivityMonitor,请使用上面的代码。如果您没有GUI,并且不喜欢stderr上的警告,请在调用SetProcessName
期间将stderr临时重定向到/ dev / null。如果您需要更改ps信息,请写入argv。
答案 1 :(得分:3)
您可以使用macOS附带的g
工具,至少从10.6开始到现在(10.13.2):
外壳:
lsappinfo
C ++:
lsappinfo setinfo <PID> --name <NAME>