如何以非 root 用户身份 运行 执行 cron 作业并记录作业的输出?
How to run a cron job as a non-root user and log the job's output?
If a service can run without privileges, use USER to change to a non-root user.
在 cron
的情况下,这似乎不切实际,因为 cron
需要 root 权限才能正常运行。然而,cron
运行s 的可执行文件不需要 root 权限。因此,我 运行 cron
本身作为 root
用户,但调用我的 crontab
脚本来 运行 可执行文件(在这种情况下,一个简单的 Python FTP 下载我写的脚本)作为非 root 用户通过 crontab -u <user>
命令。
cron/Docker 交互性和社区体验似乎仍处于起步阶段,但已经有一些非常好的解决方案。利用从 and this 优秀帖子中收集的经验教训,我得到了一个 Docker 文件,看起来像这样:
FROM python:3.7.4-alpine
RUN adduser -S riptusk331
WORKDIR /home/riptusk331
... boilerplate not necessary to post here ...
COPY mycron /etc/cron.d/mycron
RUN chmod 644 /etc/cron.d/mycron
RUN crontab -u riptusk331 /etc/cron.d/mycron
CMD ["crond", "-f", "-l", "0"]
并且 mycron
文件只是一个简单的 python 执行 运行ning 每分钟
* * * * * /home/riptusk331/venv/bin/python3 /home/riptusk331/ftp.py
这工作得很好,但我不确定这里是如何处理日志记录的。我没有看到 /var/log/cron
中保存的任何内容。我可以在我的终端上看到 cron
和 ftp.py
的输出,如果我在 Kitematic 中将其拉出,也可以在容器日志中看到。但是我不知道这里到底发生了什么。
所以我的第一个问题是:这里如何处理日志记录和输出(cron 作业后没有任何重定向),这个实现方法是否安全?
VonC 对 的回答建议将 > /proc/1/fd/1 2>/proc/1/fd/2
附加到您的 cron 作业以将输出重定向到 Docker 的 stdout
和 stderr
。这就是我俩都有些困惑的地方,并且 运行 遇到了麻烦。
我的 crontab 文件现在看起来像这样
* * * * * /home/riptusk331/venv/bin/python3 /home/riptusk331/ftp.py > /proc/1/fd/1 2>/proc/1/fd/2
没有任何重定向的输出出现已经去stdout/stderr,但我不完全确定。我只知道它出现在我的终端上。那么为什么需要这个重定向呢?
当我添加这个重定向时,我 运行 遇到了权限问题。回想一下,这个 crontab 是作为 非根用户 riptusk331
调用的。因此,我没有 root 访问权限并收到以下错误:
/bin/ash: can't create /proc/1/fd/1: Permission denied
Alpine 基础镜像基于一个名为 BusyBox and when you run crond
here you're getting the BusyBox cron and not any other implementation. Its documentation is a little sparse, but if you look at the crond source 的紧凑工具集(在 C 中),您会发现当它转到 运行 a 时根本没有任何重定向作业(参见 start_one_job
的非 sendmail 版本);作业的 stdout 和 stderr 是 crond 的 stdout 和 stderr。在 Docker 中,由于 crond 是容器的主要进程,因此它又成为容器的输出流。
docker logs
中出现的任何内容都定义为 stdout 或 stderr 或容器的主进程。如果此 cron 实现直接将您的作业输出写入那里,那么利用它并没有错或不安全。
在较重的容器编排系统中,有一些方法可以 运行 容器按计划(Kubernetes CronJobs,Nomad 周期性作业)。您可能会发现设置一个容器 运行 完成您的工作然后退出,然后设置 主机的 cron 到 运行 你的容器(必须是 root)。
您需要允许 CAP_SETGID 到 运行 crond
作为用户,如果将其设置为所有 busybox 二进制文件,这可能存在安全风险,但您可以使用 dcron
包而不是 busybox 的内置 crond
并在该程序上设置 CAP_SETGID
。这是您需要为 Alpine 添加的内容,使用 riptusk331
as 运行ning user
USER root
# crond needs root, so install dcron and cap package and set the capabilities
# on dcron binary https://github.com/inter169/systs/blob/master/alpine/crond/README.md
RUN apk add --no-cache dcron libcap && \
chown riptusk331:riptusk331 /usr/sbin/crond && \
setcap cap_setgid=ep /usr/sbin/crond
USER riptusk331
If a service can run without privileges, use USER to change to a non-root user.
在 cron
的情况下,这似乎不切实际,因为 cron
需要 root 权限才能正常运行。然而,cron
运行s 的可执行文件不需要 root 权限。因此,我 运行 cron
本身作为 root
用户,但调用我的 crontab
脚本来 运行 可执行文件(在这种情况下,一个简单的 Python FTP 下载我写的脚本)作为非 root 用户通过 crontab -u <user>
命令。
cron/Docker 交互性和社区体验似乎仍处于起步阶段,但已经有一些非常好的解决方案。利用从
FROM python:3.7.4-alpine
RUN adduser -S riptusk331
WORKDIR /home/riptusk331
... boilerplate not necessary to post here ...
COPY mycron /etc/cron.d/mycron
RUN chmod 644 /etc/cron.d/mycron
RUN crontab -u riptusk331 /etc/cron.d/mycron
CMD ["crond", "-f", "-l", "0"]
并且 mycron
文件只是一个简单的 python 执行 运行ning 每分钟
* * * * * /home/riptusk331/venv/bin/python3 /home/riptusk331/ftp.py
这工作得很好,但我不确定这里是如何处理日志记录的。我没有看到 /var/log/cron
中保存的任何内容。我可以在我的终端上看到 cron
和 ftp.py
的输出,如果我在 Kitematic 中将其拉出,也可以在容器日志中看到。但是我不知道这里到底发生了什么。
所以我的第一个问题是:这里如何处理日志记录和输出(cron 作业后没有任何重定向),这个实现方法是否安全?
VonC 对 > /proc/1/fd/1 2>/proc/1/fd/2
附加到您的 cron 作业以将输出重定向到 Docker 的 stdout
和 stderr
。这就是我俩都有些困惑的地方,并且 运行 遇到了麻烦。
我的 crontab 文件现在看起来像这样
* * * * * /home/riptusk331/venv/bin/python3 /home/riptusk331/ftp.py > /proc/1/fd/1 2>/proc/1/fd/2
没有任何重定向的输出出现已经去stdout/stderr,但我不完全确定。我只知道它出现在我的终端上。那么为什么需要这个重定向呢?
当我添加这个重定向时,我 运行 遇到了权限问题。回想一下,这个 crontab 是作为 非根用户
riptusk331
调用的。因此,我没有 root 访问权限并收到以下错误:
/bin/ash: can't create /proc/1/fd/1: Permission denied
Alpine 基础镜像基于一个名为 BusyBox and when you run crond
here you're getting the BusyBox cron and not any other implementation. Its documentation is a little sparse, but if you look at the crond source 的紧凑工具集(在 C 中),您会发现当它转到 运行 a 时根本没有任何重定向作业(参见 start_one_job
的非 sendmail 版本);作业的 stdout 和 stderr 是 crond 的 stdout 和 stderr。在 Docker 中,由于 crond 是容器的主要进程,因此它又成为容器的输出流。
docker logs
中出现的任何内容都定义为 stdout 或 stderr 或容器的主进程。如果此 cron 实现直接将您的作业输出写入那里,那么利用它并没有错或不安全。
在较重的容器编排系统中,有一些方法可以 运行 容器按计划(Kubernetes CronJobs,Nomad 周期性作业)。您可能会发现设置一个容器 运行 完成您的工作然后退出,然后设置 主机的 cron 到 运行 你的容器(必须是 root)。
您需要允许 CAP_SETGID 到 运行 crond
作为用户,如果将其设置为所有 busybox 二进制文件,这可能存在安全风险,但您可以使用 dcron
包而不是 busybox 的内置 crond
并在该程序上设置 CAP_SETGID
。这是您需要为 Alpine 添加的内容,使用 riptusk331
as 运行ning user
USER root
# crond needs root, so install dcron and cap package and set the capabilities
# on dcron binary https://github.com/inter169/systs/blob/master/alpine/crond/README.md
RUN apk add --no-cache dcron libcap && \
chown riptusk331:riptusk331 /usr/sbin/crond && \
setcap cap_setgid=ep /usr/sbin/crond
USER riptusk331