Leserartikel Remote-Startup und -Shutdown einer QNAP die nur für Veeam Backup verwendet wird

Moin,

da meine QNAP im Wohnzimmer steht und sich in der Mietwohnung auch nicht sinnvoll anders unterbringen lässt hat das immer wieder zu einem gewissen Nerv-Faktor meinerseits geführt wenn die Tagsüber angefangen hat zu rödeln usw.

Jetzt habe ich mich ein wenig ans Skripten gesetzt und zwei Skripte (plus einigen Kleinkrams rundum) erstellt, um sicherzustellen, dass die QNAP nur dann läuft, wenn sie auch gebraucht wird.

Zur allgemeinen Konfiguration:
Ich habe einen Selbstbau-Heimserver auf dem Microsoft Hyper-V (2019 Datacenter) läuft weil ich die Lizenz im Laufe der Berufsausbildung kostenlos von Microsoft bereitgestellt bekommen habe.
Sicherung aller Systeme läuft über Veeam Backup & Replication V11 Community Edition. Der Speicher auf der QNAP ist per iSCSI gemappt. Das hat den Hintergrund, dass
1) Veeam empfiehlt, iSCSI statt SMB zu verwenden
2) Bei iSCSI kann ich den Speicher auf ReFS formattieren und durch 'block cloning' viel Speicherplatz sparen.

Das konkrete Modell der QNAP ist eine QNAP TS-431x2 mit integriertem SFP+ Port. Mit 3x 14TB Toshiba Enterprise Capacity im Raid 5 ist hier 25TiB Netto für meine Backups vorhanden, was für mich auch auf längere Zeit mehr als genug sein sollte.


Starten der QNAP per Powershell Skript​

Ich hatte überlegt, ob ich das Skript um die QNAP zu starten als Start-Skript im Veeam-Job hinterlege oder von der Aufgabenplanung aus ausführen lassen soll.
Am Ende hat die Aufgabenplanung gesiegt weil die QNAP fast 5 Minuten braucht um den iSCSI-Dienst bereit zu stellen und noch einige Minuten länger um vollständig online zu sein.

Ein Powershell Skript per Aufgabenplanung ausführen ist denkbar simpel, daher gibt es nur den einen Screenshot - wer mehr wissen will, muss googeln.

2021-04-17 18_34_07-rig-hpv - Remotedesktopverbindung.png


Das Skript selber nutzt die Wake-on-LAN Funktionalität der QNAP. Dabei habe ich mit Entsetzen feststellen müssen, dass die von mir genutzte QNAP TS-431x2 auf dem 10G SFP+ Port kein WOL beherrscht.
(Wobei SFP+ Adapter die WOL unterstützen wohl eher selten sind. Trotzdem enttäuschend.)

Dann hilft alles nichts - ich muss die QNAP wohl doppelt anschließen. Hier eine Übersicht der verbundenen Adapter:
2021-04-17 18_41_17-RIG-Nas.png


Da ich mich mit Portbündelung nicht rumschlagen will aber auch keine Unsicherheit haben will, was was macht erfolgt eine Servicebindung.
2021-04-17 18_43_35-RIG-Nas.png

Ich bin mir nicht sicher, ob WOL noch funktionieren würde falls ich auch die Verwaltungsdienste deaktiviere, aber es gibt auch keinen echten Grund es auszuprobieren. Solange die Dateidienste nur die 10Gbit Verbindung nutzen ist alles prima.


Kommen wir zum verwendeten Powershell-Skript:

PowerShell:
$Folder = 'V:\Repository'
if (Test-Path -Path $Folder)
{
exit
}
else
{
Invoke-WakeOnLan -MacAddress '24:5E:BE:31:B7:CB'
}

Die Invoke-WakeOnLan Funktion habe ich mir hier geholt: https://powershell.one/code/11.html
Man muss ja nicht für jedes Projekt erstmal das Rad neu erfinden. Der V:\Repository Ordner ist - wenn nicht offensichtlich - der Ordner in dem das Veeam-Repository hinterlegt ist.

Der if-Befehl ist, jetzt wo ich drüber nachdenke, überflüssig weil WOL bei einem laufendem System einfach nichts macht, aber wayne. Jetzt habe ich ihn schon drin.

Der Praxistest ist auch erfolgreich. Wenn ich den Task in der Aufgabenplanung manuell anstoße, ist ein paar Minuten später die NAS online. Die letzte Ärgernis ist der Diagnostik-Beep beim Startvorgang, der sich nicht in Software deaktivieren lässt. Da bleibt erstmal abzuwarten, ob der mich nachts aufweckt oder ob der unproblematisch ist.


Shutdown der QNAP per Powershell Skript​

Im Vergleich zum WOL musste ich hier etwas kreativer werden, weil ich kein fertiges Skript das alle nötige Funktionalität beinhaltet finden konnte.

Die Anforderungen waren wie folgt:
1) Der Shutdown darf erst erfolgen, wenn alle drei Veeam-Jobs erfolgerich waren. Da je nachdem ob Veeam bei einem Job z.B. ein Backup Health Check angefangen hat kann ich mich nicht darauf verlassen, dass die Jobs in der Reihenfolge abschließen, in der sie angelaufen sind.
2) Ich will die QNAP auch nicht jedesmal nach Abschluss der Datensicherung sofort wieder herunterfahren, weil die QNAP selber auch einige Dienste hat, die im Hintergrund laufen sollten und eventuell auch etwas Zeit brauchen

Die Entscheidung, den Shutdown per SSH an die QNAP zu geben war einfach. So viele Möglichkeiten gibt es nicht und SSH ist am einfachsten.

Hier erstmal das Skript:

PowerShell:
#Der Befehl um PoSH-SSH zu installieren, welches für SSH per PowerShell notwendig ist
#Find-Module PoSH-SSH | Install-Module

#Dies ist Skript Nr. 1 - welches mit dem ersten Veeam Job verlinkt ist und daher die '1' hinterlegt sobald der Job durch ist
Add-Content C:\Skripte\QNAPShutoff.txt "1"

#Wenn alle 3 Veeam Jobs durch sind wird das Skript zum Ausschalten der QNAP aktiv
$ShutoffString = get-content -path "C:\Skripte\QNAPShutoff.txt"
If ($ShutoffString.Contains("1") -and $ShutoffString.Contains("2") -and $ShutoffString.Contains("3"))
{

#Allerdings soll die QNAP etwas Zeit haben um ihre Wartungsarbeiten durchzuführen, daher wird, sofern es noch nicht zwischen 1 und 5 Uhr morgens ist, solange gewartet
$TimeToSleep = ((get-date "5:00") - (get-date))
$secondsToSleep = $timeToSleep.TotalSeconds
If (($secondsToSleep -gt 0) -and ($secondsToSleep -lt 14400))
{
start-sleep $secondsToSleep
}


#Credentials erstellen für die SSH-Verbindung zur QNAP
$username = "admin"
$password = "#hierwäremeinPW"
$secstr = New-Object -TypeName System.Security.SecureString
$password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr

#Die QNAP per SSH Runterfahren
New-SSHTrustedHost -SSHHost 192.168.12.181 -FingerPrint 5e:31:53:b6:f6:eb:38:e2:46:7e:f5:e0:60:43:17:3a
New-SSHSession -ComputerName 192.168.12.181 -Port 22 -Credential $cred
Invoke-SSHCommand -SessionId 0 -Command "poweroff"
Remove-SSHSession -Index 0

Set-Content C:\Skripte\QNAPShutoff.txt "0"

exit
}
else
{
exit
}

Es gibt drei Versionen des Skript, die beim Anlaufen jeweils 1, 2 oder 3 in einer Text-File hinterlegen. Wenn alle drei Nummern angesammelt sind (also alle drei Backup-Jobs durchgelaufen) wird der Shutdown eingeleitet. Danach wird die Text-Datei zurückgesetzt.

Ja, das Admin-PW der QNAP steht im Klartext im Skript. Für meinen Heinserver ist das mMn kein Problem. In einer Firmenumgebung in einem per GPO verteilten Skript wäre das natürlich ganz was anderes. (Ja, den Code-Schnippsel zu den Credentials habe ich mir ergoogelt.)
Um das Skript auf einem anderen System verwenden zu können muss das PoSH-SSH Modul installiert und natürlich Umgebungs-spezifische Parameter wie IP, Credentials und Fingerprint angepasst werden.

Eingebaut habe ich, damit ich meine zweite Kondition erfüllen kann, einen konditionalen Sleep-Befehl, der dafür sorgt, dass die QNAP erst um 05:00 Uhr heruntergefahren wird - auch wenn die Backups schon um 02:30 fertig sind. Das ist eingebaut, um Zeit für Hintergrundaufgaben zu lassen, wie schon in den Anforderungen angesprochen.

Veeam kann Skripte vor und nach jedem Job ausführen lassen - jedoch kein Powershell. Hier muss ein Umweg über eine Batch-Datei genommen werden, die dann das entsprechende Powershell-Skript aufruft.
2021-04-17 19_15_51-rig-hpv - Remotedesktopverbindung.png


Der Inhalt der Batch ist denkbar simpel, das ist genau dasselbe Prinzip wie weiter oben beim Aufruf durch die Aufgabenplanung.
Code:
Powershell.exe -executionpolicy Bypass C:\Skripte\Shutdown_QNAP1.ps1


Und das wars auch schon - jetzt sollte ich tagsüber wieder ein stilles Wohnzimmer haben.

Falls ihr Feedback für mich habt - immer her, auch wenn's Kritik ist. Nur so werde ich besser.
 
  • Gefällt mir
Reaktionen: Turian, Thomy94, nononkk und 4 andere
Kleines Update - Veeam hat sich beschwert, dass das Skript ins Timeout läuft.

2021-04-18 09_29_20-Window.png


Okay, eine Timeout von 15min für ein Skript das planmäßig eine Wartezeit von ~2h drin hat funktioniert natürlich nicht

Aber es gibt eine Lösung, siehe hier: https://forums.veeam.com/veeam-back...cript-timed-out-hp-data-protector-t24354.html

Ein kleiner Regedit der mir eine Timeout von 3h beschert und jetzt sollten keine Warnmeldungen mehr kommen. Die maximal mögliche Laufzeit des Skript sollte 2h40 sein sofern nicht etwas schief läuft.

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Veeam\Veeam Backup and Replication
2021-04-18 09_31_52-Window.png



Abgesehen davon hat mein kleines Projekt perfekt funktioniert. Das Backup ist erfolgreich durchgelaufen, die QNAP war heute morgen wieder ausgeschaltet und durch den Beep der bootenden QNAP bin ich durch gepennt.
 
Hallo, ich habe Dein Shutdown-Script nachgebaut. Mittlerweile kann ich mich auch erfolgreich einloggen. ABER: bei der Übergabe des poweroff-Befehles erhalte ich: "Operation not permitted" Wird wohl am fehlenden SUDO liegen. Wie hast Du das gelöst? Danke für das Feedback. Grüsse
 
Das ist schon ein Weilchen her, aber ich kann mich nicht erinnern irgendwas spezifisches gemacht zu haben.
Allerdings habe ich damals auch ein Weilchen lang rumprobiert und rumgegoogelt.

Zwei Settings die du mal prüfen könntest:
2022-03-16 17_21_13-RIG-Nas.png
2022-03-16 17_21_37-RIG-Nas.png


Eventuell ist root login per SSH default disabled? Aber ich kann mich nicht erinnern etwas der Art modifiziert zu haben.


Man könnte sowieso einiges sauberer machen, würde ich das jetzt nochmal machen...
  • einen Service-User für SSH erstellen, statt den integrierten Admin-User zu benutzen
  • Das Passwort nicht im Klartext im Skript hinterlegen, sondern zumindestens sich die Mühe machen, das verschlüsselt als clixml abzulegen und dann im Skript nur daraus aufzurufen.
  • Eigentlich sollte man sowieso keys verwenden für SSH statt Passwörter, aber damit habe ich mich bisher noch überhaupt nicht beschäftigt...
PowerShell:
#Credentials exportieren
Get-Credential | Export-Clixml "c:\Credentials.xml"

#Credentials importieren um sie im Skript zu verwenden
$cred = Import-Clixml -Path "c:\Credentials.xml"
 
Zuletzt bearbeitet:
Danke für Dein Feedback. Damit wir uns recht verstehen. Ich kann mich erfolgreich per SSH verbinden. Aber ich kann den Befehl "poweroff" nicht erfolgreich absetzen. Mir fehlt vermutlich seitens Linux die Berechtigung.

1647503418235.png


Ich habe übrigens das Passwort mittels Key verschlüsselt. Zudem verwende ich nicht den Built-in Admin.
 
Was gibst du dem denn mit, dass der ein chdir durchführen möchte?

Ich würde mich an deiner Stelle mal mit Putty (oder vergleichbar) direkt mit SSH verbinden und prüfen, ob du so poweroff absetzen kannst oder wieder Berechtigungsprobleme kommen.

Auch mal einen Quervergleich machen mit dem integrierten Admin User, ob bei dem auch der Fehler auftritt oder ob der die Berechtigungen hat.

Ich muss gestehen, dass ich mich mit Linux Berechtigungen nicht sonderlich gut auskenne - ich war nur froh, dass es funktioniert :D
 
Tja, was soll ich sagen. Es funktioniert! Der Trick ist, dass der "hauseigene" Benutzer admin verwendet werden muss. Nur der hat anscheinend standardmässig ausreichende Berechtigungen. Und eben den hatte ich, wie von QNAP empfohlen, deaktiviert. Mal schauen wie ich den jetzt sicher konfigurieren kann... (least Privilege)

Aber danke für die Unterstützung!!
 
Wenn du rausfindest, wie man einen alternativen Admin dazu berechtigst, kannst du ja gerne ein kleines Howto hier rein schreiben. Ich war damals zu faul, um einen anderen Admin-User anzulegen und den hauseigenen zu deaktivieren...
 
Leider ist Linux auch (noch) nicht meine Stärke. Und zudem habe ich auch aufgehört im Unterbau von QNAP rumzupfuschen. Denn nach dem Update sind die Änderungen oft wieder zurückgesetzt. Aber wenn ich eine brauchbare Idee habe, melde ich mich zurück...

Danke für die Hilfe!
 
  • Gefällt mir
Reaktionen: Rickmer
Hallo,

ja, ein unlizensierter standalone Agent.
Ich habe mir jetzt ein Powershell Skript gebastelt, welches erst das WakeOnLan macht und dann das Backup anstößt.
Mal sehen, ob das zuverlässig ist...

Code:
function Invoke-WakeOnLan
{
  param
  (
    # one or more MACAddresses
    [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
    # mac address must be a following this regex pattern:
    [ValidatePattern('^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$')]
    [string[]]
    $MacAddress
  )
 
  begin
  {
    # instantiate a UDP client:
    $UDPclient = [System.Net.Sockets.UdpClient]::new()
  }
  process
  {
    foreach($_ in $MacAddress)
    {
      try {
        $currentMacAddress = $_
        
        # get byte array from mac address:
        $mac = $currentMacAddress -split '[:-]' |
          # convert the hex number into byte:
          ForEach-Object {
            [System.Convert]::ToByte($_, 16)
          }
 
        #region compose the "magic packet"
        
        # create a byte array with 102 bytes initialized to 255 each:
        $packet = [byte[]](,0xFF * 102)
        
        # leave the first 6 bytes untouched, and
        # repeat the target mac address bytes in bytes 7 through 102:
        6..101 | Foreach-Object {
          # $_ is indexing in the byte array,
          # $_ % 6 produces repeating indices between 0 and 5
          # (modulo operator)
          $packet[$_] = $mac[($_ % 6)]
        }
        
        #endregion
        
        # connect to port 400 on broadcast address:
        $UDPclient.Connect(([System.Net.IPAddress]::Broadcast),4000)
        
        # send the magic packet to the broadcast address:
        $null = $UDPclient.Send($packet, $packet.Length)
        Write-Verbose "sent magic packet to $currentMacAddress..."
      }
      catch
      {
        Write-Warning "Unable to send ${mac}: $_"
      }
    }
  }
  end
  {
    # release the UDF client and free its memory:
    $UDPclient.Close()
    $UDPclient.Dispose()
  }
}


Send-WOL -mac 'xx'

Start-Sleep -Seconds 2

$process = Start-Process -FilePath "C:\Program Files\Veeam\Endpoint Backup\Veeam.EndPoint.Manager.exe" -ArgumentList "/backup" -Wait -PassThru -NoNewWindow


if ($process.ExitCode -eq 0) {
    Invoke-RestMethod https://hc-ping.com/xx
} else {
    Write-Host "Das Programm wurde mit Fehler beendet."
}

Gruß,
Hendrik
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Rickmer
Zurück
Oben