使用Python查找损坏的符号链接
如果我在一个残破的符号链接上调用os.stat(),python会抛出OSError异常。这对于找到它们很有用。但是,还有其他一些原因可能导致os.stat()抛出类似的异常。在Linux下,是否有更精确的方法来使用Python检测损坏的"符号链接"?
解决方案
回答
我可以提及没有python的硬链接测试吗? / bin / test具有FILE1 -ef FILE2条件,当文件共享一个inode时为true。
因此,类似find。 -type f -exec test \ {} -ef / path / to / file \; -print
用于对特定文件的硬链接测试。
这使我阅读了" man test"以及对" -L"和" -h"的提及,它们都作用于一个文件,如果该文件是符号链接,则返回true,但是并不能告诉我们目标是否为丢失的。
我确实发现head -0 FILE1
如果可以打开文件,将返回退出代码'0',如果不能打开,则将返回'1',在符号链接到常规文件的情况下可以作为测试是否可以读取目标。
回答
我不是python家伙,但看起来像os.readlink()?我在perl中使用的逻辑是使用readlink()查找目标,并使用stat()测试目标是否存在。
编辑:我猛击了一些演示readlink的perl。我相信perl的stat和readlink以及python的os.stat()和os.readlink()都是系统调用的包装器,因此这应该可以翻译合理的概念证明代码:
wembley 0 /home/jj33/swap > cat p my $f = shift; while (my $l = readlink($f)) { print "$f -> $l\n"; $f = $l; } if (!-e $f) { print "$f doesn't exist\n"; } wembley 0 /home/jj33/swap > ls -l | grep ^l lrwxrwxrwx 1 jj33 users 17 Aug 21 14:30 link -> non-existant-file lrwxrwxrwx 1 root users 31 Oct 10 2007 mm -> ../systems/mm/20071009-rewrite// lrwxrwxrwx 1 jj33 users 2 Aug 21 14:34 mmm -> mm/ wembley 0 /home/jj33/swap > perl p mm mm -> ../systems/mm/20071009-rewrite/ wembley 0 /home/jj33/swap > perl p mmm mmm -> mm mm -> ../systems/mm/20071009-rewrite/ wembley 0 /home/jj33/swap > perl p link link -> non-existant-file non-existant-file doesn't exist wembley 0 /home/jj33/swap >
回答
os.lstat()可能会有所帮助。如果lstat()成功,而stat()失败,则可能是断开的链接。
回答
os.path
我们可以尝试使用realpath()获取符号链接指向的内容,然后使用is file尝试确定它是否为有效文件。
(目前我无法尝试,因此我们必须尝试一下并看看会得到什么)
回答
Python常见的说法是,请求宽恕比允许许可容易。尽管我不喜欢现实生活中的这种说法,但它确实适用于许多情况。通常,我们要避免将两个系统调用链接到同一文件的代码,因为我们不知道在代码中的两次调用之间文件将发生什么。
一个典型的错误是编写如下内容:
if os.path.exists(path): os.unlink(path)
如果第二次调用(os.unlink)在if测试后因其他原因被删除,则可能会失败,并引发异常并停止执行其余函数。 (我们可能会认为这在现实生活中不会发生,但是上周我们只是在我们的代码库中钓出了另一个类似的错误,这种错误使一些程序员挠头并最后声称" Heisenbug"几个月)
因此,在特定情况下,我可能会这样做:
try: os.stat(path) except OSError, e: if e.errno == errno.ENOENT: print 'path %s does not exist or is a broken symlink' % path else: raise e
烦人的是,stat对于不存在的符号链接返回了相同的错误代码,并返回了损坏的符号链接。
因此,我想我们别无选择,只能打破原子性,并做类似的事情
if not os.path.exists(os.readlink(path)): print 'path %s is a broken symlink' % path