Microsoft Task Scheduler 中是否存在初期不稳定性?

Microsoft Task Scheduler 中是否存在初期不稳定性?

背景:Microsoft Azure;Windows Server 2012 R2。

我在 Scheduler 中有少量任务。在“设置”选项卡中,所有任务均标记为“如果任务已在运行,则适用以下规则:‘不启动新实例’”。

几天内这种情况都没问题。然后,调度程序似乎会在某项任务正在运行时启动每项任务的新实例。这些实例显示在任务管理器中已运行任务的旁边,但标记为“已暂停”。

这似乎是系统不稳定的普遍迹象。此行为出现后不久,SQL Server 就开始出现异常。

我正在编写一个维护脚本(这也必须使用调度程序,这真是太可惜了),它将计算生产应用程序的实例,如果内存中有多个应用程序(一个正在运行,一个已暂停),它将向开发团队发送一条短信。这是短期的解决方法。长期修复会更好。

有没有人遇到过类似的事情?如果遇到过,如何解决?

回应建议

我可以放

var currProcName = Process.GetCurrentProcess().ProcessName;
if (Process.GetProcessesByName(currProcName).Length > 1)
{
    Warn($"An instance of {currProcName} is already running. Only one instance of this application is allowed.");
    return;
}

或将其等效项添加到所有 EXE 中。但是,在当前设置中,这永远不会发出警告,因为 EXE 的第二个实例不会以此方式运行,而是在任务管理器中显示为“已暂停”。

允许调度程序启动一项作业(无论它是否已经在运行),并要求 EXE 本身确定它是否应该运行,这似乎有点低效,因为它要求每个 EXE 启动并可能每分钟死亡,而不是允许调度程序确定是否需要启动。

大约有 20 个任务被安排,有些每分钟一次,有些每 5 分钟一次,有些每 60 分钟一次。

对评论 #1 中问题的回复

问:您使用任务计划程序具体运行了什么,例如批处理脚本、exe 文件、PowerShell 脚本还是其他?

答:仅限 EXE,例如

<Actions Context="Author">
  <Exec>
    <Command>Handler.exe</Command>
    <WorkingDirectory>C:\Web\Project</WorkingDirectory>
  </Exec>
</Actions>

问:如何在调度程序选项中设置任务?

答:XML 文件的示例设置:

  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>true</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>PT1H</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>

XML 文件中的触发器示例

<Triggers>
  <CalendarTrigger>
    <Repetition>
      <Interval>PT1M</Interval>
      <Duration>P1D</Duration>
      <StopAtDurationEnd>false</StopAtDurationEnd>
    </Repetition>
    <StartBoundary>2016-03-09T14:20:00</StartBoundary>
    <ExecutionTimeLimit>PT30M</ExecutionTimeLimit>
    <Enabled>true</Enabled>
    <ScheduleByDay>
      <DaysInterval>1</DaysInterval>
    </ScheduleByDay>
  </CalendarTrigger>
</Triggers>

对评论 #2 中问题的回复

问:您是否禁用然后又启用了这些任务?

答:应用更新时,会定期禁用并重新启用这些任务。

问:任务是从 XML 文件导入的吗?

答:原始任务(在另一台服务器上)是使用 GUI 创建的。结果被导出为 XML,移动到当前服务器,进行编辑和导入。

问:如果重新创建任务,问题能解决吗?

答:不是。

问:任务是否以退出代码终止?

答:如果您的意思是“任务是否以 Environment.Exit(n) 终止?”,那么答案是肯定的。但是,由于任务被定义为 EXE,而不是更大 CMD 的一部分,因此不会检查该值。

问:当新任务预计开始时,计划任务是否可能恰好终止?

答:我该如何证实这一点呢?

问:同时运行的同一任务的两个实例可以解释您所看到的不稳定性吗?

答:我不确定我是否理解了这个问题。我们绝不允许两个实例同时运行。目前的情况是,Windows 在其自行选择的时间允许一个实例运行,并允许另一个实例运行但处于“挂起”模式。有趣的是,我们目前的经验是挂起的任务无法终止。只有正在运行的任务才能终止。

答案1

任务计划程序和空闲条件

似乎有两种配置方法任务计划程序关于的工作空闲条件

  1. 如果StopOnIdleEnd设置为真的,那么RestartOnIdle应该是真的如果期望的结果是终止并重新启动任务

    循环空闲状态

    如果计算机在空闲状态之间循环,您可以使用以下空闲条件终止并重新启动任务。

    要终止并重新启动任务,属性和元素都必须设置为 True


    示例配置

    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>true</RestartOnIdle>
    </IdleSettings>
    

    这两个都应该设置为真的


  1. 如果期望的结果是不要让任务在空闲状态下停止运行,那么你需要确保空闲时重启空闲结束时停止设置为错误的

    示例配置

    <IdleSettings>
      <StopOnIdleEnd>false</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    

这两个都应该设置为错误的

答案2

我对您的问题的看法是,它是由以下行引起的:

<StopOnIdleEnd>true</StopOnIdleEnd>

以下是我对您的情景的理论推测:

  • 进程在内核调用中处于等待状态,在此状态下无法停止。
  • 计算机进入空闲状态然后退出。
  • 任务计划程序尝试停止该进程,但只能将其暂停在僵尸状态(停止但无法终止)。
  • 该任务被标记为终止,任务计划程序已启动一个新任务。
  • 由于原始任务可能处于 SQL 事务的中间并且可能仍然持有锁,因此 SQL 数据库的行为受到损害。

解决方案应该是设置StopOnIdleEndfalse。没有理由因为计算机进入空闲状态而终止任务,无论时间多么短暂。事实上,粗暴地停止任何连接到 SQL 服务器的任务是一个非常糟糕的想法,因为它会让正在进行的事务未完成甚至无法回滚。

相关内容