Come avviare un'applicazione GUI nella sessione grafica di un altro utente?


15

Sto cercando di capire come avviare un'applicazione GUI come un altro utente che ha effettuato l'accesso interattivo, nella sessione grafica di quell'utente.

Ad esempio, supponiamo che io abbia due utenti, foo e bar. Entrambi sono connessi, ma l'attuale utente interattivo è foo. Vorrei lanciare Calculator.app come "barra" dell'utente, in modo che quando passo velocemente l'utente alla barra, trovo che la finestra Calcolatrice sia aperta nella sessione della barra.

Ecco cosa ho provato che non funziona:

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

Questo avvia Calculator.app come barra, ma la finestra si apre nella sessione grafica di foo.

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

Stesso effetto.

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

Avvia la calcolatrice come foo, non bar.

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

Stesso effetto.

C'è un modo per raggiungere questo obiettivo? Sono disposto ad intrattenere qualsiasi tipo di soluzione possibile, inclusi script bash, AppleScript, scrittura di un programma Core Foundation o Cocoa e così via. Nella mia situazione, qualsiasi programma o script potrebbe essere eseguito come qualsiasi utente, incluso root.

Nota: sono consapevole che è possibile utilizzare Apple Event remoti, ma non posso utilizzarlo poiché nella situazione sto provando a farlo non ho alcuna garanzia che "Remote Apple Events" sarà abilitato nelle preferenze di condivisione.

Qualsiasi aiuto sarebbe molto apprezzato!


1
Hai provato il opencomando, usando SSH?
Matthieu Riegler,

Stranamente, l'icona del dock dell'app appare nella sessione di foo, ma la finestra dell'app appare nella barra. Quindi non sembra funzionare, ma un buon suggerimento. Sfortunatamente, non esiste alcuna garanzia che l'accesso sicuro sia abilitato nella situazione in cui ho bisogno di questo, che è per un installatore.
GuyGizmo,

Penso che un pezzo di questo puzzle possa coinvolgere l'argomento della riga di comando -psn, che il sistema operativo aggiunge in alcune situazioni. L'ho riscontrato in passato durante il porting di codice su OS X. Vedi questa domanda e la documentazione Apple a cui fa riferimento.
Ashley,

a partire dal 10.10 finalmente il citato bsexec funziona perfettamente
Hofi,

Risposte:


7

Quello che vuoi ottenere è possibile ma difficile. È necessario avviare l'applicazione all'interno della sessione utente appropriata. Per motivi di sicurezza, è difficile attraversare la divisione della sessione utente.

È necessario un processo già in esecuzione nella sessione dell'altro utente per ascoltare la richiesta e avviare l'applicazione per conto dell'utente.

launchd's bsexec

Per fortuna, le versioni recenti di launchdhanno questa capacità; sebbene gli ingegneri Apple non ne abbiano raccomandato l'uso generale. Utilizzare l' bsexecopzione in launchctl per indirizzare la sessione utente appropriata:

 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.

L'approccio consigliato è quello di scrivere un job ticket di avvio e riavviare il Mac o chiedere all'utente di disconnettersi e riconnettersi.

Causa dei problemi

I problemi derivano dalla connessione dell'applicazione al WindowServerprocesso errato . Ogni sessione utente ha un WindowServer separato; questo processo gestisce l'interfaccia utente. I metodi precedenti pongono la proprietà del processo con l'utente giusto ma connesso al proprio processo WindowServer.

Questo problema è menzionato nella nota tecnica Demoni e agenti di Apple.

Esperienza

Lo so per esperienza personale. Per Power Manager, ho scritto che pmuser esiste in ogni sessione utente. pmuserascolta il nostro demone e gestisce i lanci e i comandi per utente. Nonostante il nostro demone abbia l'autorità di root, avevamo ancora bisogno di un processo per utente per funzionare in modo affidabile all'interno delle sessioni utente.


Potresti fornire uno script semplice, come nella risposta di TJ lì, ma uno che funziona? O è troppo complesso per una cosa del genere?
Cregox,

La soluzione corretta è troppo complessa per uno script breve. Idealmente, nella sessione di destinazione dell'utente è richiesto un processo separato simile a un trampolino. Questo è quello che dovevamo fare per Power Manager: dssw.co.uk/powermanager Cosa speri di ottenere?
Graham Miln,

Sperando di ottenere esattamente ciò che dice nel titolo: avvia un'applicazione gui nella sessione di un altro utente . "Punti bonus" se non è necessario che l'altro utente abbia effettuato l'accesso o se sia possibile effettuare l'accesso a livello di codice. In particolare, voglio più google drive. Funziona se accedo semplicemente manualmente ed è sotto le voci di accesso dell'utente su Preferenze di Sistema. Un processo con trampolino non porterebbe i punti bonus, ma se è l'unico modo, qual è esattamente la raccomandazione degli ingegneri Apple contro di essa? Ho pensato che sarebbe stato proprio per fare script di hacking così semplici! : P
cregox,

@Cawas, ti preghiamo di porre questa domanda come nuova domanda e concentrarti sull'obiettivo di desiderare più Google Drives, piuttosto che su come potrebbe essere raggiunto. Il cambio di focus aiuterà la domanda a non essere contrassegnata come duplicata.
Graham Miln,

Abbastanza giusto e fatto .
Cregox,

7

Nessuna delle risposte di bsexec sopra funziona su El Capitan (10.11), a causa della System Integration Protection (SIP) che chiude le porte. "launchctl asuser" funziona, ma richiede di essere eseguito come root. Il comando seguente funziona su El Capitan (e sui sistemi operativi più recenti):

sudo launchctl asuser 501 open /Applications/Calculator.app

Nota che 501 è l'ID utente per il mio altro utente.


Questo è il mio risultato bruno.medeiros@brunojcm-macbook:~ $ sudo launchctl asuser 501 open /Applications/Firefox.appLSOpenURLsWithRole() failed with error -600 for the file /Applications/Firefox.app
:,

@BrunoJCM sei sicuro che 501 sia il codice ID utente per l'utente con cui vuoi aprirlo? E 'un po' più chiaro se il comando è qualcosa di simile: sudo launchctl asuser $(id -u <user_id_name>) <app>. Detto questo, ricevo un errore diverso posix_spawn(): 13: Permission deniedanche se corro con lo stesso ID utente con cui ho effettuato l'accesso (e possiede la sessione) persudo launchctl asuser $(id -u mtylutki) /Applications/Calculator.app
Marcus

2

Come finalmente 10.10 fornisce una corretta implementazione "launchctl bsexec" che puoi usare:

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

dice l'uomo

Questo esegue il comando dato in un contesto di esecuzione il più simile possibile al PID di destinazione.

Quindi, come parametro PID, è possibile utilizzare il pid del processo di loginwindow appropriato . L'UID è l'ID utente dell'utente proprietario di quella finestra di accesso e il GID è il suo gruppo primario.

Funziona bene per qualsiasi comando e, naturalmente, per i lavori avviati (per esempio) anche come:

/bin/launchctl bsexec 104 chroot -u 501 -g 20 / /bin/launchctl load -S Aqua /Library/LaunchAgents/com.youragent.plist 2>&1

Non sono sicuro che questo sia vero per gli altri, ma ora ricevo un task_for_pid(): 0x5errore per questo, in cui ho verificato che il PID è corretto.
Marcus,

1

Puoi utilizzare il Finder come host per le autorizzazioni giuste osascript -e "tell application \"Finder\" to open (\"${app}\" as POSIX file as alias)". In questo modo verrà avviato tramite qualunque contesto della GUI avviato Finder.


0

Funziona tramite 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

ma se provalo tramite Terminal.app, apre TextEdit nella GUI dell'utente corrente.

Se non sei sicuro che sshsia abilitato, forse puoi abilitarlo temporaneamente

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

e disabilitarlo di nuovo in seguito, se necessario?

Altrimenti sono perplesso.

Testato il 10.9.


Apre l'applicazione come dici tu, ma la apre nella sessione dell'utente corrente e non nella sessione dell'altro utente come richiesto.
Cregox,

-1

Semplice

sudo su name_of_user

quindi eseguire i comandi normalmente.


I comandi verrebbero eseguiti bar, ma verrebbero comunque eseguiti nella foosessione grafica.
John N,

Scusa, sì, sono confuso riguardo alla domanda, non viene eseguito su una sessione grafica.
Software PandB,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.