Запуск / остановка запуска агента для всех пользователей с сеансами графического интерфейса - PullRequest
11 голосов
/ 10 июля 2009

Мне нужно иметь возможность запускать / останавливать агента графического интерфейса для сеанса из демона корневого уровня.

Подобные вопросы обсуждаются здесь , здесь и здесь .

То, что я хочу сделать, это в основном

for num in `ps ax | grep [s]bin/launchd | cut -c 1-5`; 
do 
    if [ $num -ne 1 ]; 
    then 
        sudo launchctl bsexec $num launchctl (un)load -S Aqua /Library/LaunchAgents/com.mycompany.mydaemon.plist; 
    fi; 
done

, но это запускает / останавливает только один экземпляр и запускается от имени пользователя root в текущем сеансе графического интерфейса. Если я оставлю sudo там, я получу

task_for_pid() (os/kern) failure
Couldn't switch to new bootstrap port: (ipc/send) invalid port right

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

Я также пытался возиться с su - <user> ... и sudo -u <user> ..., но и там мне не повезло (как многие люди обсуждали в приведенных выше статьях и в других местах).

У кого-нибудь есть мысли?

EDIT: Я попытался сделать это с помощью инструмента-обертки, как предложено ниже Грэмом Ли, но я получаю следующую ошибку:

launch_msg(): Socket is not connected

Это команда, оболочка и скрипт командной строки, которые я использую (501 - это идентификатор пользователя, а 63093 - идентификатор запуска для другого пользователя, вошедшего в систему):

Командная строка:

sudo launchctl bsexec 63093 /path/TestSetUIDAndExecuteTool 501 /path/LoadBillingDialogAgent

Wrapper:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

  if (argc != 3) {
    NSLog(@"Tool called with improper arguments");
    return -1;
  }

  int uid = [[NSString stringWithUTF8String:argv[1]] intValue];
  // TODO: REMOVE
  NSLog(@"Setting uid to |%i|", uid);

  setuid(uid);
  // TODO: REMOVE
  char *command = (char *)argv[2];
  NSLog(@"Executing command |%s|", command);
  system(command);

  [pool drain];
  return 0;
}

Сценарий:

/bin/launchctl load -S Aqua /Library/LaunchAgents/com.company.agent.plist

Ответы [ 4 ]

6 голосов
/ 10 июля 2009

Использование launchctl bsexec правильно, но вам нужно запустить инструмент-обертку, который сбрасывает UID целевому пользователю перед запуском «реального» исполняемого файла агента. О, и, вероятно, лучше поискать процессы loginwindow, так как они являются лидерами сеансов входа в систему (хотя launchd, скорее всего, тоже будет работать).

4 голосов
/ 28 мая 2011

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

Используя Dock.app в качестве донора pid и некоторую магию sudo:

ps aux | grep Dock.app | grep -v grep | awk '{system("sudo launchctl bsexec "$2" sudo -u "$1" launchctl load -S Aqua /Library/LaunchAgents/com.my.agent.plist")}'

возможно запустить агент во всех запущенных сессиях.

Не аккуратно, но работает.

Обновление: не будет работать на 10.7. Да, агент будет запущен, но, как я вижу из тестов, не в том контексте.

3 голосов
/ 21 июля 2015

На основании обсуждений здесь и этого сценария я не думал, что необходим инструмент-обертка. Эти два скрипта bash могут помочь и другим.

Агенты выгрузки

#!/bin/bash
for id in `ps aux | grep -v grep | grep MyAgent | awk {'print $2'}`
do
    launchctl bsexec $id launchctl unload /Library/LaunchAgents/myAgent.plist
done

Замените 'MyAgent' на имя вашего агента запуска.

Агенты нагрузки

#!/bin/bash
for pid_uid in $(ps -axo pid,uid,args | grep -i "[l]oginwindow.app" | awk '{print $1 "," $2}'); do

    pid=$(echo $pid_uid | cut -d, -f1)
    uid=$(echo $pid_uid | cut -d, -f2)

    launchctl bsexec "$pid" chroot -u "$uid" / launchctl load /Library/LaunchAgents/myAgent.plist
done

Вызванный из корневого демона, он будет загружать и выгружать Launch Agent, указанный в myAgent.plist для всех вошедших в систему пользователей.

Обратите внимание, что из-за 'rootless' в OS X El Capitan (10.11) использование bsexec может больше не работать, но до 10.10 это должно быть хорошо.

1 голос
/ 02 сентября 2014

У меня была такая же проблема. Чтобы решить эту проблему, используйте pid "under" launchd, pid процесса, который launchd запущен.

pid, который вы указываете на 'launchctl bsexec', используется для поиска правильного загрузчика. Если вы используете pid для launchd (из пользовательского контекста), тогда вы работаете в корневой загрузке launchd. Если вы используете pe. Finder или Dock PID пользователя, вы можете работать в этом "на пользователя" начальной загрузки

...