Показаны сообщения с ярлыком Администрирование. Показать все сообщения
Показаны сообщения с ярлыком Администрирование. Показать все сообщения

Секреты командной Строки Windows часть 2.

В продолжении темы Cmd – хаков, опишу еще несколько эффективных приемов работы с командной строкой.

>> Что такое enabledelayedexpansion?

Вообще я не хотел писать об этом, но т.к. в следующем примере это используется и в справке расписано туманно, напишу.

Обычно при использовании переменных в bat/cmd сценариях используется конструкция %переменная%, однако если значение переменной меняется в теле цикла и считывается там же, это может не работать. Например:

for %%i in (1,2,3) do (
    set "var=%%i"
    echo %var%
Rem Не выведет ничего
)

pause

Если запустить этот пример то интерпретатор просто 3 раза выполнит echo без каких то либо параметров. Для того чтобы все работало верно нужно использовать расширенный режим обработки команд. Задается он командой setlocal  с параметром enabledelayedexpansion, а выключается командой endlocal. Приведу пример:

setlocal enabledelayedexpansion

for %%i in (1,2,3) do (
    set "var=%%i"
    echo !var!
Rem Выведет 1,2,3
)

Pause

Теперь все выводится как и задумано. Замечу что переменная в данном случае обрамлена восклицательными знаками (!).

>> Создание динамических переменных в bat-файлах? Легко!

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

Например есть текстовый файл, нам нужно его прочитать и вывести определенные строки на экран, покажу как это сделать при помощи динамических переменных.

Для начала создадим файл greeka.txt  с таким содержимым:

1.Ехал Грека через реку,Видит Грека - в реке рак.

2.Ехал Грека через реку,Видит Грека - в реке рак.

3.Ехал Грека через реку,Видит Грека - в реке рак.

4.Ехал Грека через реку,Видит Грека - в реке рак.

5.Ехал Грека через реку,Видит Грека - в реке рак.

6.Ехал Грека через реку,Видит Грека - в реке рак.

7.Ехал Грека через реку,Видит Грека - в реке рак.

8.Ехал Грека через реку,Видит Грека - в реке рак.

9.Ехал Грека через реку,Видит Грека - в реке рак.

10.Ехал Грека через реку,Видит Грека - в реке рак.

 

Далее, приступим к написанию нашего сценария:

    @echo off

    setlocal enabledelayedexpansion

Включаем режим расширенной обработки команд.

    set i=0

Объявляем вспомогательную переменную.

    for /F "tokens=*" %%a in (greka.txt) do (

Начало цикла  построчного перебора файла.

      set /A i=!i! + 1

Увеличиваем вспомогательный итератор на единицу. 

      set str!i!=%%a

Собственно сама незамысловатая конструкция создания динамических переменных, с именами str1, str2, str3 и так далее.

    )

Проверим как отработал наш сценарий.

Начало цикла 

Echo Это 10 строка... -------^>^> %str10%
Echo +++++++++++++++++++++++++++++++++++++++++++++
Echo +++++++++++++++++++++++++++++++++++++++++++++
Echo ...а  это вторая -------^>^> %str2%
pause

Как видим динамические переменные использовать довольно удобно и легко, они могут помочь вам заменить массивы и добавят гибкости коду.

>> Поиск и замена текста в файлах средствами cmd/bat файла.

Многие администраторы и Power-пользователи линукс, при знакомстве с возможностями cmd, замечают такую досадную деталь, как отсутствие множества утилит для поиска и замены подстрок в  файлах.

Вообще под windows существует множество утилит для обработки строк в файлах, в том числе и портированных с #nix систем (тот же sed и supersed), но мы не ищем легких путей это будет не совсем чисто, т.к. в нужный момент этого всего может не оказаться под рукой.

Возможна ли реализация данной функции на cmd ? Конечно! А поможет нам в этом специальные строки расширения, а точнее конструкция  вида %переменная:A=B%, где переменная- переменная содержащая исходную подстроку, A – подстрока которую ищем, B – подстрока на которую меняем искомую подстроку в строке.

Приступим писать наш код, т.к. он очень похож на тот что выше, особо вдаваться в детали я не буду:

@echo off

setlocal enabledelayedexpansion

rem Собираем параметры командой строки переданной сценарию.
rem Например сценарий запущен "File_str_replace.bat greka.txt Грека Гитлер"
rem %1 = greka.txt %2=Грека %3=Гитлер
Set infile=%1
Set find=%2
Set replace=%3

    @echo off

    setlocal enabledelayedexpansion

    set COUNT=0

    for /F "tokens=* delims=," %%n in (!infile!) do (
    set LINE=%%n

    set TMPR=!LINE:%find%=%replace%!

REM Именно здесь происходит замена текущей строки!

    Echo !TMPR!>>TMP.TXT

REM Добавляем строку к временному файлу
                    )

REM Делаем резервное копирование исходного файла, на случай что что то пойдет не так…

copy %infile% %infile%.bak

REM Заменяем исходный файл временным

move TMP.TXT %infile%

Наш батник для поиска и замены подстрок файла готов. Теперь сгенерируем файл для него, да побольше! Сделаем это тоже батником:

@echo off
for /L %%i in (1,1,100000) do (

echo %%i.Ехал Грека через реку,Видит Грека - в реке рак.Сунул Грека в реку руку,Рак за руку Греку - цап!>>greka.txt
)

Получился файл, забитый поговоркой, размером ~ 10 мегабайт, неплохо для примера…  Запустим Наш сценарий введя в командной строке “File_str_replace.bat greka.txt Грека Гитлер” , для того чтобы заменить все слова Грека на Гитлер. Запустив увидим что через полторы минуты(неплохо для 20-ти летнего консольного мамонта) в нашем файле поговорка заменилась на “Ехал Гитлер через реку,Видит Гитлер - в реке рак.Сунул Гитлер в реку руку,Рак за руку Греку - цап”. Можно усовершенствовать сценарий, и даже прикрутить к ней регулярные выражения, но это уже мелкие технические детали :)

На сегодня пожалуй все, попозже продолжу.

Секреты командной строки Windows, часть 1.

К сожалению, благодаря ряду независящих от нас причин, командная оболочка cmd.exe до сих пор не утратила своей актуальности. Многие системные администраторы используют ее для управления своими задачами, при отсутствии на OS других средств, либо в силу привычки. Несмотря свою на простоту, командная строка обладает рядом интересных и неочевидных возможностей. В этом посте я постараюсь рассказать, о некоторых недокументированных либо малоизвестных возможностях командной строки Windows.

>> Beep из bat-файла.

В консоли Windows отсутствует команда заставляющая пищать системный динамик, но существует "недокументированный" символ (•) при выводе которого на экран консоли системный динамик издает звук. Чтобы ввести его нужно в текстовом редакторе набрать "Alt+7". Например: @echo •.

Проблема заключается в том что не все редакторы сохраняют такие символы, а по закону подлости ты оказываешься за компьютером, который, как раз без такового. Но и это можно обойти: запустим cmd.exe и в командной строке наберем @Echo,  нажав комбинацию Ctrl+G или "Alt+7" получим ^G далее перенаправим это все в файл, должно получиться @Echo echo ^G >beep.bat. Файл-пищалка готов.

>> Внутренний вызов команды CALL.

Из справочной документации Microsoft мы знаем, что команда Call - совершает вызов одного пакетного файла из другого, без завершения выполнения первого файла, но мало кому известно что при помощи Call можно перемещаться по внутренним меткам того же cmd/bat файла, подобно команде Goto. @Зачем это нужно, ведь есть goto?" - спросите вы. А затем, что помимо просто перемещения по меткам команда Сall имеет две особенности :

  1. "Умеет" возвращаться к месту своего вызова с помощью специальной метки :EOF.
  2. Умеет передававать значения в "подпрограмму". Поясню на примере:

@echo off

Rem Вызываем подпрогамму

call :SQRT 2

call :SQRT 8

pause

goto :EOF

rem а вот тут уже выходим см. ниже.

rem ***Начало подпрограммы.***

:SQRT

set /a outputval= %1*%1

echo Корень из %1 равен %outputval%.

goto :EOF

rem не выходим, но всего лишь возвращаемся на место за вызовом

rem ***Конец подпрограммы.***

После выполнения данного командного сценария получим такой вывод:

Красиво, не правда ли? Такая незаметная возможность, может сэкономить кучу строк кода, и на время может показаться, что мы программируем на полноценном скриптовом языке.

Да, стоит учесть еще и то что в подпрограмму можно передавать несколько аргументов, тогда обращаться к ним следует так же как и к аргументам командной строки %1, %2, %3 … и далее по порядку.

Символы экранирования в bat-файле.

Что если вам надо вывести  в консоль текст содержащий операторы или спецсиволы?

Например надо вывести: “%TEMP%”. Попробуем ввести в командную строку Echo %TEMP%.

Результат:

 

На консоль вывелось значение переменной %TEMP%. Совсем не то что нам надо…  Для таких случаев и существуют символы экранирования “^” и “%”. Достаточно его подставить перед спецсимволом и интерпретатор поймет что мы хотим вывести именно символ а не строку или выражение.Для проверки создадим батник:

@Echo off
Echo съешь еще этих французских булок да выпей чаю ^
съешь еще этих французских булок да выпей чаю ^
съешь еще этих французских булок да выпей чаю ^
съешь еще этих французских булок да выпей чаю

Echo %%TEMP%%

Pause

Результат:

Как видим все работает и экономия кода на лицо.

Не смотря на то что в примере все отработало, с  экранированием в батниках надо быть более осторожным, не всегда все гладко, поэтому следует тестировать каждый скрипт.

На сегодня все, продолжение в другом посте.

Миграция на Windows 2003 Server с Novell Netware 6.5: Автоматизированный перенос пользователей.

Novell Netware одна из наиболее стабильных и надежных сетевых операционных систем, но имеет один неприятный недостаток - она разработана не в Microsoft, что влечет за собой стремительное сокращение оной на рынке серверных ОС. На сегодняшний день Novell не планирует развитие данной ОС, а стремительно (в 2008 году продано более 400 000 лицензий) выводит на рынок свои Linux дистрибутивы SLES и OES, что заставляет по крайней мере задуматься над миграцией на более перспективные современные ОС.

В этой статье я расскажу о переносе учетных записей пользователей с Novell Netware 6.5, на Windows 2003 Server путем импорта данных при помощи ODBC Driver for eDirectory и экспорта их при помощи пакетного файла Windows.


Пример не практический, но на основе его можно разработать перенос практически любой информации из базы Novel eDirectory в службу каталогов Active Directory.


Нам понадобиться:

  1. Сервер с установленным Windows 2003 Server с развернутым контроллером домена.
  2. Сервер с установленным Novell Netware 6.5 с заведенными пользователями и группами.
  3. Рабочая станция (OS Windows) с установленным клиентом Novell Netware, PHP5 и ODBC Driver for eDirectory.

Этап #1: Создание DSN Novell ODBC for NDS

ODBC Driver for eDirectory универсальный программный интерфейс, для доступа к базе Novell eDirectory, позволяющий обращаться к ней различным программным средствам (например MS Access, MS Excel, Vba и многим другим) с использованием SQL синтаксиса, незная внутреннего устройства eDirectory. ODBC позволяет значительно снизить время разработки ПО, но в то же время не расчитан на большое число подключений клиентов.

Для того чтобы установить ODBC Driver надо либо скачать его с сайта Novel, либо если у вас установлена ConsoleOne в папке *\consoleone\1.2\reporting\bin\odbc.exe. После установки необходимо настроить источник данных, для чего запустить Администратор источников данных ODBC. - odbcad32.exe. Далее перейти на вкладку Системный DSN и нажать кнопку Добавить, в следующем списке выбрать Novell ODBC Driver for NDS.



NDS - так называлось то что впоследствии переросло в eDirectory.


Далее ввести имя источников данных и обозначить дерево, имя не важно какое, но мы введем Novell.

Жмем два раза ок.

Этап #2: Извлекаем данные Novell eDirectory.

Для подключения к источникам данных ODBC будем использовать язык программирования PHP5. Итак сам код.

Объявляем переменные:

Имя домена первого и второго уровня
//Имя домена
$dc1="local";
$dc2="dc";
$context='.imns';
На следующих двух ф-ях заострять внимание пока не следует.

Вспомогательная функция для вывода на консоль в ДОС кодировке:
function echo_con($str)// вывод в консоль в дос кодировке
{
$str=convert_cyr_string($str,'w','a');
echo($str."\n");
return($str);
}
Функция для записи аварийных ситуаций
function error_con($err_dump)  // ф-я записи аварийных ситуаций
{
//Запись ошибок в лог:
$hd1=fopen("CONECT_ERROR.log", "w");
fwrite($hd1,$err_dump);
fclose($hd1);
}
Подключаемся к базе данных.

Обращаю внимание что в ф-ии odbc_connect() не обязательно вводить логин и пароль, если вы залогинены под админом, а это лучше сделать.
//***ПОДКЛЮЧАЕМСЯ К ОРАКЛУ****
echo_con("Подключаемся к базе, ждите..");

$con=odbc_connect("novell", "admin", "Очень_сложный_пароль",'SQL_CURSOR_USE_ODBC'); //УБРАТЬ ПАРОЛ�� !!!!
if ($con==0)
{
echo "Error Connect to server";
$err_dump.=odbc_error($con);

error_con($err_dump);
echo_con("/n ОШШИБКА СОЕДИНЕНИЯ С СЕРВЕРОМ!") ;
exit;
}
echo "OK... $con \n";

Тепрерь мы можем сформировать и выполнить запрос к базе eDirectory используя SQL синтаксис
Здесь мы выполняем запрос к таблице UserNDS на выборку имени пользователя в eDirectory, имени, фамилии, дерева, полного имени, группам в которых состоит пользователь, Id пользователя и емейла.

Естественно данная выборка приведена исключительно для примера, на практике можно вытянуть все что угодно, кроме пароля - пароль хеширован.

//Подготавливаем и выполняем запрос
echo_con("Ждите. Выполняем выборку из базы...");

$stmt = odbc_exec ($con,'SELECT "Given Name", "Surname", "NDS_Tree", "Full Name", "Group Membership", "GUID_Data","EMail Address_Addr", "CN"

FROM UserNDS

' );
Далее переводим полученные данные в два массива, первый - содержит все выбранные группы пользователей, второй- содержит всю информацию о пользователях.
$i=0; //для подсчета итераций в цикле
// присваеваем выходящему массиву значения из результата запроса
while(odbc_fetch_row($stmt))
{
if (odbc_result($stmt, 6)==$flagGUID_data)
{
if (trim(odbc_result($stmt, 5))!=='')
{
$groupArr[]=str_replace($context,'',trim(odbc_result($stmt, 5)));
}
$i--;
$out_arr[$i]['Group_Membership'] = $out_arr[$i]['Group_Membership']."|".str_replace($context,'',trim(odbc_result($stmt, 5)));
}
else
{
echo_con("User #: ".$i."\n");
echo_con("Given Name: ".$out_arr[$i]['Given_Name'] = trim(odbc_result($stmt, 1)));
echo_con("Surname: ".$out_arr[$i]['Surname'] = trim(odbc_result($stmt, 2)));
echo_con("Full Name: ".$out_arr[$i]['Full_Name'] = trim(odbc_result($stmt, 4)));
echo_con("Email: ".$out_arr[$i]['EMail Address_Addr'] = trim(odbc_result($stmt, 7)));
echo_con("Login: ".$out_arr[$i]['CN'] = trim(odbc_result($stmt, 8)));
echo_con("GUID_Data: ".$out_arr[$i]['GUID_Data'] = trim(odbc_result($stmt, 6)));
echo_con("Group Membership: ".$out_arr[$i]['Group_Membership'] = str_replace($context,'',trim(odbc_result($stmt, 5))));

$flagGUID_data= odbc_result($stmt, 6);
if (trim(odbc_result($stmt, 5))!=='')
{
$groupArr[]=str_replace($context,'',trim(odbc_result($stmt, 5)));
}
}
$i++;
}
В итоге имеем два массива данных, достаточных для выполнения нашей задачи.

Этап #3: Формируем пакетный файл для экспорта данных в eDirectory

Следующий код будет формировать bat файл, в котором используеться консольная утилита DSADD выполняющая добавление новых объектов в домен AD.

Почему именно бат файл? Почему не внести данные в базу AD прямо из скрипта?

Дело в том, что в Novell eDirectory есть несколько объектов (в том числе и users) являющихся системными, и переносить их в AD в подавляющем большинстве случаев не требуется. Понятно что такие объекты отследить программно сложно, поэтому и генерируем bat-ник, который потом может быть подредактирован системным администратором.
Далее код генерирующий пакетный файл.
//****Создаем cmd код для групп****
$batGroupUser.="
@ECHO OFF
rem Батник для создания пользователей и групп в домене
rem 1. Создаем группы.\n";
foreach ($groupArr as $val)
{
$batGroupUser.="dsadd group \"CN=$val"."1".",OU=test,DC=$dc2,DC=$dc1\"^
-secgrp yes^
-scope g^
-samid $val"."1"."^
-desc \"Novell_migrate\"\n Pause \n";
}
$batGroupUser.="\n\nrem 2. Создаем пользователей.\n";
foreach($out_arr as $val_u)
{
if ($val_u['CN'])
{
$batGroupUser.="\n"."dsadd user cn=\"$val_u[CN]\",ou=test,dc=$dc2,dc=$dc1^
-samID $val_u[CN]^\n";
if ($val_u['Given_Name'])
{
$batGroupUser.=" -fn \"$val_u[Given_Name]\"^\n";
}
if ($val_u['Surname'])
{
$batGroupUser.=" -ln \"$val_u[Surname]\"^\n";
}
if ($val_u['EMail Address_Addr'])
{
$batGroupUser.=" -email \"".$val_u['EMail Address_Addr']."\"^\n";
}
if ($val_u['Group_Membership'])
{ $batGroupUser.=" -memberOf";
$memb_arr=explode("|",$val_u['Group_Membership']);
foreach($memb_arr as $val_memb)
{
$batGroupUser.=" cn=\"$val_memb\",ou=test,dc=$dc2,dc=$dc1";
}
$batGroupUser.="^\n";
}
$batGroupUser.=" -pwd PassWord42^"."\n"." -desc \"Netware Migrate User\"\n Pause \n";
}
}
$batGroupUser.= "\n Pause";
$batHd=fopen("NetwareToWindows2003Server.bat",'w');
fwrite($batHd,$batGroupUser);
echo "END";

die();
В результате получаем пакетный файл, который после изучения и редактирования запускаем на Windows 2003 Server.