【问题标题】:How can I run a ruby script as root every 10 seconds on a Mac?如何在 Mac 上每 10 秒以 root 身份运行 ruby​​ 脚本?
【发布时间】:2015-05-10 18:44:51
【问题描述】:

我的 /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>

我也跑了

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

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

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

它似乎没有运行(或者如果它正在运行,它什么也没做)。我怎样才能调试它并让它工作?

【问题讨论】:

  • 您为脚本设置的permissions 是什么,您是否也尝试过将其作为cronjob 运行?还有一个想法——考虑也发布ruby script;这可能是脚本中的问题。
  • cronjobs 是否以 root 身份运行?如果是,我该怎么做才能将它添加为 cronjob,并且每次启动计算机时它会自动启动吗?权限是 a+x chmodded。
  • 文件有权限... -rwxr-xr-x@ 1 root wheel 458 May 10 11:36 com.me.filechecker.plist (IDK什么是“wheel”)
  • 对于cronjobsdaemons,这些权限通常应该没问题。 cronjobs 可以根据用户运行任务的需要使用权限,当你启动计算机时它也会自动运行,所以它相当灵活。当您从Terminal.app 执行脚本时,您的脚本是否正常运行,它有什么作用?正如我之前提到的,您可能会考虑发布脚本,以便我们可以看到它到底在做什么。也可以在终端中尝试这个命令:ps aux | grep filechecker - 你看到列出了什么吗?
  • wheelroot 用户所属的特殊用户组的名称 - 请参阅superuser.com/a/191969/139307

标签: macos launchd


【解决方案1】:

可执行文件名称及其参数应该以与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>

在这种情况下,您也可以跳过Program 键。更多内容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!

【讨论】:

  • 好建议,但您不应双引号引用第二个 &lt;string&gt; 元素的值 - 不涉及 shell,因此不执行引号删除。加上引号后,它们就成为参数本身的一部分。
  • @mklement0 已更正。谢谢!
  • P.S.:我想说,为了简单起见,通常最好只使用 ProgramArguments 键。
【解决方案2】:

补充baf's helpful answer(说明如何使用ProgramArguments 键正确调用带参数的可执行文件):

虽然使*.plist 文件可执行应该没有害处,但没有必要这样做。
重要的是文件:

  1. 必须归作业运行所在上下文的用户所有(您已经使用sudo chown root 完成了此操作,尽管sudo chown root:wheel 更利于保持一致性)。
  2. 出于安全原因,不得组可写或全局可写;因此,/Library/LaunchDaemons 中的一个典型文件,其*.plist 文件作为root 用户(默认情况下)运行,在ls -l 的输出行开头报告以下内容:-rw-r--r-- 1 root wheel ...

launchctl load,不幸的是,只有在*.plist 文件语法无效时才会生成错误消息,并且通常总是设置退出代码0,即使在发生错误。

疑难解答打开 Console.app 并查找 com.apple.xpc.launchd 条目:

如果我在加载您的 *.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"

这告诉我们launchd 认为可执行文件 路径是整个字符串 /usr/bin/ruby "/Users/me/projects/filechecker/filechecker.rb",因为Program 键必须only em> 包含可执行路径。

根据baf's answer 建议的更正,launchd 应该正确调用命令。

【讨论】:

    猜你喜欢
    • 2010-09-09
    • 2014-04-29
    • 2012-08-06
    • 2023-03-16
    • 2014-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多