Windows bat finds which process the file is occupied by and terminates the process

1. Background

I have a batch script as follows:

@echo off
chcp 936 & cls
cd /D F:\Chen\python3\ExciseC
set fdate=%date:~0,4%%date:~5,2%%date:~8,2%
python main.py >> crawl_record_%fdate%.log 2>&1
for /F %%f in ('dir crawl_record_*.log /B ^| find /V "%fdate%"') do move %%f archived\logs

Among them, for /Fthe statement is to move the log files other than the current day archived\logs, and then this batch is run regularly in the task plan.
After running for a period of time, I occasionally found that there were still log files outside the current day that had not been moved archived\logs. Later, I found that the file was python.exeoccupied by the program. It is speculated that python main.py >> crawl_record_%fdate%.log 2>&1this statement may end abnormally during the execution process (such as restart, disconnection, etc.) network, etc.), causing the file after the redirection character to be locked, and then the file could not be moved normally on the second day.

Then my demand appeared: find the process that occupies this file, then kill it, release the occupied file, and then move the file. (These steps are all done in batch processing, not graphical interface operations)

Two, solve the problem

1. Find the process pid occupying the specified file

The command program is used here handle.exe, handle.exewhich is Sysinternals Suitethe process utility in .
It can be used to display information about open handles for any process in the system. You can use this to see which program has a file open, or to see the object types and names of all handles to a program.
Help document: https://learn.microsoft.com/en-us/sysinternals/downloads/handle
Download address: https://download.sysinternals.com/files/Handle.zip
Download and unzip the handle.exe/ handle64.exeapplication, then put It is placed under a certain path in the path environment variable.

handle /v name /nobanner

/vMake the output result in csv format with comma delimiter, namethe name of the file opened by the process to search (accept fragment), /nobannerdo not display startup banner and copyright information. See handle /?help for more information.

The output structure is as follows:

C:\Users\cyinl>handle /v /nobanner crawl_record_20230722.log
Process,PID,Type,Handle,Name
python.exe,23156,File,0x000001E0,F:\test\crawl_record_20230722.log

Note:
tasklistYou can also check the process pid, but it can only be searched according to the exe/dll module name, the command format is:
tasklist /M 模块名, the file like the example in the example crawl_record_20230722.logcannot find the relevant process.

2. Terminate the process

handle.exeThe process can be terminated, the format is:

handle /nobanner /p PID /c <句柄号>

However, the handle number is not easy to get, as follows:

C:\Users\cyinl>handle /nobanner /p 23156
   40: File          D:\Chen\MySoft\Python\Python3.7.7
  1D0: File          C:\Windows\System32\zh-CN\KernelBase.dll.mui
  1E0: File          F:\test\crawl_record_20230722.log
  208: File          C:\Windows\System32\zh-CN\kernel32.dll.mui

The 40 in the first line should be the handle number of the process file to be closed, but can you ensure that the handle number in the first line is to be closed? ? ? Somewhat confused.

taskkillThe command can also terminate the process, the format is:

taskkill /f /pid <进程号>

/fIndicates that the process is forcibly terminated, /pidspecifying the pid process number of the process to be terminated.
The output results are as follows:

C:\Users\cyinl>taskkill /f /pid 23156
成功: 已终止 PID 为 23156 的进程。

3. Implement the code

There are handletwo taskkillcommands to improve batch processing to solve the problem. The specific implementation is as follows:

@echo off
chcp 936 & cls
cd /D F:\Chen\python3\ExciseC
set fdate=%date:~0,4%%date:~5,2%%date:~8,2%
python main.py >> crawl_record_%fdate%.log 2>&1
for /F %%f in ('dir crawl_record_*.log /B ^| find /V "%fdate%"') do move %%f archived\logs

REM After the above command is executed, if the files are successfully moved, they will not enter the loop of this command
for /F %%f in ('dir crawl_record_*.log /B ^| find /V "%fdate%"') do (
	echo the file to move is locked: %%f
	for /F "skip=1 tokens=2 delims=," %%p in ('handle /v %%f /nobanner') do taskkill /F /PID %%p
	REM If the move command is executed immediately after the process is deleted, it will fail. Therefore, a 5-second delay is given here
	timeout /T 5 /nobreak > nul
	move %%f archived\logs
)

explain:

  1. If the first one for /Fcan move files normally, it will not enter the second one for /F;
  2. The second one for /Fis used to find the occupied log file, and the third one is nested to for /Fget the process pid, which skipmeans to skip the first row, delims=,means to ,separate the data by columns, and tokens=2means to take the second column. Then douse the command in the structure taskkillto terminate the process corresponding to the found pid.
  3. The test found that after the process is terminated, the file cannot be moved immediately, otherwise it may fail, so the timeoutcommand is used to delay for 5 seconds before moving the file.

3. Expansion

Find and kill processes manually

1. Use the system's own资源监视器

1) Search in the taskbar 资源监视器, switch to CPUthe tab, and enter the occupied file name in the 关联的句柄- input box; 2) In the search results, select the process that needs to be terminated, right click, and select搜索句柄
终止进程
kill process manually

2. Use Process Explorertools

You can also use Process Explorer , which is handlea GUI-based version of Windows, Process Explorerto view information about which handles and DLLs a process has open or loaded.
Download address: https://download.sysinternals.com/files/ProcessExplorer.zip
After decompression, open procexp.exe/ procexp64.exeuse it directly.
1) Click 搜索the icon and enter the name of the file to be searched;
2) In the search results, click the search result, and the relevant process and file handle will be automatically located;
3) Right-click the corresponding process- kill Processor right-click the corresponding file handle-close Handle

Terminate a process or close a handle

Guess you like

Origin blog.csdn.net/B11050729/article/details/131874113