【问题标题】:Azure Cloud Service Startup task that needs to run a PowerShell script需要运行 PowerShell 脚本的 Azure 云服务启动任务
【发布时间】:2016-03-23 05:02:54
【问题描述】:

全部,

注意:我在收到一些反馈后更新了问题。

感谢 @jisaak 迄今为止的帮助。

在部署云服务时,我需要运行一个添加 TCP 绑定和其他内容的 PowerShell 脚本。

这是我的云服务项目:

这是我的云服务项目和 Webrole 项目:

这是我在 ServiceDefinition.csdef 中的任务:

这是我要运行的 PowerShell 脚本:

这是我对 Startup.cmd 的尝试:

当我部署时,我会在 Azure 日志中看到:

而这在 powershell 日志中:

非常感谢任何帮助。

我想我快到了,但在网络上遵循其他人的语法似乎并没有让我到那里。

谢谢 拉斯

【问题讨论】:

  • 如果您计划在 power shell 中执行 PS 文件或文本文件,则它不起作用。我已经观察过了。但是,如果您只是在 Azure PS 平台上运行代码,它就可以工作。这只是我的观察。

标签: powershell azure azure-cloud-services


【解决方案1】:

我认为问题在于批处理命令解释器在运行 Startup.cmd 时的工作目录与预期不符。

Startup.cmd 位于\approot\bin\Startup 目录,但工作目录为\approot\bin

因此,命令 .\RoleStartup.ps1 无法找到 RoleStartup.ps1,因为它在 bin 目录中而不是在 bin\Startup 目录中查找。

我知道的解决方案是:

解决方案 1: 使用..\Startup\RoleStartup.ps1 从 Startup.cmd 调用 RoleStartup.ps1。

解决方案 2: 更改 Startup.cmd 中的当前工作目录,以便找到相对路径 .\RoleStartup.ps1。我通过CHDIR %~dp0(请参阅here)执行此操作,以更改到包含 Startup.cmd 的目录。

解决方案 3: 正如 Don Lockhart 的回答所建议的那样,不要将 Startup 目录复制到输出中,而是在 Visual Studio 项目中将其设置为“Content”。这意味着其中的文件将存在于 Azure 实例的 \approot\Startup 目录中。 (然后,您需要确保 Startup 文件夹不能通过 IIS 公开访问!)。然后将ServiceDefinition.csdef中对Startup.cmd的引用更新为..\Startup\Startup.cmd,将Startup.cmd中对RoleStartup.ps1的引用更新为..\Startup\RoleStartup.ps1。这适用于工作目录为bin 并使用..\Startup 始终定位相对于它的启动目录这一事实。

【讨论】:

    【解决方案2】:

    您无需在 cmd 中设置执行策略 - 只需调用脚本即可。此外,您应该使用相对路径,因为您不能相信存在C 磁盘。

    将您的批次更改为:

    powershell -executionpolicy unrestricted -file .\RoleStartup.ps1
    

    在 Visual Studio 中右键单击 RoleStartup.ps1Startup.cmd,并确保将 Copy to Output directory 设置为 copy always

    如果这仍然不起作用,请删除 csdef 中的启动调用,将服务、rdp 部署到其中并尝试自己调用脚本以检索任何错误。

    编辑:

    尝试采用如下脚本:

    Import-Module WebAdministration
    
    $site = $null
    
    do # gets the first website until the result is not $null
    {
        $site = Get-WebSite | select -first 1
        Sleep 1
    }
    until ($site)
    
    # get the appcmd path
    $appcmd = Join-Path ([System.Environment]::GetFolderPath('System')) 'inetsrv\appcmd.exe'
    
    # ensure the appcmd.exe is present
    if (-not (Test-Path $appcmd))
    {
        throw "appcmd.exe not found in '$appcmd'"
    }
    
    # The rest of your script ....
    

    【讨论】:

    • 感谢您的帮助。我已经做了你建议的一切。甚至到脚本的 RDP 测试。部署通过,我可以看到,在 PowerShell 事件日志中,它至少是关于我的脚本的新内容,但服务器上没有更改任何设置。然后我在 RDPing 后运行脚本,它运行并成功更改了设置。请查看我对服务器上事件日志的修改。
    • 这看起来像是一个时间问题。您可以尝试将 taskType 更改为 background 并采用您的 powershell 脚本(请参阅我编辑的答案)。该脚本现在等待,直到有一个网站。此外,该脚本使用GetFolderPath 函数来确定system32 文件夹
    • 我已经有一段时间没有回到这个话题了,但是另一篇文章建议我在 Azure 日志中检测到 IIS 已设置并启动时使用 Windows 任务计划程序来计划我的任务。 ideliverable.com/blog/… 这在我手动运行时在服务器上有效,但在从启动任务运行时无效。所以,最终我认为我唯一的问题是让我的启动任务调用我的 cmd 文件,该文件调用 PowerShell 使用启动任务时,对 PowerShell 的调用总是失败。注意,我已经正确设置了文件的编码。
    【解决方案3】:

    过去我发现不将内容复制到输出目录更容易。我有 approot\bin 作为工作目录。我的启动任务元素的 commandLine 属性使用对 .cmd 文件的相对引用,如下所示:

    .cmd 文件也相对从工作目录引用 PowerShell 脚本:

    PowerShell -ExecutionPolicy Unrestricted -f ..\StartUp\RoleStartup.ps1
    

    【讨论】:

    • 只有一件事,我在任何地方都没有 App_Start 文件夹。
    【解决方案4】:

    好的,

    因此,经过多次尝试使其发挥作用后,我又回到了这个问题上。 我试过使用:

    • ServiceDefinition.csdef 中的启动配置
    • 我已尝试在服务器上注册一个计划任务,该任务扫描 Windows Azure 日志以查找 [System[Provider[@Name='Windows Azure Runtime 2.6.0.0'] 和 EventID=10004]]

    由于安全性或事件的时间安排以及 IIS 尚未完全设置,没有任何工作。

    所以我终于硬着头皮使用了我的 Webrole.cs => public override bool OnStart() 方法:

    在ServiceDefinition.csdef中结合这个:

    现在一切正常。这不是最令人满意的结果,因为其他一些方法感觉更优雅。此外,许多其他人发帖说他们有其他方法可以做到这一点。也许我最终会到达那里,但我的时间有限。

    谢谢 拉斯

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-05
      相关资源
      最近更新 更多