使用Python查找损坏的符号链接

时间:2020-03-05 18:41:43  来源:igfitidea点击:

如果我在一个残破的符号链接上调用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