杀死休眠 SAP 进程的脚本
Script to kill dormant SAP Processes
我们有一个客户端系统,用户通过服务器连接到 SAP 9.2。
当用户 运行 在 Web 上使用 SAP 9.2 时,SAP 会在服务器上启动一个 exe 进程,就像 运行 SAP 客户端应用程序一样。一旦用户在 SAP 上完成工作,通常用户不会 select 文件并退出,而是会假设 SAP 已关闭而关闭选项卡。
服务器上的 SAP exe 进程没有关闭,昨天我注意到服务器内存已满(100% 使用率),而只有一个用户登录。在任务管理器上,我们有超过 100 个 SAP exe 进程运行宁。我不得不手动关闭所有服务,然后 SAP 9.2 on web 顺利启动 运行ning。
今天我回到了 11 个左右的 SAP 进程,根据所附的屏幕截图,自昨天晚上以来只有四个用户登录,而我截屏时没有人登录。
我的问题是,如何使用 TASKKILL 或任何其他方法来终止属于 SAP Business One 的所有休眠进程而不影响登录用户?
用户使用 Windows Server 2012 标准版。
您没有使用任何特定标记(例如 batch-file or powershell)标记您的问题,那么我假设您需要一个批处理文件。 无论您使用何种语言,算法 都是相同的,但显然语法有很大不同(PowerShell 脚本更简单和简短)。
从命令行(然后最终使用计划任务或用户登录时的自动启动操作)您可以使用 TASKKILL
:
TASKKILL /FI "IMAGENAME eq imagename.exe" /FI "USERNAME ne %USERNAME%" /T /F
几点注意事项:
- 将
imagename.exe
替换为 SAP Business One 流程的图像名称(使用 TASKLIST
检查),或者您可以使用 WINDOWTITLE
过滤器。
- 如果用户在域下登录,您可能需要将
%USERNAME%
替换为 %USERDOMAIN%\%USERNAME%
。
/F
switch 强行关闭指定进程,只有在 gentle 终止不起作用时才这样做。
/T
关闭进程及其所有子进程(我看到其中一些进程有子进程)。
- 查看
TASKKILL
帮助以获取更多过滤器,请注意,这将终止所有不属于当前登录的正在执行此命令的用户的进程。它有一个明显的含义:登录用户必须具有所需的权限,并且您在任何时候都只有一个登录用户。
最后一点的影响在某种程度上是巨大的,如果您需要规避它,事情会变得更加复杂。鉴于您可以使用 TASKLIST /V
获取详细的过程信息,并且可以使用以下方法以方便的格式格式化输出(假设此示例过程图像名称为 sapbo.exe
):
TASKLIST /V /FO:CSV /FI "IMAGENAME eq sapbo.exe"
可以使用如下方式解析:
FOR /F "delims=, tokens=1-7" %1 IN ('TASKLIST /V /FO:CSV "IMAGENAME eq sapbo.exe"') DO (
echo %1 %7
)
您需要确定用户是否已登录。如果它是一个交互式会话,您可以只检查 Windows Shell 进程(如果您想做好事情,请从注册表中读取它...)我知道的最简单的方法是使用 this post:
TASKLIST /FI "IMAGENAME eq myapp.exe" 2>NUL | FIND /I /N "myapp.exe">NUL
IF "%ERRORLEVEL%"=="0" ECHO Programm is running
因为如果没有登录用户则需要终止进程然后将此放在 DO
部分之后(这是一行,为了清楚起见我在这里拆分):
TASKLIST /FI "IMAGENAME eq winlogon.exe" /FI "USERNAME eq %7" 2>NUL
| FIND /I /N "winlogon.exe" > NUL
|| TASKKILL /T /F /PID %2
不要忘记根据您的具体情况调整此代码...
正如我对 PowerShell 所说的那样,它要容易得多。首先你想让所有的进程有资格被杀死:
Get-Process sapbo -IncludeUserName
遍历它们并检查是否存在交互式会话:
foreach ($eligibleProcess in Get-Process sapbo -IncludeUserName)
{
if (-not Get-Process winlogon -ErrorAction SilentlyContinue -IncludeUserName | where { $_.UserName -eq $eligibleProcess.UserName })
{
$eligibleProcess.Kill();
}
}
请注意,我在这里写的代码并没有经过测试,请注意...
我们有一个客户端系统,用户通过服务器连接到 SAP 9.2。
当用户 运行 在 Web 上使用 SAP 9.2 时,SAP 会在服务器上启动一个 exe 进程,就像 运行 SAP 客户端应用程序一样。一旦用户在 SAP 上完成工作,通常用户不会 select 文件并退出,而是会假设 SAP 已关闭而关闭选项卡。
服务器上的 SAP exe 进程没有关闭,昨天我注意到服务器内存已满(100% 使用率),而只有一个用户登录。在任务管理器上,我们有超过 100 个 SAP exe 进程运行宁。我不得不手动关闭所有服务,然后 SAP 9.2 on web 顺利启动 运行ning。
今天我回到了 11 个左右的 SAP 进程,根据所附的屏幕截图,自昨天晚上以来只有四个用户登录,而我截屏时没有人登录。
我的问题是,如何使用 TASKKILL 或任何其他方法来终止属于 SAP Business One 的所有休眠进程而不影响登录用户?
用户使用 Windows Server 2012 标准版。
您没有使用任何特定标记(例如 batch-file or powershell)标记您的问题,那么我假设您需要一个批处理文件。 无论您使用何种语言,算法 都是相同的,但显然语法有很大不同(PowerShell 脚本更简单和简短)。
从命令行(然后最终使用计划任务或用户登录时的自动启动操作)您可以使用 TASKKILL
:
TASKKILL /FI "IMAGENAME eq imagename.exe" /FI "USERNAME ne %USERNAME%" /T /F
几点注意事项:
- 将
imagename.exe
替换为 SAP Business One 流程的图像名称(使用TASKLIST
检查),或者您可以使用WINDOWTITLE
过滤器。 - 如果用户在域下登录,您可能需要将
%USERNAME%
替换为%USERDOMAIN%\%USERNAME%
。 /F
switch 强行关闭指定进程,只有在 gentle 终止不起作用时才这样做。/T
关闭进程及其所有子进程(我看到其中一些进程有子进程)。- 查看
TASKKILL
帮助以获取更多过滤器,请注意,这将终止所有不属于当前登录的正在执行此命令的用户的进程。它有一个明显的含义:登录用户必须具有所需的权限,并且您在任何时候都只有一个登录用户。
最后一点的影响在某种程度上是巨大的,如果您需要规避它,事情会变得更加复杂。鉴于您可以使用 TASKLIST /V
获取详细的过程信息,并且可以使用以下方法以方便的格式格式化输出(假设此示例过程图像名称为 sapbo.exe
):
TASKLIST /V /FO:CSV /FI "IMAGENAME eq sapbo.exe"
可以使用如下方式解析:
FOR /F "delims=, tokens=1-7" %1 IN ('TASKLIST /V /FO:CSV "IMAGENAME eq sapbo.exe"') DO (
echo %1 %7
)
您需要确定用户是否已登录。如果它是一个交互式会话,您可以只检查 Windows Shell 进程(如果您想做好事情,请从注册表中读取它...)我知道的最简单的方法是使用 this post:
TASKLIST /FI "IMAGENAME eq myapp.exe" 2>NUL | FIND /I /N "myapp.exe">NUL
IF "%ERRORLEVEL%"=="0" ECHO Programm is running
因为如果没有登录用户则需要终止进程然后将此放在 DO
部分之后(这是一行,为了清楚起见我在这里拆分):
TASKLIST /FI "IMAGENAME eq winlogon.exe" /FI "USERNAME eq %7" 2>NUL
| FIND /I /N "winlogon.exe" > NUL
|| TASKKILL /T /F /PID %2
不要忘记根据您的具体情况调整此代码...
正如我对 PowerShell 所说的那样,它要容易得多。首先你想让所有的进程有资格被杀死:
Get-Process sapbo -IncludeUserName
遍历它们并检查是否存在交互式会话:
foreach ($eligibleProcess in Get-Process sapbo -IncludeUserName)
{
if (-not Get-Process winlogon -ErrorAction SilentlyContinue -IncludeUserName | where { $_.UserName -eq $eligibleProcess.UserName })
{
$eligibleProcess.Kill();
}
}
请注意,我在这里写的代码并没有经过测试,请注意...