为什么在alpine linux上,crond无法运行非root用户的crontab?

13

在Alpine Linux上,我运行一个非root用户的crontab文件时遇到了困难。

我查看了其他两篇与cron相关的文章,但没有找到答案:

https://askubuntu.com/questions/23009/why-crontab-scripts-are-not-working

https://serverfault.com/questions/449651/why-is-my-crontab-not-working-and-how-can-i-troubleshoot-it

以下是我的设置:

我的crontab看起来像这样:

PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/ec2-user/bin
SHELL=/bin/bash

* * * * * /opt/monitor/monitor.sh >> /var/log/monitor.log 2>&1
0 3 * * * /opt/monitor/monitor-log-clean.sh >> /var/log/monitor.log 2>&1

我的Dockerfile有点乱,只是因为我一直在努力解决这个问题。它看起来像这样。简而言之,我添加了SUID以使crontab -e能够像其他用户一样工作,创建了我的用户,导入了我的crontab文件,然后为我能想到的所有内容提供了权限。

FROM alpine:3.5

# DEPENDENCY TO ALLOW USERS TO RUN crontab -e
RUN apk add --update busybox-suid

# I LIKE BASH
RUN apk --no-cache add bash bash-doc
RUN apk --no-cache add util-linux pciutils usbutils coreutils binutils findutils grep

#... lots of custom stuff ...    

# CREATE USER
RUN adduser -S robuser && \
    mkdir -p /home/robuser

# ADD ENTRY POINT
ADD src/entrypoint.sh /home/robuser/entrypoint.sh

# GIVE MY USER ACCESS
RUN mkdir /etc/cron.d
RUN echo "robuser" > /etc/cron.allow
RUN echo "" >> /etc/cron.allow
RUN chmod -R 644 /etc/cron.d

# ADD MY CRONTAB
RUN mkdir -p /var/spool/cron/crontabs
ADD ./src/crontab.conf /tmp/cloudwatch/crontab.conf
RUN crontab -u robuser /tmp/cloudwatch/crontab.conf

# DEBUG... GIVE MY USER ACCESS TO EVERYTHING
RUN chown -R robuser /etc/cron.d
RUN chmod -R 755 /etc/cron.d
RUN chown -R robuser /var/spool/cron
RUN chmod -R 744 /var/spool/cron
RUN chown robuser /var/spool/cron/crontabs
RUN chmod 744 /var/spool/cron/crontabs
RUN chown -R robuser /etc/crontabs
RUN chmod -R 744 /etc/crontabs
RUN chown robuser /etc/crontabs/robuser
RUN chmod -R 744 /etc/crontabs/robuser
RUN chmod 600 /var/spool/cron/crontabs/robuser

# ADD MY MONITORING PROGRAM
RUN mkdir -p /opt/monitor
ADD src/monitor /opt/monitor
RUN mkdir -p /opt/monitor/.tmp && \
    chown -R robuser /opt/monitor && \
    chmod -R 700 /opt/monitor

RUN touch /var/log/entrypoint.log && \
    touch /var/log/monitor.log && \
    touch /var/log/cron.log && \
    touch /var/log/awslogs.log && \
    chown -R robuser /var/log

USER robuser

ENTRYPOINT /home/robuser/entrypoint.sh

同时,我的entrypoint.sh文件中有这样的内容。我将cron守护进程作为后台服务启动,并详细记录日志到cron.log中。我还尝试使用-d 0参数以获取更多的调试信息,但是它并没有真正为输出添加任何内容。

#!/bin/bash

crond -b -l 0 -L /var/log/cron.log

#... lots of other startup stuff ...

重要的一点:如果我不切换到robuser,那么以root身份一切都正常工作。

如果我检查cron.log文件,它几乎是空的:

crond: crond (busybox 1.25.1) started, log level 0
crond: wakeup dt=45
crond: wakeup dt=60
crond: wakeup dt=60

同时,/var/log/monitor.log完全为空(请参见帖子开头的crontab)。

所以crond没有打印任何错误。

我已经尝试了我能想到的所有调试方法。没有错误消息。它只是运行而不打印。一个好的建议是简化我的crontab..但这也没有起作用:

PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/ec2-user/bin
SHELL=/bin/bash

* * * * * touch /tmp/test.txt

我尝试搜索其他使用非root cron的alpine容器,但大多数人都没有费力让他们的alpine容器以非root方式运行。

有没有人有进一步的建议来帮助调试这个问题?


1
这是一个开发问题(DevOps)。我正在开发一个Docker容器,该Docker容器正在使用Alpine。请参阅Stack Overflow上大量与Docker相关的其他问题:https://stackoverflow.com/search?q=docker - Robert Allurent
2个回答

11
cron本身应该以root用户运行,无论您想使用哪个用户来运行作业。

确实,当您运行以下命令时:

RUN crontab -u robuser /tmp/cloudwatch/crontab.conf
这将为用户robuser安装一个crontab。当cron从此特定crontab执行作业时,它将自动切换到robuser用户。然而,如果cron不是以root身份运行,它不能像那样切换用户,这就是为什么需要以root身份运行cron的原因。
因此,为使cron在此处工作,您需要从Dockerfile中删除此指令:
USER robuser
注意,一旦你修复了这个问题,可能并不代表你已经解决了所有问题:如果你使用环境变量来将AWS凭据传递给监控脚本(似乎你在使用AWS),这样是行不通的,因为将在切换用户之前删除这些凭据。这主要是中的安全功能,以避免环境变量泄漏给非特权用户。
另外,我写了一个开源的crontab运行器Supercronic,专门针对容器使用情况而设计,可以解决这个问题(你也可以作为非特权用户运行它)。如果你对普通的感到沮丧,可以试试这个。

非常好的答案,谢谢你。但是,您建议删除 USER robuser 意味着我的整个容器将不会以 robuser 身份运行。这包括我的 jboss 服务器。按照您的描述,似乎无法像_root_ 一样运行 cron,同时以 robuser 身份运行我的 jboss 服务器。 - Robert Allurent
1
如果您想使用常规的 cron,那么您可能无法以非特权用户身份运行它。但是,您可以将其作为特权用户运行,然后使用 gosu 以非特权用户身份运行 jboss! - Thomas Orozco
对于仍在处理此问题的其他人,我已经成功安装了sudo并设置了sudoer条目,允许robuser运行一个启动crond的shell脚本。我通过从nginx使用sudo来将其作为root运行ngnix和crond。 - blissweb

0

编写了修复程序以将 crond 作为非 root 用户运行。实际上,crond 是在 busybox 代码库中实现的,它调用了函数“change_identity”,该函数调用系统调用 setgroups(通常需要 Linux CAP_SETGID 权限),以将作业特权切换到普通用户/组特权,与用户作业相同,因此 crond 进程必须以 root 用户身份运行。

我将修补过的 Alpine 推送到了 Docker Hub:

geekidea/alpine-cron:3.7
geekidea/alpine-cron:3.8
geekidea/alpine-cron:3.9
geekidea/alpine-cron:3.10

一个示例的Dockerfile:
FROM geekidea/alpine-cron:3.10

USER nobody
RUN mkdir /tmp/crontabs \
    && echo 'SHELL=/bin/sh' > /tmp/crontabs/nobody \
    && echo '* * * * * /tmp/nobody.sh' >> /tmp/crontabs/nobody \
    && echo 'echo "$(date) blahblahblah nobody" >> /tmp/nb-cron.log' > /tmp/nobody.sh \
    && chmod 0755 /tmp/nobody.sh \
    && chown -R nobody.nobody /tmp/crontabs/nobody

CMD ["crond", "-c", "/tmp/crontabs", "-l", "0", "-d", "0", "-f"]

查看更多:https://github.com/inter169/systs/blob/master/alpine/crond/README.md


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接