用于杀死休眠SAP进程的脚本

时间:2016-09-14 09:19:01

标签: powershell batch-file windows-server-2012

我们有一个客户端系统,用户通过服务器连接到SAP 9.2。

当用户在Web上运行SAP 9.2时,SAP会在服务器上启动exe进程,就像运行SAP客户端应用程序时一样。用户完成SAP工作后,通常用户不会选择文件并退出,但只要关闭SAP就会关闭标签。

在服务器上SAP exe进程没有关闭,昨天我注意到服务器内存已满(100%利用率),而只有一个用户登录。在任务管理器上,我们运行了100多个SAP exe进程。我不得不手动关闭所有服务,之后Web上的SAP 9.2开始顺利运行。

今天回到11个左右的SAP流程,根据所附截图,自昨天晚上以来只有四个用户登录,当我拍摄截图时没有人登录。

enter image description here

我的问题是,如何使用TASKKILL或任何其他方法来终止属于SAP Business One的所有休眠进程而不影响登录用户?

用户使用的是Windows Server 2012标准版。

1 个答案:

答案 0 :(得分:2)

您没有使用任何特定代码(例如)标记您的问题,然后我假设您需要批处理文件。无论您使用何种语言,算法都是相同的,但显然语法非常不同(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强制关闭指定的进程,只有在温和终止无法正常工作时才执行此操作。
  • /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();
    }
}

请注意我在这里编写代码然后没有经过测试,请小心......