Jak uruchomić aplikację GUI w sesji graficznej innego użytkownika?


15

Próbuję wymyślić, jak uruchomić aplikację GUI jako inny użytkownik zalogowany interaktywnie, w sesji graficznej tego użytkownika.

Powiedzmy, że mam dwóch użytkowników, foo i bar. Oba są zalogowane, ale obecny użytkownik interaktywny to foo. Chciałbym uruchomić Calculator.app jako „pasek” użytkownika, aby po szybkim przełączeniu użytkownika na pasek znajdowałem okno kalkulatora w sesji paska.

Oto, co próbowałem, to nie działa:

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

To uruchamia Calculator.app jako pasek, ale okno otwiera się w sesji graficznej foo.

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

Ten sam efekt.

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

Uruchamia kalkulator jako foo, a nie pasek.

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

Ten sam efekt.

Czy jest jakiś sposób na osiągnięcie tego? Jestem gotów zająć się wszelkimi możliwymi rozwiązaniami, w tym skryptami bash, AppleScript, pisaniem programu Core Foundation lub Cocoa i tak dalej. W mojej sytuacji każdy program lub skrypt może być uruchamiany jak każdy użytkownik, w tym root.

Uwaga: Zdaję sobie sprawę, że jest to możliwe przy użyciu zdalnych zdarzeń Apple, ale nie mogę tego użyć, ponieważ w tej sytuacji próbuję to zrobić, nie mam gwarancji, że „Zdalne zdarzenia Apple” zostaną włączone w preferencjach udostępniania.

Każda pomoc byłaby bardzo mile widziana!


1
Czy próbowałeś użyć openpolecenia SSH?
— Matthieu Riegler,

Co dziwne, ikona dokowania aplikacji pojawia się w sesji foo, ale okno aplikacji pojawia się w pasku. Więc to nie działa, ale dobra sugestia. Niestety, nie ma gwarancji, że bezpieczne logowanie jest włączone w sytuacji, gdy potrzebuję tego, co jest dla instalatora.
— GuyGizmo

Myślę, że jedna część tej układanki może zawierać argument wiersza polecenia -psn, który system operacyjny dodaje w niektórych sytuacjach. Zetknąłem się z tym w przeszłości podczas pracy nad portowaniem jakiegoś kodu do OS X. Zobacz to pytanie i dokumentację Apple, do której się odwołuje.
— Ashley

od 10.10 w końcu wspomniany bsexec działa doskonale
— Hofi

Odpowiedzi:


7

To, co chcesz osiągnąć, jest możliwe, ale trudne. Musisz uruchomić aplikację w ramach odpowiedniej sesji użytkownika. Ze względów bezpieczeństwa przekroczenie podziału sesji użytkownika jest trudne.

Potrzebujesz procesu już uruchomionego w sesji innego użytkownika, aby wysłuchać twojego żądania i uruchomić aplikację w Twoim imieniu.

Wystartował bsexec

Na szczęście najnowsze wersje launchdmają tę zdolność; chociaż inżynierowie Apple nie zalecili jego ogólnego zastosowania. Użyj bsexecopcji w launchctl, aby wybrać odpowiednią sesję użytkownika:

 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.

Zalecanym podejściem jest napisanie uruchomionego biletu zadania i zrestartowanie komputera Mac - lub poproszenie użytkownika o wylogowanie i ponowne zalogowanie.

Przyczyna problemów

Problemy wynikają z połączenia aplikacji z niewłaściwym WindowServerprocesem. Każda sesja użytkownika ma osobny WindowServer; ten proces obsługuje interfejs użytkownika. Wcześniejsze metody przypisują własność procesu właściwemu użytkownikowi, ale są połączone z własnym procesem WindowServer.

Ten problem jest wymieniony w nocie technicznej Daemons and Agents od Apple.

Doświadczenie

Wiem to z własnego doświadczenia. Dla Power Managera napisałem pmuser, aby istniał w każdej sesji użytkownika. pmusernasłuchuje naszego demona i obsługuje uruchomienia i polecenia dla poszczególnych użytkowników. Pomimo tego, że nasz demon ma uprawnienia administratora, nadal potrzebowaliśmy procesu na użytkownika, aby działać niezawodnie w sesjach użytkowników.


Czy możesz podać prosty skrypt, taki jak w odpowiedzi TJ, ale taki, który działa? Czy może jest to po prostu zbyt skomplikowane?
— cregox,

Prawidłowe rozwiązanie jest zbyt skomplikowane, aby można je było napisać krótko. Idealnie, osobny proces podobny do trampoliny jest wymagany w sesji użytkownika docelowego. Oto, co musieliśmy zrobić dla Power Managera: dssw.co.uk/powermanager Co masz nadzieję osiągnąć?
— Graham Miln,

Mając nadzieję osiągnąć dokładnie to, co mówi tytuł: uruchom aplikację GUI w sesji innego użytkownika . „Punkty bonusowe”, jeśli drugi użytkownik nie musi być zalogowany lub może zostać zalogowany programowo. W szczególności chcę wielu dysków Google. Działa, jeśli po prostu loguję się ręcznie i znajduje się w elementach logowania tego użytkownika w Preferencjach systemowych. Proces trampoliny nie przyniósłby punktów bonusowych, ale jeśli to jedyny sposób, jakie jest dokładnie zalecenie inżynierów Apple? Myślałem, że to właśnie do robienia tak prostych skryptów hakerskich! : P
— cregox

@Cawas, zadaj to pytanie jako nowe pytanie i skup się na celu, jakim jest uzyskanie wielu Dysków Google, a nie na tym, jak można to osiągnąć. Zmiana fokusu sprawi, że pytanie nie będzie oznaczone jako duplikat.
— Graham Miln,

Wystarczająco uczciwe i gotowe .
— cregox

7

Żadna z powyższych odpowiedzi bsesek nie działa na El Capitan (10.11), ze względu na zamknięcie portów przez System Integration Protection (SIP). „launchctl asuser” działa, ale wymaga uruchomienia jako root. Poniższe polecenie działa w El Capitan (i najnowszych systemach operacyjnych):

sudo launchctl asuser 501 open /Applications/Calculator.app

Zauważ, że 501 jest identyfikatorem użytkownika dla mojego innego użytkownika.


To jest mój wynik: bruno.medeiros@brunojcm-macbook:~ $ sudo launchctl asuser 501 open /Applications/Firefox.appi dostałemLSOpenURLsWithRole() failed with error -600 for the file /Applications/Firefox.app
— BrunoJCM 17.10.16

@BrunoJCM czy jesteś pewien, że 501 to kod ID użytkownika, z którym chcesz go otworzyć? Jest nieco bardziej jasne, czy polecenie jest coś takiego: sudo launchctl asuser $(id -u <user_id_name>) <app>. To powiedziawszy, otrzymuję inny błąd, posix_spawn(): 13: Permission deniednawet jeśli uruchamiam z tym samym identyfikatorem użytkownika, z którym jestem zalogowany (i jestem właścicielem sesji) dlasudo launchctl asuser $(id -u mtylutki) /Applications/Calculator.app
— Marcus

2

Ponieważ ostatecznie 10.10 zapewnia poprawną implementację „launchctl bsexec”, możesz użyć:

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

człowiek mówi

Spowoduje to wykonanie podanego polecenia w możliwie najbardziej zbliżonym kontekście wykonania do docelowego PID.

Tak więc jako parametr PID możesz użyć pid odpowiedniego procesu logowania do okna . UID to identyfikator użytkownika posiadającego loginwindow, a GID to jego podstawowa grupa.

Działa to dobrze dla każdego polecenia i oczywiście dla uruchomionych zadań (np. Launchagents), w końcu także:

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

Nie jestem pewien, czy dotyczy to innych, ale teraz pojawia się task_for_pid(): 0x5błąd, w którym sprawdziłem, czy PID jest poprawny.
— Marcus

1

Możesz użyć Findera jako hosta dla odpowiednich uprawnień osascript -e "tell application \"Finder\" to open (\"${app}\" as POSIX file as alias)". W ten sposób uruchomi się za pomocą dowolnego kontekstu GUI uruchomionego Findera.


0

Działa to przez 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

ale jeśli spróbujesz za pośrednictwem Terminal.app, to otworzy TextEdit w GUI bieżącego użytkownika.

Jeśli nie masz pewności, czy sshjest włączona, być może możesz ją tymczasowo włączyć

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

i wyłącz go później, jeśli to konieczne?

W przeciwnym razie jestem zakłopotany.

Testowane na 10.9.


Otwiera aplikację tak, jak mówisz, ale otwiera ją w bieżącej sesji użytkownika, a nie w sesji innego użytkownika, zgodnie z pytaniem.
— cregox

-1

Prosty

sudo su nazwa_użytkownika

następnie wykonuj polecenia normalnie.


Polecenia byłyby uruchamiane bar, ale nadal działałyby w foosesji graficznej.
— John N

Przepraszam, tak, mylę się co do pytania, nie jest wykonywane w sesji graficznej foo.
— PandB Software,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.