Comment fermer tous les descripteurs de fichiers sous un dossier donné par programme?


18

Je me demandais s'il existe un outil en ligne de commande qui me permet de fermer tous les descripteurs de fichiers ouverts dans un dossier spécifique.

J'ai essayé ProcessExplorer , Unlocker et des outils similaires, mais ils offrent une interface graphique et ne sont pas utiles dans un environnement de programmation

Une solution sur Python, cmd ou PowerShell serait idéale.


N'oubliez pas que la fermeture forcée d'un descripteur de fichier peut entraîner le blocage du programme utilisant ce descripteur.
Harry Johnston

1
@HarryJohnston Pire, vous pourriez finir par provoquer toutes sortes de corruption de fichiers tant que le programme est ouvert: technet.microsoft.com/en-us/magazine/…
Bob

Réponses:


7

Unlocker prétend qu'il vous donne cette capacité:

  1. Cliquez simplement avec le bouton droit sur le dossier ou le fichier et sélectionnez Unlocker

    Étape 1

  2. Si le dossier ou le fichier est verrouillé, une liste de casiers apparaîtra dans la fenêtre

    Étape 2

  3. Cliquez simplement Unlock Allet vous avez terminé!

Je ne sais pas s'il prend en charge l'utilisation de la ligne de commande.

FileAssassin de MalwareByte effectue des actions similaires et prend en charge l'utilisation de la ligne de commande, vous devriez donc être en mesure de l'écrire assez facilement.

FileAssassin's Switches


Merci techie007, je suppose que j'ai raté ça. J'ai remarqué que Unlocker manque parfois mes fichiers (ProcessExplorer ne le fait pas). Un deuxième problème est si je veux déverrouiller ou libérer des fichiers par programme (par exemple, un outil en ligne de commande aiderait dans cette direction).
Amelio Vazquez-Reina

@intrpc Voilà, j'ai ajouté une autre suggestion (adaptée à la ligne de commande). :)
Ƭᴇcʜιᴇ007

1
Attention, Unlocker est livré avec des logiciels malveillants de nos jours.
Joshua Hanley

10

Merci pour cela. Nous avons rencontré des problèmes avec les descripteurs de fichiers ouverts, ce qui a entraîné l'échec de l'extraction de git dans nos travaux Jenkins basés sur Windows, ce qui a aidé à corriger le problème facilement. Je vais jeter les bases de la technique:

  1. Installez Handle.exe sur le nœud de génération. Je l'ai téléchargé ici http://technet.microsoft.com/en-us/sysinternals/bb896655 , je l'ai décompressé et j'ai déposé Handle.exe sous C: \ Windows \ System32 pour m'assurer qu'il serait disponible sur le% PATH% par défaut

  2. Installez le plugin Jenkins pre-scm-buildstep: https://wiki.jenkins-ci.org/display/JENKINS/pre-scm-buildstep . Cela nous permet de définir les opérations avant que le plugin git ne commence à atteindre les fichiers potentiellement verrouillés.

  3. Implémentation de la commande batch suivante en tant qu'étape de génération pré-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
    

Il semble bien fonctionner et réduit définitivement les échecs parasites. Je noterai également quelques problèmes que j'ai rencontrés:

  • Handler.exe possède un CLUF qui doit être accepté lors de sa première exécution. Si vous exécutez votre agent Jenkins en tant que service dans le contexte du système local, cela pose problème car vous ne pouvez pas vous connecter en tant qu'utilisateur et l'accepter à la main. Lorsque nous avons essayé de l'exécuter à partir du travail Jenkins, le processus a simplement suspendu l'attente de l'entrée de l'utilisateur et il a fallu quelques minutes pour comprendre pourquoi. J'ai résolu ce problème en l'exécutant à partir du travail Jenkins en utilisant le drapeau / accepteula et je recommande à quiconque l'implémentant en tant que processus automatisé de faire de même. Il s'agit d'un paramètre de registre sous HKEY_CURRENT_USER \ Software \ Sysinternals \ Handle et vous pouvez également le définir et le désactiver via regedit.exe si vous devez le manipuler pour un utilisateur spécifique, mais l'option de ligne de commande semble la plus simple.

  • Le plugin de l'étape Jenkins Batch exécute le code batch comme s'il était dans un script plutôt que comme une directive de ligne de commande. Remarquez les échappements (par exemple %% i, ^ |).

Merci!


Luttant pour obtenir la syntaxe de cela, quelqu'un peut-il fournir plus de détails sur ce qui est %% i, j etc.?
c4sh

Cela pourrait aider à comprendre la syntaxe de la commande batch: robvanderwoude.com/ntfortokens.php
c4sh

Comment avez-vous résolu le fait que handle.exe doit s'exécuter en tant qu'administrateur, alors que nous l'exécutons à partir d'un utilisateur Jenkins qui n'est pas administrateur?
c4sh

8

Nous utilisons l'extrait de code suivant pour fermer le descripteur de fichier des utilisateurs vers notre serveur. Vous pourrez peut-être le modifier pour votre usage.

rem close all network files that are locked
for /f "skip=4 tokens=1" %%a in ('net files') do net files %%a /close

Merci @Brendan. Je pense que votre code n'a pas été formaté correctement. Votre réponse semble intéressante, donc si cela ne vous dérange pas de la modifier, je vous suggère de sélectionner vos lignes de code, puis de cliquer sur le bouton avec les deux bracelets bouclés. Cela transformera votre extrait de code en code lisible.
Amelio Vazquez-Reina

5

Je crée ce petit fichier batch pour libérer automatiquement tous les verrous du fichier xml par mon éclipse

@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

Vous devez télécharger l' utilitaire handle depuis le site Microsoft et l' utilitaire grep depuis GnuWin32

Si vous n'avez pas besoin de filtrer par type de fichier, vous pouvez ignorer la partie grep comme ceci:

@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

Ou si vous n'avez pas besoin de filtrer les verrous par un programme particulier, supprimez simplement le filtre de processus éclipse:

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

Rappelez - vous de remplacer e:\git\votre chemin de dossier.


4

Si vous utilisez PSTools , cela forcera la fermeture récursive de tous les fichiers ouverts:

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

Notez que c:\path\toDatabase\c'est le lecteur C: allumé \\serverName, pas votre machine locale. Ce n'était pas clair pour moi au début, alors j'ai pensé le signaler.

Il s'agit d'une approche par force brute qui est presque garantie de perdre des données, alors utilisez-la avec prudence.

Nous avons une base de données Access mal pavée qui met littéralement notre entreprise à genoux sur une base régulière (j'ai dû la réparer trois fois hier).

Le gars qui s'occupe normalement de cela est en vacances pendant quelques semaines et ses instructions utilisent une approche basée sur l'interface utilisateur (Démarrer> Ordinateur> Gérer> Gestion de l'ordinateur (local)> Se connecter à un autre ordinateur> Outils système> Dossiers partagés> Ouvrir des fichiers> Fermer Ouvrir des fichiers). Beaucoup trop de clics quand je peux simplement exécuter la commande ci-dessus et expulser toute l'entreprise de tous les fichiers de base de données et démarrer le processus de compactage et de réparation (que je travaille également sur une approche scriptée par force brute).

L'astuce est de devancer les gens qui commencent immédiatement à se reconnecter à la base de données dès qu'elle tombe en panne. Ils sont tellement habitués à cela qu'il ne leur vient pas à l'esprit de déposer un bogue contre eux, ils continuent de marteler la base de données jusqu'à ce qu'ils reviennent. Je continue de les démarrer jusqu'à ce que j'aie compacté et réparé les trois douzaines les fichiers qui composent la base de données.


4

Si vous parlez de descripteurs de fichiers ouverts via un partage SMB sur un serveur de fichiers Windows (Server 2012 ou plus récent), voici la réponse PowerShell:

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

Sur un ancien serveur de fichiers Windows, c'est openfiles.exe /disconnect.

Pour un descripteur de fichier système local, la meilleure façon que j'ai trouvée est d'utiliser Sysinternals handle.exe


3

Je préfère http://lockhunter.com car il prend en charge l'interface graphique et l'interface de ligne de commande, et dans de nombreux cas, a pu supprimer des fichiers qui ne pouvaient pas être supprimés par Unlocker.


2

Unlocker peut également fonctionner en mode silencieux.

Par exemple, pour déverrouiller tous les fichiers dans l'espace de travail Jenkins:

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

Ensuite, vous pouvez supprimer en toute sécurité les fichiers de l'espace de travail:

del "%WORKSPACE%\*.*" /s /q

0

Vous pouvez utiliser Powershell pour faire ces choses:

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
        }
    }
}

Pour plus de détails, reportez-vous à Thomas Ardal ici: https://thomasardal.com/deleting-contents-of-a-folder-containing-files-with-open-file-handles-using-powershell/

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.