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

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

Например, у меня есть два пользователя, foo и bar. Оба вошли в систему, но текущий интерактивный пользователь — foo. Я хотел бы запустить Calculator.app как пользовательскую «панель», чтобы при быстром переключении пользователя на панель я обнаружил, что окно калькулятора открыто в сеансе панели.

Вот что я пробовал, что не работает:

sudo -u bar /Applications/Calculator.app/Contents/MacOS/Calculator

Это запускает Calculator.app как панель, но окно открывается в графическом сеансе foo.

sudo -u bar osascript -e "tell application \"Calculator\" to activate"

Тот же эффект.

sudo -u bar open "/Applications/Calculator.app"

Запускает калькулятор как foo, а не как bar.

launchctl asuser [uid of bar] [any of the above commands]

Тот же эффект.

Есть ли способ сделать это? Я готов рассматривать всевозможные возможные решения, включая сценарии bash, AppleScript, написание программы Core Foundation или Cocoa и так далее. В моей ситуации любая программа или скрипт могли выполняться от имени любого пользователя, включая root.

Примечание. Я знаю, что можно использовать удаленные события Apple, но я не могу использовать это, поскольку в ситуации, в которой я пытаюсь это сделать, у меня нет гарантии, что «Удаленные события Apple» будут включены в настройках общего доступа.

Любая помощь будет принята с благодарностью!

Вы пробовали openкоманду, используя SSH?
Как ни странно, значок приложения в доке появляется в сеансе foo, но окно приложения появляется в баре. Так что это, кажется, не работает, но хорошее предложение. К сожалению, нет гарантии, что безопасный вход будет включен в ситуации, когда мне это нужно, то есть для установщика.
Я думаю, что одна часть этой головоломки может включать аргумент командной строки -psn, который ОС добавляет в некоторых ситуациях. Я сталкивался с этим в прошлом, когда работал над переносом кода на OS X. См. этот вопрос и документацию Apple, на которую он ссылается.
по состоянию на 10.10, наконец, упомянутый ниже bsexec работает отлично

Ответы (6)

Ни один из приведенных выше ответов bsexec не работает на El Capitan (10.11) из-за закрытия портов защитой системной интеграции (SIP). «launchctl asuser» работает, но требует запуска от имени пользователя root. Приведенная ниже команда работает на El Capitan (и самых последних ОС):

sudo launchctl asuser 501 open /Applications/Calculator.app

Обратите внимание, что 501 — это идентификатор другого моего пользователя.

Это мой результат: bruno.medeiros@brunojcm-macbook:~ $ sudo launchctl asuser 501 open /Applications/Firefox.app, и получилLSOpenURLsWithRole() failed with error -600 for the file /Applications/Firefox.app
@BrunoJCM, вы уверены, что 501 — это идентификационный код пользователя, с которым вы хотите его открыть? Будет немного понятнее, если команда будет выглядеть примерно так: sudo launchctl asuser $(id -u <user_id_name>) <app>. Тем не менее, я получаю другую ошибку, posix_spawn(): 13: Permission deniedдаже если я работаю с тем же идентификатором пользователя, с которым я вошел в систему (и владеет сеансом) дляsudo launchctl asuser $(id -u mtylutki) /Applications/Calculator.app

То, чего вы хотите достичь, возможно, но сложно. Вам необходимо запустить приложение в рамках соответствующего пользовательского сеанса. Из соображений безопасности пересечение границы сеанса пользователя затруднено.

Вам нужен процесс, уже запущенный в сеансе другого пользователя, чтобы прослушать ваш запрос и запустить приложение от вашего имени.

bsexec запуска

К счастью, в последних версиях launchdесть такая возможность; хотя инженеры Apple не рекомендовали его повсеместное использование. Используйте bsexecпараметр в launchctl , чтобы выбрать соответствующий сеанс пользователя:

 bslist [PID | ..] [-j]
          This prints out Mach bootstrap services and their respective states. While the namespace
          appears flat, it is in fact hierarchical, thus allowing for certain services to be only avail-
          able to a subset of processes. The three states a service can be in are active ("A"), inactive
          ("I") and on-demand ("D").

          If [PID] is specified, print the Mach bootstrap services available to that PID. If [..] is
          specified, print the Mach bootstrap services available in the parent of the current bootstrap.
          Note that in Mac OS X v10.6, the per-user Mach bootstrap namespace is flat, so you will only
          see a different set of services in a per-user bootstrap if you are in an explicitly-created
          bootstrap subset.

          If [-j] is specified, each service name will be followed by the name of the job which regis-
          tered it.

 bsexec PID command [args]
          This executes the given command in the same Mach bootstrap namespace hierachy as the given
          PID.

 bstree [-j]
          This prints a hierarchical view of the entire Mach bootstrap tree. If [-j] is specified, each
          service name will be followed by the name of the job which registered it.  Requires root priv-
          ileges.

Рекомендуемый подход состоит в том, чтобы написать билет задания launchd и перезапустить Mac или попросить пользователя выйти из системы и снова войти в нее.

Причина проблем

Проблемы возникают из-за того, что приложение подключено к неправильному WindowServerпроцессу. Каждый пользовательский сеанс имеет отдельный WindowServer; этот процесс обрабатывает пользовательский интерфейс. Ваши более ранние методы передают право собственности на процесс правильному пользователю, но подключенному к вашему собственному процессу WindowServer.

Эта проблема упоминается в технической заметке о демонах и агентах от Apple.

Опыт

Я знаю это из личного опыта. Для Power Manager я написал, что pmuser существует в каждом пользовательском сеансе. pmuserслушает нашего демона и обрабатывает запуск и команды для каждого пользователя. Несмотря на то, что у нашего демона есть полномочия root, нам по-прежнему нужен процесс для каждого пользователя, чтобы надежно работать в пользовательских сеансах.

Не могли бы вы предоставить простой сценарий, такой как в ответе TJ, но который работает? Или это слишком сложно для такой вещи?
Правильное решение слишком сложно для короткого сценария. В идеале в сеансе целевого пользователя требуется отдельный процесс, подобный батуту. Вот что нам нужно было сделать для Power Manager: dssw.co.uk/powermanager Чего вы надеетесь достичь?
Надеясь добиться именно того, что написано в заголовке: запустить приложение с графическим интерфейсом в сеансе другого пользователя . «Бонусные баллы», если другому пользователю не нужно входить в систему или если он может войти в систему программно. В частности, я хочу несколько дисков Google. Это работает, если я просто вхожу в систему вручную, и это находится в разделе « Элементы входа » этого пользователя в Системных настройках. Процесс батута не принесет бонусных очков, но если это единственный способ, что именно инженеры Apple рекомендуют против него? Я думал, что это будет именно для того, чтобы делать такие простые хакерские скрипты! :П
@Cawas, пожалуйста, задайте это как новый вопрос и сосредоточьтесь на цели получения нескольких Google Дисков, а не на том, как этого можно достичь. Изменение фокуса поможет не помечать вопрос как дубликат.
Достаточно справедливо и сделано .

Поскольку, наконец, 10.10 предоставляет правильную реализацию «launchctl bsexec», которую вы можете использовать:

sudo /bin/launchctl bsexec PID chroot -u UID -g GID / open /Applications/TextWrangler.app

человек говорит

Это выполняет данную команду в контексте выполнения, максимально похожем на целевой PID.

Таким образом, в качестве параметра PID вы можете использовать pid соответствующего процесса входа в систему . UID — это идентификатор пользователя, которому принадлежит это окно входа в систему, а GID — это его основная группа.

Это отлично работает для любой команды и, конечно же, для заданий запуска (например, агентов запуска), например:

/bin/launchctl bsexec 104 chroot -u 501 -g 20 / /bin/launchctl load -S Aqua /Library/LaunchAgents/com.youragent.plist 2>&1
Не уверен, что это верно для других, но task_for_pid(): 0x5теперь я получаю сообщение об ошибке, когда я проверил правильность PID.

Вы можете использовать Finder в качестве хоста для получения необходимых разрешений osascript -e "tell application \"Finder\" to open (\"${app}\" as POSIX file as alias)". Таким образом, он будет запускаться через любой контекст GUI, запущенный Finder.

Это работает через ssh:

#!/bin/bash

PID=$(ps auxwww | egrep "^bar" |\
fgrep /System/Library/CoreServices/loginwindow.app/Contents/MacOS/loginwindow |\
awk '{print $2}')

sudo launchctl bsexec "$PID" open -a TextEdit

но если попробовать через Terminal.app, то он открывает TextEdit в графическом интерфейсе текущего пользователя.

Если вы не уверены, что sshон включен, возможно, вы можете временно включить его.

sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist

и отключить его снова, если это необходимо?

Иначе я в тупике.

Проверено 10.9.

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

Простой

sudo su name_of_user

затем выполнять команды в обычном режиме.

Команды будут выполняться bar, но все равно будут выполняться в fooграфическом сеансе .
Извините, да, я запутался в вопросе, не выполняется в графическом сеансе foo.