#cron #jobs #container #user #run #lxc #pid

bin+lib lxcrond

为 lxc 容器提供的 cron 和 entr/inotify 服务器

2 个版本

0.2.1 2020年4月8日
0.2.0 2020年4月8日

#2 in #lxc

GPL-3.0-only

49KB
1K SLoC

lxcrond - lxc 容器的 cron

特性

  • 单个二进制文件,使用 musl 静态编译,便于 lxc 部署。

  • 无需 shell 环境。

  • 无外部依赖,既不使用 sendmail 也不使用 syslog。

  • 以 root 身份运行守护进程,作业以低权限用户身份运行。

  • 无需特殊编辑器或文件重新加载。

  • 也是 entr/inotify 的替代品或简单的 ESB,用于检测和处理传入的文件。

  • 可以作为 Rust 代码中的 cron 库使用。

  • 生成 pid 文件,因此可以在 lxinitd 中配置 service /run/lxcrond.pid /sbin/lxcrond

    let cron = Cron::new(some_jobs); std:🧵:spawn(move|| { cron.run(); });

文件格式

完整语法

启动时读取单个文件 /etc/lxcrontab,除非指定了不同的文件。

正常 cron 格式,如 /etc/crontab,但命令不是一个 bash 行。它是命令,加上可选的 " 引号参数。

# m   h  dom mon dow  user       command
23  1  *   *   *      teknopaul  /usr/bin/linci admin "backup"

支持所有 * 和一系列值 5,10,15

支持 busybox 中的标准别名 @daily 等,以及一些其他别名。

支持绝对文件名,如果文件已更改或创建,则运行作业。

# path                       user       command
/mnt/cipublish/nginx.conf    root       /bin/update-nginx

支持绝对目录,如果文件到达,则运行作业。作业应删除或移动文件,否则每 60 秒可能会重新运行。

# path             user       command
/mnt/uploads       clam       /bin/scan-uploads

用法

用法: lxcrond [options]

Options:
-c, --config [conf_file]
                    specify config file, default is /etc/lxcrontab
-h, --help          print this help menu
-v, --verbose       print debug information to stdout
-V, --version       print version number and exit
-f, --filesystem-watch 
                    use filesystem polling every 60 seconds to handle file jobs instead of inotify

如果没有作业要运行,lxcrond 将退出。

软件设计

主循环每 60 秒同步运行一次,然后在 :00 时询问是否现在是运行任何作业的时间。文件操作使用 Linux 内核的 inotify 接口,或者作为后备,每 60 秒检查目录。

时间考虑

在计算机上处理时间有许多注意事项,此程序采用简单的方法,假设时间跳跃有原因,主机所有者无需假设就能理解。
如果系统时间跳跃超过一分钟,则作业可能不会运行,因为在这个机器上“没有发生”这些时间。如果时间倒退,作业可能会运行两次,因为时间“发生了两次”。
提供的时间跳跃远小于60秒,因此不应该发生任何奇怪的事情,ntpd 确保时间同步而不出现大的时间跳跃。因此,如果您设置cron每天运行 23 12 * * *,任务将在 12:23:00 运行,前提是当主循环触发时,机器上实际上发生了时间或任何时间,直到 12:23:59
主循环每60秒触发一次。这个持续时间由可以由Rust解释的相同时钟确定。Rust在考虑Duration时对系统时间进行大量解释,具体来说,它试图确保Durations不会重复发生,无论系统时钟有多扭曲。
查看 Struct std::time::Instant
如果系统负载非常重或者进程被过度优化,则可能发生时间发生但没有代码运行的情况。
时间 now 在每个循环中只计算一次,所以如果任何作业以给定的时间规范运行,所有具有相同时间规范的作业都将运行,即使在非常重负载的系统上,也降低了作业自身消耗100% CPU的风险。

时区考虑

注意。所有时间都是本地时间。作业在当前时区运行,因此如果您使用笔记本电脑旅行并切换时区,作业可能不会触发或可能触发两次。

夏令时考虑

如果您不幸居住在实行夏令时的时区,某些时间在同一天发生两次。Busybox crond通过在时间跳跃为一小时时不重新触发作业来处理这种情况,lxcrond 则不这样做。这意味着您可以将作业计划为每5分钟运行一次,它们将在夏令时日正确运行。

inotify考虑

如果使用inotify轮询文件,存在各种注意事项,最重要的是目录不会被递归轮询。还有许多其他inotify的细节可能导致作业未运行,请参阅 man 7 inotify

待办事项请查看.later

错误请查看.later

LXC考虑

如果使用 cargo build --release --target=x86_64-unknown-linux-musl 编译,则此程序的唯一依赖项是配置文件 /etc/lxcrontab/etc/passwd
/etc/passwd 是确定执行作业的用户所需的。如果无法读取 /ect/passwd,则 lxcrond 将不会继续,以避免意外运行没有 $HOME
或意外的 pwd 的脚本。

构建

默认情况下,使用 make 使用 cargo 和 musl 目标进行构建,要安装此目标,请运行

rustup target add x86_64-unknown-linux-musl
make
make deb
make install

作者

(c) teknopaul 2020

依赖项

~4–5.5MB
~85K SLoC