4

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

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

(根据用户的不同,消息可能改为“拒绝访问”。)

请注意 $! 给出以下诊断:

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

是否通过 system() 或反引号调用 xcopy 似乎没有区别。

我应该指出,“发件人”文件夹是一个 ClearCase 动态视图(M 驱动器)。

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

以下是一些其他的怪事:

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

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

  3. 问题似乎与目标文件夹无关。一旦诅咒解除,文件就可以被复制到一个新的目的地。

以下是我用来缩小问题范围的测试 Perl 脚本的一部分(文件夹名称已通用化)。请注意,对于每个测试的“我的 $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
4

5 回答 5

3

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

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

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

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

要找出system调用时遇到的问题,您必须假设错误可能出在 ClearCase、cmd.exeshell、xcopy命令或 Perl 中。通过不使用该system命令,您已经简化了您的问题,并且实际上多次加速了该过程。

于 2012-05-10T14:38:55.103 回答
3

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

它看起来像这样:

xcopy /args $source $target <nul:;

(整个命令周围的反引号没有出现)

JKE

于 2012-10-08T16:54:33.233 回答
2

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

my @args= qw(M:\STUFF\ABC D:\temp\dest1 /c /i /e);
warn "Executing 'xcopy @args' ...\n";
system xcopy => @args;
于 2012-05-10T13:41:37.323 回答
1

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

这样,您就可以更可控地复制文件。您可以将此调用包装到一个 eval 块并在那里应用某种重试逻辑吗?

也许对有问题的文件帮​​助进行“虚拟更新”?更改文件的属性/时间戳或将其重命名为其他名称并将其重命名...

于 2012-05-10T07:53:36.283 回答
1

如果您查看ClearCase 如何管理 Vob 和 views 的读/写访问,您会发现:

  • 读取目录的内容(需要r-x
  • 读取目录中的文件(只需要--x目录上的“”+r--文件上的“”)

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

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

于 2012-05-11T20:26:28.590 回答