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

我正在Alpine Linux上运行一个非root用户的crontab文件。

我已经通过了另外两个cron相关的post,我没有答案:

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现在有点乱,但只是因为我一直在拼命解决这个问题。 看起来像这样 简而言之,我添加了crontab -e的SUID作为其他用户的工作,我创build我的用户,我导入我的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 

同时,我的入口点.sh有这个地方。 我作为后台服务启动cron守护进程,并以详细的方式logging到cron.log。 我也试过指定-d 0来获得更多的debugging,但是没有真正添加任何东西到输出。

 #!/bin/bash crond -b -l 0 -L /var/log/cron.log #... lots of other startup stuff ... 

一个重要的观点:如果我不切换到robuser一切都可以作为根

如果我检查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不会打印任何错误。

我试过所有我能想到的来debugging这个。 没有错误信息。 它只是运行,从不打印。 一个好的build议是简单的我的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的高山容器,但是大多数人并没有经历让他们的高山容器运行非root的麻烦。

有没有人有任何进一步的build议,以帮助debugging?

cron本身应该以root身份运行,不pipe你想用哪个用户来运行这个工作。

事实上,当你运行:

 RUN crontab -u robuser /tmp/cloudwatch/crontab.conf 

这将为用户robuser安装一个crontab 。 当cron从这个特定的crontab执行作业时,它会自动将用户切换到robuser但是,如果不以root身份运行, cron不能切换用户,这就是为什么您需要以root身份运行cron

所以,要使cron在这里工作,你需要从你的Dockerfile中删除这个指令:

 USER robuser 

请注意,一旦解决了这个问题,您可能不会走出困境:如果您使用环境variables将AWS凭据传递给您的监控脚本(看起来您在这里使用的是AWS),那么这将不起作用,因为cron会在切换用户之前删除那些。 这在很大程度上是cron一项安全function,可以避免无特权的用户发生环境variables泄漏。

顺便说一下:我写了一个开源的crontab runner, Supercronic ,专门为容器使用情况devise的,它修复了这个问题(你也可以将它作为非特权用户来运行)。 如果你对普通的cron感到沮丧,那么你总是可以开一枪。