在perl的反引号中使用chmod后导致权限的异步更改的原因

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在perl的反引号中使用chmod后导致权限的异步更改的原因相关的知识,希望对你有一定的参考价值。

TL; DR-转到UPDATE以获取玩具示例。以下是我最初的问题,然后才可以通过一个小示例重现此问题,并进行了清晰编辑。

我不知道这里发生了什么。我正在拔头发,试图弄清楚为什么用Perl编写的测试始终失败。

我正在测试一个功能,该功能在打开输出日志文件失败时将关闭日志记录,因此不会抑制向STDERR的输出。为了测试它是否有效,我即时创建了一个文件并将其chmod设为不可写。代码的结果运行应将打开错误以及所有其他STDERR打印到STDERR输出。在运行测试之前,我正在反引号中执行chmod。

但是,正在发生的事是日志文件不断被写入而没有错误-因此测试失败。我通过在各个位置打印ls -halF的输出来开始进行完整性检查,以查看权限更改发生的位置。最初的chmod似乎可以正常工作:

`echo > file.log;chmod 444 file.log;ls -halF file.log`

在进行一些其他设置后,随后的ls -halF file.log确认了预期的权限,但是在我运行的实际测试代码中,很早的一行代码表明所有者具有写权限!

[我最终找到了解决该问题的方法-通过在反引号中使用perl chmod()方法而不是chmod,这使我认为正在发生一些异步操作-对我来说这没有任何意义。

我最终尝试这样做,因为在众多测试中,我偶尔会看到测试随机成功。因此,我编写了一个快速循环来一次又一次地执行相同的测试-发现它可能在30%的时间内随机成功!这就是让我认为此问题可能存在某种异步性的原因,我无法解释,因为我认为反引号实际上等待该过程完成,因为它返回了输出-那么这里发生了什么?我不明白。

为了完整性-实际的测试命令也在反引号中完成-它运行一个独立的脚本。

在下面的更新中,我显示了不同的情况,但是它演示了权限状态的随机性...

更新

确定。这是一个完整的小示例,演示了该问题。注意每种情况下第二行的不同输出...

deleteme1.pl

#!/usr/bin/perl
print(`echo '' > deleteme.log;chmod 444 deleteme.log`);
print("1: ",`ls -l deleteme.log`);
`chmod 777 deleteme.log;rm -f deleteme.log`;

deleteme2.pl

#!/usr/bin/perl
print(`echo '' > deleteme.log;chmod 444 deleteme.log`);
print("2: ",`ls -l deleteme.log`);
chmod 0777, "deleteme.log";
unlink("deleteme.log");

现在观察此重复循环的输出:

tcsh> foreach f ( `seq 1 30` )
perl deleteme1.pl
perl deleteme2.pl
end
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -rw-r--r--@ 1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -rw-r--r--@ 1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--@ 1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--@ 1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -rw-r--r--@ 1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--@ 1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--@ 1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--@ 1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
1: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log
2: -r--r--r--  1 robleach  staff  1 May 31 21:01 deleteme.log

请注意,所有者权限的差异始终来自deleteme1.pl。我认为@表示macOS上的扩展属性。这可能与它有关,但是在某些情况下存在xattr,但是没有权限差异...

而且我也怀疑问题可能与此有关:

>ls -1 t | wc -l
   46391

所以异步发生了什么-到底是什么?!它可能与SIP或csr(util)有关吗?

更新2

这是我的具体情况更真实的例子。

deleteme3.pl

此代表我的解决方法:

#!/usr/bin/perl
open(TLG,">deleteme.log");
print TLG '';
close(TLG);
chmod 0444, "deleteme.log";
if(open(TEST,">deleteme.log"))
  {print "3 opened
"}
else
  {print "3 unable to open
"}
chmod 0777, "deleteme.log";
unlink("deleteme.log");

deleteme4.pl

这说明了原始问题。

#!/usr/bin/perl
`echo '' > deleteme.log;chmod 444 deleteme.log`;
if(open(TEST,">deleteme.log"))
  {print "4 opened
"}
else
  {print "4 unable to open
"}
chmod 0777, "deleteme.log";
unlink("deleteme.log");

如上所述,我循环播放了这2个:

tcsh>foreach f ( `seq 1 1000` )
perl deleteme3.pl
perl deleteme4.pl
end

在1000次尝试中,始终为3 unable to open输出deleteme3.pldeleteme4.pl输出4次4 opened,其余为4 unable to open

显然,这并不能说明我在大多数情况下看到的频率,我的权限显示为所有者可写,但是我猜是我碰到了某种甜蜜的地方,在某些情况下我的文件权限遭到破坏。

[我很想看看是否有人可以在任何平台上重现这些结果,但是我在运行系统perl版本5.18.2的macOS Sierra(10.12.6)上。

答案

我找出了异步权限更改的罪魁祸首。我的问题中缺少一条重要的信息:我工作所在的目录在Dropbox(!)中。我不知道保管箱曾经修改过文件的权限,但显然可以。

运行Dropbox应用程序:

tcsh>foreach f ( `seq 1 50` )
foreach? perl deleteme1.pl
foreach? perl deleteme2.pl
foreach? end
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -rw-r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -rw-r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -rw-r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -rw-r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -rw-r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -rw-r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -rw-r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -rw-r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -rw-r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log
1: -r--r--r--@ 1 robleach  staff  1 Jun  2 12:09 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:09 deleteme.log

退出Dropbox后(仍在dropbox目录中:

>foreach f ( `seq 1 50` )
foreach? perl deleteme1.pl
foreach? perl deleteme2.pl
foreach? end
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
2: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
1: -r--r--r--  1 robleach  staff  1 Jun  2 12:11 deleteme.log
2: -r--r

以上是关于在perl的反引号中使用chmod后导致权限的异步更改的原因的主要内容,如果未能解决你的问题,请参考以下文章

Perl 的反引号/系统给出“tcsetattr:输入/输出错误”

perl 第五弹 变量 I

linux 系统 chmod 误操作权限异常修复方式

Linux无法增加执行权限,使用chmod 777 XXX后无效

shell脚本中的反引号使用 `

Linux系统chmod 777 误操作目录权限 - 恢复方法