Je suis assez nouveau à PowerShell, et maintenant j'ai trouvé dbatools.io, où j'aimerais exécuter une tâche PowerShell dans SQL Agent comme
$ExportPath = $env:TEMP + '\DriveSpace.csv'
$datatable = Import-Csv $ExportPath | Out-DbaDataTable
Write-DbaDataTable -SqlServer MyServer -Database Utils -InputObject $datatable -Table dbo.FreeSpaceOnDiskDrive -AutoCreateTable
Cela commence, mais ça jamais se termine. J'ai aussi essayé d'avoir une tâche qui fait cela:
Get-DbaDatabaseSpace -SqlServer MyServer -IncludeSystemDBs | Out-DbaDataTable | Write-DbaDataTable -SqlServer MyServer -database utils -Table dbo.DiskSpaceExample -AutoCreateTable
Même problème. Il fonctionne bien dans Windows PowerShell Ise, mais se bloque simplement dans l'agent SQL. Donc, maintenant, il a créé une nouvelle table pour moi et l'avons renseigné avec des données, mais le travail continue de continuer à courir.
Le problème que vous rencontrez est avec le sous-système PowerShell de SQL Server Agent. Il s'agit d'un peu flakely avec d'autres modules parce que vous êtes placé dans le contexte du fournisseur SQL Server PowerShell (SQLPS.EXE). Donc, cela fonctionne de la même manière que si vous ouvrez sqlps.exe
Et puis essayer d'exécuter votre code.
Une chose à garder à l'esprit avec dbatools module est que il conflit avec les SQLPS et le sqlserver
Module que MS maintient désormais séparément pour SQL Server. Enfin, j'ai vérifié la chose principale que celle-ci en conflit était TEPP que nous avons dans le module maintenant, il ne peut tout simplement pas charger ce code. [CAVEAT: Je contribue majeur à ce module.]
Le module DBATools possède des types personnalisés et des styles intégrés. Ainsi, lorsque vous exécutez les scripts sous l'hôte PowerShell, qui dispose également de SQLPS ou du module SQLServer importé vos résultats variera.
Pour utiliser des dbatools dans une étape de l'agent SQL, assurez-vous d'utiliser uniquement le sous-système CMDEXEC (Type d'étape), puis appelez PowerShell Host pour exécuter votre code. Si vous ne souhaitez pas conserver un fichier pour chaque script, vous pouvez mettre votre code dans une étape de SQL Agent CMDEXEC de la manière illustrée ci-dessous, mais plus de script complexe, il est plus facile de maintenir via des fichiers.
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
Courir le travail ci-dessus me donne ceci dans ma base de données et table db1.dbo.FreeSpaceOnDiskDrive
Vous mal comprendre comment fonctionne l'agent SQL. Le PowerShell est exécuté sous sa propre fenêtre à l'extérieur l'instance.
Cela signifie que l'opération rapporte que fini ou une erreur de défaillance se produit, l'opération PowerShell s'asseoir à Perpétuaty. Si vous essayiez de fermer la session, cela pendait indéfiniment jusqu'à la fermeture de la coquille. Dans quelques cas, cela pourrait même être impossible si vous n'arrêtez pas correctement le bon processus que la coquille tire de.
Par exemple, et ne faites pas cela, si vous rencontrez un PowerShell avec l'opération Pause, votre coquille pauvre pendendrait simplement indéfiniment car vous n'avez pas accès à la console que l'agent a ouvert le PowerShell.
Non seulement cela est pris en charge dans les documents, il sera spécifiquement fermé après la fin de l'opération. Vous pouvez même définir toutes sortes d'étapes et la documentation est riche.
Seulement, code dur-code un chemin de sortie. Ne vous fiez pas à une opération pour revenir à l'appelant. Vous vous assurez que cela fait.
En fait, il s'agit de la règle numéro un du codage: ne supposez pas que vos travaux de code ne sont pas explicitement garantis.
Quelle que soit l'approche: DAC, ODBC, BCP, connexions, Services d'intégration (SSIS) Connexions
SSIS utilise des packages, idéal pour les opérations répétées.
ET PLUS...