Wie starte ich eine GUI-Anwendung in einer grafischen Sitzung eines anderen Benutzers?

15

Ich versuche herauszufinden, wie eine GUI-Anwendung als ein anderer Benutzer gestartet wird, der interaktiv in der grafischen Sitzung dieses Benutzers angemeldet ist.

Angenommen, ich habe zwei Benutzer, foo und bar. Beide sind angemeldet, aber der aktuelle interaktive Benutzer ist foo. Ich möchte Calculator.app als Benutzer "bar" starten, damit das Fenster "Calculator" in der Sitzung der Leiste geöffnet ist, wenn der Benutzer schnell zur Leiste wechselt.

Folgendes habe ich versucht, was nicht funktioniert:

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

Dadurch wird Calculator.app als Leiste gestartet, das Fenster wird jedoch in der grafischen Sitzung von foo geöffnet.

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

Gleicher Effekt.

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

Startet den Rechner als foo, nicht als bar.

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

Gleicher Effekt.

Gibt es eine Möglichkeit, dies zu erreichen? Ich bin bereit, alle möglichen Lösungen in Betracht zu ziehen, einschließlich Bash-Scripting, AppleScript, Schreiben eines Core Foundation- oder Cocoa-Programms und so weiter. In meiner Situation könnte jedes Programm oder Skript als jeder Benutzer ausgeführt werden, einschließlich root.

Hinweis: Ich bin mir bewusst, dass es möglich ist, Remote-Apple-Ereignisse zu verwenden, aber ich kann dies nicht verwenden, da ich in der Situation, in der ich dies versuche, keine Garantie dafür habe, dass "Remote-Apple-Ereignisse" in den Freigabeeinstellungen aktiviert werden.

Jede Hilfe wäre sehr dankbar!

GuyGizmo
quelle
1
Haben Sie den openBefehl mit ausprobiert SSH?
Matthieu Riegler
Seltsamerweise wird das Dock-Symbol der App in der Sitzung von foo angezeigt, das App-Fenster jedoch in der Leiste. Das scheint also nicht zu funktionieren, aber ein guter Vorschlag. Leider gibt es keine Garantie dafür, dass die sichere Anmeldung in der von mir benötigten Situation für einen Installateur aktiviert ist.
GuyGizmo
Ich denke, ein Teil dieses Puzzles könnte das Befehlszeilenargument -psn beinhalten, das das Betriebssystem in einigen Situationen hinzufügt. Ich habe dies in der Vergangenheit festgestellt, als ich daran arbeitete, Code auf OS X zu portieren. Siehe diese Frage und die Apple-Dokumentation, auf die sie verweist.
Ashley
ab 10.10 funktioniert der unten erwähnte bsexec einwandfrei
hofi

Antworten:

7

Was Sie erreichen wollen, ist möglich, aber schwierig. Sie müssen die Anwendung in der entsprechenden Benutzersitzung starten. Aus Sicherheitsgründen ist das Überschreiten der Benutzersitzung schwierig.

Sie benötigen einen Prozess, der bereits in der Sitzung des anderen Benutzers ausgeführt wird, um Ihre Anforderung abzuhören und die Anwendung in Ihrem Namen zu starten.

launchd's bsexec

Zum Glück launchdverfügen neuere Versionen über diese Fähigkeit. Obwohl Apple-Ingenieure die allgemeine Verwendung nicht empfohlen haben. Verwenden Sie die bsexecOption in launchctl , um die entsprechende Benutzersitzung auszuwählen :

 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.

Der empfohlene Ansatz besteht darin, ein Start-Job-Ticket zu erstellen und den Mac neu zu starten - oder den Benutzer aufzufordern, sich abzumelden und wieder anzumelden.

Ursache der Probleme

Die Probleme sind darauf zurückzuführen, dass die Anwendung mit dem falschen WindowServerProzess verbunden ist. Jede Benutzersitzung verfügt über einen separaten WindowServer. Dieser Prozess behandelt die Benutzeroberfläche. Bei Ihren früheren Methoden ist der Eigentümer des Prozesses der richtige Benutzer, der jedoch mit Ihrem eigenen WindowServer-Prozess verbunden ist.

Dieses Problem wird in dem technischen Hinweis Daemons and Agents von Apple erwähnt.

Erfahrung

Ich weiß das aus eigener Erfahrung. Für Power Manager habe ich pmuser geschrieben , damit es in jeder Benutzersitzung existiert. pmuserHört auf unseren Daemon und verwaltet die benutzerspezifischen Starts und Befehle. Obwohl unser Daemon über Root-Berechtigung verfügt, benötigten wir einen Prozess pro Benutzer, um in Benutzersitzungen zuverlässig zu arbeiten.

Graham Miln
quelle
Könnten Sie ein einfaches Skript bereitstellen, wie in der Antwort von TJ, aber eines, das funktioniert? Oder ist es einfach zu komplex für so etwas?
Cregox
Die richtige Lösung ist für ein kurzes Skript zu komplex. Idealerweise ist in der Zielbenutzersitzung ein separater trampolinähnlicher Vorgang erforderlich. Das mussten wir für Power Manager tun: dssw.co.uk/powermanager Was hoffen Sie zu erreichen?
Graham Miln
In der Hoffnung, genau das zu erreichen, was im Titel steht: Starten Sie eine GUI-Anwendung in der Sitzung eines anderen Benutzers . "Bonuspunkte", wenn der andere Benutzer nicht angemeldet sein muss oder programmgesteuert angemeldet werden kann. Im Einzelnen möchte ich mehrere Google Drive. Es funktioniert, wenn ich mich einfach manuell anmelde und es unter den Anmeldeelementen dieses Benutzers in den Systemeinstellungen ist. Ein Trampolinprozess würde keine Bonuspunkte bringen, aber wenn dies der einzige Weg ist, was genau ist die Empfehlung der Apple-Ingenieure dagegen? Ich dachte, es wäre genau das Richtige für so einfache Hack-Skripte! : P
cregox
@Cawas stellen Sie dies bitte als neue Frage und konzentrieren Sie sich auf das Ziel, mehrere Google Drives zu wollen, anstatt darauf, wie dies erreicht werden könnte. Durch die Änderung des Fokus wird die Frage nicht als Duplikat markiert.
Graham Miln
Fair genug und fertig .
Cregox
7

Keine der obigen Antworten von bsexec funktioniert auf El Capitan (10.11), da der System Integration Protection (SIP) die Ports schließt. "launchctl asuser" funktioniert, muss jedoch als root ausgeführt werden. Der folgende Befehl funktioniert auf El Capitan (und den neuesten Betriebssystemen):

sudo launchctl asuser 501 open /Applications/Calculator.app

Beachten Sie, dass 501 die Benutzer-ID für meinen anderen Benutzer ist.

Boris Vidolov
quelle
Dies ist mein Ergebnis: bruno.medeiros@brunojcm-macbook:~ $ sudo launchctl asuser 501 open /Applications/Firefox.appund bekamLSOpenURLsWithRole() failed with error -600 for the file /Applications/Firefox.app
BrunoJCM
@BrunoJCM Sind Sie sicher, dass 501 der Benutzer-ID-Code für den Benutzer ist, mit dem Sie ihn öffnen möchten? Es ist ein bisschen mehr klar , ob der Befehl wie etwas ist: sudo launchctl asuser $(id -u <user_id_name>) <app>. Das heißt, ich bekomme eine andere Fehlermeldung, posix_spawn(): 13: Permission deniedauch wenn ich mit der gleichen Benutzer-ID ausgeführt werde, mit der ich angemeldet bin (und die Sitzung besitzt) fürsudo launchctl asuser $(id -u mtylutki) /Applications/Calculator.app
Marcus
2

Ab 10.10 gibt es eine korrekte "launchctl bsexec" -Implementierung, die Sie verwenden können:

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

Mann sagt

Dadurch wird der angegebene Befehl in einem Ausführungskontext ausgeführt, der der Ziel-PID möglichst ähnlich ist.

Als PID-Parameter können Sie also die PID des entsprechenden Login-Fensters verwenden. Die UID ist die Benutzer-ID des Benutzers, der das Anmeldefenster besitzt, und die GID ist die primäre Gruppe.

Dies funktioniert für jeden Befehl und natürlich auch für gestartete Jobs (z. B. Launchagents) wie folgt:

/bin/launchctl bsexec 104 chroot -u 501 -g 20 / /bin/launchctl load -S Aqua /Library/LaunchAgents/com.youragent.plist 2>&1
Hofi
quelle
task_for_pid(): 0x5Ich bin mir nicht sicher, ob dies für andere zutrifft, aber ich erhalte jetzt eine Fehlermeldung, in der ich die Richtigkeit der PID überprüft habe.
Marcus
1

Sie können den Finder als Host für die richtigen Berechtigungen verwenden osascript -e "tell application \"Finder\" to open (\"${app}\" as POSIX file as alias)". Auf diese Weise wird Finder über den GUI-Kontext gestartet.

Atishay Jain
quelle
0

Das funktioniert via 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

Wenn Sie es jedoch über Terminal.app versuchen, wird TextEdit in der Benutzeroberfläche des aktuellen Benutzers geöffnet.

Wenn Sie nicht sicher sind, ob dies sshaktiviert ist, können Sie es möglicherweise vorübergehend aktivieren

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

und bei Bedarf danach wieder deaktivieren?

Ansonsten bin ich ratlos.

Getestet am 10.9.

TJ Luoma
quelle
Es öffnet die Anwendung, wie Sie sagen, aber es öffnet sie in der aktuellen Benutzersitzung und nicht in der Sitzung des anderen Benutzers, wie Sie dazu aufgefordert werden.
Cregox
-1

Einfach

sudo su name_of_user

Führen Sie dann die Befehle normal aus.

PandB Software
quelle
Die Befehle würden von ausgeführt bar, würden aber weiterhin in fooder grafischen Sitzung ausgeführt.
John N
Sorry, ja, ich bin verwirrt über die Frage, wird nicht in einer foo grafischen Sitzung ausgeführt.
PandB Software