none
Очень СРОЧНО нужен совет по BAT. RRS feed

  • Вопрос

  • Всем большой привет!

    Недавно появилась задача актуализации учетных данных в MSAD. Данные пользователей приходят в файле *.csv.

    Я написал bat'ник, который считывает данные из файла и на основе команда dsmod user, dsmod group, dsadd user, dsquery user, dsmove добавляет\обновляет данные юзеров.

    Все работает отлично работает, если в файле *.csv только одна запись. Как только он содержит данные по нескольким пользователем, все встает колом.

    Вот этот код

    SETLOCAL EnableDelayedExpansion
    rem @echo off
    chcp 65001
    set FILE=userlist_upd.csv
    set FILE2=userlist_upd.csv
    set AUDIT=C:\AD\History\
    set DOMEN=OU=CAFK,DC=fljme,DC=ru
    set VDATE=%date:~-10%
    set VTIME=%time:~0,-3%
    set VTIME=%VTIME::=.%
    
    for /F "tokens=1 delims=;" %%a in (%FILE%) do (	
    	for /F "Delims=" %%a in ('dsquery user -samid %%a') do (set var=%%a)
    )
    			@echo %var%
    			
    			set dnuser=%var:~1,-1%
    			set dngroup1=%var:~8,-1%
    			set dngroup2=%var:~12,-30%
    			set "dngroup3=CN=G%dngroup2%"
    			set "dngroup="%dngroup3%%dngroup1%""
    			
    			@echo dngroup1= %dngroup1%
    			@echo dngroup2= %dngroup2%
    			@echo dngroup3= %dngroup3%
    			@echo before FOR group= %dngroup%
    			@echo before FOR user= %dnuser%
    	
    
    
    	for /F "tokens=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 delims=;" %%a in (%FILE%) do (
    		if "%dnuser%" EQU "CN=%%a,OU=%%m,OU=%%l,%DOMEN%" (
    			if "%%c"=="true" (
    			dsmod user "CN=%%a,OU=%%m,OU=%%l,%DOMEN%" -fn "%%i" -ln "%%j" -disabled no -display "%%i %%j" -company "%%f" -empid "%%b" -title "%%d" -tel "%%k" -Office "%%g" -dept "%%e"
    			) 	else 	if "%%c"=="false" (
    					dsmod user "CN=%%a,OU=%%m,OU=%%l,%DOMEN%" -disabled yes
    					)
    				 
    		)	else if "%dnuser%" NEQ "CN=%%a,OU=%%m,OU=%%l,%DOMEN%" (
    				dsmod group "%dngroup%" -rmmbr "%dnuser%"
    				dsquery user -samid "%%a" | dsmod group "CN=%%o,OU=%%m,OU=%%l,%DOMEN%" -addmbr "%dnuser%"
    				dsmove "%dnuser%" -newparent "OU=%%m,OU=%%l,%DOMEN%"
    				dsmod user "CN=%%a,OU=%%m,OU=%%l,%DOMEN%" -fn "%%i" -ln "%%j" -disabled no -display "%%i %%j" -company "%%f" -empid "%%b" -title "%%d" -tel "%%k" -Office "%%g" -dept "%%e"	
    			)	
    )
    
    ENDLOCAL
    
    if ERRORLEVEL 1 echo !!!ERROR!!! 
    rem if ERRORLEVEL 0 move %FILE% %AUDIT% && REN %AUDIT%%FILE% ????????????-%VDATE%-%VTIME%.cs

    Если сделать вложенные циклы for (для обработки всех записей файла *.csv), то затык происходит в этом месте

    for /F "tokens=1 delims=;" %%a in (%USERLOGIN%) do (	
    	for /F "Delims=" %%a in ('dsquery user -samid %%a') do (
    			set var=%%a
    
    			@echo %var%
    			
    			set dnuser=%var:~1,-1%
    			set dngroup1=%var:~8,-1%
    			set dngroup2=%var:~12,-30%
    			set "dngroup3=CN=G%dngroup2%"
    			set "dngroup="%dngroup3%%dngroup1%""
    			
    			@echo dngroup1= %dngroup1%
    			@echo dngroup2= %dngroup2%
    			@echo dngroup3= %dngroup3%
    			@echo before FOR group= %dngroup%
    			@echo before FOR user= %dnuser%
    	)
    )
    

    И даже так не работает

    for /F "tokens=1 delims=" %%a in (%FILE%) do (	
    	dsquery user -samid "%%a"
    	pause
    )

    Берется первая запись подставляется в в команду dsquery user, возвращается DN пользователя и все ОК. А вот остальные значения просто подставляются в команду dsquery user и не возвращается результат поиска.

    Сломал уже всю голову, как это решить.

    18 декабря 2013 г. 11:20

Ответы

  • что вам мешает засунуть

    'dsquery user -samid %%a

    и иже с ними внутрь

    вот этого фора:

    for /F "tokens=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 delims=;" %%a in (%USERLIST%) do (

    ?

    зачем вам 2 раза читать файл?

    2х for'ов достаточно

    • Помечено в качестве ответа Sergey Zakharov 20 декабря 2013 г. 8:54
    19 декабря 2013 г. 10:30

Все ответы

  • ща посмотрим, но на будущее постите вопросы по скриптам в эту ветку:

    http://social.technet.microsoft.com/Forums/ru-RU/home?forum=scrlangru



    • Изменено Svolotch 18 декабря 2013 г. 17:09
    18 декабря 2013 г. 12:16
  • ща посмотрим, но на будущее постите вопросы по скритам в эту ветку:


    Ok,  я тут первый раз. Еще не ознакомился со всеми имеющимся ветками форума.
    18 декабря 2013 г. 12:23
  • for /F "tokens=1 delims=" %%a in (%FILE%) do (	
    	dsquery user -samid "%%a"
    	pause
    )

    работает корректно, просто перечисляет DNки пользователя (в файлике просто логины)

    			set "dngroup3=CN=G%dngroup2%"
    			set "dngroup="%dngroup3%%dngroup1%""
    а это чо за байда с кавычками?

    • Изменено Svolotch 18 декабря 2013 г. 12:37
    18 декабря 2013 г. 12:33
  • for /F "tokens=1 delims=" %%a in (%FILE%) do (	
    	dsquery user -samid "%%a"
    	pause
    )

    работает корректно, просто перечисляет DNки пользователя (в файлике просто логины)

    В файле хранится 5 логинов. Вот что возвращает for

    c:\AD>3
    
    c:\AD>setlocal enabledelayedexpansion
    
    c:\AD>chcp 65001
    Active code page: 65001
    
    c:\AD>set FILE=userlogin_upd.csv
    
    c:\AD>for /F "tokens=1 delims=" %a in (userlogin_upd.csv) do (
    dsquery user -samid "%a"
     pause
    )
    
    c:\AD>(
    dsquery user -samid "2807"
     pause
    )
    "CN=2807,OU=0104,OU=01,OU=CAFK,DC=fljme,DC=ru"
    Press any key to continue . . .
    
    c:\AD>(
    dsquery user -samid "4578"
     pause
    )
    Press any key to continue . . .
    
    c:\AD>(
    dsquery user -samid "2344"
     pause
    )
    Press any key to continue . . .
    
    c:\AD>(
    dsquery user -samid "1235"
     pause
    )
    Press any key to continue . . .
    
    c:\AD>(
    dsquery user -samid "6765"
     pause
    )
    Press any key to continue . . .
    
    c:\AD>(
    dsquery user -samid "1976"
     pause
    )
    Press any key to continue . . .
    
    c:\AD>setlocal disabledelayedexpansion
    
    c:\AD>
    

    Только для 2807 выводится DN.

    Каждый результат поиска мне нужно записать в переменную, которую потом нужно будет обрабатывать. Т.к. DN выводится только для 1го логина, то и обрабатывается только одна запись.

    Или я что-то тут не понимаю....

    18 декабря 2013 г. 12:41
  • при этом команда

    dsquery user -samid "4578"

    возвращает данные сама по себе?

    18 декабря 2013 г. 12:45

  • 			set "dngroup3=CN=G%dngroup2%"
    			set "dngroup="%dngroup3%%dngroup1%""
    а это чо за байда с кавычками?

    1. Отыскивается пользователь

    2. С помощью этой байды выясняется текущая группа безопасности пользователя (они у нас называются G0101, G0201 и т.д.), из которой он удаляется.

    c:\AD\backup>(set var="CN=2759,OU=0102,OU=01,OU=CAFK,DC=fljme,DC=ru" )
    "CN=2759,OU=0102,OU=01,OU=CAFK,DC=fljme,DC=ru"
    
    c:\AD\backup>set dnuser=CN=2759,OU=0102,OU=01,OU=CAFK,DC=fljme,DC=ru
    
    c:\AD\backup>set dngroup1=,OU=0102,OU=01,OU=CAFK,DC=fljme,DC=ru
    
    c:\AD\backup>set dngroup2=0102
    
    c:\AD\backup>set "dngroup3=CN=G0102"
    
    c:\AD\backup>set "dngroup="CN=G0102,OU=0102,OU=01,OU=CAFK,DC=fljme,DC=ru""
    dngroup1= ,OU=0102,OU=01,OU=CAFK,DC=fljme,DC=ru
    dngroup2= 0102
    dngroup3= CN=G0102
    dngroup= "CN=G0102,OU=0102,OU=01,OU=CAFK,DC=fljme,DC=ru"

    18 декабря 2013 г. 12:52
  • for /F "tokens=1 delims=" %a in (userlist_upd.csv) do dsquery user -samid "%a"
    Вот так в командной строке хотябы работает?
    18 декабря 2013 г. 13:19
  • при этом команда

    dsquery user -samid "4578"

    возвращает данные сама по себе?

    Svolotch, вот после этого вопроса мне нужно сгореть со стыда, т.к. в этих своих экспериментах я уже напрочь запутался и ищу тех юзеров, которые отсутствуют в AD.

    Спасибо, что указал на это. "Ошибку" с dsquery я исправил.

    Но остался самый главный вопрос. Как обрабатывать каждый найденный DN по отдельности с помощью байды, указанной выше.

    for /F "tokens=1 delims=" %%a in (%USERLOGIN%) do (	
    	for /F "Delims=" %%a in ('dsquery user -samid %%a') do (
    			set var=%%a
    			@echo DNuser !var!
    			
    			pause
    	
    
    			set dnuser=%var:~1,-1%
    			set dngroup1=%var:~8,-1%
    			set dngroup2=%var:~12,-30%
    			set "dngroup3=CN=G%dngroup2%"
    			set "dngroup="%dngroup3%%dngroup1%""
    			
    			@echo dnuser = %dnuser%
    			@echo dngroup1= %dngroup1%
    			@echo dngroup2= %dngroup2%
    			@echo dngroup3= %dngroup3%
    			@echo dngroup = %dngroup%
    			@echo before FOR group= %dngroup%
    			@echo before FOR user= %dnuser%
    	)
    )

    После исполнения этой части скрипта получается вот такая штука:

    c:\AD>setlocal enabledelayedexpansion
    Active code page: 65001
    DNuser "CN=2871,OU=0105,OU=01,OU=CAFK,DC=fljme,DC=ru"
    Press any key to continue . . .
    dnuser =
    dngroup1=
    dngroup2=
    dngroup3=
    dngroup =
    before FOR group=
    before FOR user=
    DNuser "CN=2807,OU=0104,OU=01,OU=CAFK,DC=fljme,DC=ru"
    Press any key to continue . . .
    dnuser =
    dngroup1=
    dngroup2=
    dngroup3=
    dngroup =
    before FOR group=
    before FOR user=
    DNuser "CN=2759,OU=0102,OU=01,OU=CAFK,DC=fljme,DC=ru"
    Press any key to continue . . .
    dnuser =
    dngroup1=
    dngroup2=
    dngroup3=
    dngroup =
    before FOR group=
    before FOR user=
    
    c:\AD>

    Как я понимаю, тут дело в теории переменных, их раскрытии и т.д. Может подскажешь, как это исправить.

    18 декабря 2013 г. 13:23
  • бгггг, бывает чо

    начнем с простого

    SETLOCAL EnableDelayedExpansion
    rem @echo off
    chcp 65001
    set FILE=list.txt
    
    for /F "tokens=1 delims=;" %%a in (%FILE%) do (    
    for /F "Delims=" %%a in ('dsquery user -samid %%a') do (
                            set var=%%a
                            echo %%a
                            echo %var%
    
            )
    
    )
    
    
                            echo +++++++++++++++++++++++++++++++++++++++++++++++++++++++
                            echo %var%
    pause
    
    

    посмотрите в частности на вывод  блока

    do (
                            set var=%%a
                            echo %%a
                            echo %var%
    
            )
    18 декабря 2013 г. 13:29
  • у вас переменная вар в цикле не будет определена... только по выходу из него
    18 декабря 2013 г. 13:31
  • бгггг, бывает чо

    начнем с простого

    посмотрите в частности на вывод  блока

    do (
                            set var=%%a
                            echo %%a
                            echo %var%
    
            )

    Получается вот такая штука

    c:\AD>(for /F "Delims=" %a in ('dsquery user -samid 2871') do (
    set var=2871
     echo 2871
     echo
    ) )
    
    c:\AD>(
    set var="CN=2871,OU=0105,OU=01,OU=CAFK,DC=fljme,DC=ru"
     echo "CN=2871,OU=0105,OU=01,OU=CAFK,DC=fljme,DC=ru"
     echo
    )
    "CN=2871,OU=0105,OU=01,OU=CAFK,DC=fljme,DC=ru"
    ECHO is on.
    
    c:\AD>(for /F "Delims=" %a in ('dsquery user -samid 2807') do (
    set var=2807
     echo 2807
     echo
    ) )
    
    c:\AD>(
    set var="CN=2807,OU=0104,OU=01,OU=CAFK,DC=fljme,DC=ru"
     echo "CN=2807,OU=0104,OU=01,OU=CAFK,DC=fljme,DC=ru"
     echo
    )
    "CN=2807,OU=0104,OU=01,OU=CAFK,DC=fljme,DC=ru"
    ECHO is on.
    
    c:\AD>(for /F "Delims=" %a in ('dsquery user -samid 2759') do (
    set var=2759
     echo 2759
     echo
    ) )
    
    c:\AD>(
    set var="CN=2759,OU=0102,OU=01,OU=CAFK,DC=fljme,DC=ru"
     echo "CN=2759,OU=0102,OU=01,OU=CAFK,DC=fljme,DC=ru"
     echo
    )
    "CN=2759,OU=0102,OU=01,OU=CAFK,DC=fljme,DC=ru"
    ECHO is on.
    
    c:\AD>echo +++++++++++++++++++++++++++++++++++++++++++++++++++++++
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++
    
    c:\AD>echo "CN=2759,OU=0102,OU=01,OU=CAFK,DC=fljme,DC=ru"
    "CN=2759,OU=0102,OU=01,OU=CAFK,DC=fljme,DC=ru"
    
    c:\AD>pause
    Press any key to continue . . .
    
    c:\AD>

    echo %var% - переменная получается пустая.

    18 декабря 2013 г. 13:38
  • у вас переменная вар в цикле не будет определена... только по выходу из него

    На выходе получается значение DN для последнего логина. Может быть как-то через Call попробовать вызвать в цикл нужный мне блок команд?
    18 декабря 2013 г. 13:53
  • не торопитесь. щас пришлю
    18 декабря 2013 г. 14:19
  • вот как то так посмотрите

    @echo off
    SETLOCAL EnableDelayedExpansion
    chcp 65001
    set FILE=list.txt
    
    for /F "tokens=1 delims=;" %%a in (%FILE%) do (    
    for /F "Delims=" %%A in ('dsquery user -samid %%a') do call :pparce %%A
    )
    
    exit /b
    :pparce
    set var=%~1
       set dnuser=%var%
       set dngroup1=%var:~7%
       set dngroup2=%var:~11,-29%
       set dngroup3=CN=G%dngroup2%
       set dngroup=%dngroup3%%dngroup1%
       
       @echo dnuser = %dnuser%
       @echo dngroup1= %dngroup1%
       @echo dngroup2= %dngroup2%
       @echo dngroup3= %dngroup3%
       @echo dngroup = %dngroup%
       @echo before FOR group= %dngroup%
       @echo before FOR user= %dnuser%
    
       set dnuser=
       set dngroup1=
       set dngroup2=
       set dngroup3=
       set dngroup=
       set var=
    )
    @echo +++++++++++++++++++
    pause
    :exit 
    
    взял на себя смелость немножно поиграться с кавычками... не нравится ваше решение. так что придется вам проверить правильно ли я обрезал ваши DN'ки

    18 декабря 2013 г. 14:36
  • Кавычки я убрал, без них работает также, как и с ними ))

    На данный момент с помощью call добился следующего.

    - в 1м FOR считываются логины из файла.

    - во 2м FOR ищутся DN юзеров в AD. Тут же вызывается блок команд, который определяют текущую группу безопасности пользователя. И вызывается 3 FOR, где происходит обновление информации.

    - 3 FOR считывает всю инфу по юзеру.

    Вот код:

    SETLOCAL EnableDelayedExpansion
    rem @echo off
    chcp 65001
    set USERLIST=userlist_upd.csv
    set AUDIT=C:\AD\History\
    set DOMEN=OU=CAFK,DC=fljme,DC=ru
    set VDATE=%date:~-10%
    set VTIME=%time:~0,-3%
    set VTIME=%VTIME::=.%
    
    for /F "tokens=1 delims=;" %%a in (%USERLIST%) do (    
    	for /F "Delims=" %%a in ('dsquery user -samid %%a') do (
    	                        set v=%%a
    	                        CALL :dnGroups
    								
    	)
    )
    goto :EOF
    
    :dnGroups		
    			set var=%1
    			set dnuser=%var:~1,-1%
    			set dngroup1=%var:~8,-1%
    			set dngroup2=%var:~12,-30%
    			set dngroup3=CN=G%dngroup2%
    			set dngroup="%dngroup3%%dngroup1%"
    
    			CALL :UserMode
    			exit /B 0
    
    					
    			@echo  group= %dngroup%
    			@echo  user= %dnuser%
    
    :UserMode
    
    for /F "tokens=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 delims=;" %%a in (%USERLIST%) do (
    		if "%dnuser%" EQU "CN=%%a,OU=%%m,OU=%%l,%DOMEN%" (
    			if "%%c"=="true" (
    			dsmod user "CN=%%a,OU=%%m,OU=%%l,%DOMEN%" -fn "%%i" -ln "%%j" -disabled no -display "%%i %%j" -company "%%f" -empid "%%b" -title "%%d" -tel "%%k" -Office "%%g" -dept "%%e"
    			) 	else 	if "%%c"=="false" (
    					dsmod user "CN=%%a,OU=%%m,OU=%%l,%DOMEN%" -disabled yes
    					)
    				 
    		)	else if "%dnuser%" NEQ "CN=%%a,OU=%%m,OU=%%l,%DOMEN%" (
    				dsmod group "%dngroup%" -rmmbr "%dnuser%"
    				dsquery user -samid "%%a" | dsmod group "CN=%%o,OU=%%m,OU=%%l,%DOMEN%" -addmbr "%dnuser%"
    				dsmove "%dnuser%" -newparent "OU=%%m,OU=%%l,%DOMEN%"
    				dsmod user "CN=%%a,OU=%%m,OU=%%l,%DOMEN%" -fn "%%i" -ln "%%j" -disabled no -display "%%i %%j" -company "%%f" -empid "%%b" -title "%%d" -tel "%%k" -Office "%%g" -dept "%%e"	
    			)	
    exit /B 0
    )
    exit /B 0
    ENDLOCAL

    Все работает корректно 1 раз для 1 учетки (1 запись в файле). Далее происходит следующее: определяется DN юзера и группа, вызывается блок :UserMode, где FOR начинает считывать файл снова с 1й записи, т.е. сравнивает уже 2го пользователя с 1м., затем 3го с опять с 1м.

    Пока пытаюсь понять, как заставить 3 FOR читать файл с нужного пользователя, т.е. сравнивать 2го юзера со 2й строкой, 3го с 3й и т.д.


    18 декабря 2013 г. 15:02
  • слушайте, ну зачем насиловать труп? возмите повершелл или на крайнний случай вбскрипт, а? :))))

    по вашему вопросу: в первом форе можно использовать 2 переменные -

    tokens=1,2*

    в итоге у вас будет необходимый samid в переменной %%a и вся остальная строчка для последующего разбора в %%b

    или просто разобрать строчку на составляющие прямо на первом этапе.

    18 декабря 2013 г. 15:18
  • слушайте, ну зачем насиловать труп? возмите повершелл или на крайнний случай вбскрипт, а? :))))

    по вашему вопросу: в первом форе можно использовать 2 переменные -

    tokens=1,2*

    в итоге у вас будет необходимый samid в переменной %%a и вся остальная строчка для последующего разбора в %%b

    или просто разобрать строчку на составляющие прямо на первом этапе.

    Есть определенные условия, из-за которых пришлось отказаться от powershell в пользу bat cmd. Поэтому приходится, как Вы сказали, "насиловать труп".

    Пытался я сделать 3 вложенных цикла, но пока все безрезультатно...

    19 декабря 2013 г. 9:47
  • что вам мешает засунуть

    'dsquery user -samid %%a

    и иже с ними внутрь

    вот этого фора:

    for /F "tokens=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 delims=;" %%a in (%USERLIST%) do (

    ?

    зачем вам 2 раза читать файл?

    2х for'ов достаточно

    • Помечено в качестве ответа Sergey Zakharov 20 декабря 2013 г. 8:54
    19 декабря 2013 г. 10:30
  • Svolotch, огромное спасибо за помощь. Вопрос закрываю. Решил написать нужный мне функционал на VB с использование LDAP.
    20 декабря 2013 г. 8:56