2012-08-04 22 views
7

Ho un numero di attività di avvio in file batch. In particolare, chiamo IIS appcmd.exe per configurare IIS. Le attività di avvio in Azure dovrebbero idivotent (cioè essere in grado di essere eseguite ripetutamente con gli stessi risultati), nel caso in cui il ruolo venga riavviato per qualche motivo. Sfortunatamente molti dei miei comandi di configurazione IIS falliranno la seconda volta, ad esempio perché eliminano un nodo di configurazione la prima volta che non è presente nelle esecuzioni successive.Come rendere identienti le attività di avvio?

La mia domanda è, come posso rendere queste attività di avvio idempotenti? C'è un modo per rendere appcmd.exe non generare errori? C'è un modo per far sì che la shell catturi gli errori? C'è un modo per far sì che il framework di Azure ignori gli errori?

Ecco un esempio delle mie attività di avvio. Tutto ciò è contenuto in un file di comando, configiis.cmd.

@REM Enable IIS compression for application/json MIME type 
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/json',enabled='True']" /commit:apphost 
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/json; charset=utf-8',enabled='True']" /commit:apphost 

@REM Set IIS to automatically start AppPools 
%windir%\system32\inetsrv\appcmd.exe set config -section:applicationPools -applicationPoolDefaults.startMode:AlwaysRunning /commit:apphost 

@REM Set IIS to not shut down idle AppPools 
%windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00 /commit:apphost 

@REM But don't automatically start the AppPools that we don't use, and do shut them down when idle 
%windir%\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/applicationPools "/[name='Classic .NET AppPool'].startMode:OnDemand" "/[name='Classic .NET AppPool'].autoStart:False" "/[name='Classic .NET AppPool'].processModel.idleTimeout:00:01:00" /commit:apphost 
%windir%\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/applicationPools "/[name='ASP.NET v4.0'].startMode:OnDemand" "/[name='ASP.NET v4.0'].autoStart:False" "/[name='ASP.NET v4.0'].processModel.idleTimeout:00:01:00" /commit:apphost 
%windir%\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/applicationPools "/[name='ASP.NET v4.0 Classic'].startMode:OnDemand" "/[name='ASP.NET v4.0 Classic'].autoStart:False" "/[name='ASP.NET v4.0 Classic'].processModel.idleTimeout:00:01:00" /commit:apphost 


@REM remove IIS response headers 
%windir%\system32\inetsrv\appcmd.exe set config /section:httpProtocol /-customHeaders.[name='X-Powered-By'] 
+0

Abbastanza sicuro che le linee che dovrebbero impedire l'avvio automatico di AppPools inutilizzati non funzioneranno. Invece di utilizzare "Classic .NET AppPool" ecc. Come nome da utilizzare, Clr2ClassicAppPool, ecc. –

+0

In realtà quei nomi funzionano bene, ma ha bisogno di essere citati in modo leggermente diverso. Ho aggiornato il codice sopra, nel caso in cui qualcuno lo guardi più tardi. –

risposta

4

Oltre alla risposta di @ Syntaxc4: Considerare l'utilizzo di un breadcrumb (file) localmente. Nel tuo script, controlla la presenza di un file conosciuto (che crei). Se non esiste, passa allo script di avvio, creando anche un file breadcrumb. La prossima volta che il vm si avvia, controlla nuovamente l'esistenza del file breadcrumb e, se esiste, esce dal file cmd. Se il file breadcrumb scompare, ciò significa che il tuo vm è stato ricostituito da qualche altra parte (una nuova istanza o un'istanza rigenerata potrebbe essere su hardware diverso) e sarebbe necessaria la configurazione di IIS.

+0

Sembra una buona idea. Qualche idea su come implementarlo in uno script .cmd? Sono sicuro di poterlo scoprire alla fine, ma sembra che tu abbia già fatto qualcosa di simile prima. –

+0

Nel caso qualcuno lo legga in futuro, ho aggiunto il codice per implementarlo in un'altra risposta. –

3

Si dovrà verificare se l'impostazione di configurazione è presente prima di tentare di eliminarlo (aggiungere logica condizionale). Ciò potrebbe essere realizzato:

'appcmd.exe Lista config -Dettagli'

Catturare un valore di ritorno darebbe qualcosa da confrontare con, sia che si tratti di lunghezza di uscita o di un valore reale.

2

Sulla base del suggerimento di David Makogon, ho aggiunto quanto segue all'inizio di ciascuno dei miei file .cmd. Questo sembra fare il trucco. Creerà un file di flag (quello che David ha chiamato un file breadcrumb) nella stessa directory dello script in esecuzione, quindi verificarlo nelle esecuzioni successive.

@REM A file to flag that this script has already run 
@REM because if we run it twice, it errors out and prevents the Azure role from starting properly 
@REM %~n0 expands to the name of the currently executing file, without the extension 
SET FLAGFILE=c:\%~n0-flag.txt 

IF EXIST "%FLAGFILE%" (
    ECHO %FLAGFILE% exists, exiting startup script 
    exit /B 
) ELSE (
    date /t > %FLAGFILE% 
) 
+0

Dovresti inserire anche il '% ComputerName%' nel nome del file flag! .. Sarebbe utile! – wasatchwizard

+0

Perché sarebbe utile? –

3

MSDN contiene ora un'eccellente guida per farlo gestendo i codici di errore da APPCMD.

http://msdn.microsoft.com/en-us/library/windowsazure/hh974418.aspx

In pratica dopo ogni operazione appcmd, è possibile effettuare le seguenti operazioni:

IF %ERRORLEVEL% EQU 183 DO VERIFY > NUL 

e ignorare qualsiasi codice di errore accettabile.

+0

Molto bello. Sembra che potrebbe essere il modo "giusto" per farlo. Peccato che la gestione degli errori sia così prolissa. –

+1

Sembra un errore nell'articolo MSDN - "DO" è eccessivo poiché la sintassi per il comando "IF" è: 'IF [/ I] stringa1 comando compar-par string2'. E la parola chiave DO si applica solo al comando 'FOR'. Quindi il comando corretto dovrebbe essere simile a: 'IF% ERRORLEVEL% EQU 183 VERIFY> NUL'. Questo ha funzionato per me mentre l'originale interrompeva il copione impedendogli di iniziare il ruolo. – Vertigo

0

Si consiglia vivamente di utilizzare /config:* /xml alla fine del comando list. Per ulteriori informazioni su come ho creato idispositivo, consultare: https://github.com/opscode-cookbooks/iis

Chef è una delle molteplici piattaforme di gestione della configurazione e sto solo suggerendo di guardarlo per il codice (in ruby) che fa idempotente elencando le impostazioni correnti e confrontandoli con le impostazioni richieste per cambiare.