¿Cómo iniciar una aplicación GUI en la sesión gráfica de otro usuario?

Estoy tratando de descubrir cómo iniciar una aplicación GUI como otro usuario que inició sesión de forma interactiva, en la sesión gráfica de ese usuario.

Por ejemplo, digamos que tengo dos usuarios, foo y bar. Ambos están conectados, pero el usuario interactivo actual es foo. Me gustaría iniciar Calculator.app como "barra" de usuario, de modo que cuando cambie rápido de usuario a la barra, encuentre que la ventana de la Calculadora está abierta en la sesión de la barra.

Esto es lo que he intentado que no funciona:

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

Esto inicia Calculator.app como barra, pero la ventana se abre en la sesión gráfica de foo.

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

Mismo efecto.

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

Inicia la Calculadora como foo, no como bar.

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

Mismo efecto.

¿Hay alguna forma de lograr esto? Estoy dispuesto a contemplar todo tipo de soluciones posibles, incluidas secuencias de comandos bash, AppleScript, escribir un programa Core Foundation o Cocoa, etc. En mi situación, cualquier programa o script podría ejecutarse como cualquier usuario, incluido el root.

Nota: Soy consciente de que es posible usar eventos remotos de Apple, pero no puedo usarlo ya que en la situación en la que estoy tratando de hacer esto, no tengo garantía de que los "Eventos remotos de Apple" estén habilitados en las preferencias de uso compartido.

¡Cualquier ayuda sería muy apreciada!

¿Probaste el opencomando, usando SSH?
Por extraño que parezca, el ícono de la base de la aplicación aparece en la sesión de foo, pero la ventana de la aplicación aparece en la barra. Así que eso no parece funcionar, pero es una buena sugerencia. Desafortunadamente, no hay garantía de que el inicio de sesión seguro esté habilitado en la situación en que lo necesito, que es para un instalador.
Creo que una pieza de este rompecabezas podría involucrar el argumento de línea de comando -psn, que el sistema operativo agrega en algunas situaciones. Me encontré con esto en el pasado cuando trabajé en la transferencia de algún código a OS X. Consulte esta pregunta y la documentación de Apple a la que hace referencia.
a partir de las 10.10, por fin, el bsexec mencionado a continuación funciona perfectamente

Respuestas (6)

Ninguna de las respuestas de bsexec anteriores funciona en El Capitan (10.11), debido a que la Protección de integración del sistema (SIP) cierra los puertos. "launchctl asuser" funciona, pero requiere que se ejecute como root. El siguiente comando funciona en El Capitan (y los sistemas operativos más recientes):

sudo launchctl asuser 501 open /Applications/Calculator.app

Tenga en cuenta que 501 es el ID de usuario de mi otro usuario.

Este es mi resultado: bruno.medeiros@brunojcm-macbook:~ $ sudo launchctl asuser 501 open /Applications/Firefox.app, y obtuveLSOpenURLsWithRole() failed with error -600 for the file /Applications/Firefox.app
@BrunoJCM, ¿está seguro de que 501 es el código de identificación de usuario para el usuario con el que desea abrirlo? Es un poco más claro si el comando es algo como: sudo launchctl asuser $(id -u <user_id_name>) <app>. Dicho esto, recibo un error diferente de posix_spawn(): 13: Permission deniedincluso si ejecuto con la misma ID de usuario con la que inicié sesión (y es propietario de la sesión) parasudo launchctl asuser $(id -u mtylutki) /Applications/Calculator.app

Lo que quieres lograr es posible pero difícil. Debe iniciar la aplicación dentro de la sesión de usuario correspondiente. Por razones de seguridad, cruzar la brecha de la sesión de usuario es difícil.

Necesita un proceso que ya se esté ejecutando en la sesión del otro usuario para escuchar su solicitud e iniciar la aplicación en su nombre.

bsexec de launchd

Afortunadamente, las versiones recientes de launchdtienen esta capacidad; aunque los ingenieros de Apple no han recomendado su uso general. Use la bsexecopción en launchctl para apuntar a la sesión de usuario adecuada:

 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.

El enfoque recomendado es escribir un ticket de trabajo de lanzamiento y reiniciar la Mac, o pedirle al usuario que cierre la sesión y vuelva a iniciarla.

Causa de los problemas

Los problemas se derivan de que la aplicación está conectada al WindowServerproceso incorrecto. Cada sesión de usuario tiene un WindowServer separado; este proceso maneja la interfaz de usuario. Sus métodos anteriores colocan la propiedad del proceso con el usuario correcto pero conectado a su propio proceso de WindowServer.

Este problema se menciona en la nota técnica Daemons and Agents de Apple.

Experiencia

Sé esto por experiencia personal. Para Power Manager, escribí pmuser para que exista dentro de cada sesión de usuario. pmuserescucha nuestro demonio y maneja los lanzamientos y comandos por usuario. A pesar de que nuestro daemon tiene autoridad de raíz, aún necesitábamos un proceso por usuario para trabajar de manera confiable dentro de las sesiones de usuario.

¿Podría proporcionar un script simple, como en la respuesta de TJ allí, pero que funcione? ¿O es demasiado complejo para tal cosa?
La solución correcta es demasiado compleja para un guión breve. Idealmente, se requiere un proceso similar a un trampolín en la sesión del usuario de destino. Esto es lo que teníamos que hacer para Power Manager: dssw.co.uk/powermanager ¿Qué espera lograr?
Con la esperanza de lograr exactamente lo que dice en el título: iniciar una aplicación de interfaz gráfica de usuario en la sesión de otro usuario . "Puntos de bonificación" si el otro usuario no necesita iniciar sesión o si puede iniciar sesión mediante programación. En específico, quiero múltiples unidades de Google. Funciona si simplemente inicio sesión manualmente y está bajo los Elementos de inicio de sesión de ese usuario en Preferencias del sistema. Un proceso de trampolín no traería los puntos de bonificación, pero si esa es la única forma, ¿cuál es precisamente la recomendación de los ingenieros de Apple en contra? ¡Pensé que sería precisamente para hacer scripts de pirateo tan simples! :PAG
@Cawas, formule esta pregunta como nueva y concéntrese en el objetivo de querer múltiples unidades de Google Drive, en lugar de cómo podría lograrse. El cambio de enfoque ayudará a que la pregunta no se marque como duplicada.
Bastante justo y hecho .

Como finalmente 10.10 proporciona una implementación correcta de "launchctl bsexec", puede usar:

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

el hombre dice

Esto ejecuta el comando dado en un contexto de ejecución lo más similar posible al PID de destino.

Entonces, como parámetro PID, puede usar el pid del proceso de ventana de inicio de sesión apropiado . El UID es el ID de usuario del usuario que posee esa ventana de inicio de sesión y el GID es su grupo principal.

Esto funciona bien para cualquier comando y, por supuesto, para trabajos de lanzamiento (fe launchagents) también por fin como:

/bin/launchctl bsexec 104 chroot -u 501 -g 20 / /bin/launchctl load -S Aqua /Library/LaunchAgents/com.youragent.plist 2>&1
No estoy seguro de si esto es cierto para otros, pero ahora recibo un task_for_pid(): 0x5error para esto, donde verifiqué que el PID es correcto.

Puede utilizar el Finder como anfitrión para obtener los permisos adecuados osascript -e "tell application \"Finder\" to open (\"${app}\" as POSIX file as alias)". De esa manera, se iniciará a través de cualquier contexto de GUI que haya iniciado Finder.

Esto funciona a través de 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

pero si lo intenta a través de Terminal.app, abre TextEdit en la GUI del usuario actual.

Si no está seguro de que sshesté habilitado, tal vez pueda habilitarlo temporalmente

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

y desactivarlo de nuevo después si es necesario?

De lo contrario, estoy perplejo.

Probado el 10.9.

Abre la aplicación como usted dice, pero la abre en la sesión del usuario actual y no en la sesión del otro usuario como se le solicitó.

Simple

sudo su nombre_de_usuario

luego ejecute los comandos normalmente.

Los comandos serían ejecutados por bar, pero aún se ejecutarían en foola sesión gráfica de .
Lo siento, sí, estoy confundido con la pregunta, no se ejecuta en una sesión gráfica foo.