Shutdown-Skripts ausführen

Erstellen und führen Sie Shutdown-Skripts aus, die unmittelbar vor dem Beenden oder Neustarten einer VM-Instanz Befehle ausführen. Das ist vor allem nützlich, wenn Sie möchten, dass automatische Skripts Instanzen starten oder beenden und andere Instanzen genug Zeit haben sollen, Aufgaben zu erledigen (Export von Logs oder Synchronisation mit anderen Systemen).

Shutdown-Skripts sind besonders nützlich bei VMs in einer verwalteten Instanzgruppe mit Autoscaling. Wenn das Autoscaling eine VM in der Gruppe schließt, wird das Shutdown-Skript ausgeführt, bevor sie tatsächlich geschlossen wird. Das Skript führt alle Aktionen aus, die Sie dafür definiert haben. Das Skript wird während der begrenzten Shutdown-Phase ausgeführt, bevor die VM beendet wird. Ein Shutdown-Skript kann zum Beispiel verarbeitete Daten in Cloud Storage speichern oder Protokolle sichern.

Shutdown-Skripts funktionieren ähnlich wie Startskripts. Ein Großteil der Dokumentation für Startskripts gilt auch für Shutdown-Skripts.

Bei Aufgaben zum Herunterfahren und Neustart führen VMs immer Shutdown-Skripts aus:

  • Für Linux-VMs mit dem Nutzer root.
  • Für Windows-VMs mit dem Konto System.

Vorbereitung

Damit in Metadaten gespeicherte Skripts auf einer VM-Instanz ausgeführt werden können, muss die Gastumgebung installiert sein und ausgeführt werden.

  • Die Gastumgebung enthält den Gast-Agent (z. B. google-guest-agent unter Linux), der den Skriptinhalt oder die URL aus den Metadaten der Instanz liest und die Ausführung initiiert.
  • Auf allen öffentlichen Compute Engine-Images ist die Gastumgebung vorinstalliert.
  • Wenn Sie ein benutzerdefiniertes Image erstellen, müssen Sie die Google-Gastumgebung manuell installieren, damit Scripts aus Metadaten und andere Google Cloud -Features ordnungsgemäß funktionieren.

Hinweis

Erforderliche Berechtigungen für diese Aufgabe

Zum Ausführen dieser Aufgabe benötigen Sie die folgende Berechtigung:

  • Alle Berechtigungen, die für das Erstellen einer Instanz erforderlich sind.
  • compute.instances.setMetadata für die Instanz

Spezifikationen

In den folgenden Abschnitten werden die Spezifikationen für Shutdown-Skripts beschrieben.

Beschränkungen

Bei der Verwendung von Shutdown-Skripts gibt es einige Beschränkungen:

  • Compute Engine führt Shutdown-Scripts nur nach Best-Effort-Prinzip aus. In einigen wenigen Fällen kann Compute Engine daher nicht dafür sorgen, dass das Shutdown-Script abgeschlossen wird.
  • Unter Windows wird die lokale Gruppenrichtlinie verwendet, um das Shutdown-Script zu starten.
    • Das Installationspaket konfiguriert die Computer Configuration/Windows Setting/Scripts (Startup/Shutdown)-Einstellung der lokalen Gruppenrichtlinie so, dass das Script beim Herunterfahren des Systems gestartet wird.

Shutdown-Skripts aufrufen

Shutdown-Skripts werden ausgelöst, wenn die Instanz nach einem der folgenden Ereignisse heruntergefahren wird:

  • Sie gehen so vor:

  • Compute Engine beendet eine Instanz im Rahmen eines programmierten Stopp- oder Löschvorgangs.

  • Compute Engine beendet eine Spot-VM oder eine Instanz auf Abruf im Rahmen des Prozesses für vorzeitiges Beenden.

Ein Shutdown-Skript kann einen beliebigen Dateityp haben. Wenn in der Instanz ein Shutdown-Script vorhanden ist, führt Compute Engine die folgenden Schritte aus:

  1. Kopiert das Skript in eine lokale Datei auf der Instanz.
  2. Legt Berechtigungen für die Datei fest, um das Skript ausführbar zu machen.
  3. Führt die Datei aus, wenn die Instanz heruntergefahren wird.

Sie können zum Beispiel ein Python-Skript statt eines Bash-Skripts verwenden. Aber denken Sie daran, dass Compute Engine das Skript so ausführt, wie es ist. Dabei kommt es nicht auf die Art des Skripts an.

Bei der Ausführung eines Skripts, das nicht in Bash geschrieben ist, müssen Sie eine Shebang-Zeile zu Beginn der Datei hinzufügen, damit das Betriebssystem erkennen kann, welcher Interpreter verwendet werden muss. Bei einem Python-Skript können Sie zum Beispiel die folgende Shebang-Zeile hinzufügen:

#!/usr/bin/python

Ausführungszeit für das Shutdown-Skript

Ihre Shutdown-Skripts werden ausgeführt, wenn Compute Engine den Instanzstatus auf STOPPING setzt. Ihre Skripts müssen abgeschlossen sein, bevor die Instanz vollständig beendet wird. Dies ist der Fall, wenn sich der Status in TERMINATED ändert. Die Zeit, die die Instanz benötigt, um den Status TERMINATED zu erreichen, variiert je nach Instanztyp.

Wenn die Ausführung Ihrer Scripts länger dauert als das Beenden der Instanz, werden die Scripts von Compute Engine erzwungen. Dies kann zu Datenverlust oder unvollständigen Aufgaben führen. Um dies zu verhindern, beenden Sie die Instanz innerhalb des Gastbetriebssystems. Bei diesem Ansatz bleibt der Instanzstatus auf STOPPING, bis die Shutdown-Skripts ausgeführt wurden.

Lokale Shutdown-Skripts

Ein lokales Shutdown-Skript ist auf Ihrem lokalen Computer ansässig. Sie können es als Datei verwenden oder den Inhalt direkt an Compute Engine weiterleiten.

Mit Shutdown-Skripts können so viele Aktionen wie nötig ausgeführt werden. Wenn Sie die Datei jedoch lokal übertragen, darf Ihr Skript die Längenbeschränkung für Metadatenwerte von 256 KB nicht überschreiten. Um ein Skript zu verwenden, das die Längenbeschränkung überschreitet, sollten Sie Ihre Datei in Cloud Storage speichern. Weitere Informationen finden Sie unter Shutdown-Skript aus Cloud Storage verwenden.

Shutdown-Skriptdatei angeben

Sie können eine lokale Shutdown-Skriptdatei nur über das gcloud-Befehlszeilentool übertragen.

gcloud

Geben Sie zum Übertragen einer lokalen Shutdown-Skriptdatei das Flag --metadata-from-file gefolgt vom Metadaten-Schlüsselpaar shutdown-script=PATH/TO/FILE an, wobei PATH/TO/FILE für den relativen Pfad zum Shutdown-Skript steht. Beispiel:

gcloud compute instances create example-instance \
    --metadata-from-file shutdown-script=examples/scripts/install.sh

Terraform

Wenn Sie ein Shutdown-Script direkt angeben möchten, verwenden Sie die Ressource google_compute_instance mit dem Pfad zum Shutdown-Script in den Metadaten.

resource "google_compute_instance" "shutdown_content_from_file" {
  name         = "instance-name-shutdown-content-from-file"
  machine_type = "f1-micro"
  zone         = "us-central1-c"
  metadata = {
    # Shuts down Apache server
    shutdown-script = file("${path.module}/shutdown-script.sh")
  }
  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-13"
    }
  }
  network_interface {
    # A default network is created for all Google Cloud projects
    network = "default"
    access_config {
    }
  }
}

Informationen zum Anwenden oder Entfernen einer Terraform-Konfiguration finden Sie unter Grundlegende Terraform-Befehle.

Shutdown-Skriptinhalte direkt angeben

Alternativ können Sie die Inhalte Ihres Shutdown-Skripts auch direkt eingeben.

Console

In der Google Cloud Console können Sie ein Shutdown-Script direkt mit dem Metadatenschlüssel shutdown-script angeben:

  1. Zur Seite Instanz erstellen.

    Zur Seite „Instanz erstellen“

  2. Geben Sie die VM-Details an

  3. Maximieren Sie den Bereich Erweiterte Optionen.

  4. Maximieren Sie Verwaltung und gehen Sie so vor:

    1. Klicken Sie im Abschnitt Benutzerdefinierte Metadaten auf Element hinzufügen.
    2. Geben Sie im Feld Schlüssel shutdown-script für den Metadatenschlüssel ein.
    3. Geben Sie im Feld Werte den Inhalt Ihres Shutdown-Skripts ein.
  5. Fahren Sie mit dem VM-Erstellungsprozess fort.

gcloud

Verwenden Sie in der Google Cloud-Befehlszeile das Flag --metadata, um den Inhalt Ihres Shutdown-Skripts gefolgt vom Schlüsselpaar shutdown-script=CONTENTS anzugeben, wobei CONTENTS für den Inhalt Ihres Shutdown-Skripts steht.

gcloud compute instances create example-instance --metadata shutdown-script="#! /bin/bash
> # Shuts down Apache server
> /etc/init.d/apache2 stop"

Terraform

Wenn Sie ein Shutdown-Script direkt angeben möchten, verwenden Sie die Ressource google_compute_instance mit dem Shutdown-Script in den Metadaten.

resource "google_compute_instance" "default" {
  name         = "instance-name-shutdown-content-directly"
  machine_type = "f1-micro"
  zone         = "us-central1-c"
  metadata = {
    # Shuts down Apache server
    shutdown-script = "#! /bin/bash /etc/init.d/apache2 stop"
  }
  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-13"
    }
  }
  network_interface {
    # A default network is created for all Google Cloud projects
    network = "default"
    access_config {
    }
  }
}

Informationen zum Anwenden oder Entfernen einer Terraform-Konfiguration finden Sie unter Grundlegende Terraform-Befehle.

REST

Beim Erstellen einer Instanz können Sie ein Shutdown-Skript als Teil des Metadatenattributs für Ihre Anfrage angeben. Verwenden Sie shutdown-script als Metadatenschlüssel:

POST https://compute.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a/instances

{...
  "metadata": {
    "items": [
      {
       "key": "shutdown-script",
       "value": "#! /bin/bash\n\n# Shuts down Apache server\n/etc/init.d/apache2 stop"
      }
    ]
  }...
}

Shutdown-Skript für Windows-Instanzen angeben

Sie können Shutdown-Skripte auf Windows-Instanzen mit den folgenden Metadatenschlüsseln für Windows ausführen. Wählen Sie einen der folgenden Sonderschlüssel. Jeder Schlüssel sollte zu dem Skript passen, das Sie verwenden wollen.

Sie können mehrere Shutdown-Skripts anhand verschiedener Schlüssel in Ihrer Instanz verwenden. Dabei darf jedoch jeder Schlüssel nur einmal pro virtueller Maschine eingesetzt werden.

Die folgenden Schlüssel können mit einem lokalen Shutdown-Skript verwendet werden. Folgen Sie dazu der Anleitung weiter oben in diesem Dokument.

cmd-Shutdown-Skripts bat-Shutdown-Skripts ps1-Shutdown-Skripts
windows-shutdown-script-cmd windows-shutdown-script-bat windows-shutdown-script-ps1

Shutdown-Skript aus Cloud Storage verwenden

Sie können Shutdown-Skripts in Cloud Storage speichern und von dort aus verwenden. Folgen Sie der Anleitung in der Dokumentation zu Startskripts, aber ersetzen Sie startup-script-url durch shutdown-script-url.

Ersetzen Sie bei Windows-Instanzen windows-startup-script-url durch windows-shutdown-script-url.

Shutdown-Skript auf laufende Instanzen anwenden

Folgen Sie der Anleitung in der Dokumentation Startskript für laufende Instanzen anwenden. Ersetzen Sie die Metadatenschlüssel mit einem der folgenden:

  • shutdown-script: Geben Sie mit diesem Schlüssel den Inhalt des Shutdown-Skripts direkt an. Mit der Google Cloud CLI können Sie den Pfad für ein Shutdown-Script mit dem Flag --metadata-from-file und dem Metadatenschlüssel shutdown-script angeben.
  • shutdown-script-url: Geben Sie mit diesem Schlüssel die Cloud Storage-URL zur Shutdown-Skriptdatei an.

Shutdown-Skript während eines ordnungsgemäßen Herunterfahrens ausführen

Wenn für eine Compute-Instanz das ordnungsgemäße Herunterfahren aktiviert ist, werden alle Shutdown-Scripts, die Sie in Metadatenschlüsseln konfigurieren, standardmäßig nach dem ordnungsgemäßen Herunterfahren ausgeführt.

Wenn Sie Befehle während eines ordnungsgemäßen Herunterfahrens ausführen möchten, müssen Sie ein benutzerdefiniertes Watcher-Script verwenden, das den Metadatenserver kontinuierlich im Hintergrund abfragt, wie in diesem Abschnitt gezeigt. Damit Ihre Skripts genügend Zeit haben, um abgeschlossen zu werden, und um potenziellen Datenverlust oder unvollständige Aufgaben zu vermeiden, empfehlen wir, Ihre Shutdown-Skripts zu ändern, indem Sie Ihre Logik in dieses Watcher-Skript verschieben.

Wählen Sie eine der folgenden Optionen aus, um ein Shutdown-Script während eines ordnungsgemäßen Herunterfahrens auszuführen. Die Optionen hängen vom Gastbetriebssystem ab, das Ihre Compute-Instanz verwendet:

Linux

  1. Stellen Sie eine Verbindung zur Compute-Instanz her, falls Sie dies noch nicht getan haben.

  2. Führen Sie ein Watcher-Skript aus oder konfigurieren Sie es so, dass es beim Booten ausgeführt wird, z. B. so: Fügen Sie die spezifische Logik für das Herunterfahren an der angegebenen Stelle hinzu:

    #!/bin/bash
    
    # --------------------------------------------------------
    # Script for graceful shutdown based on the metadata value
    # --------------------------------------------------------
    #
    # This script monitors the metadata key `shutdown-status` and
    # waits for its value to change to `PENDING_STOP`. After the script
    # runs a series of user-defined commands, it runs `sudo shutdown -h now`
    # to signal to Compute Engine that the shutdown process is
    # complete.
    #
    # To run this script, you must have passwordless sudo privileges.
    
    METADATA_URL="http://metadata.google.internal/computeMetadata/v1/instance/attributes/shutdown-status"
    LAST_ETAG="0"
    
    echo "Starting shutdown status watcher"
    
    while true; do
      # Wait for the metadata value to change.
      # The metadata server blocks the request until a change occurs or a timeout is reached.
      RESPONSE=$(curl -H "Metadata-Flavor: Google" -s -i "${METADATA_URL}?wait_for_change=true&last_etag=${LAST_ETAG}")
      CURL_EXIT_STATUS=$?
    
      if [[ ${CURL_EXIT_STATUS} -ne 0 ]]; then
        echo "Error: curl command failed with exit status ${CURL_EXIT_STATUS}. Retrying in 5 seconds..."
        sleep 5
        continue
      fi
    
      # Strip carriage returns (\r) immediately to prevent CRLF line endings from corrupting string comparisons
      RESPONSE=$(echo "$RESPONSE" | tr -d '\r')
    
      # Extract the HTTP status code from the first line of the response
      HTTP_STATUS=$(echo "$RESPONSE" | head -n 1 | awk '{print $2}')
    
      if [[ "${HTTP_STATUS}" -eq 200 ]]; then
        # Read the new etag value to re-subscribe on the next poll.
        NEW_ETAG=$(echo "$RESPONSE" | grep -i "^ETag:" | awk '{print $2}')
        if [[ -n "${NEW_ETAG}" ]]; then
          LAST_ETAG="${NEW_ETAG}"
        fi
    
        # Extract the value of the shutdown status from the last line of the response body.
        SHUTDOWN_STATUS=$(echo "$RESPONSE" | tail -n 1)
    
        echo "Metadata changed. New ETag: ${LAST_ETAG}, shutdown-status: '${SHUTDOWN_STATUS}'"
    
        if [[ "${SHUTDOWN_STATUS}" == "PENDING_STOP" ]]; then
          echo "Shutdown signal 'PENDING_STOP' received. Exiting watcher loop."
          break
        fi
      elif [[ "${HTTP_STATUS}" -eq 503 ]]; then
        # 503 Service Unavailable: wait_for_change timed out with no change. Sleep and loop again.
        echo "Service temporarily unavailable or request timed out. Retrying in 2 seconds..."
        sleep 2
        continue
      else
        # Unexpected HTTP status
        echo "Warning: Unexpected HTTP status ${HTTP_STATUS}. Retrying in 5 seconds..."
        sleep 5
      fi
    done
    
    # --------------------------------------------------------
    # Graceful shutdown commands section
    # --------------------------------------------------------
    echo "Watcher loop exited. Starting graceful shutdown procedures..."
    
    # --- ADD YOUR GRACEFUL SHUTDOWN COMMANDS HERE ---
    
    echo "Graceful shutdown commands executed."
    
    # --------------------------------------------------------
    # Signal OS to stop
    # --------------------------------------------------------
    echo "Shutting down the guest OS to turn off the compute instance..."
    sudo shutdown -h now
    

Windows

  1. Falls noch nicht geschehen, stellen Sie mit einer der folgenden Methoden eine Verbindung zur Compute-Instanz her:

  2. Führen Sie ein Watcher-Script aus oder konfigurieren Sie es so, dass es beim Booten ausgeführt wird, z. B. so: Fügen Sie die spezifische Logik für das Herunterfahren an der angegebenen Stelle hinzu:

    <#
    .SYNOPSIS
    pre-shutdown-script.ps1
    #>
    
    # --------------------------------------------------------
    # Script for graceful shutdown based on the metadata value
    # --------------------------------------------------------
    #
    # This script monitors the metadata key `shutdown-status` and
    # waits for its value to change to `PENDING_STOP`. After the script
    # runs a series of user-defined commands, it runs `Stop-Computer -Force`
    # to signal to Compute Engine that the shutdown process is
    # complete.
    
    $METADATA_URL = "http://metadata.google.internal/computeMetadata/v1/instance/attributes/shutdown-status"
    $LAST_ETAG = "0"
    
    Write-Host "Starting shutdown status watcher"
    
    while ($true) {
        $Response = $null
        $HTTP_STATUS = 0
    
        # Wait for the metadata value to change.
        # The metadata server blocks the request until a change occurs or a timeout is reached.
        try {
            $Response = Invoke-WebRequest `
                -Headers @{"Metadata-Flavor" = "Google"} `
                -Uri "${METADATA_URL}?wait_for_change=true&last_etag=${LAST_ETAG}" `
                -TimeoutSec 320 `
                -ErrorAction Stop
    
            if ($null -ne $Response) {
                $HTTP_STATUS = [int]$Response.StatusCode
            }
        } catch {
            # Invoke-WebRequest throws an error for non-2xx status codes or connection failures.
            $Exception = $_.Exception
            if ($null -ne $Exception -and $null -ne $Exception.Response) {
                $HTTP_STATUS = [int]$Exception.Response.StatusCode
            } else {
                $HTTP_STATUS = 0
            }
        }
    
        if ($HTTP_STATUS -eq 0) {
            Write-Host "Error: Request failed. Retrying in 5 seconds..."
            Start-Sleep -Seconds 5
            continue
        }
    
        if ($HTTP_STATUS -eq 200) {
            # Read the new etag value to re-subscribe on the next poll.
            $NEW_ETAG = $Response.Headers["ETag"]
            if ($null -ne $NEW_ETAG) {
                $LAST_ETAG = $NEW_ETAG
            }
    
            # Extract the value of the shutdown status from the response body.
            $SHUTDOWN_STATUS = $Response.Content.Trim()
    
            Write-Host "Metadata changed. New ETag: ${LAST_ETAG}, shutdown-status: '${SHUTDOWN_STATUS}'"
    
            if ($SHUTDOWN_STATUS -eq "PENDING_STOP") {
                Write-Host "Shutdown signal 'PENDING_STOP' received. Exiting watcher loop."
                break
            }
        } elseif ($HTTP_STATUS -eq 503) {
            # 503 Service Unavailable: wait_for_change timed out with no change. Sleep and loop again.
            Write-Host "Service temporarily unavailable or request timed out. Retrying in 2 seconds..."
            Start-Sleep -Seconds 2
            continue
        } else {
            # Unexpected HTTP status
            Write-Host "Warning: Unexpected HTTP status ${HTTP_STATUS}. Retrying in 5 seconds..."
            Start-Sleep -Seconds 5
        }
    }
    
    # --------------------------------------------------------
    # Graceful shutdown commands section
    # --------------------------------------------------------
    Write-Host "Watcher loop exited. Starting graceful shutdown procedures..."
    
    # --- ADD YOUR GRACEFUL SHUTDOWN COMMANDS HERE ---
    
    Write-Host "Graceful shutdown commands executed."
    
    # --------------------------------------------------------
    # Signal OS to Halt
    # --------------------------------------------------------
    Write-Host "Shutting down the guest OS to turn off the compute instance..."
    Stop-Computer -Force
    

Ausgabe eines Shutdown-Skripts ansehen

Linux

Sie können die Ausgabe eines Linux-Shutdown-Skripts aufrufen, indem Sie eines der folgenden Dinge tun:

Windows

Sehen Sie sich die Ausgabe eines Windows Server-Shutdown-Script an. Verwenden Sie dazu eines der folgenden Dinge und prüfen Sie, ob GCEMetadataScripts-Ereignisse vorhanden sind: