我有一个 Perl 脚本,它调用 'gsutil cp' 将一个从 GCS 中选择的复制到本地文件夹:

$cmd = "[bin-path]/gsutil cp -n gs://[gcs-file-path] [local-folder]";
$output = `$cmd 2>&1`;

该脚本通过 HTTP 调用,因此可以多次启动(例如,通过双击链接)。发生这种情况时,本地文件最终可能是正确大小的两倍,因此显然已损坏。三件事看起来很奇怪:
  • gsutil 在写入时似乎没有锁定本地文件
    它,允许另一个线程(在这种情况下是另一个 gsutil 实例)
    写入同一个文件。
  • '-n' 似乎没有效果。我原以为它会阻止
    尝试复制操作的 gsutil 的第二个实例。
  • MD5 签名检查失败:通常 gsutil 会删除
    目标文件,如果签名不匹配,但这显然是
    并不总是发生。

  • 有问题的文件大于 2MB(通常约为 5MB),因此可能会与自动恢复功能发生一些交互。 Perl 脚本仅在本地文件不存在时调用 gsutil,但这不会捕获双击(因为 GCS 传输身份验证的时间延迟)。

    gsutil 版本:FreeBSD 8.2 上的 3.42

    有人遇到过类似的问题吗?任何有任何见解的人?

    爱德华·利

    最佳答案

    1)你是对的,我没有看到源代码的锁定。

    2) 这可能是由竞争条件引起的 - 进程 1 检查,发现文件不存在。进程 2 检查,发现文件不存在。进程 1 开始上传。进程 2 开始上传。文档说这是实际上传过程之前的 HEAD 操作——这不是实际上传的原子操作。

    3) 对此没有任何意见。

    您可以通过让您的脚本在启动传输之前在文件上维护某种原子锁来解决该问题 - 即您的支票将是以下几行:

    use Lock::File qw(lockfile);
    
    if (my $lock = lockfile("$localfile.lock", { blocking => 0 } )) {
         ... perform transfer ...
         undef $lock;
    }
    else {
        die "Unable to retrieve $localfile, file is locked";
    }
    

    关于perl - gsutil cp : concurrent execution leads to local file corruption,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23681911/

    10-12 03:06