我需要有关批处理脚本处理方面的帮助,因为需要再次使用板载工具,无法安装任何额外工具。
我有一个 CMD.exe 脚本,它收集有关正在运行的进程的信息(通过 tasklist.exe),并将它们像 tee 一样传输到一个文件中,每行前面都有一个时间戳。该文件稍后用于为所有消耗内存或 CPU 时间超过某个阈值的进程生成一些精美的图表。
但问题是,我必须在负载测试运行之前从我的环境中启动此脚本,并在测试完成后停止它。启动和停止不在一个进程中,并且可能运行很长时间(从几分钟到几个小时)。
我已经尝试使用该TITLE
命令来识别正在运行的脚本,然后将其终止,TASKKILL /F /FI "WINDOWTITLE EQ PSMON"
但这样做不起作用,如果脚本没有手动启动,则窗口标题似乎没有设置。
对于感兴趣的人,下面是脚本:
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
TITLE=PSMON
:START
SET FILE=%TEMP%\psmon.csv
ECHO TIMESTAMP^;IMAGENAME^;PID^;MEMKB^;CPUTIME>%FILE%
:LOOP
TITLE=PSMON
SET TS=%TIME%
SET SEK=%TS:~7,1%
IF %SEK% == 0 (
FOR /F "tokens=1-12 delims=,:" %%A IN ('TASKLIST /V /NH /FO CSV') DO (
SET IMAGE=%%A
SET PID=%%B
SET MEM=%%E
SET CPUH=%%H
SET CPUM=%%I
SET CPUS=%%J
SET /A CPU=!CPUH!*3600 + !CPUM!*60 + !CPUS!
IF !CPU! GTR 100 (
ECHO %DATE:~-4%%DATE:~-7,2%%DATE:~-10,2%%TS:~0,2%%TS:~3,2%%TS:~6,2%^;!IMAGE:~1,-1!^;!PID:~1,-1!^;!MEM:~1,-3!^;!CPU!>>%FILE%
)
)
)
GOTO LOOP
要明确的是,问题是,如果这个实例不是直接在命令行上启动的也不是通过双击启动的(尝试使用启动命令通过第二个 batch.cmd 文件启动它),我该如何使用 Windows 板载工具识别这个实例并终止该进程。
我想要一些类似在脚本启动时获取 PID 并将其写入临时文件或类似在 unix 系统上完成的操作,但我怀疑是否存在这样的事情。
编辑:得到了如下一堆代码行的提示:
for /f "usebackq tokens=2" %%a in (`tasklist /FO list /FI "SESSIONNAME eq %SESSIONNAME%" /FI "USERNAME eq %USERNAME%" /FI "WINDOWTITLE eq %instance%" ^| find /i "PID:"`) do set PID=%%a
if not defined PID for /f "usebackq tokens=2" %%a in (`tasklist /FO list /FI "SESSIONNAME eq %SESSIONNAME%" /FI "USERNAME eq %USERNAME%" /FI "WINDOWTITLE eq Administrator: %instance%" ^| find /i "PID:"`) do set PID=%%a
if not defined PID echo !Error: Could not determine the Process ID of the current script. Exiting.& exit /b 1
遗憾的是它们不起作用,脚本总是在定义的错误消息下停止。也许我应该提一下,我正在使用 Win7?
答案1
好的,感谢大卫·波斯蒂尔以及此链接当前 cmd.exe 的 PID 是什么,确实存在一种使用板载工具获取 PID 的有效方法。
SET T=%TEMP%\sthUnique.tmp
wmic process where (Name="WMIC.exe" AND CommandLine LIKE "%%%TIME%%%") get ParentProcessId /value | find "ParentProcessId" >%T%
SET /P PID=<%T%
ECHO %PID:~16%>%TEMP%\my.pid
这样我稍后就可以终止该任务了。