如何在Mac上每10秒以root用户身份运行一个ruby脚本?

时间:2022-06-01 18:13:48

I have the following in my /Library/LaunchDemons as com.me.filechecker.plist

我在/ Library / LaunchDemons中有以下内容作为com.me.filechecker.plist

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">
    <dict>
        <key>Label</key>
        <string>File Checker</string>
        <key>StartInterval</key>
        <integer>10</integer>
        <key>Program</key>
        <string>/usr/bin/ruby "/Users/me/projects/filechecker/filechecker.rb"</string>
    </dict>
</plist>

I also ran

我也跑了

sudo chown root /Library/LaunchDaemons/com.me.filechecker.plist

and

sudo chmod a+x /Library/LaunchDaemons/com.me.filechecker.plist

and

sudo launchctl load -w /Library/LaunchDaemons/com.me.filechecker.plist

It doesn't appear to be running (or if it is running, it isn't doing anything). How can I debug this and get it to work?

它似乎没有运行(或者如果它正在运行,它没有做任何事情)。我该如何调试它并使其工作?

2 个解决方案

#1


The executable name and its arguments should be passed the same way as to execvp function. You have to pass executable name and all arguments separately. Arguments should be passed in ProgramArguments key:

可执行文件名及其参数应该以与execvp函数相同的方式传递。您必须分别传递可执行文件名和所有参数。参数应该在ProgramArguments键中传递:

    <key>Program</key>
    <string>/usr/bin/ruby</string>
    <key>ProgramArguments</key>
    <array>
       <string>/usr/bin/ruby</string>
       <string>/Users/me/projects/filechecker/filechecker.rb</string>
    </array>

You can also skip Program key in this case. More in man launchd.plist

在这种情况下,您也可以跳过程序键。更多关于man launchd.plist

 Program <string>
 This key maps to the first argument of execvp(3).  If this key is missing, then the first element of
 the array of strings provided to the ProgramArguments will be used instead.  This key is required in
 the absence of the ProgramArguments key.

 ProgramArguments <array of strings>
 This key maps to the second argument of execvp(3).  This key is required in the absence of the Program
 key. Please note: many people are confused by this key. Please read execvp(3) very carefully!

#2


To complement baf's helpful answer (which shows how to use the ProgramArguments key to invoke an executable with arguments correctly):

补充baf的有用答案(显示如何使用ProgramArguments键正确调用带有参数的可执行文件):

While making the *.plist file executable should do no harm, there is no need to do so.
What matters is that the file:

虽然使* .plist文件可执行不会造成伤害,但是没有必要这样做。重要的是文件:

  1. must be owned by the user in whose context the job runs (which you've done with sudo chown root, though sudo chown root:wheel is better for consistency).
  2. 必须由作业运行的用户所拥有(使用sudo chown root执行的用户,尽管sudo chown root:wheel更好的一致性)。

  3. must not be group- or world-writeable for security reasons; thus, a typical file in /Library/LaunchDaemons, whose *.plist files run as the root user (by default), reports the following at the beginning of an output line from ls -l: -rw-r--r-- 1 root wheel ...
  4. 出于安全原因,不得为群组或世界可写;因此,/ Library / LaunchDaemons中的典型文件,其* .plist文件作为root用户运行(默认情况下),在ls -l的输出行的开头报告以下内容:-rw-r - r-- 1个根轮......

launchctl load, unfortunately, only generates an error message if the *.plist file is syntactically invalid, and generally always sets exit code 0, even in the event of an error.

遗憾的是,如果* .plist文件在语法上无效,则launchctl加载仅生成错误消息,并且通常始终设置退出代码0,即使出现错误也是如此。

To troubleshoot, open Console.app and look for com.apple.xpc.launchd entries:

要进行故障排除,请打开Console.app并查找com.apple.xpc.launchd条目:

If I do this after loading your *.plist file, I see several relevant entries, notably this one:

如果我在加载* .plist文件后这样做,我会看到几个相关的条目,特别是这个:

5/10/15 11:33:38.653 PM com.apple.xpc.launchd[1]: (File Checker[61800]) 
Could not find and/or execute program specified by service: 2: 
No such file or directory: /usr/bin/ruby "/Users/me/projects/filechecker/filechecker.rb"

This tells us that launchd thinks that the executable path is the whole string /usr/bin/ruby "/Users/me/projects/filechecker/filechecker.rb", because the Program key must only contain the executable path.

这告诉我们launchd认为可执行路径是整个字符串/ usr / bin / ruby​​“/Users/me/projects/filechecker/filechecker.rb”,因为Program key必须只包含可执行路径。

With the correction suggested by baf's answer, launchd should invoke the command correctly.

通过baf答案建议的修正,launchd应该正确调用命令。

#1


The executable name and its arguments should be passed the same way as to execvp function. You have to pass executable name and all arguments separately. Arguments should be passed in ProgramArguments key:

可执行文件名及其参数应该以与execvp函数相同的方式传递。您必须分别传递可执行文件名和所有参数。参数应该在ProgramArguments键中传递:

    <key>Program</key>
    <string>/usr/bin/ruby</string>
    <key>ProgramArguments</key>
    <array>
       <string>/usr/bin/ruby</string>
       <string>/Users/me/projects/filechecker/filechecker.rb</string>
    </array>

You can also skip Program key in this case. More in man launchd.plist

在这种情况下,您也可以跳过程序键。更多关于man launchd.plist

 Program <string>
 This key maps to the first argument of execvp(3).  If this key is missing, then the first element of
 the array of strings provided to the ProgramArguments will be used instead.  This key is required in
 the absence of the ProgramArguments key.

 ProgramArguments <array of strings>
 This key maps to the second argument of execvp(3).  This key is required in the absence of the Program
 key. Please note: many people are confused by this key. Please read execvp(3) very carefully!

#2


To complement baf's helpful answer (which shows how to use the ProgramArguments key to invoke an executable with arguments correctly):

补充baf的有用答案(显示如何使用ProgramArguments键正确调用带有参数的可执行文件):

While making the *.plist file executable should do no harm, there is no need to do so.
What matters is that the file:

虽然使* .plist文件可执行不会造成伤害,但是没有必要这样做。重要的是文件:

  1. must be owned by the user in whose context the job runs (which you've done with sudo chown root, though sudo chown root:wheel is better for consistency).
  2. 必须由作业运行的用户所拥有(使用sudo chown root执行的用户,尽管sudo chown root:wheel更好的一致性)。

  3. must not be group- or world-writeable for security reasons; thus, a typical file in /Library/LaunchDaemons, whose *.plist files run as the root user (by default), reports the following at the beginning of an output line from ls -l: -rw-r--r-- 1 root wheel ...
  4. 出于安全原因,不得为群组或世界可写;因此,/ Library / LaunchDaemons中的典型文件,其* .plist文件作为root用户运行(默认情况下),在ls -l的输出行的开头报告以下内容:-rw-r - r-- 1个根轮......

launchctl load, unfortunately, only generates an error message if the *.plist file is syntactically invalid, and generally always sets exit code 0, even in the event of an error.

遗憾的是,如果* .plist文件在语法上无效,则launchctl加载仅生成错误消息,并且通常始终设置退出代码0,即使出现错误也是如此。

To troubleshoot, open Console.app and look for com.apple.xpc.launchd entries:

要进行故障排除,请打开Console.app并查找com.apple.xpc.launchd条目:

If I do this after loading your *.plist file, I see several relevant entries, notably this one:

如果我在加载* .plist文件后这样做,我会看到几个相关的条目,特别是这个:

5/10/15 11:33:38.653 PM com.apple.xpc.launchd[1]: (File Checker[61800]) 
Could not find and/or execute program specified by service: 2: 
No such file or directory: /usr/bin/ruby "/Users/me/projects/filechecker/filechecker.rb"

This tells us that launchd thinks that the executable path is the whole string /usr/bin/ruby "/Users/me/projects/filechecker/filechecker.rb", because the Program key must only contain the executable path.

这告诉我们launchd认为可执行路径是整个字符串/ usr / bin / ruby​​“/Users/me/projects/filechecker/filechecker.rb”,因为Program key必须只包含可执行路径。

With the correction suggested by baf's answer, launchd should invoke the command correctly.

通过baf答案建议的修正,launchd应该正确调用命令。