Powershell — переменная Clear-Item: vs Remove-Variable

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

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

РЕДАКТИРОВАТЬ: я должен был сделать это немного яснее, почему я спрашиваю.

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

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

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

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

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

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

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


person Graham Gold    schedule 08.12.2012    source источник


Ответы (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()
person LaPhi    schedule 09.12.2012
comment
Я поиграю с этим, когда вернусь в офис, см. РЕДАКТИРОВАТЬ мой вопрос, чтобы понять, почему скорость имеет значение :-) - person Graham Gold; 09.12.2012
comment
В вашем особом случае я рекомендую перезаписать переменную. Вы можете запустить gc с помощью [System.GC]::Collect(), но это не очень хорошая идея. Поэтому я думаю, что перезаписать переменную - лучшее решение :-) - person LaPhi; 09.12.2012

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

Remove-Variable -Name * -ErrorAction SilentlyContinue

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

НЕДОСТАТОК: если вам нужно очистить только одну переменную, что было в моем случае несколько минут назад, вам нужно повторно создать экземпляр входных переменных, требуемых вашим сценарием.

person itmadez    schedule 02.03.2016

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

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

person Neolisk    schedule 09.12.2012
comment
Я поиграю с областью видимости, когда вернусь в офис, см. РЕДАКТИРОВАТЬ мой вопрос, чтобы понять, почему скорость имеет значение :-) - person Graham Gold; 09.12.2012
comment
Круто, понятно, когда вы объясняете, как работают Clear-Item и Remove-Variable! - person Graham Gold; 09.12.2012

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

person Keith Hill    schedule 09.12.2012
comment
Я думаю, что в этом суть, можете ли вы заставить GC запускаться немедленно для одной или нескольких переменных и быть уверенным, что они больше не находятся в памяти? См. РЕДАКТИРОВАТЬ для получения информации о том, почему это важно :-) - person Graham Gold; 09.12.2012

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

person syanzy    schedule 11.04.2014
comment
Вы полностью упустили суть - речь идет не о том, как быстро запускается командлет, а о том, как быстро очищается память после выполнения команды - это не то, что может измерить команда измерения. - person Graham Gold; 11.04.2014