Powershell - "Clear-Item variable:" vs " Remove-Variable"


При временном хранении текста в переменных powershell во время выполнения каков наиболее эффективный способ удаления содержимого переменных из памяти, когда оно больше не требуется?

Я использовал и Clear-Item variable:, и Remove-Variable, но как быстро что-то удаляется из памяти с последним против обнуления содержимого памяти с первым?

EDIT: мне следовало бы немного прояснить, почему я спрашиваю.

Я автоматизирую вход RDP для группы виртуальных машин приложений (приложение не делает запуск как сервис, аутсорсинг разработчиков, долгая история).

Итак, я разрабатываю (в основном законченный) сценарий для группирования сеансов запуска для каждой из виртуальных машин.

Идея состоит в том, что функция скрипта, хранящая учетные данные, использует read-host для запроса имени хоста, а затем get-credentials для выбора домена/пользователя/пароля.

Затем проход преобразуется из secure-string с помощью 256-битного ключа (ключа времени выполнения, уникального для машины / пользователя, который хранил creds и запускал запуск группы).

Имя виртуальной машины, домен, пользователь и зашифрованный пропуск хранятся в файле. При запуске сеанса данные считываются, пароль расшифровывается, данные передаются в cmdkey.exe для хранения учетных данных generic:TERMSRV для этой виртуальной машины, очистить переменную передачи открытого текста, запустить mstsc для этого узла, через несколько секунд удалить учетные данные из хранилища учетных данных windows. (Если я передал пароль в cmdkey.exe как что-либо другое, кроме открытого текста, сеанс RDP либо получит неверные учетные данные, либо их не будет).

Итак, отсюда вопрос, мне нужно пароль в открытом виде должен существовать в памяти как можно меньше времени.

Чтобы ребята из Службы безопасности были довольны, сам скрипт зашифрован aes256, а оболочка c# со своим собственным хостом ps читает, расшифровывает и запускает скрипт, поэтому на машине, которая его запускает, нет источника открытого текста. (Зашифрованный источник на файловом ресурсе так эффективно, что у меня есть переключатель kill, можно просто заменить зашифрованный скрипт на другой, отображающий сообщение о том, что это приложение было отключено)

5 6

5 ответов:

Вы можете использовать секундомер для получения времени выполнения командлетов. Я думаю, что на самом деле нет разницы во времени между этими двумя командлетами. Я использую обычно "Remove-Item", потому что в моих глазах лучше удалить переменную complete.

$a = "TestA"
$b = "TestB"
$c = "TestC"
$d = "TestD"

$time = New-Object system.Diagnostics.Stopwatch  

Start-Sleep 1
$time.Start() 
$time.Stop()
$system = $time.Elapsed.TotalMilliseconds
Write-Host "Stopwatch StartStop" $system
$time.Reset()

Start-Sleep 1
$time.Start() 
Clear-Item Variable:a
$time.Stop()
$aTime = $time.Elapsed.TotalMilliseconds - $system
Write-Host "Clear-Item in " $aTime
$time.Reset()

Start-Sleep 1
$time.Start() 
Remove-Variable b
$time.Stop()
$bTime  = $time.Elapsed.TotalMilliseconds - $system
Write-Host "Remove-Variable in " $bTime
$time.Reset()

Start-Sleep 1
$time.Start() 
Clear-Item Variable:c
$time.Stop()
$cTime = $time.Elapsed.TotalMilliseconds - $system
Write-Host "Clear-Item in " $cTime
$time.Reset()

Start-Sleep 1
$time.Start() 
Remove-Variable d
$time.Stop()
$dTime  = $time.Elapsed.TotalMilliseconds - $system
Write-Host "Remove-Variable in " $dTime
$time.Reset()

Самый эффективный способ-позволить сборке мусора делать свою работу. Помните, что Powershell - это все .NET, со своим знаменитым управлением памятью. Всегда контролируйте свою область и убедитесь, что переменные выходят из области, как только они не нужны. Например, если временные переменные необходимы внутри циклов, они автоматически аннулируются в конце цикла, поэтому не нужно беспокоиться об этом и т. д.

EDIT: Что касается вашего обновления, почему бы просто не сделать $yourPasswordVariable = $null? Я думаю, что это было бы намного проще сделать. понимать. И это должен быть самый быстрый способ сделать это. Поскольку Remove-Item и Clear-Item являются своего рода универсальными обработчиками, они должны сначала обработать некоторые вещи, прежде чем определить, что вы действительно хотите стереть переменную.

Единственный способ, которым я смог с уверенностью очистить переменные данные / содержимое, - это удалить все переменные, работающие в текущем сеансе, используя:

Remove-Variable -Name * -ErrorAction SilentlyContinue

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

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

Оба эффективно удаляют ссылку "a"на объект .NET. Теперь, если эта ссылка является последней ссылкой на объект, то GC определит, когда будет собрана память для указанного объекта. Однако если переменная больше не нужна, то используйте Remove-Variable, чтобы также разрешить сбор памяти, связанной с объектом System.Management.Automation.PSVariable.

Чтобы измерить время, необходимое для запуска блоков сценариев и командлетов, используйте Measure-Command