SQL Agent-Powershell-Kontextreferenz

13

In meinem neuen Job haben wir mehrere benannte Instanzen auf jedem Server. z.B

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

Ich habe ein SQL PowerShell-Skript in Arbeit, das das Betriebssystem aufruft, Foo.exeaber einen Befehlszeilenparameter (die Verbindungszeichenfolge) übergeben muss. Auf jeder Instanz ist ein SQL Agent-Auftrag mit einem Schritt vom Typ PowerShell vorhanden, der den aktuellen Kontext kennen muss. dh Diese Ausführung begann am DevIntegrated.

Ich möchte nicht, dass jedes Skript mit ... beginnt.

$thisInstance = "Dev"

... vor allem, weil ich das ändern muss, wenn wir in den kommenden Monaten auf Umgebungen (neue Server und benannte Instanzen) migrieren.

Wenn ich SQLPS starte, kann ich meine Instanz bestimmen, indem ich die Ergebnisse von Get-Location zerlege und zerlege oder ausführe

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

Wenn der SQL-Agent einen Auftrag vom Typ PowerShell startet, wird er im Get-LocationVerzeichnis C: \ windows \ system32 gestartet, und die Route funktioniert nicht, da sie nicht im SQLSERVER-Kontext enthalten ist. Ich kann in diesen Kontext wechseln, aber ich befinde mich im "Stammverzeichnis" von SQL Server und weiß nicht, in welcher Instanz ich mich befinden soll. Die Verwendung der Invoke-SqlcmdRoute funktioniert auch nicht aus dem gleichen Grund (technisch gesehen läuft das Zeitlimit wie dort ab) ist keine Standardinstanz)

Nach meinem besten Wissen habe ich alle grundlegenden "Dinge" aufgelistet, die ich in das Jobprotokoll aufnehmen kann, aber nichts scheint zu zeigen SQLSERVER:\SQL\Server1\DevIntegrated

Get-ProcessEs scheint, als könnte ich das und ein bisschen Voodoo gebrauchen, wenn ich versuche, Dinge zusammenzubasteln, indem ich auf die Instanzen treffe und Spids zusammenpasse. Es muss etwas Grundlegendes geben, das mir fehlt. Kann jemand etwas Licht ins Dunkel bringen?

Alternativen zu PowerShell untersucht

Ich hatte mit anderen Jobtypen nachgeforscht und keine zufriedenstellende Lösung erhalten. Nachforschungen haben ergeben, dass es sich bei der unter SQL Agent aufgelisteten PowerShell um SQLPS handelt, und das Starten einer Instanz durch Klicken mit der rechten Maustaste auf den Agent hat mich automatisch an den richtigen Speicherort gebracht. Erst als ich meinen interaktiven Code in den Auftragsschritt eingefügt habe, habe ich von dem Unterschied erfahren, wie bereits erwähnt.

Der Job-Typ des Betriebssystems versetzte mich in einen identischen Zustand, in dem ich keinen Weg finden konnte, um zu bestimmen, welche Instanz mich in die Befehlsshell fallen ließ. Klar, ich könnte sqlcmd und den Wert von @@servernameabrufen, aber wenn ich wüsste, welche Verbindung ich zum Starten von sqlcmd benötige, müsste ich die Datenbank nicht abfragen;)

TSQL könnte wahrscheinlich funktionieren, wenn wir es aktivieren, xp_cmdshellaber ich bin nicht sicher, ob sie es aktiviert haben - Regierungsfunktion und sie können bei nicht standardmäßigen Einstellungen hartnäckig sein. Sogar dann bin ich mit dynamischem SQL beschäftigt und verliere einen Großteil der Ausdruckskraft und Kraft, die PowerShell verleiht.

Ich war zwar etwas unpraktisch, dachte aber, ich definiere eine Variable im ersten Schritt und übergebe sie an die Nachfolgeschritte. Nachforschungen ergaben jedoch, dass dieser Artikel Umgang mit mehreren Auftragsschritten (BOL)

Jobschritte müssen in sich geschlossen sein. Das heißt, ein Job kann keine Booleschen Werte, Daten oder numerischen Werte zwischen Jobschritten übergeben. Sie können jedoch Werte von einem Transact-SQL-Auftragsschritt an einen anderen übergeben, indem Sie permanente Tabellen oder globale temporäre Tabellen verwenden. Sie können Werte von Jobschritten, die ausführbare Programme ausführen, mithilfe von Dateien von einem Jobschritt an einen anderen Jobschritt übergeben.

Ich kann keine allgemeinen Tricks wie eine bekannte Datei- / Umgebungsvariablen- / Registrierungseinstellung verwenden, nach der Foo.exegesucht wird, da dies die gleichzeitige Ausführung über Instanzen hinweg verhindern würde.

TL; DR:

Wie können Sie in einem SQL Agent-Auftragsschritt vom Typ PowerShell die Instanz von SQL Server ermitteln, die den Prozess gestartet hat?

billinkc
quelle
4
Ist Powershell eine Voraussetzung für das, was Sie tun?
Johndacostaa
Die wahre Anforderung wäre, dass der SQL-Agent ein reuasble "something" enthält, mit dem ein DOS-Prozess mit einem Parameter der aufrufenden Instanz gestartet werden kann. PowerShell schien am besten zu passen, wenn man bedenkt, was oben nicht funktioniert hat. Entschuldigung für die verspätete Antwort, ich war im Pfadfinderlager.
billinkc

Antworten:

9

Wenn Sie in SQL Server BOL nachsehen, stellt der SQL Server-Agent eine Reihe von "Token" zur Verfügung, die sowohl in den Jobschritt-Befehlstext als auch in die Ausgabedatei eingefügt werden (letztere verhindern, dass die GUI-Schaltfläche "Anzeigen" funktioniert). Diese Token scheinen für alle Arten von Schritten außer T-SQL zu funktionieren.

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

Wenn Sie also über einen SQL 2008 PowerShell-Schritt verfügen, können Sie diesen wie folgt starten:

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

Möglicherweise müssen Sie stattdessen MACH(Computername) und INST(nur Instanzname) verwenden, da dies bei der Standardinstanz der Fall ist SRVR == MACH, jedoch bei benannten Instanzen SRVR == MACH\INST.

David Lathrop
quelle
3

Leider habe ich nicht viel mit PowerShell-Skripten gemacht, die in SQL Server aufgerufen wurden. Ich bin auch nicht an einem Computer, mit dem ich gerade spielen könnte.

Ich glaube jedoch, anstatt den PowerShell-Typ step zu verwenden, dass Sie, wenn Sie CmdExec verwenden und Ihr Skript einfach so aufrufen, als würden Sie von einer Befehlszeile "powershell 'MyScript.ps1'" aus einen Parameter übergeben könnten, der die Instanz hat, von der aus Sie ausgeführt werden. Wie "Powershell 'MyScript.ps1' MyInstanceName".

Zu Beginn Ihres Skripts haben Sie ein param () - Setup, um den Wert von MyInstanceName zu akzeptieren:


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

Zu Beginn haben Sie den einen Schritt angegeben, der erforderlich ist, um zu ermitteln, auf welcher Instanz es sich befindet, damit das PowerShell-Skript Foo.exe ordnungsgemäß aufrufen kann. Später erwähnen Sie jedoch, dass Sie den Wert an andere Schritte übergeben können. Wenn dies zutrifft, sollten Sie ein kleines SSIS-Paket erstellen, das Ihr PowerShell-Skript aufruft und alle erforderlichen Aktionen ausführt. Mit SSIS können Sie möglicherweise eine globale Variable einrichten, die das gesamte Paket verwenden kann.


quelle