使用query session和 logoff的批处理脚本无法从远程服务器登出用户
我正在尝试在多台Windows服务器上自动化应用更新。在更新运行之前,我需要从几台服务器登出所有用户(Active、Disconnected、Hung等),但不包括在当前机器上运行脚本的用户。
服务器是:
NRD01-A
NRD01-B
NRD02-A
NRD02-B
PowerShell在这些服务器上受限/被阻止,因此我必须使用批处理脚本。
思路是:
- 使用
query session来识别服务器上的所有会话 - 使用
logoff或reset session注销每一个会话 - 在执行脚本的这台机器上跳过当前脚本运行者的会话
然而,当我运行脚本时,服务器上没有注销任何用户。
下面是我写的批处理脚本:
for /f %%H in ('hostname') do set "CURRENT_SERVER=%%H"
set "CURRENT_USER=%USERNAME%"
setlocal EnableDelayedExpansion
set "SERVERS=NRD01-A NRD01-B NRD02-A NRD02-B"
set "RUNSERVER=%COMPUTERNAME%"
set "CURRENT_USER=%USERNAME%"
for /F "tokens=3" %%S in ('query session ^| findstr /R /C:" %CURRENT_USER% "') do set "MYSESSION=%%S"
for %%S in (%SERVERS%) do (
for /f "skip=1 tokens=1,2,3,4" %%A in ('query session /server:%%S 2^>nul') do (
set "USER=%%B"
set "COL3=%%C"
set "COL4=%%D"
set "ID="
if "!COL3!"=="Disc" set "ID=!COL4!"
if not "!COL3!"=="Disc" set "ID=!COL3!"
if not "!ID!"=="" (
if /I "!USER!"=="!CURRENT_USER!" if /I "%%S"=="!RUNSERVER!" if "!ID!"=="!MYSESSION!" (
REM Protect script runner
) else (
logoff !ID! /server:%%S >nul 2>&1
reset session !ID! /server:%%S >nul 2>&1
)
)
)
)
for %%S in (%SERVERS%) do (
for /f "skip=1 tokens=2" %%A in ('query session /server:%%S 2^>nul ^| findstr /V "services console rdp-tcp"') do (
set "USER=%%A"
if not "!USER!"=="" (
set "SKIP=0"
if /I "!USER!"=="!CURRENT_USER!" (
if /I "%%S"=="!RUNSERVER!" set "SKIP=1"
)
if "!SKIP!"=="0" (
logoff %%A /server:%%S >nul 2>&1
rwinsta %%A /server:%%S >nul 2>&1
)
)
)
)
Expected behavior:
All sessions on all listed servers should be logged off
The session of the user running the script on the current machine should be skipped
Actual behavior:
The script runs but no users are logged out from the servers
Questions:
Why is this script not logging out users from the remote servers?
Is there an issue with how the session IDs are parsed from query session?
Is there a more reliable way to log off all sessions from multiple servers using only batch (no PowerShell)?
Any suggestions or improvements would be appreciated.
解决方案
我没有访问到一个能够让query session 返回值的系统。Google给了我一个典型返回值的简短示例:
SESSIONNAME USERNAME ID STATE TYPE DEVICE
>console Admin 0 active wdcon
rdp-tcp#1 User1 1 active wdtshare
rdp-tcp 2 listen wdtshare
因此我会研究一些可能性:
在你的脚本中,你使用
set "USER=%%B"
set "COL3=%%C"
set "COL4=%%D"
set "ID="
if "!COL3!"=="Disc" set "ID=!COL4!"
if not "!COL3!"=="Disc" set "ID=!COL3!"
我会非常仔细地看这个。我建议 col3 实际上是 ID,col4 是 STATE,其中可能缺少 USER。 (在这里对你的查询结果进行一个模糊化的部分清单编辑可能有帮助)
我也会查看 Using Boolean 这可能有助于简化代码,例如用 if defined ID 代替 if not "!ID!"=="",并将 skip 设为 nothing 或 something 可能更简单。
我遵循这样一个系统:仅在一个块内的 var 发生变化时才使用 !var!;否则使用 %var%。这起到直观提示的作用:“我预计这会变化” 与 “这应该是静态”。例如,你在一个块内设置了 ID COL3 COL4,因此访问这些值时应该是 !var!,但 CURRENT_USER 在该块内并不变化,因此应当按 %CURRENT_USER% 访问。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。