Почему другой сценарий powershell запускается дважды?

#powershell

#powershell

Вопрос:

У меня есть скрипт, который проверяет, есть ли на диске определенное количество свободного места. Если нет, появится всплывающее окно с запросом «да» или «нет». Если да, то для сигнала тревоги устанавливается значение 1, а затем запускается другой сценарий, который удаляет файлы из папки. Моя проблема в том, что, похоже, он удаляет в два раза больше числа, указанного в скрипте. Основной сценарий:

 $limit_low = 0.1 # låg gräns 10%
$DiskD = Get-PSDrive D | Select-Object Used,Free | Write-Output
$DiskD_use = [math]::Round(($DiskD.Free / ($DiskD.Used   $DiskD.Free)),2)
 
if( $DiskD_use -le $limit_low ) {
    Write-Host "RDS-server har för lite utrymme på disk D $diskD_use < $limit_low" -ForegroundColor Red -BackgroundColor Yellow    
    
    $ButtonType = 4
    $Timeout = 60
    $Confirmation = New-Object -ComObject wscript.shell
    $ConfirmationAnswer = $Confirmation.popup("Clear disk space?",$Timeout,"No space",$ButtonType)

    If( $ConfirmationAnswer -eq 6 ) { 
        Write-Host "Kör script Diskspace.ps1 under P:backupscripts"
        amp; c:dynamicsappJDSend.exe "/UDP /LOG:c:dynamicsappFixskick.log /TAG:Lunsc2:K_PROCESS_LARM_DISKUTRYMME "1""
        amp; P:BackupScriptsDelete_archives_test.ps1 # here i call the other script       
    } else { 
         Write-Host "Gör ingenting"
         amp; c:dynamicsappJDSend.exe "/UDP /LOG:c:dynamicsappFixskick.log /TAG:Lunsc2:K_PROCESS_LARM_DISKUTRYMME "0""
    } 
}
 

Другой сценарий:

 # List all txt-files in directory, sort them och select the first 10, then delete
Get-ChildItem -Path c:temp -File Archive*.txt | Sort-Object | Select-Object -First 10 | Remove-Item -Force
 

Приветствия

Редактировать

Поэтому было бы достаточно заключить первый оператор следующим образом:

 (Get-ChildItem -Path c:temp -File Archive*.txt) | Sort-Object | Select-Object -First 10 | Remove-Item -Force
 

?? Забавно, что я попытался воспроизвести это сегодня дома без какого-либо эффекта. Отсюда работает так, как задумано, даже без скобок.
Кроме того, я совершенно не осведомлен о том, как использовать foreach statement, поскольку он не передает ублюдка 🙂

 foreach ($file in $filepath) {$file} | Sort-Object | Select-Object -First 10 | Remove-Item -Force
 

Попытался поместить сортировку и выбрать часть в {} тоже, но ничего хорошего из этого не вышло. Поскольку я застрял в трубе и не понимаю foreach логики.

Комментарии:

1. Загрузите procmon из Sysinternals (Microsoft), запустите его от имени администратора и выполните свой сценарий. Остановите procmon от сбора информации (может получить очень много за очень короткое время!) и фильтруйте файлы / ваш скрипт / папку или что-то еще, чтобы убедиться, что ваш скрипт вызывается только один раз и что только 10 файлов удалены (или нет).

2. итак, ваш 2-й сценарий удаляет 20 файлов вместо 10? я не знаю, почему он это делает… но бывают случаи, когда использование G-CI для подачи конвейера может привести к повторному прочтению списка. я бы заключил G-CI вызов в начале вашего конвейера в скобки, чтобы заставить его читать все элементы сразу .

3. Итак, проблема здесь только в Delete_archives_test.ps1 ? Что произойдет, если вы запустите второй сценарий сам по себе? Перед его запуском попробуйте изменить его на использование Remove-Item -Force -Verbose вместо. Это покажет вам, какие именно файлы были удалены. Или вы можете использовать -WhatIf , если на самом деле ничего не хотите удалять.

4. @zett42 — подумайте о том, что делает конвейер … он берет ЧТО-то ОДНО, выполняет с ним какие-то действия, а затем передает это на следующий этап. в случае Get-ChildItem это означает, что он может повторно прочитать тот же файл, когда что-то изменяет файл. заключая вызов в скобки, вы заставляете G-CI захватывать все файлы сразу… а ЗАТЕМ передайте их в конвейер. возможно, вы видите свое «делает это дважды», потому что вы меняете список файлов в процессе использования списка файлов.

5. @Theo — готово! дайте мне знать, если он нуждается в доработке. [ усмешка ]

Ответ №1:

похоже, ваша проблема вызвана тем, как работает ваш конвейер. [усмешка]

подумайте о том, что он делает…

  • прочитайте ОДИН элемент fileinfo
  • отправьте его в конвейер
  • изменение / добавление файла
  • продолжайте конвейер

этот 3-й шаг приведет к изменению списка файлов… и может привести к повторному чтению файла ИЛИ к каким-либо другим изменениям в списке файлов для работы.

на ум приходят два решения…

  • оберните Get-ChildItem вызов в скобки
    , которые заставят одно чтение списка перед отправкой чего-либо в конвейер… и это будет игнорировать любые изменения, вызванные более поздними этапами конвейера.
  • используйте foreach цикл
    , который будет считывать весь список, а затем выполнять итерацию по списку по одному элементу за раз.

преимущество 2-го решения также заключается в том, что его легче отлаживать, поскольку значение вашего current item значения изменяется только при явном изменении. current pipeline item изменения на каждом этапе конвейера… и это легко забыть. [усмешка]