web-dev-qa-db-ja.com

SQLエージェントPowerShellタスクが完了しない

私はPowerShellにかなり慣れていないので、SQLエージェントでPowerShellタスクを実行したいdbatools.ioを見つけました。

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

開始しますが、neverは終了します。私はこれを実行しているタスクを持つことも試みました:

Get-DbaDatabaseSpace -SqlServer MyServer -IncludeSystemDBs | Out-DbaDataTable | Write-DbaDataTable -SqlServer MyServer -database utils -Table dbo.DiskSpaceExample -AutoCreateTable

同じ問題。 Windows PowerShell ISEでは問題なく動作しますが、SQLエージェントでハングするだけです。これで、新しいテーブルが作成され、データが入力されましたが、ジョブは実行を続けます。

発生している問題は、SQL ServerエージェントのPowerShellサブシステムにあります。 SQL Server PowerShellプロバイダー(SQLPS.exe)のコンテキストに置かれているため、他のモジュールを使用する場合とは少し異なります。したがって、sqlps.exeを開いてコードを実行する場合と同じように機能します。

dbatools モジュールで留意すべきことの1つは、-それはがSQLPSとsqlserverモジュールの両方と競合することです。最後に、競合している主なものを確認しましたが、モジュールに現在あるTEPPです。コードをロードできません。 [警告:私はこのモジュールの主要な貢献者です。]

Dbatoolsモジュールにはカスタムのタイプとスタイルが組み込まれているため、SQLPSまたはSQLServerモジュールもインポートされているPowerShellホストでスクリプトを実行すると、結果が異なります。

SQLエージェントステップでdbatoolsを利用するには、CmdExecサブシステム(ステップタイプ)のみを使用し、PowerShellホストを呼び出してコードを実行します。スクリプトごとにファイルを維持したくない場合は、以下の方法でコードをSQLエージェントの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

上記のジョブを実行すると、データベースとテーブルdb1.dbo.FreeSpaceOnDiskDriveにこれが表示されます

enter image description here

5
user507

SQLエージェントの動作を誤解している。 PowerShellは、インスタンスの外部の外部で実行されます。

これは、操作がfinishedとして報告されるか、障害エラーが発生するまで、Powershell操作が永続的に行われることを意味します。セッションを閉じようとすると、シェルを閉じるまで無期限にハングします。場合によっては、シェルが起動している適切なプロセスを正しく停止しないと、これが不可能になることさえあります。

たとえば、これを行わない場合、一時停止操作でpowershellを実行した場合、エージェントがpowershellを開いたコンソールにアクセスできないため、貧弱なシェルは無期限にハングします。

  • SQLCMDを使用する

これはドキュメントで正しくサポートされているだけでなく、操作が完了した後に明確に閉じられます。すべての種類のステップを設定することもでき、ドキュメントも豊富です。

  • PowerShellの使用を継続する

のみ、出口パスをハードコーディングします。呼び出し元に戻る操作に依存しないでください。あなたはそれがそうであることを確認します。

実際、これがコーディングの最大のルールです。明示的に保証されていない限り、コードが機能すると想定しないでください。

  • 別の方法を使用してください。

どのアプローチでも:DAC、ODBC、bcp、接続、 統合サービス(SSIS)接続

SSISはパッケージを使用しており、繰り返しの操作にも最適です。

もっと...

2
clifton_h