В этой статье рассматривали как можно скопировать файлы на несколько удаленных узлов, но есть одна проблема при копировании файлов большого объема, копирование будет занимать много времени, если копировать на каждый узел последовательно как в данной статье.
Распараллелим процесс копирования, но с оговоркой, в моем примере будет ограничение на 5 процессов копирования за раз. Можно будет увеличить, но все равно будет ограничение по количеству свободных меток дисков.
Также добавим логирование действий в файл и отключим вывод информации в консоль.
В файле ip_list.txt первая строка путь до файла. Начиная со второй строки начинаются узлы, на которые будем копировать данные.
C:\TEMP\test
172.24.69.194
172.24.69.196
bat - файл запуска:
@echo off
Setlocal EnableDelayedExpansion
for /f "usebackq" %%S in (`find /c /v ""^<"%~dp0ip_list.txt"`) do (set /a NumStr=%%S)
set /A NumStr-=1
IF %NumStr% GTR 5 (
echo IP addresses more than 5
exit /b
)
set /P path_to_file=<%~dp0ip_list.txt
set i=0
FOR /F "skip=1" %%a IN (%~dp0ip_list.txt) DO (
set /A i+=1
if !i! == 1 set disk=Z:
if !i! == 2 set disk=Y:
if !i! == 3 set disk=W:
if !i! == 4 set disk=V:
if !i! == 5 set disk=U:
start %~dp0copy_files.bat %%a %path_to_file% !i! !disk!
)
endlocal
@echo on
@echo off - отключает вывод текста в терминал
Setlocal EnableDelayedExpansion - включает режим "отложенного раскрытия переменных", т. е. чтобы переменные, измененные внутри "скобок" (типа FOR … DO …) обновлялись именно в момент изменения, а не при выходе за "скобки" (при этом к переменным надо обращаться через восклицательный знак: !i!, а не через процент, как обычно).
for /f "usebackq" %%S in (`find /c /v ""^<"ip_list.txt"`) do (set /a NumStr=%%S)
set /A NumStr-=1 - этот блок подсчитывает количество строк в файле ip_list.txt и передает значение в переменную NumStr, отнимаем одну строку в переменной NumStr, т. к. первая строка в файле это путь до файлов.
Т.к. я ввел ограничение на количество одновременных копирований в размере 5 штук, для этого и необходимо подсчитать количество узлов для копирования.
IF %NumStr% GTR 5 (
echo IP addresses more than 5
exit /b
) - если количество узлов в файле ip_list.txt больше 5, то выводим сообщение, что узлов больше чем 5 и завершаем программу.
set /P path_to_file=<%~dp0ip_list.txt - В переменную path_to_file записываем первую строку нашего файла ip_list.txt, там у нас храниться путь до файла/файлов/подпапок.
set i=0 - в переменную i будут записывать значения нашего счетчика. Обнуляем счетчик
FOR /F "skip=1" %%a IN (%~dp0ip_list.txt) DO (
set /A i+=1
if !i! == 1 set disk=Z:
if !i! == 2 set disk=Y:
if !i! == 3 set disk=W:
if !i! == 4 set disk=V:
if !i! == 5 set disk=U:
start %~dp0copy_files.bat %%a %path_to_file% !i! !disk!
) - идем по строкам (ip адресам) файла ip_list.txt, минуя первую строку "skip=1", в переменную i прибавляем единицу при каждой итерации цикла. Проверяем переменную i. Относительно значения счетчика i переменной disk присваивается метка диска. start - запускает команду или программу в отдельном окне, позволяет нам выполнять несколько копирований одновременно. copy_files.bat - файл содержит команды по копированию данных в узел, его разберем позднее, в данный bat - файл передаем параметры: 1) %%a - ip адрес узла,
2) %path_to_file% - путь до файлов которые нужно скопировать,
3) !i! - значение счетчика, нужен для создания log файла,
4) !disk! - метка диска
endlocal - окончание использования локального окружения в пакетной программе, восстановление значений переменных среды, имевшихся до выполнения соответствующей команды setlocal.
@echo on -включает вывод текста в терминал.
Файл copy_files.bat
@echo off
Setlocal EnableDelayedExpansion
set login=<имя пользователя>
set pass=<пароль>
set ip=%1
set files=%2
set log_name=log_%3.log
set disk=%4
ECHO Start run bat_file %0 Date: %DATE% Time: %TIME% >> %log_name%
IF EXIST %disk% net use %disk% /delete /y >> %log_name% 2>&1
net use %disk% \\%ip%\C$ %pass% /USER:%login% /persistent:no >> %log_name% 2>&1
if %ERRORLEVEL% GTR 0 exit /b
IF NOT EXIST %disk%\install mkdir %disk%\install >> %log_name% 2>&1
xcopy /y /z /h /c /i /r /s %files% %disk%\install >> %log_name% 2>&1
net use %disk% /delete /y >> %log_name% 2>&1
ECHO End of the bat_file %0 Date: %DATE% Time: %TIME% >> %log_name%
@echo on
exit 0
set login=<имя пользователя> - присваиваем переменной login имя пользователя учетной записи ОС, у которого есть доступ к диску С
set pass=<пароль> - присваиваем переменной pass пароль пользователя
set ip=%1 - присваиваем переменной ip ip-адрес узла, к которому будем подключаться, здесь присваиваем первый параметр передаваемый в bat-файл copy_files.bat
set files=%2 - присваиваем переменной files путь до фалов/файла, здесь присваиваем второй параметр передаваемый в bat-файл copy_files.bat
set log_name=log_%3.log - присваиваем переменной log_name имя лог файла, здесь присваиваем имя + третий параметр передаваемый в bat-файл copy_files.bat
set disk=%4 - присваиваем переменной disk метку диска, здесь присваиваем четвертый параметр передаваемый в bat-файл copy_files.bat
ECHO Start run bat_file %0 Date: %DATE% Time: %TIME% >> %log_name% - передаем в лог файл дату и время запуска bat-файла. %0 - возвращает наименование файла с полным путем.
IF EXIST %disk% net use %disk% /delete /y >> %log_name% 2>&1Далее проверяем существование сетевого диска , если существует удаляем, т.к. может быть привязан к другому узлу сети. Если возникнет ошибка логируем в файл.
net use %disk% \\%ip%\C$ %pass% /USER:%login% /persistent:no >> %log_name% 2>&1 создаем сетевой диск на нашем узле, ip до сетевого узла берем из переменой ip. Будем получать целиком до диска С:, запись C$ Дальше команде передаем пароль из переменной %pass% и логин /USER:%login% /persistent:no - при выходе из системы не сохраняется сетевое подключение. Если возникнет ошибка логируем в файл.
if %ERRORLEVEL% GTR 0 exit /b - если предыдущая команда завершиться с ошибкой, завершаем выполнение программы, т.к. сетевой диск не создан, копирование не возможно.
IF NOT EXIST %disk%\install mkdir %disk%\install >> %log_name% 2>&1 Проверяем существует ли папка install на сетевом диске, если папки нет создаем папку install
xcopy /y /z /h /c /i /r /s %files% %disk%\install >> %log_name% 2>&1 копируем файлы с нашего узла по пути хранящимся в переменной files в сетевую папку
net use %disk% /delete /y >> %log_name% 2>&1 удалям созданный нами сетевой диск с нашего хоста
Статья по bat-файлам здесь
Более детально по используемым командам можно почитать тут: