在我被击倒之前,我知道如何安排任务、使用 powershell 重新启动服务或授予非管理员帐户重新启动服务的权限。这不是问题。然而,问题在于这三个任务的组合。
我有一个 Windows 服务需要处理网络文件夹中的文件。因此,它使用“服务帐户”登录,该帐户实际上只是一个普通域帐户。此域帐户不是管理员,但具有该文件夹的访问权限。该服务运行良好并完成其工作。
但是,有时某个文件出错,导致其他文件无法处理。通常需要一段时间才会有人注意到,并且会造成一些积压。
于是我在 powershell 中创建了一个监控脚本,轮询网络文件夹中是否存在这些错误文件。如果发现这些文件,则将这些文件移动到临时文件夹进行检查,并且需要重新启动服务。
我通过组策略授予服务帐户权限来启动和停止该服务。
当我使用服务帐户登录服务器时,我能够使用服务 MMC 手动重新启动服务。我还可以执行 powershell 脚本,它完全按照预期执行:轮询文件夹、移动文件并重新启动服务。太棒了!
在下一阶段,我创建了一个每 10 分钟运行一次的计划任务。该任务使用与服务相同的服务帐户来执行 powershell 脚本。选中“以最高权限执行”框。就像我说的,powershell 脚本需要访问网络驱动器,所以我无法以本地服务器管理员身份运行它,而且我不想使用域管理员凭据来执行这种琐碎的任务。(我尽可能地尝试实现最小权限原则。)
我使用本地安全策略 MMC 授予服务帐户在本地服务器上的“作为批处理作业登录”权限。
现在说说我无法理解的部分:在预定的时间,预定的任务成功完成,并且正在执行 powershell 脚本。脚本轮询文件夹,错误文件被移动。唯一不起作用的是重新启动服务……?!再次,以同一用户身份手动运行脚本,效果很好。
我在事件查看器中看不到太多内容,但是我的脚本上的日志记录指出了此错误:
TerminatingError(Stop-Service):“无法在计算机‘.’上打开服务控制管理器。此操作可能需要其他权限。”
我用来重新启动服务的命令是:
Stop-Service -Verbose -DisplayName $($service[1])
...
Start-Service -Verbose -DisplayName $($service[1])
(我在 2008 R2 域上使用 Windows Server 2012 R2 和 Powershell 版本 4。)
更新: 我尝试使用 subinacl 为用户设置服务权限(如上所述这里)并手动设置 SDDL 字符串(如所述这里),所以我的控制标志如下所示 (A;;CCLCSWRPWPDTLOCRRC;;;S-1-X-XX-XXXXXXXXXX-XXXXXXXX-XXXXXXXXX-XXXX)。我还尝试在 GPO 中将服务的权限设置为完全控制。这些都无法解决问题。这肯定是权限问题某处我仍然忽略了这一点,因为当我使用服务器上的本地管理员域帐户安排任务时,它运行良好。
答案1
这回答另一个问题也解决了我的问题。
我采取的步骤如下:
enable-psremoting
在服务器上的管理员 powershell 提示符下Set-PSSessionConfiguration -Name Microsoft.PowerShell -ShowSecurityDescriptorUI
在服务器上的管理员 powershell 提示符下- 添加了具有完全权限的服务帐户(或安全组)
sc sdshow scmanager
在服务器上的管理命令提示符中- 复制 SDDL 输出
(A;;KA;;;SID_OF_USER_OR_SECURITY_GROUP)
在 SDDL 的 S: 部分之前添加sc sdset scmanager THE_MODIFIED_SDDL
我的看起来像这样:sc sdset scmanager D:(A;;CC;;;AU)(A;;CCLCRPRC;;;IU)(A;;CCLCRPRC;;;SU)(A;;CCLCRPWPRC;;;SY)(A;;KA;;;BA)(A;;CC;;;AC)(A;;KA;;;S-1-X-XX-XXXXXXXXXX-XXXXXXXX-XXXXXXXXX-XXXX)S:(AU;FA;KA;;;WD)(AU;OIIOFA;GA;;;WD)
- 更改我的 powershell 脚本,以便它使用
Start-Service
CmdLet 而不是Set-Service
(Set-Service 不起作用)。
看起来简单的事情变得比它本来的要复杂得多......