Obtener launchd para leer los argumentos del programa correctamente

Tengo un script de lanzamiento donde el comando que estoy tratando de ejecutar tiene un error (aparentemente eso no es una palabra, lo es ahora), quejándose de un uso inadecuado.

El error específico que recibo es el texto de uso del comando descargado en el registro del sistema. De esto, infiero que la otra información (ruta al comando, tiempo, etc.) en el plist se analiza correctamente, pero no las opciones del comando.

Después del uso del comando, tengo una última línea:

18/11/2013 09:30:00.101 com.apple.launchd.peruser.501: (fake.lable.seti[33833]) Exited with code: 1

Pero eso solo significa "Salí con un error".

Sé que launchd divide el comando de sus opciones y en la página de manual le informa sobre ProgramArguments: "... Tenga en cuenta: muchas personas están confundidas con esta clave. ¡Lea execvp (3) con mucho cuidado! ..."

Bueno, leí execvp (3) y no soy más sabio, así que les pido mucho.

Normalmente, ejecutar el comando desde la terminal se vería así:

/Library/Application\ Support/BOINC\ Data/boinccmd --host localhost --passwd gobbledygook --project http://setiathome.berkeley.edu/ update

Esto funciona de maravilla.

Y así es como lo dividí en la sección Program/ProgramArguments de mi plist de LaunchAgent:

<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>

(para que conste, originalmente tenía la ruta para boinccmd \escaped out, pero eso no funciona, lanzó espacios de escape en la ruta para usted)

He intentado dividir los argumentos aún más:

<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>

Pero eso tampoco pareció funcionar.

Como siempre, estoy muy seguro de que me estoy perdiendo algo tan simple.

Gracias.


RESPUESTA:

La primera línea de ProgramArguments debe ser la ruta al programa. Esto es lo que me estaba haciendo tropezar y, de hecho, lo que probablemente significaba el comentario "... ¡Lea con mucho cuidado! ..." :) También descubrí que tenía que dividir los argumentos en sus partes componentes. Cuando tuve todo eso en su lugar, todo funciona a la perfección. Muchísimas gracias.

<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>

Una edición final para decir una explicación fácil de entender de POR QUÉ debería ser esto, vea la explicación de SirPavlova.

~W

Al usar la lista de launchctl com.label.plist, puedo ver que launchd obtiene las partes correctas del comando para unirlas. Estaba pensando que tal vez era un problema relacionado con el --, pero aparentemente no.
No tengo una respuesta para su problema, pero su primer ejemplo <string>--host localhost</string>definitivamente no funcionará. Recuerde, cuando escribe una línea de comando en un shell, no tiene idea de qué es parte de una opción y qué es un argumento regular; simplemente se divide en espacios antes de pasar los argumentos al programa que se está ejecutando. Además, podría ayudar si mostrara el error exacto que boinccmdse informa.
Edité mi publicación para decir lo que estoy viendo. ¡No es que vaya a ser de alguna ayuda! Además, recibo el mismo error si divido las opciones en su espacio en blanco. Supongo que es el... lo que está causando el problema de alguna manera.
Intentaría usar solo Program o ProgramArguments, no ambos

Respuestas (2)

La Programclave especifica el archivo a ejecutar, y la ProgramArgumentsclave especifica los argumentos que se pasarán al proceso de ejecución. Estrictamente hablando, puede pasar los argumentos que desee a un proceso, pero la convención es que el primero debe ser el nombre con el que se invocó el proceso, por lo que la mayoría de los programas ignoran su primer argumento. El archivo a ejecutar es obviamente información necesaria, pero si Programfalta la clave, launchd finge que tiene el mismo valor que el primer argumento ProgramArguments simplemente por conveniencia .

Su primer ejemplo comienza boinccmd y le da argumentos que serían equivalentes al comando de terminal

--host\ localhost --passwd\ gobbledygook --project\ http://setiathome.berkeley.edu/\ update

que le dice a boinccmd que lo invocaste como "--host localhost" y solo le pasaste dos argumentos extraños.

Su segundo ejemplo separa los argumentos correctamente, pero como sugirió Eddie Kelley, necesita uno insertado en el frente. Le dice a boinccmd que lo invocó como "--host", luego pasó otros seis argumentos. boinccmd puede reconocer las últimas cinco como dos opciones, pero no tiene idea de qué se trata el negocio "localhost". Por lo que boinccmd puede decir, se invocó desde la terminal como

/Library/Application\ Support/BOINC\ Data/boinccmd localhost --passwd gobbledygook --project http://setiathome.berkeley.edu/ update

(tenga en cuenta el "--host" que falta).

boinccmd es probablemente uno de la gran mayoría de los programas a los que no les importa cuál es su primer argumento, por lo que probablemente podría empujar <string>HELLO</string>en la parte superior de la ProgramArgumentsmatriz, pero probablemente sea más limpio eliminar la Programclave por completo y simplemente usar esto:

<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>

Puede parecer una redundancia sin sentido, pero algunos programas usan esto con buenos resultados: bash et al. actúan como shells de inicio de sesión si su primer argumento comienza con -, & Vim ingresa a varios modos de emulación si su primer argumento es edo vien lugar de vim.

¡Publicaste mientras yo estaba editando mi publicación principal! Esta es una gran explicación. Gracias.
Me alegra ser de ayuda :)
@SirPavlova, ¡gran ayuda! Sin embargo, ¿hay alguna herramienta que ayude a la persona a convertir la invocación de la consola al formato plist?

Según la página de manual de exec(3), parece que el primer argumento del programa debería ser la ruta al ejecutable:

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.

Si puede especificar la ruta al ejecutable como argumento en el índice 0, puede ayudar...

Como he editado la publicación para mostrar, el boinccmd se está encontrando y ejecutando, las opciones que se le pasan de alguna manera están siendo alteradas. A menos que me esté perdiendo lo que estás diciendo.
@Woodgie Sí, eso se encontró en el programa: sus argumentos de programa son incorrectos, necesita el nombre de la ruta del ejecutable
Vaya. ¡OH! Creo que ahora veo. Espera, déjame probar eso.
BINGO, hacer eso y poner cada parte de cada comando en su propio contenedor <string></string> funcionó. Gracias. ¡Te dije que era sencillo!