Resumen
¿Cómo puedo ejecutar scripts desde el menú scriptsscriptscripts 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ú scriptsscriptscripts pueden encontrar y ejecutar comandos del sistema base. Sin embargo, las utilidades instaladas por el usuario no se encuentran en la ruta. También, /usr/bin/env foo
no encuentra los comandos que están instalados fuera del sistema base.
Antecedentes
El menú del sistema script aparece en la parte derecha de la barra de menús. Se habilita a través de scriptEditor.app > Preferencias > Mostrar scriptmenú en la barra de menús. Muestra ubicados en ~/Library/Scripts
y otras ubicaciones del sistema. El menú puede ejecutar AppleScript, JXA, bash, Python y otros scripts (utilice shebang según sea necesario).
La investigación hasta ahora
Los scripts que se ejecutan desde el menú scriptsscriptscripts 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 scriptsscriptscripts para volcar el env
a un archivo de texto
~/Library/scripts/dump_env.sh (asegúrese de hacerla 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, las siguientes no están disponibles:
/usr/local/bin/svn # Subversion source control client
/opt/local/bin/python3 # python3 installed via MacPorts
~/bin
Estos dos últimos se encuentran normalmente en mi .bash_profile. /usr/local/bin/
está configurado por path_helper
que es llamado por /etc/profile
(aunque aparentemente no para el menú script).
Estoy usando MacOS 10.13 High Sierra, pero me interesa saber si otros están obteniendo resultados diferentes.
Solución ideal
- Evite codificar la ruta de acceso a los ejecutables en el shebang. Por ejemplo: si instalo una versión / distribución de Python diferente, quiero usarla en todos mis scripts.
/usr/bin/env python3
logra esto, pero parece depender de la PATH? - Busca utilidades en /usr/local/bin
- Especificar PATH una vez para el CLI y el menú script (¿y GUI?). Si instalo un nuevo Python me gustaría que se utilizara en todas partes.
- Especifique la ruta de acceso sólo para los procesos de nivel de usuario. No quiero que los procesos del sistema utilicen los binarios de mis entradas de ruta de acceso (especialmente las entradas de ruta de acceso con permiso de usuario).
- Evitar romper builds/instaladores/programas de terceros que fueron escritos con suposiciones sobre lo que está presente en mi instalación de MacOS.
Estoy investigando launchctl
que se puede utilizar para configurar el entorno de las aplicaciones de la GUI. No estoy seguro si todavía funciona o si funcionará con el menú script.
Actualización
He añadido declaraciones de rastreo 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 originado. Ninguno de ellos se ejecuta para scripts ejecutados desde el menú scriptsscriptscripts.
launchctl setenv KEY VALUE
establecerá una variable de entorno para todos los procesos lanzados posteriormente por los servicios de lanzamiento (launchd) en el espacio de usuario.
Esto funciona para Terminal.app, las aplicaciones GUI y los scripts sobre los que se hace doble clic en el Finder. Sin embargo, no funciona para el menú scriptsscriptscripts.
He añadido ps -ef
al dump_env.sh script. Esto me dice que el menú script no está invocando a bash con ningún argumento que pueda despojar el entorno (como -r o -p). El proceso padre es UserScriptService
.
Corriendo
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. De la documentación de la API:
La clase NSUserScriptTask es capaz de ejecutar todos los scripts que normalmente ejecuta una de sus subclases
https://developer.apple.com/documentation/foundation/nsuserscripttask?language=objc
Sospecho fuertemente que esto es lo que el menú script utiliza para ejecutar . El documento de la API no dice nada sobre el entorno de ejecución de script.