Работая в большой компании меня попросили скопировать файл размером 1Мб на удаленные машины под управление Windows XP Pro.

Все было бы хорошо, если бы не количество ПК, на которые необходимо было копировать файл. Их оказалось около 800!. Хорошей новостью было то, что на всех ПК были идентичные настройки, т.е. на каждом ПК был прописан пользователь с правами администратора и разрешен доступ к дискам по сети. У меня имеется рабочий ноутбук, на котором утановлена Xubuntu 10.4, его-то я и задумал использовать, так как много раз читал и слышал о скриптах в Linux и ни разу не доводилось писать их самому.

Итак, начнем…


Перебирая в голове возможные варианты я сразу отмел на последний план вариант с монтированием сетевого каталога, т.к хотелось какой-то легкости и универсальности. Посоветовавшись в IRC на канале #ubuntu-ru, мне было предложено использовать smbclient. Как я и поступил.

Проверка сетевого доступа.

Для начала я посмотрел синтаксис smbclient.

# smbclient
Использование: smbclient [-?EgBVNkPe] [-?|--help] [--usage]
        [-R|--name-resolve=NAME-RESOLVE-ORDER] [-M|--message=HOST]
        [-I|--ip-address=IP] [-E|--stderr] [-L|--list=HOST]
        [-t|--terminal=CODE] [-m|--max-protocol=LEVEL]
        [-T|--tar=<c|x>IXFqgbNan] [-D|--directory=DIR] [-c|--command=STRING]
        [-b|--send-buffer=BYTES] [-p|--port=PORT] [-g|--grepable]
        [-B|--browse] [-d|--debuglevel=DEBUGLEVEL]
        [-s|--configfile=CONFIGFILE] [-l|--log-basename=LOGFILEBASE]
        [-V|--version] [-O|--socket-options=SOCKETOPTIONS]
        [-n|--netbiosname=NETBIOSNAME] [-W|--workgroup=WORKGROUP]
        [-i|--scope=SCOPE] [-U|--user=USERNAME] [-N|--no-pass]
        [-k|--kerberos] [-A|--authentication-file=FILE]
        [-S|--signing=on|off|required] [-P|--machine-pass] [-e|--encrypt]
        service <password>

Меня интересовали параметры -U и -c. В параметре -U передается имя пользователя, от чьего имени будем выполнять действия. В параметре -c передается строка, состоящая из команд smbclient'а, разделенных знаком «;». Поиграв немного с различными вариантами я нашел свой вариант:

smbclient //<IP ПК>/D$/ <пароль> -U <пользователь> -c 'cd Data; put test.rar; exit'

После тестирования на 2-3 удаленных ПК я озадачился мыслью: «Как же имея список IP адресов в текстовом файле я буду подставлять значения в терминал?». И тут же понял, что необходимо приступать к написанию скритпа.

Пишем скрипт

Имея в запасе немного времени и огромное желание научиться работать со скриптами, я начал осваивать «Bash-Scripting». Посмотрев примеры я сразу для наглядности выделил переменные.

В моем случае это:

cmdline1='cd Data; put test.rar; exit'
share_drive='D$'	#диск на удаленной машине
login='admin'	#логин удаленного пользователя
pass='password'		#пароль удаленного пользователя

Далее, полистав руководство по Баш-Скриптингу, я нашел как осуществить чтение строк из файла, что давало мне возможность редактировать список хостов независимо от основного скрипта:

while read line #читаем строку из файла data-file в переменную line и
do              #выводим значение переменной на экран
  echo "$line" 
done <data-file

Вместо вывода на экран я подставил выполнение команды smbclient с аргументами.

while read line #читаем строку из файла data-file в переменную line и
do              #и используем ее в скрипте.
  smbclient //"$line"/D$/ password -U admin -c 'cd Data; put test.rar; exit'
done <file_ip

При выполнении этого цикла я обнаружил, что последняя строка из файла считывается, но не используется. Из-за сжатых сроков, я решил добавить строку и записать в нее произвольное значение.

В итоге я пришел к такому варианту, при котором аргументы передаются из переменных:

#!/bin/bash
# IP брать из файла file_ip
#команды, которые надо выполнить при логине SmbClient'a на удаленной машине
cmdline1='cd Data; put test.rar; exit'
share_drive='D$'	#диск на удаленной машине
login='admin'		#логин удаленного пользователя
pass='password'		#пароль удаленного пользователя

while read share_ip 	#читаем построчно файл с ip адресами (одна строка = один ip адрес)
			#при таком построении цикла последняя строка в файле помещается в переменную и цикл завершается,
			#т.е. переменная не используется. Для этого в конце файла я поместил строку 'EoF'.
do
	#используя SMBClient заходим по логину паролю на удаленную машину и выполняем команды, переданные в cmdline1
	echo "$share_ip" # для тестирования чтения я использовал вывод значения переменной на экран.
	smbclient //"$share_ip"/"$share_drive"/ "$pass" -U "$login" -c "$cmdline1" 
done <file_ip
echo "All done!..."

Заключение

После написания данного скрипта я получил хороший инструмент для сравнительно быстрого копирования файлов по сети. Со временем в скрипт можно добавлять различные проверки (к примеру: убирать дубликаты IP адресов в списке), добавлять команды… Список ограничевается только вашими потребностями и фантазией.

Надеюсь данное руководство найдет своего читателя и поможет приобрести первый опыт по написанию Bash-Script'ов, как помог мне.