在大多数现代 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
.