Почему Windows XCOPY не работает при вызове через системный вызов Perl через psexec?

Я использую psexec для запуска программы Perl на удаленных компьютерах с Windows. Программа выполняет системный вызов xcopy. Это отлично работает при прямом (локальном) запуске на машинах, но при удаленном запуске через psexec xcopy завершается ошибкой со следующим сообщением:

Ошибка создания файла - Неправильная функция.

(В зависимости от пользователя вместо этого может отображаться сообщение «Доступ запрещен».)

Обратите внимание, что $! дает следующую диагностику:

Неверный файловый дескриптор на syscall.pl. perl завершился на УДАЛЕННОМ УДАЛЕНСТВЕ с кодом ошибки 9.

Кажется, не имеет значения, вызывается ли xcopy через system () или через обратные кавычки.

Я должен отметить, что папка «от» представляет собой динамическое представление ClearCase (диск M).

Как ни странно, похоже, что xcopy работает правильно, когда вызывается непосредственно из psexec.

Вот еще несколько странностей:

  1. Xcopy не всегда терпит неудачу. Некоторые файлы просто кажутся «проклятыми». Атрибут только для чтения не играет роли.

  2. После успешного копирования (например, через проводник Windows) проклятие снимается, и этот конкретный файл больше не вызывает ошибок xcopy.

  3. Проблема не в папке назначения. Как только проклятие будет снято, файл можно будет скопировать в новое место назначения.

Ниже приводится часть тестового сценария 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

person UhClem    schedule 10.05.2012    source источник
comment
Я предполагаю, что в действительности виноваты динамические представления ClearCase. Я бы попробовал тот же код для обычной файловой системы, чтобы исключить это.   -  person msw    schedule 10.05.2012
comment
Между прочим: использование одинарных кавычек позволяет сэкономить здесь много обратных косых черт.   -  person reinierpost    schedule 10.05.2012
comment
попробуйте system ($cmd) or die "'$cmd' failed: $!"; это должно сказать вам, что это за сообщение об ошибке, если оно существует (я думаю, что это будет более надежным, чем ваша команда печати).   -  person Barton Chittenden    schedule 10.05.2012
comment
@BartonChittenden Это будет печатать $! только в случае system успеха. Вместо этого используйте system ($cmd) and die "'$cmd' failed: $!". Подробнее см. perldoc -f system. Также используйте форму LIST, как я предлагал.   -  person Sinan Ünür    schedule 10.05.2012
comment
@ SinanÜnür - о, ты совершенно прав, я изменил логику системной команды. Я сосредоточился на использовании $! и не заметил этого.   -  person Barton Chittenden    schedule 11.05.2012
comment
@msw, динамические представления ClearCase действительно могут иметь значение. Как вы можете видеть в моем примере, мой локальный тест диска D прошел нормально. К сожалению, мы застряли на копировании из динамического представления. Как ни странно, содержимое можно увидеть, но в некоторых, казалось бы, случайных случаях его просто нельзя скопировать с помощью psexec - ›системный вызов Perl -› xcopy, по крайней мере, до тех пор, пока проклятие не будет снято (обычно с помощью ручного копирования).   -  person UhClem    schedule 11.05.2012
comment
@reinierpost, ты прав насчет одинарных кавычек. В исходном источнике есть части пути, расширенные с помощью $ переменных, поэтому они заключены в двойные кавычки.   -  person UhClem    schedule 11.05.2012
comment
@BartonChittenden, к сожалению, $! не предоставляет никакой дополнительной информации. Хотя я должен отметить, что файлы, которые я вчера заставил скопировать, сегодня снова выходят из строя.   -  person UhClem    schedule 11.05.2012
comment
@BartonChittenden, я беру это обратно. Я попробовал это без / c и получил следующую диагностику: Неверный файловый дескриптор в строке 59 syscall.pl. Perl завершился на УДАЛЕННОМ режиме с кодом ошибки 9.   -  person UhClem    schedule 11.05.2012


Ответы (5)


Я предлагаю вместо использования команды xcopy выполнять копирование с использованием самого Perl. Есть модуль File :: Copy :: Recursive это довольно просто использовать. Это не часть стандартного дистрибутива Perl, поэтому вы должны установить его с помощью cpan.

Если вы не хотите использовать неродные модули, вы можете попробовать использовать File :: Find, чтобы найти файлы в каталоге, затем объедините это с помощью File :: Copy.

Нашел два примера на Perl Monks. Один использует комбинацию, а другой - File::Copy::Recursive

Да, это не ответ на ваш вопрос напрямую, но вам следует по возможности избегать использования system команд. Когда вы взаимодействуете с системной оболочкой и командным процессором (особенно когда ClearCase взламывает файловую систему), вы можете столкнуться с множеством непреднамеренных взаимодействий, которые могут заставить что-то работать в некоторых ситуациях, но не другие.

Чтобы выяснить, в чем проблема, связанная с вызовом system, вы должны предположить, что ошибка может быть в ClearCase, оболочке cmd.exe, команде xcopy или Perl. Не используя команду system, вы упростили задачу и во много раз фактически ускорили процесс.

person David W.    schedule 10.05.2012
comment
Возможно, нам придется использовать комбинацию File :: Find / File :: Copy, пока не будет дано добро на развертывание модуля File :: Copy :: Recursive в нашей компании. Но я надеюсь, что мы сможем обойти эту специфическую проблему xcopy и не прибегать к ней. - person UhClem; 11.05.2012
comment
@UhClem: Не должно быть так сложно написать подпрограмму-оболочку вокруг File :: Find / File :: Copy. На этом этапе все, что вам нужно сделать, это преобразовать все ваши системные вызовы для использования вашей процедуры рекурсивного копирования. По крайней мере, попробуйте использовать File :: Copy, чтобы увидеть, работает ли он там, где xcopy не работает. Возможно, вы сможете извлечь из этого некоторую информацию. Еще одно преимущество File :: Copy заключается в том, что вы можете использовать косую черту в качестве разделителей пути, тем самым устраняя необходимость в экранированных обратных косых чертах. Одно это было бы достаточно большой победой в моей книге. - person Barton Chittenden; 11.05.2012

Попробуйте перенаправить INPUT с нулевого устройства, чтобы проверить, работает ли ваш xcopy. Не знаю почему, я столкнулся с этой проблемой очень давно и каким-то образом (возможно, через веб-поиск) понял это.

Это выглядело бы примерно так:

xcopy /args $source $target <nul:;

(Обратные кавычки вокруг всей команды не отображаются)

JKE

person John Elion    schedule 08.10.2012
comment
Спасибо, ты палочка-выручалочка. У меня была такая же проблема с UniVerse EXECUTE "DOS /C XCOPY ...", он работал из подпрограммы, но не работал без вывода при вызове из фантомного процесса. Добавление редиректа в конец решило эту проблему. - person DarthJDG; 27.01.2014

Вы пробовали system со списком аргументов?

my @args= qw(M:\STUFF\ABC D:\temp\dest1 /c /i /e);
warn "Executing 'xcopy @args' ...\n";
system xcopy => @args;
person Sinan Ünür    schedule 10.05.2012
comment
Мысль о том, чтобы попробовать это, а также open (), но поскольку обратные кавычки и система дают тот же результат, и проблема устраняется последовательно после ручного копирования, я полагаю, что тип системного вызова не является виновником . - person UhClem; 11.05.2012

File :: Copy :: Recursive может решить вашу проблему.

Таким образом, у вас будет более управляемый способ копирования файлов. Вы могли бы обернуть этот вызов в блок eval и применить там какую-то логику повтора?

Может, "пустышка" по проблемному файлу поможет? Измените атрибут / метку времени файла или переименуйте его во что-нибудь другое и переименуйте обратно ...

person user1126070    schedule 10.05.2012
comment
Да, 6 месяцев назад я добавил в свой код комментарий, что лучше использовать File :: Copy :: Recursive. Системный вызов xcopy - временное решение, пока сотрудники моей компании не убедятся разрешить этот модуль. (Длинная история.) - person UhClem; 11.05.2012

Если вы посмотрите на как ClearCase управляет доступом для чтения и записи для Vob и представлений, вы увидите разницу между:

  • чтение содержимого каталога (нужно r-x)
  • чтение файла в каталоге (нужно просто "--x" в каталоге + "r--" в файле)

Таким образом, в зависимости от того, какой пользователь стоит за процессом, запускающим xcopy, у вас могут возникнуть проблемы с чтением / доступом к определенным каталогам / файлам.
И вам нужно убедиться, что использование установило CLEARCASE_PRIMARY_GROUP на правильное значение (т. Е. Группа, указанная как первичная группа vob или одна из его вторичных групп), чтобы получить доступ к Vob (но если его защита достаточно слабая, каждый может получить к нему доступ в любом случае).

Все, что применимо к динамическому представлению, и применимо только к обновлению представления моментального снимка (после завершения обновления вы получаете файлы, скопированные локально и которые могут быть прочитаны любым процессом).

person VonC    schedule 11.05.2012