启动以正确读取程序参数


18

我有一个启动的脚本,其中我尝试运行的命令出错(显然这不是一个字,现在是),抱怨使用不当。

我得到的特定错误是转储到系统日志中的命令用法文本。据此,我推断plist中的其他信息(命令的路径,时间等)已正确解析,而不是命令的选项。

使用命令后,我有最后一行:

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

但这仅表示“我退出并出错”。

我知道launchd会将命令从其选项中分离出来,并且在手册页中向您介绍了ProgramArguments:“ ...请注意:许多人对此键感到困惑。请非常仔细地阅读execvp(3)!。”

好吧,我读了execvp(3),但我也不是明智的,所以我想问你很多。

通常,从终端运行命令如下所示:

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

这可以治疗。

这就是我在LaunchAgent plist的Program / ProgramArguments部分中将其拆分的方式:

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

(为记录起见,我本来拥有boinccmd的路径\\逃逸了,但这不起作用,为您启动了路径中的转义空格)

我试着进一步分解参数:

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

但这似乎也不起作用。

和以往一样,我非常确定自己缺少这么简单的东西。

谢谢。


回答:

ProgramArguments的第一行必须是程序的路径。这就是让我绊倒的东西,的确是“ ...请仔细阅读!..”注释的意思:)我还发现我不得不将参数分解为它们的组成部分。当我将所有这些都放在适当的位置时,整个过程就很有吸引力。非常感谢你。

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

关于为什么要这样的一个易于理解的解释的最终编辑,请参阅SirPavlova的解释。

〜W


通过使用launchctl list com.label.plist,我可以看到launchd正在将命令的正确部分拼凑在一起。我当时想这可能是与-有关的问题,但显然不是。
伍德吉

1
我没有你的问题的答案,但你与第一例子<string>--host localhost</string>肯定不会工作。请记住,当您向外壳程序编写命令行时,它不知道选项的组成部分和常规参数是什么- 将参数传递给正在运行的程序之前,它只是在空格上分割。另外,如果您要显示boinccmd正在报告的确切错误,则可能会有所帮助。
凯文·里德

编辑我的帖子以说出我所看到的。并非所有的帮助!另外,如果我在空格上拆分选项,也会遇到相同的错误。我猜这是-某种程度上导致了问题。
伍德吉

1
我会尝试仅使用Program或ProgramArguments而不是全部使用
user151019 2013年

Answers:


19

Program键指定文件来执行,与该ProgramArguments键指定将被传递到执行过程中的参数。严格来说,您可以将所需的任何参数传递给流程,但是约定是,第一个参数应该是调用流程的名称,因此大多数程序会忽略其第一个参数。要执行的文件显然是必要的信息,但是如果 Program缺少密钥,则启动只是假装它具有与第一个参数相同的值,这ProgramArguments 只是为了方便

第一个示例启动boinccmd并为其提供与terminal命令等效的参数

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

它告诉boinccmd您以“ --host localhost”的身份调用了它,并且只向它传递了两个奇怪的参数。

您的第二个示例正确地分隔了参数,但是正如Eddie Kelley所建议的,它需要在前面插入一个参数。它告诉boinccmd您以“ --host”的身份调用了它,然后传递了另外六个参数。boinccmd可以将最后五个识别为两个选项,但不知道“ localhost”业务是什么。据boinccmd所知,它是从终端调用的

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

(请注意缺少的“ --host”)。

boinccmd可能是大多数程序中的其中一个,它们并不关心第一个参数是什么,因此您实际上可以将其推<string>HELLO</string>ProgramArguments数组的最前面,但是Program完全删除键并使用以下代码可能更干净:

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

看起来似乎毫无意义的冗余,但是某些程序使用它会产生良好的效果:bash等。如果它们的第一个参数以'。'开头,则充当登录shell;如果-Vim的第一个参数是edvi代替,Vim会进入各种仿真模式vim


1
您是在我编辑主帖子时发布的!这是一个很好的解释。谢谢。
伍德吉

1
很高兴能为您提供帮助:)
SirPavlova

@SirPavlova,很大的帮助!但是,是否有任何工具可以帮助人们将控制台调用转换为plist格式?
gaussblurinc 2014年

6

根据exec(3)的手册页,似乎第一个程序参数应该是可执行文件的路径:

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.

如果您可以将可执行文件的路径指定为索引0处的参数,则可能会有所帮助...


当我编辑该帖子以显示时,正在找到并运行boinccmd,传递给它的选项在某种程度上受到了干扰。除非我想念你在说什么。
伍德吉

1
@Woodgie是的,可以在程序中找到-您的ProgramArguments不正确,它需要可执行文件的路径名
user151019 2013年

哦。哦!我想我现在知道了。等一下,让我测试一下。
伍德吉

BINGO这样做,然后将每个命令的每个部分放入其自己的<string> </ string>容器中即可。谢谢。我告诉你这很简单!
伍德吉
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.