Làm cách nào để khởi chạy ứng dụng GUI trong phiên đồ họa của người dùng khác?


15

Tôi đang cố gắng tìm ra cách khởi chạy một ứng dụng GUI khi một người dùng khác đăng nhập tương tác, trong phiên đồ họa của người dùng đó.

Ví dụ: giả sử tôi có hai người dùng, foo và bar. Cả hai đều đăng nhập, nhưng người dùng tương tác hiện tại là foo. Tôi muốn khởi chạy Calculator.app dưới dạng "thanh" người dùng, để khi tôi nhanh chóng chuyển sang thanh, tôi thấy cửa sổ Máy tính đang mở trong phiên của thanh.

Đây là những gì tôi đã thử mà không hoạt động:

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

Thao tác này sẽ khởi chạy Calculator.app dưới dạng thanh, nhưng cửa sổ sẽ mở trong phiên đồ họa của foo.

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

Hiệu quả tương tự.

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

Khởi chạy Máy tính dưới dạng foo, không phải thanh.

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

Hiệu quả tương tự.

Có cách nào để thực hiện điều này? Tôi sẵn sàng giải trí theo mọi cách của các giải pháp khả thi, bao gồm bash scripting, AppleScript, viết chương trình Core Foundation hoặc ca cao, v.v. Trong tình huống của tôi, bất kỳ chương trình hoặc tập lệnh nào cũng có thể thực thi như bất kỳ người dùng nào, kể cả root.

Lưu ý: Tôi biết rằng có thể sử dụng Sự kiện Apple từ xa, nhưng tôi không thể sử dụng điều đó vì trong tình huống tôi đang cố gắng làm điều này, tôi không đảm bảo rằng "Sự kiện Apple từ xa" sẽ được bật trong tùy chọn Chia sẻ.

Mọi sự trợ giúp sẽ rất được trân trọng!


1
Bạn đã thử openlệnh, sử dụng SSH?
Matthieu Riegler

Thật kỳ lạ, biểu tượng dock của ứng dụng xuất hiện trong phiên của foo, nhưng cửa sổ ứng dụng xuất hiện trong thanh. Vì vậy, nó dường như không hoạt động, nhưng gợi ý tốt. Thật không may, không có gì đảm bảo rằng đăng nhập an toàn được kích hoạt trong tình huống tôi cần cái này, dành cho trình cài đặt.
GuyGizmo

Tôi nghĩ rằng một phần của câu đố này có thể liên quan đến đối số dòng lệnh -psn, mà HĐH thêm vào trong một số tình huống. Tôi đã gặp điều này trong quá khứ khi làm việc chuyển một số mã sang OS X. Xem câu hỏi này và tài liệu Apple mà nó tham khảo.
Ashley

vào ngày 10.10 cuối cùng, bsexec được đề cập dưới đây hoạt động hoàn hảo
Hofi

Câu trả lời:


7

Những gì bạn muốn đạt được là có thể nhưng khó khăn. Bạn cần khởi chạy ứng dụng trong phiên người dùng thích hợp. Vì lý do bảo mật, vượt qua phân chia phiên người dùng là khó khăn.

Bạn cần một quy trình đã chạy trong phiên của người dùng khác để lắng nghe yêu cầu của bạn và khởi chạy ứng dụng thay mặt bạn.

bsexec của launchd

Rất may, các phiên bản gần đây launchdcó khả năng này; mặc dù các kỹ sư của Apple đã không khuyến nghị sử dụng chung. Sử dụng bsexectùy chọn trong launchctl để nhắm mục tiêu phiên người dùng phù hợp:

 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.

Cách tiếp cận được đề xuất là viết một vé công việc khởi động và khởi động lại máy Mac - hoặc yêu cầu người dùng đăng xuất và đăng nhập lại.

Nguyên nhân của vấn đề

Các vấn đề bắt nguồn từ ứng dụng được kết nối với WindowServerquá trình sai . Mỗi phiên người dùng có một WindowServer riêng; quá trình này xử lý giao diện người dùng. Các phương thức trước đó của bạn đặt quyền sở hữu quy trình với đúng người dùng nhưng được kết nối với quy trình WindowServer của riêng bạn.

Vấn đề này được đề cập trong ghi chú kỹ thuật của Daemons và Agents từ Apple.

Kinh nghiệm

Tôi biết điều này từ kinh nghiệm cá nhân. Đối với Power Manager, tôi đã viết pmuser tồn tại trong mỗi phiên người dùng. pmuserlắng nghe trình nền của chúng tôi và xử lý các lệnh và lệnh khởi chạy cho mỗi người dùng. Mặc dù trình nền của chúng tôi có quyền root, chúng tôi vẫn cần một quy trình cho mỗi người dùng để hoạt động đáng tin cậy trong các phiên của người dùng.


Bạn có thể cung cấp một tập lệnh đơn giản, như trong câu trả lời của TJ không, nhưng một kịch bản có hiệu quả không? Hay nó chỉ quá phức tạp cho một điều như vậy?
cregox

Giải pháp chính xác là quá phức tạp cho một kịch bản ngắn. Lý tưởng nhất, một quy trình giống như tấm bạt lò xo được yêu cầu trong phiên người dùng mục tiêu. Đây là những gì chúng tôi phải làm cho Power Manager: dssw.co.uk/powermanager Bạn hy vọng đạt được điều gì?
Graham Miln

Hy vọng đạt được chính xác những gì nói trong tiêu đề: khởi chạy một ứng dụng gui trong phiên khác của người dùng . "Điểm thưởng" nếu người dùng khác không cần phải đăng nhập hoặc nếu có thể đăng nhập theo chương trình. Cụ thể, tôi muốn nhiều ổ google. Nó hoạt động nếu tôi chỉ cần đăng nhập thủ công và nó nằm dưới Mục Đăng nhập của người dùng đó trên Tùy chọn hệ thống. Một quy trình của tấm bạt lò xo sẽ ​​không mang lại điểm thưởng, nhưng nếu đó là cách duy nhất, chính xác thì các kỹ sư của Apple khuyến nghị chống lại điều gì? Tôi nghĩ rằng nó sẽ chính xác để làm các kịch bản hack đơn giản như vậy! : P
cregox

@Cawas vui lòng hỏi câu hỏi này như một câu hỏi mới và tập trung vào mục tiêu muốn có nhiều Ổ đĩa Google, thay vì làm thế nào để đạt được nó. Sự thay đổi trọng tâm sẽ giúp câu hỏi không bị đánh dấu là trùng lặp.
Graham Miln

Đủ công bằng và thực hiện .
cregox

7

Không có câu trả lời nào của bsexec ở trên hoạt động trên El Capitan (10.11), do Bảo vệ Tích hợp Hệ thống (SIP) đóng các cổng. "launchctl asuser" hoạt động, nhưng yêu cầu phải được chạy dưới quyền root. Lệnh dưới đây hoạt động trên El Capitan (và hệ điều hành gần đây nhất):

sudo launchctl asuser 501 open /Applications/Calculator.app

Lưu ý rằng 501 là userid cho người dùng khác của tôi.


Đây là kết quả của tôi: bruno.medeiros@brunojcm-macbook:~ $ sudo launchctl asuser 501 open /Applications/Firefox.appvà đã nhậnLSOpenURLsWithRole() failed with error -600 for the file /Applications/Firefox.app
BrunoJCM

@BrunoJCM bạn có chắc 501 là mã ID người dùng cho người dùng bạn muốn mở không? Rõ ràng hơn một chút nếu lệnh là một cái gì đó như : sudo launchctl asuser $(id -u <user_id_name>) <app>. Điều đó nói rằng, tôi nhận được một lỗi khác posix_spawn(): 13: Permission deniedngay cả khi tôi chạy với cùng một ID người dùng mà tôi đã đăng nhập (và sở hữu phiên) chosudo launchctl asuser $(id -u mtylutki) /Applications/Calculator.app
Marcus

2

Cuối cùng, 10.10 cung cấp một triển khai "launchctl bsexec" chính xác, bạn có thể sử dụng:

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

người đàn ông nói

Điều này thực thi lệnh đã cho trong bối cảnh thực thi tương tự nhất có thể với PID đích.

Vì vậy, với tư cách là param param, bạn có thể sử dụng pid của quá trình loginwindow thích hợp . UID là id người dùng của người dùng sở hữu thông tin đăng nhập đó và GID là nhóm chính.

Điều này hoạt động tốt cho bất kỳ lệnh nào và tất nhiên cho các công việc launchd (các trình khởi chạy) cũng cuối cùng như:

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

Không chắc điều này có đúng với người khác không, nhưng hiện tại tôi đã gặp task_for_pid(): 0x5lỗi vì điều này, nơi tôi đã xác minh PID là chính xác.
Marcus

1

Bạn có thể sử dụng Finder làm máy chủ cho các quyền phù hợp osascript -e "tell application \"Finder\" to open (\"${app}\" as POSIX file as alias)". Bằng cách đó, nó sẽ khởi chạy thông qua bất kỳ bối cảnh GUI nào đã khởi chạy Finder.


0

Điều này hoạt động thông qua 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

nhưng nếu thử qua Terminal.app, thì nó sẽ mở TextEdit trong GUI của người dùng hiện tại.

Nếu bạn không chắc chắn rằng nó sshđược kích hoạt, có lẽ bạn có thể tạm thời kích hoạt nó

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

và vô hiệu hóa nó một lần nữa sau đó nếu cần thiết?

Nếu không thì tôi đã bối rối.

Đã thử nghiệm vào ngày 10.9.


Nó không mở ứng dụng như bạn nói, nhưng nó sẽ mở nó trong phiên người dùng hiện tại chứ không phải trong phiên của người dùng khác như đã hỏi.
cregox

-1

Đơn giản

tên sudo su_of_user

sau đó thực hiện các lệnh bình thường.


Các lệnh sẽ được chạy bởi bar, nhưng vẫn sẽ chạy trong foophiên đồ họa của.
John N

Xin lỗi, có tôi nhầm lẫn về câu hỏi, không được thực thi trên phiên đồ họa foo.
Phần mềm PandB
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.