Запуск приложения из учетной записи root - PullRequest
3 голосов
/ 01 декабря 2010

Я разрабатываю приложение с графическим интерфейсом Cocoa, в котором есть демон Objective-C. Демон запускается LaunchDaemon, графический интерфейс запускается с использованием loginItems для каждого пользователя.

При развертывании обновления мне нужно обновить простой демон, а также обновить графический интерфейс. Я хотел бы иметь возможность выйти из графического интерфейса, заменить приложение и перезапустить его на каждой учетной записи пользователя, на которой он в данный момент работает. Я хотел бы сделать все это из демона, который, конечно, работает от имени пользователя root.

Как я могу: 1) В качестве пользователя root выйдите из системы, а затем повторно запустите приложение в интерфейсе другого пользователя? 2) В качестве пользователя root выйдите из системы, а затем повторно запустите определенный элемент loginItem для каждого пользователя, вошедшего в систему в данный момент?

Я попытался выполнить поиск, и существует множество дискуссий, включая этот похожий вопрос , но, похоже, не существует работающего решения.

Любая помощь очень ценится.

Ответы [ 3 ]

3 голосов
/ 01 декабря 2010

Я считаю, что NSDistributedNotificationCenter должен работать для этого. Обратите внимание, что использование NSDistributedNotificationCenter для взаимодействия между процессами в разных учетных записях пользователей само по себе не требует привилегий root.

Чтобы помочь в координации между учетными записями пользователей, может помочь определить, какие экземпляры приложения с графическим интерфейсом и демон в настоящее время активны и находятся под контролем, а какие - пассивны. Вы можете использовать уведомления NSWorkspace (NSWorkspaceSessionDidBecomeActiveNotification, NSWorkspaceSessionDidResignActiveNotification), чтобы определить, когда пользователь переключается между учетными записями пользователей и т. Д., И чтобы ваши экземпляры устанавливали себя соответствующим образом.

Допустим, у вашего GUI-приложения и демона есть экземпляры, запущенные в 3 разных учетных записях пользователей. Если в активной учетной записи пользователя вы хотите начать процесс обновления, вы можете использовать NSDistributedNotificationCenter, чтобы, например, легко сказать всем остальным экземплярам о немедленном завершении работы. Для этого вы должны определить что-то вроде следующего.

В файле .h объявите имена ваших различных уведомлений:

extern NSString * const MDShouldTerminateImmediatelyNotification;

в (реализации) файле реализации, создайте имена и настройте класс так, чтобы он интересовался распределенным уведомлением с этим именем и т. Д.: * 10101 *

NSString * const MDShouldTerminateImmediatelyNotification = @"MDShouldTerminateImmediately";


- (id)init {
   if (self = [super init]) {
       [[NSDistributedNotificationCenter defaultCenter]
       addObserver:self
       selector:@selector(shouldTerminateImmediately:)
       name:MDShouldTerminateImmediatelyNotification
       object:nil];
   }
   return self;
}

- (void)dealloc {
   [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
   [super dealloc];
}

- (void)shouldTerminateImmediately:(NSNotification *)notification {
   if (ourInstanceIsInControl == NO) {
     [NSApp terminate:nil];
    }
}

В классе, который будет инициировать процесс обновления, вы должны сделать что-то вроде этого, чтобы отправить уведомление:

- (void)beginUpdate {
   [[NSDistributedNotificationCenter defaultCenter]
    postNotificationName:MDShouldTerminateImmediatelyNotification
       object:[self description] // or just nil
       userInfo:nil
       options:NSNotificationDeliverImmediately | NSNotificationPostToAllSessions];
    // continue

}

Это должно быть, по крайней мере, начало работы, я думаю ....

На самом деле, если вы говорите об одном экземпляре демона, работающем от имени пользователя root, который выполняет все функции во всех учетных записях пользователей, вам может потребоваться включить эту часть в процесс типа агента Launchd (фоновый процесс, запускаемый на уровне пользователя, каждая учетная запись пользователя будет иметь свой собственный экземпляр).

Для получения дополнительной информации:

Техническое примечание TN2083 Демоны и агенты

Сеансы рутирования и входа в систему

Создание запускаемых демонов и агентов

3 голосов
/ 17 декабря 2010

Поэтому я использовал запрос в службу поддержки Apple, чтобы получить лучший ответ в сочетании с некоторыми онлайн-исследованиями.

Основной план атаки состоял в том, чтобы каждый экземпляр графического интерфейса перезапускался сам, когда демон сказал ему об этом.

Во-первых, у меня был демон, заменяющий пакет графического интерфейса пользователя (папка .app).Вы можете сделать это, пока приложение работает потрясающе.Вот где поддержка Apple помогла.Я все еще поражаюсь, что приложение может быть заменено во время его работы, но мне сказали, что это будет нормально.

Затем у меня был демон, запускающий DistributedNotification для GUI с сообщением для перезапуска.сам.Чтобы заставить графический интерфейс реагировать правильно, я создал класс рестартера, который будет захватывать его собственный путь pid и bundle, затем я создал сценарий оболочки в памяти, который убил pid, подождал 10 секунд, а затем выполнил оболочку «open bundlepath.app» иперезапуск.

Я использовал NSTask для вызова сценария оболочки "в памяти", который на самом деле был просто @ "kill% @; sleep 10; open% @", pid, bundlePath ....

Работает потрясающе!

Спасибо за ваши предложения!

0 голосов
/ 01 декабря 2010

Ищите «службы авторизации» в документации Apple.

...