使用异步功能的任务调度程序中的PowerShell脚本

发布于 2025-02-09 07:17:00 字数 4055 浏览 1 评论 0原文

我有一个相当大的PowerShell脚本,我将其分为两个单独的脚本。第一个脚本以调用异步函数然后退出结束。

该功能检查了上一个脚本中生成的电子邮件导出的状态,该函数每60秒钟都会致电Google,以查看是否准备就绪导出。出口准备就绪后,它会更新几个SQL DB,而我的第二个脚本知道要接管。

当我在Shell/Console中运行“第一个脚本”时,这有100%的时间。但是我开始注意到,当我的计划任务在任务调度程序中触发时...什么都没有发生。我有广泛的记录,所以我知道这些参数已发送到异步函数,但是它似乎只是大便而不是继续循环循环,每60秒进行检查。

我觉得我在这里谷歌搜索方面做了尽职调查,但是...我在任务调度程序作业中是否缺少某些东西,以确保包含段循环的功能可以正确运行?

编辑下面的编辑

更好地解释我在做什么,我将在下面的主要脚本中包括我功能中的剥离代码以及对功能的调用。

首先,在“ script_01”末尾对函数的调用。

# Let's send the Google Vault export information over to our function.
        Try {
            $VaultParameters = @{
                employee_name = "$employee_name"
                export_name = "$export_name"
                sql_id = "$sql_id"
                vault_status_id = "$vault_status_id"
            }
            VaultExport @VaultParameters

            $LoggingParameters = @{
                logfile = "C:\script_logs\log.log"
                log = "INFO: Sent the Google Vault export information over to our async function."
            }
            EventLogging @LoggingParameters
        } Catch {
            $LoggingParameters = @{
                logfile = "C:\script_logs\log.log"
                log = "ERROR: Could not send the Google Vault export information over to our async function.`n$_"
            }
            EventLogging @LoggingParameters
        }

现在功能本身。它很大...

function VaultExport {
    param (
        [cmdletbinding()]
        [parameter()]
        [string]$employee_name,
        [parameter()]
        [string]$export_name,
        [parameter()]
        [string]$sql_id,
        [parameter()]
        [string]$vault_status_id
    )

    $scriptBlock = {
        param ($employee_name,$export_name,$sql_id,$vault_status_id)
        Import-Module SimplySQL
        $logfile = "C:\script_logs\log.log"
        $now = (Get-Date).tostring("MM-dd-yyyy hh:mm:ss")

        # Let's define our MySQL database credentials for later use.
        # DEFINING SQL CREDS HERE

        # Let's generate secure credentials for our MySQL 'terms' db.
        # GENERATING SECURE CREDS HERE

        # And now we'll connect to our SQL db...
        # CONNECTING TO SQL HERE

        $vault_ready = "no"
        Add-Content $logfile "$now INFO: Beginning the WHILE loop while $export_name completes..."
        while ($vault_ready -eq "no") {
            $vault_status = gam info export "Email Exports" "$export_name"
            $vault_status = $vault_status -Match "COMPLETED"
            $vault_status = $vault_status -split(": ")
            $vault_status = $vault_status[1]
            if ($vault_status -eq "COMPLETED") {
                $vault_ready = "yes"
                $completed = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
                Invoke-SqlUpdate -Query "UPDATE ``table`` SET ``vault_status`` = '$vault_status', ``vault_completed`` = '$completed' WHERE ``id`` = '$vault_status_id'"
                Invoke-SqlUpdate -Query "UPDATE ``table`` SET ``vault_status`` = '1' WHERE ``id`` = '$sql_id'"
                $now = (Get-Date).tostring("MM-dd-yyyy hh:mm:ss")
                Add-Content $logfile "$now INFO: $export_name is ready to download. Updated vault_status in our dbs."
            } else {
                $vault_status = gam info export "Email Exports" "$export_name"
                $vault_status = $vault_status -Match "IN_PROGRESS"
                $vault_status = $vault_status -split(": ")
                $vault_status = $vault_status[1]
                Invoke-SqlUpdate -Query "UPDATE ``table`` SET ``vault_status`` = '$vault_status' WHERE ``id`` = '$vault_status_id'"
                $now = (Get-Date).tostring("MM-dd-yyyy hh:mm:ss")
                Add-Content $logfile "$now INFO: $export_name is not yet ready: ($vault_status). Checking again in sixty seconds."
                Start-Sleep 60
            }
        }
    }
    Start-Job -ScriptBlock $scriptBlock -ArgumentList @($employee_name,$export_name,$sql_id,$vault_status_id)
}
exit

I have a fairly large PowerShell script that I've broken into two separate scripts. The first script ends with a call to an async function and then exits.

The function checks on the status of an e-mail export that was generated in the previous script, performing a WHILE loop where it makes a call to Google every sixty seconds to see if the export is ready. Once the export is ready it updates a couple of SQL dbs and my second script knows to take over.

This works 100% of the time when I run the "first script" in the shell/console. But I've started noticing that when my scheduled task is triggered in Task Scheduler that... nothing happens. I have extensive logging, so I know that the parameters ARE being sent over to the async function, but it seems to just poop out rather than continue to loop through the WHILE and do the every-sixty-second checks.

I feel like I've done my due diligence in Googling here, but... is there something I'm missing with a Task Scheduler job to ensure that a function containing a WHILE loop will properly run?

EDIT BELOW

To better explain what I'm doing I will include stripped code from my function and the call to the function from the main script below.

First, the call to the function at the very end of "script_01."

# Let's send the Google Vault export information over to our function.
        Try {
            $VaultParameters = @{
                employee_name = "$employee_name"
                export_name = "$export_name"
                sql_id = "$sql_id"
                vault_status_id = "$vault_status_id"
            }
            VaultExport @VaultParameters

            $LoggingParameters = @{
                logfile = "C:\script_logs\log.log"
                log = "INFO: Sent the Google Vault export information over to our async function."
            }
            EventLogging @LoggingParameters
        } Catch {
            $LoggingParameters = @{
                logfile = "C:\script_logs\log.log"
                log = "ERROR: Could not send the Google Vault export information over to our async function.`n$_"
            }
            EventLogging @LoggingParameters
        }

And now the function itself. It is large...

function VaultExport {
    param (
        [cmdletbinding()]
        [parameter()]
        [string]$employee_name,
        [parameter()]
        [string]$export_name,
        [parameter()]
        [string]$sql_id,
        [parameter()]
        [string]$vault_status_id
    )

    $scriptBlock = {
        param ($employee_name,$export_name,$sql_id,$vault_status_id)
        Import-Module SimplySQL
        $logfile = "C:\script_logs\log.log"
        $now = (Get-Date).tostring("MM-dd-yyyy hh:mm:ss")

        # Let's define our MySQL database credentials for later use.
        # DEFINING SQL CREDS HERE

        # Let's generate secure credentials for our MySQL 'terms' db.
        # GENERATING SECURE CREDS HERE

        # And now we'll connect to our SQL db...
        # CONNECTING TO SQL HERE

        $vault_ready = "no"
        Add-Content $logfile "$now INFO: Beginning the WHILE loop while $export_name completes..."
        while ($vault_ready -eq "no") {
            $vault_status = gam info export "Email Exports" "$export_name"
            $vault_status = $vault_status -Match "COMPLETED"
            $vault_status = $vault_status -split(": ")
            $vault_status = $vault_status[1]
            if ($vault_status -eq "COMPLETED") {
                $vault_ready = "yes"
                $completed = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
                Invoke-SqlUpdate -Query "UPDATE ``table`` SET ``vault_status`` = '$vault_status', ``vault_completed`` = '$completed' WHERE ``id`` = '$vault_status_id'"
                Invoke-SqlUpdate -Query "UPDATE ``table`` SET ``vault_status`` = '1' WHERE ``id`` = '$sql_id'"
                $now = (Get-Date).tostring("MM-dd-yyyy hh:mm:ss")
                Add-Content $logfile "$now INFO: $export_name is ready to download. Updated vault_status in our dbs."
            } else {
                $vault_status = gam info export "Email Exports" "$export_name"
                $vault_status = $vault_status -Match "IN_PROGRESS"
                $vault_status = $vault_status -split(": ")
                $vault_status = $vault_status[1]
                Invoke-SqlUpdate -Query "UPDATE ``table`` SET ``vault_status`` = '$vault_status' WHERE ``id`` = '$vault_status_id'"
                $now = (Get-Date).tostring("MM-dd-yyyy hh:mm:ss")
                Add-Content $logfile "$now INFO: $export_name is not yet ready: ($vault_status). Checking again in sixty seconds."
                Start-Sleep 60
            }
        }
    }
    Start-Job -ScriptBlock $scriptBlock -ArgumentList @($employee_name,$export_name,$sql_id,$vault_status_id)
}
exit

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我最亲爱的 2025-02-16 07:17:00

我不确定为什么您不仅要执行任务每30秒执行一次,而不是无限期地运行过程并使用其自己的计时器,即

您要为While语句设置的条件,这就是为什么循环不得没有继续。
将条件更改为永远无法满足的事物,问题应该消失,即

$Value1 = 0
WHILE($Value1 -ne 1){
#do things, never updating the $value1 variable
}

I'm unsure why you wouldn't just have the task execute every 30 seconds instead of having a process run indefinitely and using it's own timers

The condition you are setting for the WHILE statement is being met, this is why the loop doesn't continue.
Change the condition to something that will never be met and the problem should go away, i.e.

$Value1 = 0
WHILE($Value1 -ne 1){
#do things, never updating the $value1 variable
}
燕归巢 2025-02-16 07:17:00

最终,“修复”是将“ -noexit”添加到任务调度程序操作中的参数列表中。


最终,我了解到的是,一旦“外壳”关闭,开始工作就会死亡,并且当脚本/任务以任务调度程序结束时,壳将始终关闭。

-noexit标志确实“修复”了此操作,但是我很快了解到,由于第一个任务仍未退出,因此它阻止了将来的任何任务。对于整个永恒而言,此任务每分钟运行一次,因此,NoExit很快就打破了我的自动化。

我最终重写了整个流程,因此我不再使用异步函数,而是三个单独的脚本,这些脚本知道何时根据我在每个所述脚本的开始和结尾进行的SQL更新运行。

这到底是如何工作的(而且已经有多年)仍然超出了我的范围。我觉得我的任务调度程序“动作”中有一些非常具体的标志,这些标志使外壳保持打开状态,直到确认开始工作。不太确定,这不是我的专业...

Ultimately the "fix" was to add "-NoExit" to the argument list in the Task Scheduler action.


Ultimately what I learned was that a Start-Job is going to die as soon as the "shell" is closed, and the shell will always close when the script/task ends in Task Scheduler.

The -NoExit flag did "fix" this, but I very quickly learned that it prevented any future task from running since the first task still hadn't exited. This task runs once a minute, for all of eternity, so -NoExit broke my automations pretty quickly.

I ended up rewriting the entire flow so I am no longer using an async function but three separate scripts that know when to run based on SQL updates that I am making at the beginning and end of each said script.

How exactly this had been working before (and it was, for years) is still beyond me. I feel like I had some very specific flags in my Task Scheduler "Action" that kept the shell open until the Start-Job was confirmed done. Not really sure, this ain't my forte...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文