如何非侵入性地测试对文件的写访问权限?


20

在Shell脚本中,如何在不实际尝试修改文件的情况下轻松地且非侵入性地测试对文件的写访问权限?

我可以解析的输出stat,但这看起来确实很复杂,并且可能很脆弱,尽管我不确定实现和时间之间的统计输出有多少不同。

我可以附加到文件的末尾,看看是否成功,但这有潜在的危险,原因有两个:

  1. 我现在必须删除添加项,并且如果其他进程将文件写入文件,由于我的行不再是最后一行,因此这立即变得很简单。
  2. 任何读取文件的过程可能对该文件的内容有任意要求,而我可能只是破坏了该应用程序。

Answers:


29

只需使用实用程序的- w标志test

[ -w /path/to/file ] && echo "writeable" || echo "write permission denied"

请注意,如果稍后要写入文件,则仍然有可能无法写入文件。该文件可能已移动,权限可能已更改,等等。它也可能会-w检测到写权限,但由于其他一些因素而使文件不可写


1
当然!我应该考虑检查测试的手册页。谢谢。
user50849 2014年

1
@qweilun这是一个内置的shell,但是您可以通过man testorman [
混乱

5
@chaos它既是内置的shell,又是外部可执行文件-尝试type -a
Volker Siegel,

1
每个源test使用euidaccess仅检查权限位。是否没有其他可能禁止写访问的因素(例如SELinux)?
zamnuts 2014年

2
@BroSlow,&&并且||具有相同的优先级。他们从左到右进行评估。
通配符

11

另一种方法:

if >> /path/to/file
then
    echo "writeable"
else
    echo "write permission denied"
fi

这将尝试打开文件进行追加,如果成功, 则不运行命令(即,运行null命令),并输出到文件。 

请注意,这将创建一个空文件(如果不存在)。

该命令的-w运算符test可能只是执行a stat ,然后尝试找出它是否应该具有访问权限。test在某些特殊情况下,我的选择(上面)比该方法更可靠,因为它强制访问检查由内核而不是外壳完成。例如,

  • 如果该文件位于非Unix文件系统上(尤其是从非Unix文件服务器远程挂载),则stat可能会导致模式值误导。
  • 如果文件位于以只读方式安装的文件系统上。
  • 如果文件具有ACL,并且该模式使它看起来像您应该具有访问权限,但ACL拒绝它,反之亦然。
  • 如果某些安全框架(AppArmor,SELinux等)拒绝访问该文件。

3
我刚刚在Debian上测试了这个。两种时间都没有改变,这就是它在任何Unix上都应该起作用的方式。仅当您从文件中读取访问时间时,才应更新访问时间;仅当您写入文件时,才应更新访问时间。这段代码都不做。@Schwern:您有陈述的参考吗?你们有没有尝试过?
G-Man说'Resstate Monica''2014年

2
PS @muru:我只是尝试保存touch一个我拥有但没有写权限的文件,所以成功了。我想这chmod是文件,然后chmod又返回。因此touch,对于该问题的答案似乎绝对没有用。
G-Man说'Resstate Monica''2014年

2
@ G-Man啊,这很有趣。vim当强制在只读文件上写入时,IIRC 具有快速更改权限的行为。我检查stracetouchopen失败EACCES,但后续调用utimensat成功,这就是为什么我认为touch对整个出口成功。
大师

2
@muru:感谢您检查。utimensat(2)说:“ 权限要求: 1.写入访问权限(或)2.调用者的有效用户ID必须与文件的所有者匹配,…。”
G-Man说'Reinstate Monica'2014/

3
类似Champignac的其他问题:>> file不可移植(例如,在zsh中运行NULLCMD),请true >> file改用。而且,如果该文件是命名管道,则它会带来讨厌的副作用。
斯特凡Chazelas

3

G人是对的:[ -w ]不会总是说实话。这里是为了处理外壳中不存在的文件和“ 权限被拒绝”消息:

( [ -e /path/to/file ] && >> /path/to/file ) 2> /dev/null && 
  echo writable || 
  echo not writable

更新:看起来很恐怖,不是吗?好吧,是的。嗯...如何措辞...请勿使用此功能,除非您完全知道自己处于要求它按预期工作的条件下。请参阅Stephane的评论。

那么得出什么结论呢?即使[ -w ]不说实话,它也是旨在完成这项工作的一个命令。如果不行,那么我们会怪罪它,编写错误报告,并且它将在将来运行。更好地检查其工作和使用条件[ -w ];为特殊情况编写特殊代码。解决方法有其自身条件。

[ -w /path/to/file ]

是最好的先验


3
如果文件是命名管道,则在没有读取的情况下它将挂起,即使有读取器也会产生讨厌的副作用。test -w在大多数实现中,使用它access(2)应该足以测试权限。
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.