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

15

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

Например, скажем, у меня есть два пользователя, 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» будут включены в настройках «Общий доступ».

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

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

Ответы:

7

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

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

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.

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

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

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

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

Опыт

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

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

Ни один из ответов 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
@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
Marcus
2

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

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

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

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

Таким образом, в качестве параметра PID вы можете использовать pid соответствующего процесса loginwindow . 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 верен.
Маркус
1

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

Атишай Джайн
источник
0

Это работает через 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 в GUI текущего пользователя.

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

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

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

В противном случае я в тупике.

Проверено на 10.9.

Ти Джей Луома
источник
Он действительно открывает приложение, как вы говорите, но открывает его в текущем сеансе пользователя, а не в сеансе другого пользователя, как было предложено.
Cregox
-1

просто

sudo su name_of_user

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

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