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

Ich versuche herauszufinden, wie eine GUI-Anwendung als ein anderer Benutzer gestartet werden kann, 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 ich beim schnellen Wechsel des Benutzers zur Bar feststelle, dass das Rechnerfenster in der Sitzung der Bar geöffnet ist.

Hier ist, was ich versucht habe, das nicht funktioniert:

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

Dadurch wird Calculator.app als Leiste gestartet, aber das Fenster wird 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-Skripting, 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: Mir ist bewusst, dass es möglich ist, Remote Apple Events zu verwenden, aber ich kann das nicht verwenden, da ich in der Situation, in der ich dies versuche, keine Garantie dafür habe, dass „Remote Apple Events“ in den Freigabeeinstellungen aktiviert wird.

Jede Hilfe wäre sehr willkommen!

Haben Sie den openBefehl mit SSH?
Seltsamerweise erscheint das Dock-Symbol der App in der Sitzung von foo, aber das App-Fenster erscheint in der Sitzung von bar. Scheint also nicht zu funktionieren, aber guter Vorschlag. Leider gibt es keine Garantie dafür, dass die sichere Anmeldung in der Situation aktiviert ist, in der ich dies benötige, was für ein Installationsprogramm gilt.
Ich denke, ein Teil dieses Puzzles könnte das Befehlszeilenargument -psn beinhalten, das das Betriebssystem in einigen Situationen hinzufügt. Ich bin in der Vergangenheit darauf gestoßen, als ich daran gearbeitet habe, Code auf OS X zu portieren. Siehe diese Frage und die Apple-Dokumentation, auf die sie verweist.
ab 10.10 funktioniert endlich das unten erwähnte bsexec einwandfrei

Antworten (6)

Keine der obigen bsexec-Antworten funktioniert auf El Capitan (10.11), da der Systemintegrationsschutz (SIP) die Ports schließt. "launchctl asuser" funktioniert, muss aber 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.

Das ist mein Ergebnis: bruno.medeiros@brunojcm-macbook:~ $ sudo launchctl asuser 501 open /Applications/Firefox.app, und bekamLSOpenURLsWithRole() failed with error -600 for the file /Applications/Firefox.app
@BrunoJCM sind Sie sicher, dass 501 der Benutzer-ID-Code für den Benutzer ist, mit dem Sie ihn öffnen möchten? Es ist etwas klarer, wenn der Befehl etwa so lautet: sudo launchctl asuser $(id -u <user_id_name>) <app>. Allerdings erhalte ich einen anderen Fehler, posix_spawn(): 13: Permission deniedselbst wenn ich mit derselben Benutzer-ID laufe, mit der ich angemeldet bin (und die Sitzung besitzt).sudo launchctl asuser $(id -u mtylutki) /Applications/Calculator.app

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

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

launchds bsexec

Glücklicherweise haben neuere Versionen von launchddiese Fähigkeit; obwohl Apple-Ingenieure seine allgemeine Verwendung nicht empfohlen haben. Verwenden Sie die bsexecOption in launchctl , um auf die entsprechende Benutzersitzung abzuzielen:

 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 launchd-Jobticket zu schreiben und den Mac neu zu starten – oder den Benutzer zu bitten, sich abzumelden und wieder anzumelden.

Ursache der Probleme

Die Probleme ergeben sich daraus, dass die Anwendung mit dem falschen WindowServerProzess verbunden ist. Jede Benutzersitzung hat einen separaten WindowServer; Dieser Prozess behandelt die Benutzeroberfläche. Ihre früheren Methoden übertragen den Besitz des Prozesses auf den richtigen Benutzer, der jedoch mit Ihrem eigenen WindowServer-Prozess verbunden ist.

Dieses Problem wird im technischen Hinweis zu Daemons und Agents von Apple erwähnt.

Erfahrung

Das weiß ich aus eigener Erfahrung. Für Power Manager habe ich geschrieben, dass pmuser in jeder Benutzersitzung vorhanden ist. pmuserhört auf unseren Daemon und verarbeitet die Starts und Befehle pro Benutzer. Obwohl unser Daemon Root-Berechtigung hatte, brauchten wir immer noch einen Pro-Benutzer-Prozess, um innerhalb von Benutzersitzungen zuverlässig zu arbeiten.

Könnten Sie ein einfaches Skript bereitstellen, wie in TJs Antwort dort, aber eines, das funktioniert? Oder ist es einfach zu komplex für so etwas?
Die richtige Lösung ist für ein kurzes Skript zu komplex. Idealerweise ist in der Zielbenutzersitzung ein separater Trampolin-ähnlicher Prozess erforderlich. Das mussten wir für Power Manager tun: dssw.co.uk/powermanager Was hoffen Sie zu erreichen?
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. Insbesondere 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 Trampolin-Prozess würde nicht die Bonuspunkte bringen, aber wenn das der einzige Weg ist, was genau ist die Empfehlung der Apple-Ingenieure dagegen? Ich dachte, es wäre genau für solche einfachen Hack-Skripte! :P
@Cawas, stellen Sie dies bitte als neue Frage und konzentrieren Sie sich auf das Ziel, mehrere Google Drives zu wollen, und nicht darauf, wie es erreicht werden könnte. Die Fokusänderung trägt dazu bei, dass die Frage nicht als Duplikat markiert wird.
Fair genug und fertig .

Da 10.10 endlich eine korrekte "launchctl bsexec"-Implementierung bietet, können Sie Folgendes verwenden:

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

Mann sagt

Dies führt den gegebenen Befehl in einem möglichst ähnlichen Ausführungskontext wie die Ziel-PID aus.

Als PID-Parameter können Sie also die PID des entsprechenden Anmeldefenster- Prozesses verwenden. Die UID ist die Benutzer-ID des Benutzers, dem dieses Anmeldefenster gehört, und die GID ist seine primäre Gruppe.

Dies funktioniert gut für jeden Befehl und natürlich für Launchd-Jobs (z. B. Launchagents) auch endlich wie:

/bin/launchctl bsexec 104 chroot -u 501 -g 20 / /bin/launchctl load -S Aqua /Library/LaunchAgents/com.youragent.plist 2>&1
Ich bin mir nicht sicher, ob dies für andere gilt, aber ich bekomme task_for_pid(): 0x5jetzt eine Fehlermeldung dafür, wo ich überprüft habe, dass die PID korrekt ist.

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 es über den GUI-Kontext gestartet, der den Finder gestartet hat.

Dies funktioniert über 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 GUI des aktuellen Benutzers geöffnet.

Wenn Sie nicht sicher sind, ob sshes aktiviert ist, können Sie es vielleicht vorübergehend aktivieren

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

und danach ggf. wieder deaktivieren?

Ansonsten bin ich ratlos.

Getestet am 10.9.

Es öffnet die Anwendung, wie Sie sagen, aber es öffnet sie in der aktuellen Benutzersitzung und nicht wie gewünscht in der Sitzung des anderen Benutzers.

Einfach

sudo su name_of_user

dann Befehle normal ausführen.

Die Befehle würden von ausgeführt bar, würden aber weiterhin in fooder grafischen Sitzung von ausgeführt.
Entschuldigung, ja, ich bin verwirrt über die Frage, wird nicht in der foo-Grafiksitzung ausgeführt.