Ich habe ein launchd-Skript, in dem der Befehl, den ich ausführen möchte, fehlerhaft ist (anscheinend ist das kein Wort, es ist jetzt) und sich über unsachgemäße Verwendung beschwert.
Der spezifische Fehler, den ich erhalte, ist der Verwendungstext des Befehls, der im Systemprotokoll abgelegt wird. Daraus schließe ich, dass die anderen Informationen (Pfad zum Befehl, Timing usw.) in der plist korrekt analysiert werden, nur nicht die Optionen des Befehls.
Nach der Befehlsverwendung habe ich eine letzte Zeile:
18/11/2013 09:30:00.101 com.apple.launchd.peruser.501: (fake.lable.seti[33833]) Exited with code: 1
Aber das bedeutet nur "Ich habe mit einem Fehler beendet".
Ich weiß, dass launchd den Befehl von seinen Optionen trennt und in der Manpage über ProgramArguments informiert: "...Bitte beachten Sie: Viele Leute sind durch diesen Schlüssel verwirrt. Bitte lesen Sie execvp(3) sehr sorgfältig!..."
Nun, ich habe execvp(3) gelesen und bin nicht klüger geworden, also frage ich Sie sehr viel.
Normalerweise würde es beim Ausführen des Befehls vom Terminal so aussehen:
/Library/Application\ Support/BOINC\ Data/boinccmd --host localhost --passwd gobbledygook --project http://setiathome.berkeley.edu/ update
Das funktioniert wunderbar.
Und so habe ich es im Abschnitt Program/ProgramArguments meiner LaunchAgent-Liste aufgeteilt:
<key>Program</key>
<string>/Library/Application Support/BOINC Data/boinccmd</string>
<key>ProgramArguments</key>
<array>
<string>--host localhost</string>
<string>--passwd gobbledygook</string>
<string>--project http://setiathome.berkeley.edu/ update</string>
</array>
(Für die Aufzeichnung, ich hatte ursprünglich den Pfad zu boinccmd \escaped out, aber das funktioniert nicht, launchd entkommt Leerzeichen im Pfad für Sie)
Ich habe versucht, die Argumente weiter aufzuteilen:
<key>Program</key>
<string>/Library/Application Support/BOINC Data/boinccmd</string>
<key>ProgramArguments</key>
<array>
<string>--host</string>
<string>localhost</string>
<string>--passwd</string>
<string>gobbledygook</string>
<string>--project</string>
<string>http://setiathome.berkeley.edu/</string>
<string>update</string>
</array>
Aber auch das schien nicht zu funktionieren.
Wie immer bin ich mir sehr sicher, dass ich etwas so Einfaches vermisse.
Vielen Dank.
ANTWORTEN:
Die erste Zeile von ProgramArguments muss der Pfad zum Programm sein. Das war es, was mich stolperte und was wahrscheinlich mit dem Kommentar "... Bitte sehr sorgfältig lesen! ..." gemeint war :) Ich fand auch, dass ich die Argumente in ihre Bestandteile aufteilen musste. Wenn ich das alles an Ort und Stelle hatte, wirkt das Ganze wie ein Zauber. Ich danke Ihnen sehr.
<key>Program</key>
<string>/Library/Application Support/BOINC Data/boinccmd</string>
<key>ProgramArguments</key>
<array>
<string>/Library/Application Support/BOINC Data/boinccmd</string>
<string>--host</string>
<string>localhost</string>
<string>--passwd</string>
<string>gobbledygook</string>
<string>--project</string>
<string>http://setiathome.berkeley.edu/</string>
<string>update</string>
</array>
Eine abschließende Bearbeitung für eine leicht verständliche Erklärung, WARUM dies sein sollte, siehe SirPavlovas Erklärung.
~W
Der Program
Schlüssel gibt die auszuführende Datei an, und der ProgramArguments
Schlüssel gibt die Argumente an, die an den ausführenden Prozess übergeben werden. Genau genommen können Sie einem Prozess beliebige Argumente übergeben, aber die Konvention ist, dass das erste Argument der Name sein sollte, mit dem der Prozess aufgerufen wurde, sodass die meisten Programme ihr erstes Argument ignorieren. ‡ Die auszuführende Datei ist offensichtlich eine notwendige Information, aber wenn der Program
Schlüssel fehlt, gibt launchd aus ProgramArguments
reiner Bequemlichkeit vor, denselben Wert wie das erste Argument zu haben .
Ihr erstes Beispiel startet boinccmd und gibt ihm Argumente, die dem Terminalbefehl entsprechen würden
--host\ localhost --passwd\ gobbledygook --project\ http://setiathome.berkeley.edu/\ update
was boinccmd mitteilt, dass Sie es als "--host localhost" aufgerufen und ihm nur zwei seltsame Argumente übergeben haben.
Ihr zweites Beispiel trennt die Argumente korrekt, aber wie Eddie Kelley vorgeschlagen hat, muss eines an der Vorderseite eingefügt werden. Es teilt boinccmd mit, dass Sie es als "--host" aufgerufen und dann weitere sechs Argumente übergeben haben. boinccmd kann die letzten fünf als zwei Optionen erkennen, hat aber keine Ahnung, worum es bei dem „localhost“-Geschäft geht. Soweit boinccmd das beurteilen kann, wurde es vom Terminal als aufgerufen
/Library/Application\ Support/BOINC\ Data/boinccmd localhost --passwd gobbledygook --project http://setiathome.berkeley.edu/ update
(beachten Sie das fehlende "--host").
boinccmd ist wahrscheinlich eines der allermeisten Programme, die sich nicht darum kümmern, was ihr erstes Argument ist, also könnten Sie wahrscheinlich einfach <string>HELLO</string>
an den Anfang des ProgramArguments
Arrays schieben, aber es ist wahrscheinlich sauberer, den Schlüssel ganz zu entfernen Program
und einfach dies zu verwenden:
<key>ProgramArguments</key>
<array>
<string>/Library/Application Support/BOINC Data/boinccmd</string>
<string>--host</string>
<string>localhost</string>
<string>--passwd</string>
<string>gobbledygook</string>
<string>--project</string>
<string>http://setiathome.berkeley.edu/</string>
<string>update</string>
</array>
‡ Es mag wie eine bedeutungslose Redundanz erscheinen, aber einige Programme nutzen dies mit gutem Effekt: bash et al. fungieren als Login-Shells, wenn ihr erstes Argument mit beginnt -
, & Vim tritt in verschiedene Emulationsmodi ein, wenn sein erstes Argument ed
oder vi
anstelle von ist vim
.
Basierend auf der Manpage für exec(3) scheint es, dass das erste Programmargument der Pfad zur ausführbaren Datei sein sollte:
The execv(), execvp(), and execvP() functions provide an array of pointers to null-terminated strings
that represent the argument list available to the new program. The first argument, by convention,
should point to the file name associated with the file being executed. The array of pointers must be
terminated by a NULL pointer.
Wenn Sie den Pfad zur ausführbaren Datei als Argument bei Index 0 angeben können, kann dies hilfreich sein ...
Woodgie
Kevin Reid
<string>--host localhost</string>
wird definitiv nicht funktionieren. Denken Sie daran, wenn Sie eine Befehlszeile in eine Shell schreiben, hat diese keine Ahnung, was Teil einer Option und was ein reguläres Argument ist – sie teilt sich einfach bei Leerzeichen auf, bevor sie die Argumente an das ausgeführte Programm weitergibt. Es könnte auch hilfreich sein, wenn Sie den genauen Fehler anzeigen würden,boinccmd
der gemeldet wird.Woodgie
mmmmmm