在 OSX 上模拟 /etc/cron.d/

在 OSX 上模拟 /etc/cron.d/

在大多数现代 UNIX 上,cron 支持 中的各个 crontab 文件/etc/cron.d,其中每个任务都以指定用户的身份执行。这些文件编辑后会自动更新 crontab。它们允许各个包安装自己的自动化任务,而不会污染全局 crontab 或使用特定于用户的 crontab。

OSX 似乎不支持这一点——这是真的吗?

如果是这样,实施它的最佳方法是什么?由于我在 OSX 上进行开发,但在 Linux 上运行生产代码,因此我需要使用 crond 而不是 launchd,即使后者具有潜在的好处。

答案1

在 OS X 上,您应该使用 launchd。为了实现它,我将用一个例子来解释。

转到文件夹/Users/your-username/Library/LaunchAgents并保存以下 plist 文件。我命名了它com.username.testscript.plist,但请随意更改它。

<?xml version="1.0" encoding="UTF-8"?>
<!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>com.your-username.testscript</string>

  <key>ProgramArguments</key>
  <array>
    <string>/Users/your-username/bin/testscript.sh</string>
  </array>

  <key>Nice</key>
  <integer>1</integer>

  <key>StartInterval</key>
  <integer>60</integer>

  <key>RunAtLoad</key>
  <true/>

  <key>StandardErrorPath</key>
  <string>/tmp/com.your-username.testscript.err</string>

  <key>StandardOutPath</key>
  <string>/tmp/com.your-username.testscript.out</string>
</dict>
</plist>

该文件非常不言自明。它将/Users/your-username/bin/testscript.sh每 60 秒启动一次命令,将在加载时启动,将保存错误/tmp/com.username.testscript.err并登录/tmp/com.username.testscript.out

您还可以使用目录/Library/LaunchAgents//Library/LaunchDaemos/.

答案2

您可以像往常一样在 OS X 上使用 crontab,唯一的区别是每个用户的文件位于 /usr/lib/cron/tabs/ 中。该corontab命令知道如何访问它们。请注意,cron 守护程序默认情况下不会在 OS X 上运行,但launchd如果 /usr/lib/cron/tabs/ 中有任何文件,或者 /etc/crontab 存在,则会启动它。

说到launchd:正如 @jherran 所说,launchd项目是在 OS X 上执行此类操作的更正常方式,但它们与 cron 作业有点不同:

  • 有两种主要类型的launchd项目:LaunchDaemons(通常以 root 身份运行)和 LaunchAgents(以普通用户身份运行,但仅在登录会话中运行)。 LaunchAgents 还可以在系统范围内安装在 /Library/LaunchAgents(它们将为任何登录的用户运行)或按用户安装在 ~/Library/LaunchAgents(它们仅为该用户运行)。 LaunchDaemons 只能在系统范围内安装。

    相比之下,cron 作业(包括每用户作业)独立于任何登录会话运行。

  • 如果计算机在计划的启动时间处于睡眠状态或关闭状态,则 cron 作业将被跳过。launchd项目将在下一次机会运行(即在唤醒、启动、登录等之后),尽管多次错过的运行将合并为一次运行。

  • cron 以一种即发即忘的方式开始其工作;launchd监视其子项,如果它们崩溃或退出,可能会重新启动它们(请KeepAlive参阅man launchd.plist)和/或清理(即杀死)它们启动的任何子进程(请参阅密钥AbandonProcessGroup)。如果您的作业自行守护,并且不调整 .plist 文件中的相关设置,这可能会导致很多麻烦。

  • launchd支持何时启动项目的更多选项:特定时间、时间间隔、许多不同类型的事件,始终保持运行...再次,请参阅man launchd.plist

  • 最后,launchd.plist 文件中的命令格式让很多人困惑。launchd不通过 shell 运行命令,因此变量引用、~路径、I/O 重定向等不起作用。此外,它不需要命令行,它需要ProgramArguments键中的单词“数组”,这些单词本质上被视为命令及其参数。例如/path/to/somecommand -xv "arg number 1" arg2 arg3 >>/tmp/somecommand.log可以写成:

    <key>ProgramArguments</key>
    <array>
        <string>/path/to/somecommand</string>
        <string>-xv</string>
        <string>arg number 1</string>
        <string>arg2</string>
        <string>arg3</string>
    </array>
    <key>StandardOutPath</key>
    <string>/tmp/somecommand.log</string>
    

    还有一个关键,但除非你很好地理解了 的论点,Program否则不要使用它。execvp说真的,只是不要。

    如果您需要让 shell 解释您的命令,您可以显式调用一个:

    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>-c</string>
        <string>~/bin/somecommand -xv "arg number 1" arg2 arg3 >>~/Desktop/somecommand.log</string>
    </array>
    

答案3

如果您查看目录,/usr/lib/cron那里有一个子目录,jobs我只能假设它与/etc/cron.d.

相关内容