Как программно закрыть все файловые дескрипторы в данной папке?

18

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

Я пробовал ProcessExplorer , Unlocker и подобные инструменты, но они предлагают интерфейс с графическим интерфейсом и не полезны в среде программирования

Решение на Python, cmd или PowerShell было бы идеальным.

Амелио Васкес-Рейна
источник
Помните, что принудительное закрытие дескриптора файла может привести к сбою программы, использующей этот дескриптор.
Гарри Джонстон
1
@HarryJohnston Хуже того, вы можете в конечном итоге вызывать все виды повреждения файлов, пока программа открыта: technet.microsoft.com/en-us/magazine/…
Боб

Ответы:

7

Unlocker утверждает, что дает вам эту способность:

  1. Просто щелкните правой кнопкой мыши папку или файл и выберите Unlocker

    Шаг 1

  2. Если папка или файл заблокированы, появится окно со списком шкафчиков

    Шаг 2

  3. Просто нажмите Unlock Allи все готово!

Я не уверен, поддерживает ли он использование командной строки.

FileASSASSIN MalwareByte в выполняет аналогичные действия, и делает поддержку использования командной строки, так что вы должны быть в состоянии сценария это довольно легко.

FileAssassin's Switches

Ƭᴇcʜιᴇ007
источник
Спасибо techie007, я думаю, что пропустил это. Я заметил, что Unlocker иногда пропускает мои файлы (ProcessExplorer этого не делает). Вторая проблема - если я хочу разблокировать или выпускать файлы программно (например, инструмент командной строки поможет в этом направлении).
Амелио Васкес-Рейна
@intrpc Пойдем, я добавил еще одно (для командной строки) предложение. :)
Ƭᴇcʜιᴇ007
1
Осторожно, в настоящее время Unlocker поставляется с вредоносным ПО.
Джошуа Хенли
10

Спасибо за это. У нас были некоторые проблемы с дескрипторами открытых файлов, которые приводили к сбою проверок git в наших заданиях Jenkins на базе Windows, и это помогло легко устранить проблему. Я выкину основы техники:

  1. Установите Handle.exe на узле сборки. Я загрузил его отсюда http://technet.microsoft.com/en-us/sysinternals/bb896655 , разархивировал и удалил файл Handle.exe в C: \ Windows \ System32, чтобы убедиться, что он будет доступен по умолчанию% PATH%

  2. Установите плагин Jenkins pre-scm-buildstep: https://wiki.jenkins-ci.org/display/JENKINS/pre-scm-buildstep . Это позволяет нам определять операции до того, как плагин git начал достигать потенциально заблокированных файлов.

  3. В качестве шага сборки перед scm реализована следующая пакетная команда:

    @echo off
    echo Cleaning up open file handles from %NODE_NAME%:%WORKSPACE%...
    for /f "tokens=3,6,8 delims=: " %%i in ('Handle /accepteula %WORKSPACE% ^| grep workspace') do echo Releasing file lock on E:%%k & handle -c %%j -y -p %%i
    

Похоже, что работает хорошо и определенно сокращает ложные сбои. Также отмечу пару ошибок, с которыми я работал:

  • Handler.exe имеет лицензионное соглашение, которое должно быть принято при первом запуске. Если вы используете свой агент Jenkins в качестве службы в контексте локальной системы, это проблематично, поскольку вы не можете войти в систему под этим пользователем и принять его вручную. Когда мы попытались запустить его из задания Jenkins, процесс просто завис в ожидании ввода данных пользователем, и потребовалось несколько минут, чтобы выяснить, почему. Я решил это, запустив его из задания Jenkins с использованием флага / accepteula, и я рекомендую всем, кто реализует это как автоматизированный процесс, сделать то же самое. Это происходит с параметром реестра в HKEY_CURRENT_USER \ Software \ Sysinternals \ Handle, и вы также можете установить и сбросить его с помощью regedit.exe, если вам нужно манипулировать им для конкретного пользователя, но опция командной строки казалась самой простой.

  • Плагин Jenkins Batch step выполняет пакетный код, как если бы он был в скрипте, а не в качестве директивы командной строки. Обратите внимание на экранирование (например, %% i, ^ |).

Благодарность!

Томас Бойлс
источник
Пытаясь получить синтаксис этого, кто-нибудь может предоставить более подробную информацию о том, что %% i, j и т. Д.?
c4sh
Это может помочь понять синтаксис пакетной команды: robvanderwoude.com/ntfortokens.php
c4sh
Как вы, ребята, решили, что handle.exe должен запускаться от имени администратора, а мы запускаем его от пользователя Jenkins, который не является администратором?
c4sh
8

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

rem close all network files that are locked
for /f "skip=4 tokens=1" %%a in ('net files') do net files %%a /close
Brendan
источник
Спасибо @ Брендан. Я думаю, что ваш код не был правильно отформатирован. Ваш ответ выглядит интересным, поэтому, если вы не против его редактирования, я бы посоветовал вам выбрать строки кода, а затем нажать кнопку с двумя фигурными браслетами. Это превратит ваш фрагмент в читаемый код.
Амелио Васкес-Рейна
5

Я создаю этот маленький командный файл для автоматического снятия всех блокировок в XML-файл по моему затмению

@echo off
for /f "tokens=3,6,8 delims=: " %%i in ('handle -p eclipse e:\git\ ^| grep .xml') do echo Releasing %%k & handle -c %%j -y -p %%i

Вам необходимо скачать утилиту handle с сайта Microsoft и утилиту grep из GnuWin32

Если вам не нужен фильтр по типу файла, вы можете пропустить часть grep следующим образом:

@echo off
for /f "tokens=3,6,8 delims=: " %%i in ('handle -p eclipse e:\git\') do echo Releasing %%k & handle -c %%j -y -p %%i

Или, если вам не нужно фильтровать блокировки определенной программой, просто удалите фильтр процесса eclipse:

@echo off
for /f "tokens=3,6,8 delims=: " %%i in ('handle e:\git\') do echo Releasing %%k & handle -c %%j -y -p %%i

Не забудьте заменить e:\git\путь к папке.

coolersport
источник
4

Если вы используете PSTools , это приведет к рекурсивному закрытию всех открытых файлов:

psfile \\serverName c:\path\toDatabase\ -c

Обратите внимание, что c:\path\toDatabase\диск C: включен \\serverName, а не локальный компьютер. Сначала это было неясно для меня, поэтому я решил указать на это.

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

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

Парень, который обычно обрабатывает это, находится в отпуске в течение нескольких недель, и его инструкции используют подход, основанный на интерфейсе пользователя (Пуск> Компьютер> Управление> Управление компьютером (локальный)> Подключиться к другому компьютеру> Системные инструменты> Общие папки> Открытые файлы> Открыть Открытые файлы). Слишком много щелчков мышью, когда я могу просто выполнить указанную выше команду и выкинуть всю компанию из всех файлов базы данных и запустить процесс Compact & Repair (к которому я также работаю над подходом, основанным на скрипте методом грубой силы).

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

delliottg
источник
4

Если вы говорите о дескрипторах файлов, открытых через общий ресурс SMB на файловом сервере Windows (Server 2012 или новее), вот ответ PowerShell:

Get-SmbOpenFile | Where-Object { $_.Path -like "D:\Folder\*" } | Close-SmbOpenFile -Force

На старом файловом сервере Windows это так openfiles.exe /disconnect.

Для дескриптора локального системного файла лучший способ, который я нашел, это использовать Sysinternals handle.exe.

Джошуа Хэнли
источник
3

Я предпочитаю http://lockhunter.com, потому что он поддерживает как графический интерфейс, так и интерфейс командной строки, и во многих случаях смог удалить файлы, которые не удалось удалить с помощью Unlocker.

Владимир Решетников
источник
2

Unlocker может работать и в беззвучном режиме.

Например, чтобы разблокировать все файлы в рабочем пространстве Jenkins:

"C:\Program Files\Unlocker\unlocker.exe" "%WORKSPACE%" /S

Затем вы можете безопасно удалить файлы рабочей области:

del "%WORKSPACE%\*.*" /s /q
Ноам Манос
источник
0

Вы можете использовать Powershell для этого:

function KillProcessesWithHandles
{
    param([string]$path)

    $allProcesses = Get-Process

    # Start by closing all notepad processes. Someone may have left a logor config file open
    $allProcesses | Where-Object {$_.Name -eq "notepad"} | Stop-Process -Force -ErrorAction SilentlyContinue

    # Then close all processes running inside the folder we are trying to delete
    $allProcesses | Where-Object {$_.Path -like ($path + "*")} | Stop-Process -Force -ErrorAction SilentlyContinue

    # Finally close all processes with modules loaded from folder we are trying to delete
    foreach($lockedFile in Get-ChildItem -Path $path -Include * -Recurse) {
        foreach ($process in $allProcesses) {
            $process.Modules | Where-Object {$_.FileName -eq $lockedFile} | Stop-Process -Force -ErrorAction SilentlyContinue
        }
    }
}

Для получения более подробной информации, обратитесь к Томасу Ардалу здесь: https://thomasardal.com/deleting-contents-of-a-folder-conisting-files-with-open-file-handles-using-powershell/

Аби
источник