1

Ich habe eine benutzerdefinierte Batch-Bereitstellung Skript für eine Azure-Funktion, die vorzeitig beendet wird, ohne Fehler. Ich hoffe, dass mir jemand helfen kann zu verstehen, was vor sich geht.Azure-Funktion/Azure-Website Benutzerdefinierte Bereitstellung Skript vorzeitig beenden

Der problematische Teil in dem „Pre-Deployment“ Abschnitt des Skripts zu sein scheint:

for /F %%f in ('git.exe diff --name-only %PREVIOUS_SCM_COMMIT_ID% %SCM_COMMIT_ID% ^| grep package.json') do (
    SET PACKAGEJSON=%%~f 
    SET PKGFOLDER=!DEPLOYMENT_SOURCE!\!PACKAGEJSON:package.json=! 
    echo "NPM Install: !PKGFOLDER!package.json" 
    pushd "!PKGFOLDER!" 
    npm install --production --progress=false --cache-min=432000 
    npm install --save json-loader --progress=false --cache-min=432000 
    IF !ERRORLEVEL! NEQ 0 goto error 
    popd 
) 

Wenn ein package.json nicht zwischen den beiden letzten Commits geändert hat, überspringt das Skript diesen Abschnitt als erwartet und fährt fort, den Abschnitt "Deployment" auszuführen.

Wenn eine package.json geändert wurde, funktioniert der Code zunächst wie erwartet und es werden die npm-Installationen ausgeführt. Danach endet es jedoch ohne einen Fehler und fährt nicht mit dem Deployment-Abschnitt fort. Es gibt keine zusätzliche Ausgabe vom Skript, nachdem die letzte npm-Installation ausgeführt wurde.

Kann mir jemand helfen zu verstehen, was los ist? Das sieht für mich richtig aus.

Das vollständige Skript ist unten, und es ist ein Teil des folgenden Projektes: https://github.com/securityvoid/.deploy

@if "%SCM_TRACE_LEVEL%" NEQ "4" @echo off 
@echo Started: %date% %time% 

:: ---------------------- 
:: KUDU Deployment Script 
:: Version: 1.0.12 
:: ---------------------- 

:: Prerequisites 
:: ------------- 

:: Verify node.js installed 
where node 2>nul >nul 
IF %ERRORLEVEL% NEQ 0 (
    echo Missing node.js executable, please install node.js, if already installed make sure it can be reached from current environment. 
    goto error 
) 

:: Setup 
:: ----- 

setlocal enabledelayedexpansion 

SET ARTIFACTS=%~dp0%..\artifacts 

IF NOT DEFINED DEPLOYMENT_SOURCE (
    SET DEPLOYMENT_SOURCE=%~dp0%. 
) 
echo "Deployment Source: %DEPLOYMENT_SOURCE%" 

IF NOT DEFINED DEPLOYMENT_DIST (
    SET DEPLOYMENT_DIST=%DEPLOYMENT_SOURCE%\dist 
) ELSE (
    ECHO "Deployement Dist already set" 
) 
echo "Deployment Dist: %DEPLOYMENT_DIST%" 

IF NOT DEFINED DEPLOYMENT_TARGET (
    SET DEPLOYMENT_TARGET=%ARTIFACTS%\wwwroot 
) 
echo "Deployment Target: %DEPLOYMENT_TARGET%" 

IF NOT DEFINED NEXT_MANIFEST_PATH (
    SET NEXT_MANIFEST_PATH=%ARTIFACTS%\manifest 

    IF NOT DEFINED PREVIOUS_MANIFEST_PATH (
    SET PREVIOUS_MANIFEST_PATH=%ARTIFACTS%\manifest 
) 
) 

IF NOT DEFINED KUDU_SYNC_CMD (
    :: Install kudu sync 
    echo Installing Kudu Sync 
    call npm install kudusync -g --silent 
    IF !ERRORLEVEL! NEQ 0 goto error 

    :: Locally just running "kuduSync" would also work 
    SET KUDU_SYNC_CMD=%appdata%\npm\kuduSync.cmd 
) 

for /F "tokens=5 delims=.\" %%a in ("%PREVIOUS_MANIFEST_PATH%") do SET PREVIOUS_SCM_COMMIT_ID=%%a 

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 
:: Pre-Deployment 
:: ---------- 
@echo "Initiating Pre-Deployment: %date% %time%" 
@echo "Previous Commit: %PREVIOUS_SCM_COMMIT_ID% Current Commit: %SCM_COMMIT_ID%" 
for /F %%f in ('git.exe diff --name-only %PREVIOUS_SCM_COMMIT_ID% %SCM_COMMIT_ID% ^| grep package.json') do (
    SET PACKAGEJSON=%%~f 
    SET PKGFOLDER=!DEPLOYMENT_SOURCE!\!PACKAGEJSON:package.json=! 
    echo "NPM Install: !PKGFOLDER!package.json" 
    pushd "!PKGFOLDER!" 
    npm install --production --progress=false --cache-min=432000 
    npm install --save json-loader --progress=false --cache-min=432000 
    IF !ERRORLEVEL! NEQ 0 goto error 
    popd 
) 


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 
:: Deployment 
:: ---------- 

@echo "Initiating Deployment: %date% %time%" 

:: 1. Build Script 
node %DEPLOYMENT_SOURCE%\.deploy\deploy.js 

:: 2. KuduSync 
IF /I "%IN_PLACE_DEPLOYMENT%" NEQ "1" (
    call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 50 -f "%DEPLOYMENT_DIST%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd" 
    IF !ERRORLEVEL! NEQ 0 goto error 
) 

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 
goto end 

:: Execute command routine that will echo out when error 
:ExecuteCmd 
setlocal 
set _CMD_=%* 
call %_CMD_% 
if "%ERRORLEVEL%" NEQ "0" echo Failed exitCode=%ERRORLEVEL%, command=%_CMD_% 
exit /b %ERRORLEVEL% 

:error 
endlocal 
echo An error has occurred during web site deployment. 
call :exitSetErrorLevel 
call :exitFromFunction 2>nul 

:exitSetErrorLevel 
exit /b 1 

:exitFromFunction 
() 

:end 
endlocal 
echo Finished successfully. 
+0

Wie lange dauert es bis zum Ende? Ist es immer dasselbe? Befindet sich Ihre App im Verbrauchsmodus oder im App Service Plan-Modus? –

+0

Verbrauchsmodus, und es ist ziemlich schnell. Dauert ungefähr 60-90 Sekunden, um die NPM-Befehle auszuführen. Es ist nicht immer der gleiche genaue Zeitraum. Ich habe auch SCM_COMMAND_IDLE_TIMEOUT auf 900 Sekunden erhöht. – Doug

+0

Nicht sicher, was vor sich geht. Eine Sache zu prüfen ist, ob der Kudu w3wp irgendwie abstürzt. Sie können sich den Kudu-Prozessmanager vorher und nachher ansehen, um zu sehen, ob sich die PID ändert (für den scm-Wert). –

Antwort

4

Die Ursache des Problems ist, dass npm eine Batch-Datei ist. Wenn eine Stapeldatei (Ihre Stapeldatei) eine andere Stapeldatei aufruft, wird der Ausführungsablauf an den aufgerufenen Zweig übergeben, und sobald die Ausführung beendet ist, kehrt der Ausführungsablauf nicht zum Aufrufer zurück. Dieses Verhalten ändert sich, wenn der Aufruf mit dem Befehl call erfolgt.

call npm .... 

Die Ausführungssteuerung wird in die aufgerufene Stapeldatei übertragen, und am Ende kehrt der Ausführungsablauf zum Aufrufer zurück.

Hinweis: Das exponierte Verhalten ist eine Vereinfachung des unverzögerten Prozesses. Batch-Dateien werden in einem Speicher "Kontext" ausgeführt. Ohne den Befehl call ersetzt die aufgerufene Stapeldatei den Aufrufer "context". Mit dem Befehl call wird ein neuer "context" erstellt.

Dies hinterlässt eine andere Frage: Wenn der Aufruf der Charge npm Batch-Dateiübertragung Ausführung fließen und es nicht zurück, warum der zweite npm Befehl ausgeführt wird?

Beim Ausführen einer Batch-Datei (oder Befehlszeilen) werden Code-Blöcke (in Klammern eingeschlossener Code) in den Speicher geladen und als Ganzes analysiert. Ihr for Befehl wird in Arbeitsspeicher platziert und alle Befehle, die in seiner do-Klausel enthalten sind, werden weiter ausgeführt, bis die Schleife beendet wird.

Anmerkung: Nicht relevant in in diesem Fall, aber sobald die ersten npm aufgerufen wurde (ohne call) und der Anrufer Batch „Kontext“ verworfen wurde (durch den gerufenen Kontext ersetzt), der Rest die Befehle in der for Schleife ausgeführt werden in Befehlszeilenkontext und nicht in batch Kontext und als „Kontext“ (sie immer noch im Speicher sind) verworfen wurde, hat die setlocal worden zurückgesetzt und variable Änderungen, Directoy Änderungen und verzögerte Erweiterungen werden verworfen.

+0

Vielen Dank für die tolle Erklärung, das ist wirklich interessant! – Doug

Verwandte Themen