SQL 代理 PowerShell 任务永远不会完成

Hen*_*sen 7 sql-server powershell sql-server-2016 dbatools

我对 PowerShell 很陌生,现在我找到了 dbatools.io,我想在其中运行 SQL 代理中的 PowerShell 任务,例如

$ExportPath = $env:TEMP + '\DriveSpace.csv'
$datatable = Import-Csv $ExportPath | Out-DbaDataTable
Write-DbaDataTable -SqlServer MyServer -Database Utils -InputObject  $datatable -Table dbo.FreeSpaceOnDiskDrive -AutoCreateTable
Run Code Online (Sandbox Code Playgroud)

它开始了,但它永远不会结束。我也尝试过执行此操作的任务:

Get-DbaDatabaseSpace -SqlServer MyServer -IncludeSystemDBs | Out-DbaDataTable | Write-DbaDataTable -SqlServer MyServer -database utils -Table dbo.DiskSpaceExample -AutoCreateTable
Run Code Online (Sandbox Code Playgroud)

同样的问题。它在 Windows PowerShell ISE 中运行正常,但只是在 SQL 代理中挂起。所以现在它为我创建了一个新表,并用数据填充它,但工作只是继续运行。

小智 7

您遇到的问题是 SQL Server 代理中的 PowerShell 子系统。使用其他模块有点不稳定,因为您处于 SQL Server PowerShell 提供程序 (SQLPS.exe) 的上下文中。所以它的工作方式就像你打开sqlps.exe然后尝试执行你的代码一样。

使用dbatools模块要记住的一件事是,它会与 SQLPS 和sqlserverMS 现在为 SQL Server 单独维护的模块发生冲突。最后我检查了它的主要冲突是我们现在在模块中的 TEPP,它只是无法加载该代码。[警告:我是这个模块的主要贡献者。]

dbatools 模块具有内置的自定义类型和样式,因此当您在还导入了 SQLPS 或 SQLServer 模块的 PowerShell 主机下运行脚本时,您的结果会有所不同。

要在 SQL 代理步骤中使用 dbatools,请确保您只使用 CmdExec 子系统(步骤类型),然后调用 PowerShell 主机来执行您的代码。如果您不想为每个脚本维护一个文件,您可以按照下图所示的方式将代码放在 SQL Agent CmdExec 步骤中,但更复杂的脚本通过文件更容易维护。

USE [msdb]
GO

/****** Object:  Job [dbatools_example]    Script Date: 2017-08-30 8:53:15 AM ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object:  JobCategory [[Uncategorized (Local)]]    Script Date: 2017-08-30 8:53:15 AM ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

END

DECLARE @jobId BINARY(16)
EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'dbatools_example', 
        @enabled=1, 
        @notify_level_eventlog=0, 
        @notify_level_email=0, 
        @notify_level_netsend=0, 
        @notify_level_page=0, 
        @delete_level=0, 
        @description=N'No description available.', 
        @category_name=N'[Uncategorized (Local)]', 
        @owner_login_name=N'sa', @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [dbatools_command]    Script Date: 2017-08-30 8:53:15 AM ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'dbatools_command', 
        @step_id=1, 
        @cmdexec_success_code=0, 
        @on_success_action=1, 
        @on_success_step_id=0, 
        @on_fail_action=2, 
        @on_fail_step_id=0, 
        @retry_attempts=0, 
        @retry_interval=0, 
        @os_run_priority=0, @subsystem=N'CmdExec', 
        @command=N'powershell.exe -ExecutionPolicy Bypass -Command "Import-Module dbatools; $server = ''manatarms''; Get-DbaDatabaseSpace -SqlInstance $server -IncludeSystemDbs | Out-DbaDataTable | Write-DbaDataTable -SqlInstance $server -Database db1 -Table dbo.FreeSpaceOnDiskDrive -AutoCreateTable"', 
        @flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
    IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:
GO
Run Code Online (Sandbox Code Playgroud)

运行上面的作业在我的数据库和表中给了我这个 db1.dbo.FreeSpaceOnDiskDrive

在此处输入图片说明