Menú de secuencias de comandos: cómo hacer referencia a las utilidades de ruta de usuario (Falta PATH/entorno)

Resumen

¿Cómo puedo ejecutar secuencias de comandos desde el menú de secuencias de comandos de todo el sistema con un entorno normal? Parece que el entorno no se está configurando en absoluto.

Los scripts que se ejecutan desde el menú de scripts pueden buscar y ejecutar comandos desde el sistema base. Sin embargo, las utilidades instaladas por el usuario no se encuentran en la ruta. Además, /usr/bin/env foono encuentra comandos que estén instalados fuera del sistema base.

Fondo

El menú Script del sistema aparece en el lado derecho de la barra de menú. Se habilita a través de Script Editor.app > Preferencias > Mostrar menú Script en la barra de menú. Muestra scripts ubicados en ~/Library/Scriptsy otras ubicaciones del sistema. El menú puede ejecutar AppleScript, JXA, bash, python y otros scripts (use shebang según sea necesario).

ingrese la descripción de la imagen aquí

Investigación hasta ahora

Los scripts que se ejecutan desde el menú Script no heredan el entorno bash del usuario. Saben que el shell es BASH y su nombre de USUARIO, pero no se produce ninguna inicialización. Ejecuté un pequeño script para volcarlo enven un archivo de texto.

~/Library/Scripts/dump_env.sh (asegúrese de hacerlo ejecutable) :

#!/bin/bash
env > ~/env.txt
ps -ef >> ~/env.txt

Aquí están las entradas interesantes.

USER=mat
LOGNAME=mat
SHELL=/bin/bash
PATH=/usr/bin:/bin:/usr/sbin:/sbin
PWD=/
HOME=/Users/mat
_=/usr/bin/env

Es muy vainilla. No se incluye ninguna de las rutas personalizadas. Por ejemplo, los siguientes no están disponibles:

/usr/local/bin/svn # Subversion source control client
/opt/local/bin/python3 # python3 installed via MacPorts
~/bin

Los dos últimos normalmente se encuentran en mi .bash_profile. /usr/local/bin/es la configuración por path_helperla cual es llamado /etc/profile(aunque aparentemente no para el menú Script).

Estoy ejecutando macOS 10.13 High Sierra, pero me interesa saber si otros obtienen resultados diferentes.

Solución ideal

  1. Evite la ruta de codificación rígida a los ejecutables en shebang. Ej: si instalo una versión/distribución de python diferente, quiero usarla en todos mis scripts. /usr/bin/env python3logra esto, pero parece depender de la RUTA?
  2. Encuentra utilidades en /usr/local/bin
  3. Especifique PATH una vez para el menú CLI y Script (¿y GUI?). Si instalo un nuevo Python, me gustaría que se use en todas partes.
  4. Especifique PATH solo para procesos de nivel de usuario. No quiero que los procesos del sistema usen archivos binarios en mis entradas de rutas adicionales (especialmente las entradas de rutas autorizadas por el usuario).
  5. Evite romper compilaciones/instaladores/programas de terceros que se escribieron con suposiciones sobre lo que está presente en mi instalación de macOS.

Estoy buscando en launchctl, que se puede usar para configurar el entorno para aplicaciones GUI. No estoy seguro si todavía funciona o si funcionará con el menú Script.

Actualizar


Agregué instrucciones de seguimiento a todos los archivos de entorno de bash: /profile, /bashrc, ~/.bash_profile, ~/.bashrc. Estas declaraciones exportan la variable de entorno para que pueda ver que el archivo se ha obtenido. Ninguno de estos se ejecuta para los scripts que se ejecutan desde el menú Script.

launchctl setenv KEY VALUEestablecerá una variable ambiental para todos los procesos lanzados posteriormente por los servicios de lanzamiento (launchd) en el espacio del usuario.

Esto funciona para Terminal.app, aplicaciones GUI y scripts en los que se hace doble clic en el Finder. Sin embargo, no funciona para el menú Script.

Agregué ps -efal script dump_env.sh. Esto me dice que el menú Script no está invocando a bash con argumentos que eliminarían el entorno (como -r o -p). El proceso padre es UserScriptService.

Correr…

otool -tV /System/Library/Frameworks/Foundation.framework/Versions/C/XPCServices/com.apple.foundation.UserScriptService.xpc/Contents/MacOS/com.apple.foundation.UserScriptService.

… revela un símbolo llamado __NSUserScriptTaskServiceStart. Esto suena terriblemente similar a NSUserScriptTask en la API de CoreFoundation. Del documento API:

La clase NSUserScriptTask puede ejecutar todos los scripts normalmente ejecutados por una de sus subclases...

https://developer.apple.com/documentation/foundation/nsuserscripttask?language=objc

Sospecho firmemente que esto es lo que usa el menú Script para ejecutar scripts. El documento API no dice nada sobre el entorno de tiempo de ejecución del script.

¿No puede simplemente obtener .bashrc y todo desde su secuencia de comandos?
nohillside: sí, el abastecimiento .bashrcfunciona bien para scripts bash. Estoy haciendo la transición de mis scripts a python, por lo que mi caso principal es que #!/usr/bin/env python3funcione. Necesito el entorno para encontrar python3. Probé un script bash con un here-doc para python; funciona, pero eso rompe la coloración de la sintaxis del editor. Eso probablemente también rompa el depurador de python.
¿Por qué no especificar la ruta a python3 directamente entonces?
No entiendo la premisa de "entorno normal", el editor de secuencias de comandos gráficas es para AppleScript y JXA, por lo que tendrá que manejar shells arbitrarios que no invocan un inicio de sesión interactivo como lo hace con tareas cron o launchd. (¿Con referencias, supongo que esta podría ser la respuesta?)

Respuestas (1)

bashpuede iniciarse de tres maneras diferentes y la forma en que usa los archivos rc es diferente en cada caso.

Para dar una respuesta corta cuando se llama como shell de inicio de sesión, lee .profileo .bash_profilepara configurar cosas como PATH. Cuando se llama como un shell interactivo pero no como un shell de inicio de sesión, digamos que ejecuta bashdesde la línea de comando, luego lee ~/.bashrcpara configurar estas cosas.

Si se ejecuta desde un script de shell (o por launchctl), entonces busca una variable de entorno BASH_ENVy ejecuta el archivo nombrado en la variable.

Consulte https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html

Para responder a su pregunta, debe configurar todas las variables en .bashrc, llámelo en su .bash_profilearchivo con la línea if [ -f ~/.bashrc ]; then source ~/.bashrc; fiFinalmente, .bashrcdebe configurar la BASH_ENVvariableexport BASH_ENV='.bashrc'

Esto le daría un PATHy así sucesivamente en todas partes.

Cuando pasa al zshshell, las cosas son ligeramente diferentes, lea http://zsh.sourceforge.net/Intro/intro_3.html

La mayoría de los administradores e ingenieros de Mac lo ignoran todo y codificamos la ruta a todo nuestro software en scripts. Ciertamente, nunca he visto un script de Apple que no tenga todas las rutas de herramientas codificadas.

Desafortunadamente, todo esto está siendo ignorado por el menú Script del sistema. Ver mi actualización a la pregunta. Parece que necesitamos un cuarto caso: invocar bash a través de la API de Objective-C . Actualmente estoy usando un kluge donde especifico mi propio script de inicialización de entorno en el shebang. Algunas advertencias aquí: stackoverflow.com/a/9988385/199296
¿Estaba configurando y exportando BASH_ENVy en qué lo estaba configurando? Sospecho que launchctl no respetará una tilde para casa, por ejemplo.
Tengo una ~/Library/Launch Agents/bashenv.plistque especifica launchctl setenv BASH_ENV /Users/mat/.bashrc. También /bin/sh -c /Users/mat/.bashrcpor si acaso. • Necesito publicar otra actualización: mi suposición acerca de que NSUserScriptTask eliminaba el entorno era incorrecta. El env se pierde solo cuando se ejecutan scripts desde el menú Script en el NSStatusBar de todo el sistema. • Me pregunto si está arreglado en las ediciones más recientes de macOS. ¿Tiene unos minutos para intentar ejecutar el dump_env.shscript en mi pregunta anterior desde el menú Script?
Lo siento, ya ni siquiera uso bash, estoy en zsh.
Hola, @TonyWilliams, dije la parte tranquila en voz alta en mi comentario. ¿Robarías mis palabras como prefacio a tu asombrosa respuesta? El nudo parece ser como cron y launchd, no hay un proceso de inicio de sesión interactivo para configurar el entorno, ya que el menú de la secuencia de comandos de la GUI es para JXA y AppleScript, no para la línea de comandos.