Archiv der Kategorie: Tipps

Tipp des Tages: Ein Sql-Skript nach Tabellennamen gruppieren

Ausgangspunkt ist eine (sehr große) Sql-Skriptdatei, die mehrere Zehntausend Insert Into-Befehlszeilen enthält (es können auch ein paar mehr sein;). Insgesamt werden ca. ein Dutzend unterschiedliche Tabellen angesprochen.

Problem: Ich möchte die Namen aller Tabellen enthalten.

Lösung: Zerlegen der Datei per Select-String und einem einfachen Regex und gruppieren nach einer per Select-Object angelegten Property. Also, alles klassische PowerShell-Zutaten, die auch Anwendern geläufig sind, die die PowerShell nur sporadisch benutzen.

PS D:\Datenbanken\Select-String .\VGEFA.sql -Pattern "[dbo].[(\w+)]" | Select-Object @{n="TabName";e={$_.Matches[0].Groups[1].Value}} | Group-Object TabName

Tipp des Tages: Einzelaktionen ausführen mit Invoke-Command statt ForEach-Object

Eine der größten Hürden, die PowerShell-Einsteiger (bildlich gesprochen) überwinden müssen ist zu verstehen, wie auf eine Get-Abfrage eine individuell festgelegte Aktion folgen kann.

Beispiel: Wenn ein bestimmter Dienst nicht ausführt, soll eine Mail verschickt und ein Eintrag in einer Log-Datei geschrieben werden. Das Beispiel wirkt vielleicht ein wenig konstruiert. Es geht im Grunde darum, dass auf eine Get-Abfrage eine Aktion folgen soll, die sich nicht nur ein einzelnes Cmdlet abbilden lässt.

Die Lösung besteht normalerweise im Aufruf des ForEach-Object-Cmdlets, in dessen Process-Scriptblock alle Aktionen aneinandergereiht werden:

Get-Service -Name WinRM| Where-Object Status -ne "Running" | ForEach-Object {
"Aktion1"
"Aktion2"
}

Was mir an der Umsetzung nicht ganz so gut gefällt ist der Umstand, dass ForEach-Object auch dann verwendet wird, wenn nur eine Aktion ausgeführt werden soll.

Eine Alternative ist das Invoke-Command-Cmdlet. Auch wenn es in erster Linie für PowerShell-Remoting verwendet wird, kann es natürlich auch für lokale Ausführungen verwendet werden. Im einfachsten Fall wie folgt.

Get-Service -Name WinRM | Where-Object Status -ne "Running" | Invoke-Command {
"Aktion1"
"Aktion2"
}

Ganz optimal ist diese Variante sicher auch nicht. Vielleicht sollte es einfach nur mit „Invoke-Scriptblock“ einen weiteren Alias für ForEach-Object geben:

Set-Alias -Name Invoke-Scriptblock -Value ForEach-Object

Get-Service -Name WinRM | Where-Object Status -ne "Running" | Invoke-Scriptblock {
"Aktion1"
"Aktion2"
}

PowerShell-Remoting mit SSH

PowerShell-Remoting mit SSH ist gut dokumentiert. Zwei sehr gute Artikel sollten für einen erfolgreichen Probelauf genügen:

https://www.thomasmaurer.ch/2020/04/enable-powershell-ssh-remoting-in-powershell-7/

und

https://4sysops.com/archives/enable-powershell-core-6-remoting-with-ssh-transport/

Ein dritter Artikel beschreibt die Verwendung der Public Key-Authentifizierung als Alternative zur Passwort-Eingabe:

https://4sysops.com/archives/powershell-remoting-with-ssh-public-key-authentication/

Was eventuell noch nicht jeder weiß, der sich für das Thema SSH mit PowerShell interessiert. Seit ein paar Monaten gibt es in der PowerShell Gallery ein kleines Modul des PowerShell-Teams, mit dessen einzigem Enable-SSHRemoting-Command das Einrichten von SSH auf dem Remote-Computer sehr einfach wird. Der Eintrag

PasswordAuthentication yes

muss allerdings auch in diesem Fall einkommentiert werden, falls eine Kennwort-Authentifizierung gewünscht ist. Für das erste Kennenlernen ist dies die einfachste Variante.

Das Modul gibt es unter

https://www.powershellgallery.com/packages/Microsoft.PowerShell.RemotingTools/0.1.0

Damit hat es sogar bei mir auf Anhieb funktioniert;)

Insgesamt sind damit folgende Schritte auf dem SSH-Server zu erledigen:

  1. PowerShell 7 installieren
  2. OpenSSH Client und OpenSSH Server installieren
  3. Enable-SSHRemoting ausführen oder den subsystem-Eintrag in der sshd-config-Datei „zu Fuß“ anlegen
  4. sshd-Dienst (nicht ssh) neu starten – unter Linux service ssh restart (eigentlich gar nicht so schwer;)

Damit kann per New-PSSession, Enter-PSSession und Invoke-Command unter einer PowerShell ab Version 6.0 SSH über den SSHTransport-Parameter verwendet werden:

#requires -version 
$hostname="Ubunti
#$hostname="172.23.25.12"
$Username="pemo"
$S1 = New-PSSession -Hostname $Hostname -Username $Username -SSHTransport -Subsystem powershell
Invoke-Command -ScriptBlock { Get-Process} -Session $S1
Remove-PSSession -Session $S1

Der Subsystem-Parameter wählt den Namen des auf dem SSH-Server angelegten subsystem-Eintrag in sshd_config aus. Das Passwort wird bei jedem (!) Aufruf abgefragt. Wer das nicht möchte, muss Public Key-Authentizierung verwenden. Wie das geht, wird in einem der genannten Blog-Artikel beschrieben.

Viel Erfolg!

Abb. Dank snap besteht die Installation der PowerShell unter Ubuntu aus einem Aufruf (sofern sie nicht bereits vorinstalliert ist)