Résumé
Comment puis-je exécuter des scripts depuis le menu global du Script avec un environnement normal ? Il semble que l'environnement ne soit pas du tout configuré.
Les scripts qui sont exécutés à partir du menu script peuvent trouver et exécuter des commandes du système de base. Cependant, les utilitaires installés par l'utilisateur ne sont pas trouvés sur le chemin. De plus, /usr/bin/env foo
ne trouve pas les commandes installées en dehors du système de base.
Contexte
Le menu Script du système apparaît sur le côté droit de la barre de menus. Il est activé via Script Editor.app > Préférences > Afficher le menu Script dans la barre de menus. Il affiche des scripts situés dans ~/Library/Scripts
et d'autres emplacements système. Le menu peut exécuter des scripts AppleScript, JXA, bash, python et autres scripts (utilisez un shebang si nécessaire).
Enquête Jusqu'à Présent
Les scripts exécutés à partir du menu Script n'héritent pas de l'environnement bash de l'utilisateur. Ils connaissent le shell BASH et le nom de l'utilisateur, mais aucune initialisation ne se produit. J'ai exécuté un petit script pour enregistrer l' env
dans un fichier texte
~/Library/Scripts/dump_env.sh (assurez-vous de le rendre exécutable):
#!/bin/bash
env > ~/env.txt
ps -ef >> ~/env.txt
Voici les entrées intéressantes.
USER=mat
LOGNAME=mat
SHELL=/bin/bash
PATH=/usr/bin:/bin:/usr/sbin:/sbin
PWD=/
HOME=/Users/mat
_=/usr/bin/env
C'est très basique. Aucun des chemins personnalisés ne sont inclus. Par exemple, les suivants sont indisponibles :
/usr/local/bin/svn # Client de contrôle de source Subversion
/opt/local/bin/python3 # python3 installé via MacPorts
~/bin
Les deux derniers sont normalement sourcés dans mon .bash_profile. /usr/local/bin/
est configuré par path_helper
qui est appelé par /etc/profile
(bien que apparemment pas pour le menu Script).
Je suis sous macOS 10.13 High Sierra, mais je suis intéressé de savoir si d'autres obtiennent des résultats différents.
Solution Idéale
- Éviter de coder en dur le chemin des exécutables dans le shebang. Par exemple, si j'installe une version/distribution de python différente, je veux l'utiliser dans tous mes scripts.
/usr/bin/env python3
permet d'accomplir cela, mais cela semble dépendre du PATH ? - Trouver des utilitaires dans /usr/local/bin
- Spécifier le PATH une fois pour l'interface en ligne de commande et le menu Script (et l'interface graphique ?). Si j'installe un nouveau Python, je voudrais qu'il soit utilisé partout.
- Spécifier le PATH uniquement pour les processus de niveau utilisateur. Je ne veux pas que les processus système utilisent des binaires à partir de mes entrées de chemin d'extension (surtout les entrées de chemin d'extension avec les permissions utilisateur).
- Éviter de casser les installations/programmes tiers qui ont été écrits en supposant ce qui est présent sur mon installation macOS.
Je regarde launchctl
, qui peut être utilisé pour configurer l'environnement des applications graphiques. Je ne sais pas si cela fonctionne toujours ou s'il fonctionnera avec le menu Script.
Mise à Jour
J'ai ajouté des déclarations de traçage à tous les fichiers d'environnement bash : /profile
, /bashrc
, ~/.bash_profile
, ~/.bashrc
. Ces déclarations exportent des variables d'environnement pour que je puisse voir que le fichier a été sourcé. Aucun de ceux-ci n'est exécuté pour les scripts exécutés à partir du menu Script.
launchctl setenv CLÉ VALEUR
définira une variable d'environnement pour tous les processus lancés ultérieurement par les services de lancement (launchd) dans l'espace utilisateur.
Cela fonctionne pour Terminal.app, les applications GUI et les scripts qui sont double-cliqués dans le Finder. Cependant, cela ne fonctionne pas pour le menu Script.
J'ai ajouté ps -ef
au script dump_env.sh. Cela me dit que le menu Script n'appelle pas bash avec des arguments qui supprimeraient l'environnement (comme -r ou -p). Le processus parent est UserScriptService
.
En cours d'exécution…
otool -tV /System/Library/Frameworks/Foundation.framework/Versions/C/XPCServices/com.apple.foundation.UserScriptService.xpc/Contents/MacOS/com.apple.foundation.UserScriptService.
…révèle un symbole nommé __NSUserScriptTaskServiceStart
. Cela ressemble étrangement à NSUserScriptTask dans l'API CoreFoundation. D'après la documentation de l'API :
La classe NSUserScriptTask est capable d'exécuter tous les scripts normalement exécutés par l'un de ses sous-classes…
https://developer.apple.com/documentation/foundation/nsuserscripttask?language=objc
Je soupçonne fortement que c'est ce que le menu Script utilise pour exécuter les scripts. La documentation de l'API ne dit rien sur l'environnement d'exécution du script.