为什么Windows XCOPY在通过psexec通过Perl系统调用调用时失败?

时间:2012-05-10 01:45:42

标签: windows perl clearcase xcopy psexec

我正在使用psexec在远程Windows机器上启动Perl程序。该程序对xcopy进行系统调用。这在机器上直接(本地)运行时工作正常,但是当通过psexec远程运行时,xcopy失败并显示以下消息:

  

文件创建错误 - 功能不正确。

(取决于用户,该消息可能改为“拒绝访问”。)

注意$!给出以下诊断:

  

syscall.pl中的错误文件描述符。   perl在REMOTE上退出,错误代码为9。

通过system()或反引号调用xcopy似乎没什么区别。

我应该指出“from”文件夹是一个ClearCase动态视图(M盘)。

奇怪的是,直接从psexec调用时,xcopy似乎正常工作。

以下是其他一些奇怪之处:<​​/ p>

  1. xcopy并不总是失败。某些文件似乎只是“被诅咒”。只读属性似乎不是一个因素。

  2. 一旦复制成功(例如,通过Windows资源管理器),解除了诅咒,该特定文件将不再导致xcopy错误。

  3. 问题似乎与目标文件夹无关。解除诅咒后,可以将文件xcopy到新目的地。

  4. 以下是我用来缩小问题的测试Perl脚本的一部分(文件夹名称已被通用化)。 请注意,对于每个测试的“my $ cmd”,我都会注释掉前一个,并添加了状态注释。

    # ClearCase directory M:\STUFF\ABC contains ABC.tst, ABC.zip and several nonempty subfolders
    
    # Directory copy, D drive to D drive
    #my $cmd = "xcopy D:\\temp\\src D:\\temp\\dest /e /i /y";
    # works
    
    # Directory copy, M drive to D drive
    #my $cmd = "xcopy M:\\STUFF\\ABC D:\\temp\\dest /e /i /k /y";
    # fails with "File creation error - Incorrect function" or "Access denied"
    
    # File copy (.tst), M drive to D drive (trailing backslash)
    #my $cmd = "xcopy M:\\STUFF\\ABC\\ABC.tst D:\\temp\\dest\\";
    # works!
    
    # Directory copy, M drive to D drive (trailing backslash)
    #my $cmd = "xcopy M:\\STUFF\\ABC D:\\temp\\dest\\ /e /i /k /y";
    # copies the .tst file, but fails on the .zip (yes, the .tst file is now getting copied)
    
    # Directory copy, M drive to D drive (same as above but without trailing backslash)
    #my $cmd = "xcopy M:\\STUFF\\ABC D:\\temp\\dest /e /i /k /y";
    # copies the .tst file, but fails on the .zip
    
    # File copy (.zip), M drive to D drive
    #my $cmd = "xcopy M:\\STUFF\\ABC\\ABC.zip D:\\temp\\dest";
    # fails 
    
    # File copy (.zip), M drive to D drive (trailing backslash)
    #my $cmd = "xcopy M:\\STUFF\\ABC\\ABC.zip D:\\temp\\dest\\";
    # fails
    
    # After manually (Windows Explorer) copying the .zip file to the dest folder and deleting it  
    # Directory copy, M drive to D drive with /c (continue after failure)
    #my $cmd = "xcopy M:\\STUFF\\ABC D:\\temp\\dest /c /i /e";
    # copies the .tst and .zip file (!), but fails on all other files (folders were successfully created)
    
    # After manually copying the Folder1 folder to the dest folder and then deleting it  
    #my $cmd = "xcopy M:\\STUFF\\ABC D:\\temp\\dest /c /i /e";
    # copies the .tst and .zip file and the contents of Folder1(!), but fails on all other files
    
    # Different dest:
    my $cmd = "xcopy M:\\STUFF\\ABC D:\\temp\\dest1 /c /i /e";
    # Same results as immediately above
    
    print "Executing system command: $cmd ...\n";
    system ($cmd);
    #print(`$cmd 2>&1`); #same
    

5 个答案:

答案 0 :(得分:3)

我建议您不要使用xcopy命令,而是使用Perl本身进行复制。有一个模块File::Copy::Recursive,使用起来非常简单。它不是标准Perl发行版的一部分,因此您必须使用cpan安装它。

如果您不想使用非本机模块,可以尝试使用File::Find查找目录中的文件,然后将其与File::Copy结合使用。

Perl Monks上找到了两个例子。一个使用组合,另一个使用File::Copy::Recursive

是的,这不是直接回答您的问题,但您应尽量避免使用system命令。当您与系统 shell 和命令处理器进行交互时(特别是当ClearCase与文件系统混乱时),您最终可能会遇到许多无意的交互,这些交互可能会导致某些情况下的某些工作,但不会其他

要找出您在system调用时遇到的问题,您必须假设错误可能在ClearCase,cmd.exe shell,xcopy命令中,或者Perl。通过不使用system命令,您已经简化了问题,并且很多时候实际上加快了这个过程。

答案 1 :(得分:3)

尝试从空设备重定向INPUT以查看xcopy是否有效。我不知道为什么,我很久以前遇到过这个问题,不知何故(可能通过网络搜索)想出来了。

它看起来像这样:

xcopy /args $source $target <nul:;

(围绕整个命令反击不显示)

JKE

答案 2 :(得分:1)

File::Copy::Recursive可能会解决您的问题。

通过这种方式,您可以更加轻松地复制文件。您可以将此调用包装到eval块并在那里应用某种重试逻辑吗?

有问题的文件上的“虚拟更新”可能有帮助吗?更改文件的属性/时间戳或将其重命名为其他内容并重命名为...

答案 3 :(得分:1)

您是否尝试过使用参数列表system

my @args= qw(M:\STUFF\ABC D:\temp\dest1 /c /i /e);
warn "Executing 'xcopy @args' ...\n";
system xcopy => @args;

答案 4 :(得分:1)

如果你看how ClearCase manages read/write access for Vob and views,你会发现:

之间存在差异
  • 阅读目录内容(需要r-x
  • 读取目录中的文件(文件上只需要“--x”+“r--

因此,根据启动xcopy的流程背后的用户,您可能无法读取/访问某些目录/文件。
并且您需要确保使用已将CLEARCASE_PRIMARY_GROUP设置为正确的值(即,作为vob的主要组或其次要组之一列出的组),以便访问Vob(但如果是保护是松散的,无论如何每个人都可以访问它。)

所有这些都适用于动态视图,并且仅适用于快照视图的更新(更新完成后,您可以在本地复制文件,任何进程都可以读取这些文件)。