Там хорошие причины для изменения имени процесса. Программное обеспечение 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;
}
Edit: Это сложная и запутанная проблема.
На OS X нет setproctitle (3). Нужно написать в массив argv (уродливый и немного опасно, потому что можно переписать некоторые переменные среды фиктивным материалом). Правильно работает, он работает очень хорошо.
Кроме того, у Apple есть приложение ActivityMonitor, что-то вроде диспетчера задач под Windows. Приведенный выше код манипулирует ActivityMonitor, но эта манипуляция, похоже, не поощряется Apple (отсюда и использование недокументированных функций).
Важно: ps и ActivityMonitor не отображают ту же информацию.
Также важно: ActivityMonitor недоступен, если у вас нет графического интерфейса. Это может произойти, если вы подключились к удаленному ящику Apple, и никому не удалось войти в систему по графическому интерфейсу. К сожалению, есть ошибка Apple IMO. Просто запрос, если есть GUI, отправляет раздражающее предупреждающее сообщение в stderr.
Резюме: Если вам нужно изменить ActivityMonitor, используйте приведенный выше код. Если у вас есть ситуации с графическим интерфейсом и не нравятся предупреждения на stderr, временно перенаправляйте stderr на/dev/null во время вызова SetProcessName
. Если вам нужно изменить информацию о ps, напишите в argv.
@ Alex Brown (кто редактировал теги): Я намеренно установил тег для этого вопроса на «Mac» вместо «posix», потому что POSIXy-пути, которые я нашел для этого, не сработали для меня ('argv [0]' и 'setproctitle()'). –