【问题标题】:How to create 2 scheduled tasks that run with a difference of one hour but never overlap?如何创建 2 个运行时间相差一小时但从不重叠的计划任务?
【发布时间】:2019-01-31 09:32:36
【问题描述】:

我需要使用 powershell 创建两个计划任务,每个任务将运行一个 powershell 脚本。

一个应该在每天 08:00 触发,每两小时运行一次。所以在 10:00 ,12:00, 14:00 等.. 另一个每天 9 点,每两个小时运行一次。所以在 11:00 ,13:00, 15:00 等..

如果用户未登录,任务仍应在他登录后立即触发。 假设他在 9:35 登录,这将触发这两个任务。它们怎么能不同时运行?

我尝试向其中一个添加延迟,但延迟有可能为 0

解决方案可以是:

  1. 当它们同时运行时,它们会检查是否是这种情况以及其中一个出口。或者,
  2. 其他一些确保它们不拦截的方法
   $taskAction1 = New-ScheduledTaskAction -Execute 'Powershell.exe' -argument "-NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -File $script1"
   $taskAction2 = New-ScheduledTaskAction -Execute 'Powershell.exe' -argument "-NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -File $script2"

   $taskSettings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -Hidden -DontStopIfGoingOnBatteries

   $taskTrigger = New-ScheduledTaskTrigger -AtLogOn
   $taskTriggerWithDelay = New-ScheduledTaskTrigger -AtLogOn -RandomDelay 00:15:00

   Register-ScheduledTask -User System -Action $taskAction1 -Trigger $TasKTrigger -TaskName "Task1" -RunLevel Highest -Settings $TaskSettings -f | Out-Null
   Register-ScheduledTask -User System -Action $taskAction2 -Trigger $taskTriggerWithDelay -TaskName "Task2" -RunLevel Highest -Settings $TaskSettings -f | Out-Null

   $trigger= Get-ScheduledTask -TaskName Task1
   $trigger.Triggers.repetition.Interval = "PT2H"
   $trigger.Triggers.repetition.duration = ""
   $trigger | Set-ScheduledTask | Out-Null

   $trigger= Get-ScheduledTask -TaskName Task2
   $trigger.Triggers.repetition.Interval = "PT2H"
   $trigger.Triggers.repetition.duration = ""
   $trigger | Set-ScheduledTask | Out-Null

【问题讨论】:

  • 听起来像是功课。 ;-) 到目前为止你尝试了什么?请显示您的代码。你可以看看the tour 或者How do I ask a good question?
  • 我添加了我的代码。好吧,这不是家庭作业,而是更大项目的一部分。

标签: powershell scheduled-tasks


【解决方案1】:

问题是关于mutual exclusion,一个经过充分研究的问题。

一个简单的解决方案是基于共享资源。当任务启动时,它会尝试获取资源的排他锁。如果这是不可能的,任务会等待并再次尝试,直到超时或锁定被授予。当锁持有任务完成它的工作时,它会释放锁作为清理的一部分。

简单的解决方案不能保证公平调度,如果需要公平,请查找更多实现。

至于评论:不要依赖 pid。在 Windows 中,进程 ID 可以重复使用。

为了快速演示,让我们使用这样的标志文件,

function getlock() {
    $file = $null
    while($file -eq $null) {
        try { $file = [System.IO.File]::Open("c:\temp\flag.txt", "open", "read", "none") } catch {
            write-host "waiting..."
            start-sleep -seconds 2
        }
    }

    write-host "got lock!"
    start-sleep -seconds 5
    $file.close()
}

通过将函数加载到两个 Powershell 会话中并在几秒钟内调用它们来尝试一下。如果您在任务切换时遇到问题,请增加 5 秒的睡眠时间。每个函数都会尝试获得一个标志文件的排他锁。如果这是不可能的,则会抛出异常。游戏中迟到的进程将休眠两秒钟,然后重试,直到第一个释放锁。有关文件共享模式的更多详细信息,请参阅File.Open()

标志文件有问题,所以要获得更强大的 IPC,请查看earlier an answer。它适用于 C#,但也可以针对 Powershell 进行调整。

【讨论】:

  • 这个锁可以和定时任务的pid关联吗?这意味着如果计划任务结束/失败,或者在此过程中电脑关闭,文件是否会被解锁?您能否指定执行此操作的 powershell cmdlet?
猜你喜欢
  • 2018-08-13
  • 1970-01-01
  • 1970-01-01
  • 2015-03-26
  • 2018-02-03
  • 2023-03-08
  • 1970-01-01
  • 2023-03-24
  • 2018-12-01
相关资源
最近更新 更多