我每天午夜都会失去许可

我每天午夜都会失去许可

require的 PHP 脚本顶部有一个文件。该文件只有 MySQL 的连接对象:

$c->new mysqli('host','usr','pass','db')

该文件具有400权限:-r-------- 并且我将其/etc/mysql/远离我的网页根目录(/var/www/html)。

它工作得很好,除了每天晚上午夜它都会停止,我的所有页面都会收到权限被拒绝的错误:

Warning: require(/etc/mysql/.myfile.php): Failed to open stream: Permission denied in...

如果我将权限更改为444,请登录我的网站,然后将权限更改回400。它一直工作到第二天午夜。我可以全天多次登录和注销我的网站,但是当午夜到来时,它就会失败。

造成这种情况的原因是什么以及如何解决?

显然我想保留它,以便只能root读取该文件,因为它有明文密码。

答案1

这应该是一条评论 - 但空间有限,格式也有限。

你并没有真正对这种情况提供一个很好的解释。

您已经说过您“失去权限”以及如何恢复正常操作,但您没有说明权限是什么午夜活动。

在确定访问权限时,如果没有所有权详细信息,权限就没有意义。据推测,该文件最初由您的网络服务器 uid 拥有(尽管您实际上并没有说该文件是由从网络服务器运行的脚本访问的)。再说一遍,这些之前和之后是什么?

你是如何确定它在午夜停止的?确切地知道事件发生的时间是解决问题的有用垫脚石。如果它发生在 00:00:00 和 00:03:00 之间,那么很有可能这是由于某些计划任务造成的。这也使其成为很多更容易将事件与系统日志(以及网络服务器日志)交叉引用。

不过,感谢您考虑权限和访问......

您选择的权限并不理想。再次假设这是一个网络服务器,那么该文件只能由 root 用户管理。如果您是唯一维护服务器的人,那么更好的方法是将所有权设置为 bungee1980:wwwgrp (其中 wwwgrp 是网络服务器 uid 的默认组)和权限 -rw-r----- (0750) 。

您选择的位置并不理想。大多数现代操作系统通过强制访问控制机制(RHEL 及其衍生产品上的 SELinux,其他地方的 Apparmor)来限制文件访问。通常将网络服务器限制为仅包含其内容的目录树。虽然出于明显的原因您不希望此文件位于文档根目录中,但您(通常)也不希望允许您的脚本直接从 /etc 中的许多其他文件读取

一个小问题是 PHP提供了一种机制用于设置默认凭据和数据库详细信息(以及运行额外的样板代码在目标脚本之前)。鉴于这可以在您的网络服务器配置中设置,这可能是更合适的凭证工具。

答案2

如果我将权限更改为 444,请登录我的网站,然后将权限更改回 400。

换句话说:使用权限 400,您的脚本无法读取该文件,但使用权限 444,它们可以,然后某个进程将保持文件打开或将凭据保留在 RAM 中,直到午夜,此时某些事件会触发重新启动或清理某种形式的。

您没有提到您正在使用的操作系统/发行版,但我会首先检查/etc/cron.*任何相关用户的 crontab(通常为/var/spool/cron[/crontabs]或类似),以查找在午夜运行的任何每日 cron 作业。也许有什么东西可以清理旧的 PHP 会话?或者它可能会logrotate触发某些事情的重新启动,例如php-fpm作为每日日志轮换计划的一部分?

如果您的系统使用systemd,还要检查其计时器单位:systemctl list-units --type=timer列出所有系统范围的计时器,然后systemctl cat <name>.timer查看它们。


例如,在 Debian 12 中,logrotate可以由 触发/etc/cron.daily/logrotate,它可能anacron在 中指定的时间运行/etc/cron.d/anacron,默认是系统运行时的 07:30 到 23:30 之间的最早时间...但实际上会使用这个时间表仅当systemd不使用时,因为中指定的工作/etc/cron.d/anacron是有条件的/run/systemd/system 不是现存的。

使用systemd,logrotate.timer来代替,它的指定如下:

systemctl cat logrotate.timer 

# /lib/systemd/system/logrotate.timer
[Unit]
Description=Daily rotation of log files
Documentation=man:logrotate(8) man:logrotate.conf(5)

[Timer]
OnCalendar=daily
AccuracySec=1h
Persistent=true

[Install]
WantedBy=timers.target

如 中所述man systemd.timeOnCalendar=daily的意思是*-*-* 00:00:00,即每天恰好在午夜。允许AccuracySec=1h将此计时器与在 00:00 和 01:00 之间触发的其他计时器(如果存在)合并,以优化节能。至少在我的系统上,最终结果似乎是日志轮换正好发生在午夜,除非系统当时停机。

使用systemctl status logrotate.timer,您可以查看定时器的下一个预定触发时间。

相关内容