Conseguindo que o launchd leia os argumentos do programa corretamente

18

Eu tenho um script launchd em que o comando que estou tentando executar está com erro (aparentemente isso não é uma palavra, é agora), reclamando de uso inadequado.

O erro específico que estou recebendo é o texto de uso do comando despejado no log do sistema. A partir disso, deduzo que as outras informações (caminho para o comando, tempo etc.) no plist estão sendo analisadas corretamente, mas não as opções do comando.

Após o uso do comando, tenho uma última linha:

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

Mas isso significa apenas "Saí com um erro".

Eu sei que o launchd divide o comando de suas opções e, na página de manual, fala sobre os ProgramArguments: "... Observe: muitas pessoas ficam confusas com essa chave. Por favor, leia o execvp (3) com muito cuidado! .."

Bem, eu li o execvp (3) e não sou o mais sábio, então estou pedindo muito a você.

Normalmente, executando o comando a partir do terminal, ficaria assim:

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

Isso funciona um prazer.

E foi assim que eu o dividi na seção Program / ProgramArguments da minha lista do 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 constar, eu originalmente tinha o caminho para boinccmd \ escapou, mas isso não funciona, o launchd escapa espaços no caminho para você)

Eu tentei dividir os argumentos ainda mais:

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

Mas isso também não parecia funcionar.

Como sempre, tenho certeza de que estou perdendo algo tão simples.

Obrigado.


RESPONDA:

A primeira linha de ProgramArguments precisa ser o caminho para o programa. Isso é o que estava me atrapalhando e, na verdade, o que provavelmente significava o comentário "... Por favor, leia com muito cuidado! .." :) Eu também descobri que precisava dividir os argumentos em suas partes componentes. Quando eu tinha tudo isso no lugar, a coisa toda funciona como um encanto. Muito obrigado.

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

Uma edição final para dizer uma explicação fácil de entender sobre POR QUE deveria ser, consulte a explicação de SirPavlova.

~ W

Woodgie
fonte
Usando launchctl list com.label.plist, posso ver que o launchd está reunindo as partes corretas do comando. Eu estava pensando que talvez fosse um problema relacionado ao -, mas aparentemente não.
Woodgie
1
Não tenho uma resposta para o seu problema, mas o seu primeiro exemplo <string>--host localhost</string>definitivamente não funcionará. Lembre-se, quando você escreve uma linha de comando em um shell, ela não faz ideia do que faz parte de uma opção e do que é um argumento regular - apenas divide os espaços antes de passar os argumentos para o programa que está sendo executado. Além disso, pode ajudar se você mostrar o erro exato que boinccmdestá relatando.
Kevin Reid
Editou minha postagem para dizer o que estou vendo. Não que isso ajude! Além disso, estou recebendo o mesmo erro se dividir as opções em seus espaços em branco. Eu estou supondo que é o que está causando o problema de alguma forma.
Woodgie
1
Eu tentaria usar apenas Program ou
ProgramArguments

Respostas:

19

A Programchave especifica o arquivo a ser executado e a ProgramArgumentschave especifica os argumentos que serão passados ​​para o processo de execução. A rigor, você pode passar os argumentos que deseja para um processo, mas a convenção é que o primeiro deve ser o nome pelo qual o processo foi chamado, para que a maioria dos programas ignore o primeiro argumento. O arquivo a ser executado é obviamente uma informação necessária, mas se a Programchave estiver faltando, o launchd finge que tem o mesmo valor que o primeiro argumento ProgramArguments apenas por conveniência .

Seu primeiro exemplo inicia o boinccmd e fornece argumentos que seriam equivalentes ao comando terminal

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

que diz ao boinccmd que você o chamou como "--host localhost" e só passou dois argumentos estranhos.

Seu segundo exemplo separa os argumentos corretamente, mas, como Eddie Kelley sugeriu, ele precisa de um inserido na frente. Diz ao boinccmd que você o chamou como "--host" e passou outros seis argumentos. O boinccmd pode reconhecer as cinco últimas como sendo duas opções, mas não tem idéia do que se trata o negócio "localhost". Tanto quanto o boinccmd pode dizer, foi invocado no terminal como

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

(observe o "--host" ausente).

O boinccmd é provavelmente um dos grandes programas que não se importam com o primeiro argumento deles, então você provavelmente pode simplesmente empurrar <string>HELLO</string>a cabeça da ProgramArgumentsmatriz, mas provavelmente é mais fácil remover a Programchave completamente e usar o seguinte:

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

Pode parecer uma redundância sem sentido, mas alguns programas usam isso com bom efeito: bash et al. agir como shells de login se o primeiro argumento começar com -, & Vim entra em vários modos de emulação se o primeiro argumento for edou vinão vim.

SirPavlova
fonte
1
Você postou enquanto eu estava editando meu post principal! Esta é uma ótima explicação. Obrigado.
Woodgie
1
Fico feliz em ajudar :)
#
@SirPavlova, grande ajuda! No entanto, existe alguma ferramenta que ajude a pessoa a converter a chamada do console para o formato plist?
gaussblurinc
6

Com base na página de manual do exec (3), parece que o primeiro argumento do programa deve ser o caminho para o executável:

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.

Se você pode especificar o caminho para o executável como o argumento no índice 0, isso pode ajudar ...

Eddie Kelley
fonte
Como editei a postagem para mostrar, o boinccmd está sendo encontrado e executado, as opções que estão sendo passadas para ele de alguma forma estão sendo confundidas. A menos que eu esteja perdendo o que você está dizendo.
Woodgie
1
@Woodgie Sim que foi encontrado em Programa - seus ProgramArguments é imcorrect que necessita o nome do caminho do executável
user151019
Oh OH! Eu acho que vejo agora. Espere, deixe-me testar isso.
Woodgie
BINGO, fazendo isso e colocando cada parte de cada comando em seu próprio contêiner <string> </string> funcionou. Obrigado. Eu disse que era simples!
Woodgie