Référence du contexte PowerShell de l'Agent SQL

13

Dans mon nouveau travail, nous avons plusieurs instances nommées sur chaque serveur. par exemple

  • Server1 \ Dev
  • Server1 \ DevIntegrated
  • Server1 \ QA

J'ai un script SQL PowerShell en cours qui appelle le système d'exploitation, appelle Foo.exemais doit passer un paramètre de ligne de commande (la chaîne de connexion). Un travail SQL Agent existera sur chaque instance, avec une étape de type PowerShell, qui doit connaître le contexte actuel. ie Cette exécution a commencé sur DevIntegrated.

Je ne souhaite pas que chaque script commence par ...

$thisInstance = "Dev"

... d'autant plus que je devrais le modifier lorsque nous migrerons vers des environnements (nouveaux serveurs et instances nommées) dans les mois à venir.

Si je démarre SQLPS, je peux déterminer mon instance en découpant et en découpant les résultats de Get-Location ou en exécutant

(Invoke-Sqlcmd -Query "SELECT @@servername AS ServerName" -SuppressProviderContextWarning).ServerName

Lorsque l'Agent SQL démarre un travail de type PowerShell, il démarre dans C: \ windows \ system32 et l' Get-Locationitinéraire ne fonctionne pas car il ne se trouve pas dans le contexte SQLSERVER. Je peux changer dans ce contexte mais je serai à la "racine" de SQL Server et je ne saurai pas dans quelle instance je devrais être. L'utilisation de la Invoke-Sqlcmdroute ne fonctionnera pas non plus pour la même raison (techniquement, elle expire comme n'est pas une instance par défaut)

À ma connaissance, j'ai énuméré toutes les «choses» de base que je peux entrer dans le journal des tâches, mais rien ne semble montrer SQLSERVER:\SQL\Server1\DevIntegrated

Get-Processsemble que je pourrais utiliser cela et un vaudou d'essayer de bricoler les choses ensemble en frappant les instances et en faisant correspondre les spids, mais cela ressemble juste à un hack sanglant de l'enfer. Il doit y avoir quelque chose de basique qui me manque, quelqu'un peut-il faire la lumière?

Recherche d'alternatives à PowerShell

J'avais étudié l'utilisation d'autres types d'emploi et je n'ai pas obtenu de résolution satisfaisante. La recherche a indiqué que PowerShell répertorié sous SQL Agent était SQLPS et que le démarrage d'une instance de celui-ci en cliquant avec le bouton droit sur l'agent m'a automatiquement déposé au bon endroit. Ce n'est que lorsque j'ai collé mon code interactif dans l'étape de travail que j'ai appris la différence comme mentionné précédemment.

Le type de travail du système d'exploitation m'a mis dans un état identique en ce sens que je ne pouvais pas trouver un moyen de déterminer quelle instance m'avait déposé dans le shell de commande. Bien sûr, je pourrais sqlcmd et obtenir la valeur de @@servernamemais si je savais quelle connexion pour démarrer sqlcmd, je n'aurais pas besoin d'interroger la base de données;)

TSQL pourrait probablement fonctionner si nous l'activions xp_cmdshellmais je ne sais pas s'ils l'ont activé --- installation gouvernementale et ils peuvent être persnickety sur des paramètres non par défaut. Même alors, je suis coincé avec le SQL dynamique et je perds beaucoup de l'expressivité et de la puissance que PowerShell prête.

Bien qu'un peu disgracieux, je pensais définir une variable à la première étape et la transmettre aux étapes successives, mais la recherche a révélé cet article Gestion des étapes de travail multiples (BOL)

Les étapes du travail doivent être autonomes. En d'autres termes, un travail ne peut pas transmettre de valeurs booléennes, de données ou de valeurs numériques entre les étapes du travail. Vous pouvez toutefois transmettre des valeurs d'une étape de travail Transact-SQL à une autre en utilisant des tables permanentes ou des tables temporaires globales. Vous pouvez transmettre des valeurs d'étapes de travail qui exécutent des programmes exécutables d'une étape de travail à une autre étape de travail à l'aide de fichiers.

Je ne peux pas utiliser des astuces courantes comme un fichier / des variables d'environnement / un paramètre de registre bien connus qui Foo.exerecherchent car cela empêcherait l'exécution simultanée entre les instances.

TL; DR:

Dans une étape de travail de l'Agent SQL de type PowerShell, comment pouvez-vous déterminer l'instance de SQL Server qui a lancé le processus?

billinkc
la source
4
PowerShell est-il obligatoire pour ce que vous faites?
johndacostaa
La vraie exigence serait d'avoir un "quelque chose" réutilisable dans l'agent SQL qui puisse lancer un processus DOS avec un paramètre de l'instance appelante. PowerShell semblait le mieux adapté compte tenu de ce qui n'a pas fonctionné ci-dessus. Désolé pour une réponse tardive, j'étais au camp scout.
billinkc

Réponses:

9

Si vous regardez dans SQL Server BOL, l'Agent SQL Server fournit un ensemble de "jetons" qu'il remplacera à la fois dans le texte de la commande de l'étape de travail et dans le fichier de sortie (le dernier empêchera le bouton "Affichage" de l'interface graphique de fonctionner). Ces jetons semblent fonctionner pour tout type d'étape à l'exception de T-SQL.

https://docs.microsoft.com/en-us/sql/ssms/agent/use-tokens-in-job-steps#sql-server-agent-tokens

Donc, si vous avez une étape SQL 2008 PowerShell, vous pouvez la démarrer avec:

$sqlInstance = "$(ESCAPE_DQUOTE(SRVR))"

Vous devrez peut-être utiliser MACH(nom de l'ordinateur) et INST(uniquement le nom de l'instance) à la place, car avec l'instance par défaut SRVR == MACH, mais avec les instances nommées SRVR == MACH\INST.

David Lathrop
la source
3

Malheureusement, je n'ai pas fait grand-chose avec les scripts PowerShell appelés dans SQL Server. Je ne suis pas non plus devant un ordinateur avec lequel je pourrais jouer en ce moment.

Je pense cependant qu'au lieu d'utiliser l'étape de type PowerShell, si vous utilisez CmdExec et appelez simplement votre script comme vous le feriez à partir d'une ligne de commande "powershell 'MyScript.ps1'", vous pouvez alors passer un paramètre qui a l'instance à partir de laquelle vous exécutez. Comme "Powershell 'MyScript.ps1' MyInstanceName".

Donc, au début de votre script, vous avez une configuration param () pour accepter cette valeur de MyInstanceName:


param(
   [Parameter(Position=0,Mandatory=$True)]
   [string]$InstanceName
)
#so if I wanted to use sqlcmd
sqlcmd -S $InstanceName -Q "SELECT @@VERSION"

Lorsque vous avez commencé à indiquer la première étape nécessaire pour savoir sur quelle instance il se trouvait afin que le script PowerShell puisse appeler correctement Foo.exe. Cependant, plus tard, vous mentionnez pouvoir transmettre la valeur à d'autres étapes. Si cela est vrai, vous voudrez peut-être envisager de créer un petit package SSIS qui appelle votre script PowerShell et fait tout ce dont vous avez besoin. Avec SSIS, vous pouvez configurer une variable globale que l'ensemble du package pourrait utiliser.


la source