В файле CSV у меня есть список машин, если неактивен в AD, удалите его из файла - PullRequest
0 голосов
/ 21 января 2019

У меня есть CSV-файл, который содержит 2 поля: 1. ComputerName 2. ErrorCode. Он создается из приложения безопасности.

Мне нужно сравнить список ComputerName с AD. Если он активен, мне нужно экспортировать его в другой файл CSV.

Звучит достаточно просто, но я не могу понять, как также записать сообщение об ошибке в тот же файл. Если бы я мог прочитать AD и просто удалить несуществующие строки, это тоже было бы здорово, но у меня уже есть большая часть того, что мне нужно.

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

Изменить для уточнения

В database-1.csv:

Computername,Error
4140lw7,Systems Partion too small

Когда я запускаю скрипт, вывод выглядит следующим образом и не удаляет неактивные машины;

4140lw7,System Partition too small

Сценарий, который я использую, будет отделять то, что активно в AD, от того, чего нет, но только в том случае, если столбец ошибок не существует, т.е. database-1.csv без столбца ошибок:

ComputerName
2sd8cfngw98
23987hgivuw

Это создаст следующее:

exist.csv (активен в AD):

2sd8cfngw98

nonexist.csv (неактивен в AD):

23987hgivuw

Но это не будет работать, если код ошибки находится в файле. Мне нужен код ошибки в файле, который связан с именем машины.

foreach ($computer in (Get-Content C:\apps\database-1.csv)) {
    try {
        $test = Get-ADComputer -Identity $computer -ErrorAction Stop
        if ($test) {
            Write-Output "$computer" | Out-File C:\apps\exist.csv -Append
        }
    } catch {
        Write-Output "$computer" | Out-File C:\apps\Nonexist.csv -Append
    }
}

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Прежде всего, вы хотите прочитать входной файл как CSV (Import-Csv), а не как простой текстовый файл (Get-Content), потому что последний выдаст вам всю строку (включая сообщение об ошибке) тогда как первый даст вам доступ к обоим полям отдельно.

Простое решение будет примерно таким:

foreach ($computer in (Import-Csv 'C:\input.csv')) {
    if (Get-ADComputer -Filter "Name -eq '$($_.ComputerName)'") {
        $_ | Export-Csv 'C:\exist.csv' -NoType -Append
    } else {
        $_ | Export-Csv 'C:\nonexist.csv' -NoType -Append
    }
}

Однако, в зависимости от количества компьютеров в вашей AD и количества записей во входном CSV, это не очень хорошо масштабируется, потому что запросы AD стоят дорого. Используйте этот подход только в том случае, если у вас в CSV очень мало записей по сравнению с общим числом компьютеров в AD.

Как правило, лучшим подходом является создание хеш-таблицы из ваших компьютеров AD:

$computers = @{}
Get-ADComputer -Filter * | ForEach-Object { $computers[$_.Name] = $true }

позволяет вам найти недорогие имена компьютеров.

foreach ($computer in (Import-Csv 'C:\input.csv')) {
    if ($computers.ContainsKey($_.ComputerName)) {
        $_ | Export-Csv 'C:\exist.csv' -NoType -Append
    } else {
        $_ | Export-Csv 'C:\nonexist.csv' -NoType -Append
    }
}

Запрос всех компьютеров из AD занимает сравнительно много времени по сравнению с запросом только одного компьютера, но время выполнения для этого является более или менее постоянным, тогда как для отдельных запросов время выполнения пропорционально количеству запросов. Как это:

  ^
t |
  |                ,´
  |              ,´ individual queries
  |            ,´
  |          ,´
  |        ,´
  |------,´---------- 
  |    ,´           query all
  |  ,´
  |,´
  +-------------------->
                      n

На приведенной выше грубой диаграмме t - время выполнения скрипта и n количество записей во входном CSV.

0 голосов
/ 22 января 2019

Задумывались ли вы о сравнении выходных файлов:

Compare-Object -DifferenceObject (Get-Content file1.txt ) -ReferenceObject (Get-Content file2.txt ) -PassThru |
    Out-File file3.txt 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...