我更改了我的服务器;旧的运行Centos 8
,新的运行Ubuntu 20.4
。现在我的 php 脚本在权限方面有问题 - 为什么?
例:
current user: root
script was executed under user: nobody
Message: fopen(/tmp/RebuildCat_sequence.cnt): failed to open stream: Permission denied
实际上这个文件归nobody
所有,所以我根本不应该收到这个警告:
CS-1 01:47:22 :/tmp# ls -latr /tmp/RebuildCat_sequence.cnt
--wxrwxrwT+ 1 nobody nogroup 480 Oct 23 00:02 /tmp/RebuildCat_sequence.cnt
这个php文件通常由cron(root
)调用,因为我注意到一些类似的cron触发文件归systemd-timesync
所有,我发出了
setfacl -m u:systemd-timesync:rwX /tmp
setfacl -m u:nobody:rwX /tmp
甚至
setfacl -R -m u:nobody:rwX /tmp
setfacl -R -m u:systemd-timesync:rwX /tmp
无济于事。我如何理解这一点?
据我了解,systemd-timesync
和nobody
的用户都应该能够以/tmp
读写文件,而不会因acl
而出现问题。我认为必须有人在这里教育我。
/tmp
驻留在/dev/md2
CS-1 01:32:34 :/tmp# tune2fs -l /dev/md2 | grep "Default mount options:"
Default mount options: user_xattr acl
我想这里没问题。
CS-1 01:46:09 :/tmp# getfacl /tmp
getfacl: Removing leading '/' from absolute path names
# file: tmp
# owner: root
# group: root
# flags: --t
user::rwx
user:systemd-timesync:rwx
user:nobody:rwx
group::rwx
mask::rwx
other::rwx
对我来说看起来也不错。无能。
补遗
好的,我设置了chmod 777 /tmp
,但仍然fopen(/tmp/RebuildCat_sequence.cnt): failed to open stream: Permission denied
出现PHP
错误,但file_put_contents
777
一起使用 - 我如何理解这一点?为什么fopen
抛出错误,而file_put_contents
不会?
唉,控制台中的chmod 777 /tmp
不是答案。它比这复杂得多。所以我一点也不傻。
如何繁殖?
就我而言,我有 2 个 dockerPHP
容器写入许多特定于案例的日志文件,其中一个使用apache
,另一个nginx
。两者都有一个 映射/tmp:/tmp
,因此我们可以从主机或容器内部查看文件。
从容器内部,如果所有者是在apache
容器中创建的,则apache:apache
在nginx
容器中创建nginx:nginx
,但从主机的角度来看,在这两种情况下,它都是针对同一文件的systemd-timesync:systemd-journal
。
当然,apache
容器没有用户nginx
,反之亦然(主机也没有)。因此,如果我的PHP
脚本想要写入由其他容器创建的文件,我已经说权限问题。
修复
如果在创建时将所有者更改为nobody
并具有666
权限,则补救措施很容易。
如果没有,我们无法从另一个容器更改所有者并获取failed to open stream: Permission denied
.请参阅 https://serverfault.com/questions/772227/chmod-not-working-correctly-in-docker(另请参阅下面有关通过system
调用从主机更改权限的讨论)。
所以我写了一个包装函数str_to_file
来添加这个操作:
function str_to_file($str, $filename= "/tmp/tmp.txt", $mode="a+") {
if (!file_exists($filename)){
touch($filename); # create file
chmod($filename, 0666); # the owner can chmod
chown($filename, 'nobody'); # the owner can chown
} # if (!file_exists($filename))
$mode = $mode == 'w'
? LOCK_EX
: FILE_APPEND | LOCK_EX;
file_put_contents($filename, $str . PHP_EOL, $mode);
} # str_to_file
这适用于apache
和nginx
容器。
解释
我到底是怎么陷入这个烂摊子的?
看起来要么我在CentOS
上没有搞砸它,所以在这种情况下很可能与我切换到Ubuntu
无关。我不记得我做了什么,但我不记得我在CentOS
上有这种权限问题。
或者CentOS
处理容器中创建的文件的方式与Ubuntu
.我敢肯定我从未见过用户systemd-timesync:systemd-journal
CentOS
.不幸的是,我无法不费吹灰之力地调查用户CentOS
会从主机的角度替换什么以及这会产生什么后果。
哦,等等,我记得我确实有另一台服务器运行PHP
并在CentOS
上运行nginx
.从容器内创建/tmp
文件会显示容器内部和主机的所有者nobody
。因此,两个Linux版本之间存在显着差异。
更重要的是,这种见解解释了为什么我只有在从CentOS
切换到Ubuntu
之后才遇到此权限问题,由于我的提供商出于明显的原因不再提供CentOS
,我被迫这样做。
顺便说一下,我首先尝试了CentOS
替代品AlmaLinux
和RockyLinux
,结果不同,最终迫使我使用Ubuntu
。这种转换反过来揭示了很多问题,这是最后一个,到目前为止,我花了几个星期的时间。我希望这场噩梦现在结束。
从cron
开始,apache
版本是并且曾经是专门使用的,所以这里没有问题。
最近从浏览器进行测试,我偶然且无缘无故地从apache
版本切换到nginx
版本,反之亦然,从而产生了这些描述的问题。
实际上,我不知道为什么容器代表这些用户编写。在这两种情况下,容器的用户都是root
的,这是docker
的标准。我想是浏览器引擎引入了这些用户。
有趣的是,如果我没记错的话,当尝试在创建后通过system
调用更改权限和所有权时,我失败了,尽管用户应该是root
的,root
应该能够做到这一点。
事实证明,在apache
system
用户[system('whoami)]不是root
而是apache
,但是文件所有者是apache
,而nginx
系统用户是nobody
,文件所有者是nginx
。因此,使用system
更改权限应该适用于apache
[system("chmod 0666 $filename"); system("chown nobody:nobody $filename");],但不适用于nginx
。唉,它也不适用于apache
。
快速入住apache
集装箱:
/tmp # whoami
root
/tmp # ls -la *6_0.ins
-rw-r--r-- 1 apache apache 494 Nov 14 18:25 tmp_test_t6_0.ins
/tmp # su apache chmod 0666 tmp_test_t6_0.ins
This account is not available
对不起,我无法理解这一点。而且对ACL一无所知。
阿帕奇 vs. 恩金克斯
为什么我首先同时使用两个 Web 服务器版本?
好吧,我调用的进程处理随机数据,这可能需要很长时间,所以很可能nginx
超时。这是一个众所周知的nginx
功能。
尽管我进行了所有的研究和明显的指示,但我无法管理nginx
行为。吉兹语!
最后,作为适当的解决方法,我引入了apache
,它没有这个问题。当然,对于体面的运行时,这没有什么区别。
嗯,看起来我有点傻。我确定我在WinSCP
(1777
) 中仔细检查了对/tmp
的权限,但我不确定我是否在控制台中这样做了。
现在我在控制台中发布了chmod 777 /tmp
,它就在那里!这个问题消失了。chmod 666 /tmp
重新引入了这个问题。chmod 676 /tmp
也可以。
我用谷歌搜索了很多关于这个话题的教育自己,但坦率地说我不明白。特别是为什么我一开始就会遇到问题,为什么ACL没有解决问题?我希望得到一些启发。