Script-Menü: Referenzieren von Benutzerpfad-Dienstprogrammen (PATH / Umgebung fehlt)

Zusammenfassung

Wie kann ich Skripte aus dem systemweiten Skriptmenü mit einer normalen Umgebung ausführen? Es scheint, dass die Umgebung überhaupt nicht eingerichtet wird.

Skripte, die über das Skriptmenü ausgeführt werden, können Befehle vom Basissystem finden und ausführen. Vom Benutzer installierte Dienstprogramme werden jedoch nicht im Pfad gefunden. Außerdem /usr/bin/env foowerden keine Befehle gefunden, die außerhalb des Basissystems installiert sind.

Hintergrund

Das Systemskriptmenü wird auf der rechten Seite der Menüleiste angezeigt. Es wird über Script Editor.app > Preferences > Show Script menu in der Menüleiste aktiviert. Es zeigt Skripte an, die sich in ~/Library/Scriptsund anderen Systemspeicherorten befinden. Das Menü kann AppleScript, JXA, Bash, Python und andere Skripte ausführen (verwenden Sie Shebang nach Bedarf).

Geben Sie hier die Bildbeschreibung ein

Untersuchung bisher

Skripte, die über das Skriptmenü ausgeführt werden, erben nicht die Bash-Umgebung des Benutzers. Sie wissen, dass die Shell BASH und Ihr USER-Name ist, aber es findet keine Initialisierung statt. Ich habe ein kleines Skript ausgeführt, um das envin eine Textdatei zu kopieren

~/Library/Scripts/dump_env.sh (ausführbar machen) :

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

Hier die interessanten Einträge.

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

Es ist sehr vanillig. Keiner der benutzerdefinierten Pfade ist enthalten. Nicht verfügbar sind beispielsweise:

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

Die beiden letzteren stammen normalerweise aus meinem .bash_profile. /usr/local/bin/ist Setup, von path_helperdem aufgerufen wird /etc/profile(allerdings anscheinend nicht für das Script-Menü).

Ich verwende macOS 10.13 High Sierra, bin aber interessiert, ob andere andere Ergebnisse erzielen.

Ideale Lösung

  1. Vermeiden Sie die Hartcodierung des Pfads zu ausführbaren Dateien in Shebang. Beispiel: Wenn ich eine andere Python-Version / -Distribution installiere, möchte ich sie in allen meinen Skripten verwenden. /usr/bin/env python3erreicht dies, aber es scheint vom PATH abzuhängen?
  2. Findet Dienstprogramme in /usr/local/bin
  3. Geben Sie PATH einmal für CLI und Skriptmenü (und GUI?) an. Wenn ich ein neues Python installiere, möchte ich, dass es überall verwendet wird.
  4. Geben Sie PATH nur für Prozesse auf Benutzerebene an. Ich möchte nicht, dass Systemprozesse Binärdateien von in meinen Add-On-Pfadeinträgen verwenden (insbesondere Pfadeinträge mit Benutzerberechtigung).
  5. Vermeiden Sie es, Builds/Installer/Programme von Drittanbietern zu beschädigen, die mit Annahmen darüber geschrieben wurden, was in meiner macOS-Installation vorhanden ist.

Ich untersuche launchctl, mit dem die Umgebung für GUI-Apps eingerichtet werden kann. Ich bin mir nicht sicher, ob es noch funktioniert oder ob es mit dem Skriptmenü funktioniert.

Aktualisieren


Ich habe Trace-Anweisungen zu allen Bash-Umgebungsdateien hinzugefügt: /profile, /bashrc, ~/.bash_profile, ~/.bashrc. Diese Anweisungen exportieren Umgebungsvariable, damit ich sehen kann, dass die Datei bezogen wurde. Keines davon wird für Skripte ausgeführt, die über das Skriptmenü ausgeführt werden.

launchctl setenv KEY VALUEsetzt eine Umgebungsvariable für alle Prozesse, die anschließend von Startdiensten (launchd) im Benutzerbereich gestartet werden.

Dies funktioniert für Terminal.app, GUI-Anwendungen und Skripte, die im Finder doppelt angeklickt werden. Es funktioniert jedoch nicht für das Skriptmenü.

Ich habe ps -efdas Skript dump_env.sh hinzugefügt. Dies sagt mir, dass das Skriptmenü bash nicht mit Argumenten aufruft, die die Umgebung entfernen würden (wie -r oder -p). Der übergeordnete Prozess ist UserScriptService.

Betrieb…

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

… enthüllt ein Symbol namens __NSUserScriptTaskServiceStart. Das klingt sehr ähnlich wie NSUserScriptTask in der CoreFoundation-API. Aus dem API-Dokument:

Die Klasse NSUserScriptTask kann alle Skripte ausführen, die normalerweise von einer ihrer Unterklassen ausgeführt werden …

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

Ich vermute stark, dass dies das ist, was das Skriptmenü verwendet, um Skripte auszuführen. Das API-Dokument sagt nichts über die Laufzeitumgebung des Skripts aus.

Können Sie nicht einfach .bashrc usw. aus Ihrem Skript beziehen?
nohillside – Ja, Sourcing .bashrcfunktioniert gut für Bash-Skripte. Ich stelle meine Skripte auf Python um, also ist mein Hauptfall, so etwas wie #!/usr/bin/env python3das Arbeiten zu bekommen. Ich brauche die Umgebung, um python3 zu finden. Ich habe ein Bash-Skript mit einem Here-Doc für Python ausprobiert. Es funktioniert, aber das bricht die Syntaxfärbung des Editors. Das bricht wahrscheinlich auch den Python-Debugger.
Warum dann nicht direkt den Pfad zu python3 angeben?
Ich verstehe die Prämisse der „normalen Umgebung“ nicht, der grafische Skripteditor ist für AppleScript und JXA, also müssen Sie beliebige Shells handhaben, die keine interaktive Anmeldung aufrufen, wie Sie es mit cron- oder launchd-Aufgaben tun. (Mit Referenzen könnte dies die Antwort sein?)

Antworten (1)

bashkann auf drei verschiedene Arten gestartet werden und wie es rc-Dateien verwendet, ist in jedem Fall unterschiedlich.

Um eine kurze Antwort zu geben, wenn es als Login-Shell aufgerufen wird, liest es .profileoder .bash_profileDinge wie PATH. Wenn es als interaktive Shell, aber nicht als Login-Shell aufgerufen wird, sagen Sie, dass Sie es bashvon der Befehlszeile aus ausführen, dann liest es, ~/.bashrcum diese Dinge festzulegen.

Wenn es von einem Shell-Skript (oder von launchctl) ausgeführt wird, sucht es nach einer Umgebungsvariablen BASH_ENVund führt die in der Variablen benannte Datei aus.

Überprüfen Sie https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html

Um Ihre Frage zu beantworten, sollten Sie alle Variablen in setzen .bashrc, rufen Sie das in Ihrer .bash_profileDatei mit der Zeile if [ -f ~/.bashrc ]; then source ~/.bashrc; fiSchließlich in sollten Sie die Variable .bashrcsetzenBASH_ENVexport BASH_ENV='.bashrc'

Das würde dir dann PATHüberall ein und so weiter geben.

Wenn Sie zur zshShell wechseln, sind die Dinge etwas anders, lesen Sie http://zsh.sourceforge.net/Intro/intro_3.html

Die meisten Mac-Administratoren und -Ingenieure ignorieren das alles, und wir codieren den Pfad zu all unserer Software in Skripten fest. Ich habe sicherlich noch nie ein Apple-Skript gesehen, in dem nicht alle Werkzeugpfade fest codiert waren.

Leider wird all dies vom System-Script-Menü ignoriert. Siehe mein Update zur Frage. Anscheinend brauchen wir einen vierten Fall: Aufrufen von Bash über die Objective-C-API . Ich verwende derzeit ein Kluge, bei dem ich mein eigenes Umgebungsinitialisierungsskript im Shebang angebe. Einige Vorbehalte hier: stackoverflow.com/a/9988385/199296
Haben Sie eingestellt und exportiert BASH_ENVund worauf haben Sie es eingestellt? Ich vermute, dass launchctl zum Beispiel keine Tilde für Zuhause respektiert.
Ich habe eine ~/Library/Launch Agents/bashenv.plist, die angibt launchctl setenv BASH_ENV /Users/mat/.bashrc. Es auch /bin/sh -c /Users/mat/.bashrcfür ein gutes Maß. • Ich muss ein weiteres Update posten – meine Vermutung, dass NSUserScriptTask die Umgebung entfernt, war falsch. Die env geht nur verloren , wenn Skripte aus dem Skriptmenü in der systemweiten NSStatusBar ausgeführt werden. • Ich frage mich, ob es in neueren Ausgaben von macOS behoben ist. dump_env.shHaben Sie ein paar Minuten Zeit, um das Skript in meiner obigen Frage über Ihr Skriptmenü auszuführen ?
Tut mir leid, ich benutze bash nicht einmal mehr, ich bin auf zsh.
Hallo @TonyWilliams, ich habe den leisen Teil in meinem Kommentar laut ausgesprochen. Würdest du meine Worte als Vorwort zu deiner großartigen Antwort stehlen? Der Nub scheint wie cron und launchd zu sein, es gibt keinen interaktiven Anmeldeprozess, um die Umgebung festzulegen, da das GUI-Skriptmenü für JXA und AppleScript ist, nicht für die Befehlszeile.