Bagaimana cara meluncurkan aplikasi GUI di sesi grafis pengguna lain?

15

Saya mencoba mencari cara untuk meluncurkan aplikasi GUI sebagai pengguna lain yang masuk secara interaktif, dalam sesi grafis pengguna tersebut.

Misalnya, saya punya dua pengguna, foo dan bar. Keduanya masuk, tetapi pengguna interaktif saat ini adalah foo. Saya ingin meluncurkan Calculator.app sebagai "bilah" pengguna, sehingga ketika saya berpuasa pengguna beralih ke bilah, saya menemukan jendela Kalkulator terbuka di sesi bilah.

Inilah yang saya coba yang tidak berhasil:

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

Ini meluncurkan Calculator.app sebagai bilah, tetapi jendela terbuka di sesi grafis foo.

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

Efek yang sama.

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

Meluncurkan Kalkulator sebagai foo, bukan bar.

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

Efek yang sama.

Apakah ada cara untuk mencapai ini? Saya bersedia untuk menghibur segala macam solusi yang mungkin, termasuk bash scripting, AppleScript, menulis Core Foundation atau program Cocoa, dan sebagainya. Dalam situasi saya, semua program atau skrip dapat dijalankan sebagai pengguna mana pun, termasuk root.

Catatan: Saya sadar bahwa itu mungkin menggunakan Acara Apple jarak jauh, tetapi saya tidak dapat menggunakannya karena dalam situasi yang saya coba lakukan ini saya tidak memiliki jaminan bahwa "Acara Apple Jarak Jauh" akan diaktifkan di preferensi Berbagi.

Bantuan apa pun akan sangat dihargai!

GuyGizmo
sumber
1
Apakah Anda mencoba openperintah, menggunakan SSH?
Matthieu Riegler
Anehnya, ikon dok aplikasi muncul di sesi foo, tetapi jendela aplikasi muncul di bar. Jadi sepertinya itu tidak berhasil, tetapi saran yang bagus. Sayangnya, tidak ada jaminan bahwa login aman diaktifkan dalam situasi yang saya butuhkan ini, yaitu untuk installer.
GuyGizmo
Saya pikir satu bagian dari teka-teki ini mungkin melibatkan argumen baris perintah -psn, yang ditambahkan OS dalam beberapa situasi. Saya pernah mengalami ini di masa lalu ketika bekerja pada porting beberapa kode ke OS X. Lihat pertanyaan ini dan dokumentasi Apple referensi.
Ashley 5'13
pada 10,10 akhirnya bsexec yang disebutkan di bawah berfungsi dengan baik
Hofi

Jawaban:

7

Apa yang ingin Anda capai adalah mungkin tetapi sulit. Anda harus meluncurkan aplikasi dalam sesi pengguna yang sesuai. Untuk alasan keamanan, melintasi pembagian sesi pengguna sulit.

Anda memerlukan proses yang sudah berjalan di sesi pengguna lain untuk mendengarkan permintaan Anda dan meluncurkan aplikasi atas nama Anda.

bsexec launchd

Untungnya, versi terbaru launchdmemiliki kemampuan ini; meskipun insinyur Apple belum merekomendasikan penggunaan umumnya. Gunakan bsexecopsi di launchctl untuk menargetkan sesi pengguna yang sesuai:

 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.

Pendekatan yang disarankan adalah menulis tiket kerja launchd dan me-restart Mac - atau meminta pengguna untuk log-out dan kembali lagi.

Penyebab Masalah

Masalahnya berasal dari aplikasi yang terhubung ke WindowServerproses yang salah . Setiap sesi pengguna memiliki WindowServer yang terpisah; proses ini menangani antarmuka pengguna. Metode Anda sebelumnya menempatkan kepemilikan proses dengan pengguna yang tepat tetapi terhubung ke proses WindowServer Anda sendiri.

Masalah ini disebutkan dalam catatan teknis Daemon dan Agen dari Apple.

Pengalaman

saya mengetahui ini dari pengalaman pribadi. Untuk Power Manager, saya menulis pmuser agar ada dalam setiap sesi pengguna. pmusermendengarkan daemon kami dan menangani peluncuran dan perintah per pengguna. Meskipun daemon kami memiliki otoritas root, kami masih membutuhkan proses per pengguna untuk bekerja dengan andal dalam sesi pengguna.

Graham Miln
sumber
Bisakah Anda memberikan skrip sederhana, seperti dalam jawaban TJ di sana, tetapi yang berfungsi? Atau itu terlalu rumit untuk hal seperti itu?
cregox
Solusi yang benar terlalu kompleks untuk skrip pendek. Idealnya, proses seperti trampolin terpisah diperlukan dalam sesi pengguna target. Inilah yang harus kami lakukan untuk Power Manager: dssw.co.uk/powermanager Apa yang ingin Anda capai?
Graham Miln
Berharap untuk mencapai apa yang tertulis dalam judul: luncurkan aplikasi gui di sesi pengguna lain . "Poin bonus" jika pengguna lain tidak perlu masuk atau jika bisa masuk secara terprogram. Secara khusus, saya ingin beberapa google drive. Ini berfungsi jika saya cukup login secara manual dan itu di bawah Item Login pengguna pada System Preferences. Proses trampolin tidak akan menghasilkan poin bonus, tetapi jika itu satu-satunya cara, apa tepatnya yang direkomendasikan oleh insinyur Apple? Saya pikir akan tepat untuk melakukan skrip hack sederhana seperti itu! : P
cregox
@Cawas tolong ajukan ini sebagai pertanyaan baru dan fokus pada tujuan menginginkan beberapa Google Drives, daripada bagaimana hal itu dapat dicapai. Perubahan fokus akan membantu pertanyaan tidak ditandai sebagai duplikat.
Graham Miln
Cukup adil dan selesai .
cregox
7

Tidak ada jawaban bsexec di atas yang berfungsi pada El Capitan (10.11), karena System Integration Protection (SIP) menutup port. "launchctl asuser" berfungsi, tetapi harus dijalankan sebagai root. Perintah di bawah ini berfungsi pada El Capitan (dan OS terbaru):

sudo launchctl asuser 501 open /Applications/Calculator.app

Perhatikan bahwa 501 adalah userid untuk pengguna saya yang lain.

Boris Vidolov
sumber
Ini adalah hasil saya bruno.medeiros@brunojcm-macbook:~ $ sudo launchctl asuser 501 open /Applications/Firefox.appLSOpenURLsWithRole() failed with error -600 for the file /Applications/Firefox.app
:,
@ BrunoJCM Anda yakin 501 adalah kode ID pengguna untuk pengguna yang ingin Anda buka? Ini sedikit lebih jelas jika perintah adalah sesuatu seperti: sudo launchctl asuser $(id -u <user_id_name>) <app>. Yang mengatakan, saya mendapatkan kesalahan yang berbeda posix_spawn(): 13: Permission deniedbahkan jika saya menjalankan dengan ID pengguna yang sama dengan yang saya masuki (dan memiliki sesi) untuksudo launchctl asuser $(id -u mtylutki) /Applications/Calculator.app
Marcus
2

Akhirnya, 10.10 menyediakan implementasi "launchctl bsexec" yang benar yang dapat Anda gunakan:

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

kata pria

Ini mengeksekusi perintah yang diberikan dalam konteks eksekusi yang mirip dengan PID target.

Jadi sebagai PID param Anda dapat menggunakan pid dari proses loginwindow yang sesuai . UID adalah id pengguna dari pengguna yang memiliki loginwindow dan GID adalah grup utamanya.

Ini berfungsi dengan baik untuk setiap perintah dan tentu saja untuk pekerjaan launchd (fe launchagents) juga pada akhirnya seperti:

/bin/launchctl bsexec 104 chroot -u 501 -g 20 / /bin/launchctl load -S Aqua /Library/LaunchAgents/com.youragent.plist 2>&1
Hofi
sumber
Tidak yakin apakah ini benar untuk orang lain, tetapi saya mendapatkan task_for_pid(): 0x5kesalahan sekarang untuk ini, di mana saya telah memverifikasi PID sudah benar.
Marcus
1

Anda dapat menggunakan Finder sebagai tuan rumah untuk izin yang tepat osascript -e "tell application \"Finder\" to open (\"${app}\" as POSIX file as alias)". Dengan begitu ia akan diluncurkan melalui konteks GUI apa pun yang diluncurkan Finder.

Atishay Jain
sumber
0

Ini bekerja melalui 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

tetapi jika mencobanya melalui Terminal.app, maka itu akan membuka TextEdit di GUI pengguna saat ini.

Jika Anda tidak yakin itu sshdiaktifkan, mungkin Anda dapat mengaktifkannya untuk sementara

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

dan nonaktifkan lagi setelah itu jika perlu?

Kalau tidak, saya bingung.

Diuji pada 10.9.

TJ Luoma
sumber
Itu memang membuka aplikasi seperti yang Anda katakan, tetapi membukanya di sesi pengguna saat ini, dan tidak di sesi pengguna lain seperti yang diminta.
cregox
-1

Sederhana

sudo su name_of_user

kemudian jalankan perintah secara normal.

Perangkat Lunak PandB
sumber
Perintah akan dijalankan oleh bar, tetapi masih akan berjalan dalam foosesi grafis.
John N
Maaf, ya saya bingung tentang pertanyaan, tidak dieksekusi pada sesi grafis foo.
Perangkat Lunak PandB