L' AUTOEXEC.BAT del nuovo millennio: gli Startup Tasks di Windows Azure

Chi, come me, è nato nell’era dell’ AUTOEXEC.BAT e CONFIG.SYS e si divertiva un mondo con l’uso dei GOTO , delle variabili d’ambiente, nella configurazione di schede (SoundBlaster), mouse, programmi e programmini vari (vi ricordate I TSR, come il mitico l’ NC – Norton Commander ?? ) e cercava di spremere fino all’inverosimile l’ottimizzazione della memoria (LOADHIGH/LH,EMM386,...), allora troverà nei nuovi Startup-Tasks di Windows Azure un piacevole dejà-vù…

Infatti con il nuovo SDK 1.3 di Windows Azure sono stati introdotti (anche)gli Startup-Task che semplicemente permettono di eseguire del codice durante l’inizializzazione dell’istanza di un ruolo (Web role e Worker role).

Certo dopo 30 anni, il nuovo autoexec.bat (che per la cronaca NON si chiama veramente così ma startup task ;-)) si presenta in una forma più moderna ed attuale. Infatti, la struttura degli startup-task è definita tramite uno uno schema XML (cos’altro altrimenti? J) presente all’interno del file ServiceDefinition.csdef:

<Startup priority="">

      <Task commandLine="<command-to=execute>"

         executionContext="[limited|elevated]"

  taskType="[simple|foreground|background]">

        <Environment>

          <Variable name="<variable-name>"

  value="<variable-value>"/>

        </Environment>

      </Task>

    </Startup>

L’elemento Startup, opzionale ed univoco, descrive una collezione di tasks che vengono eseguiti all’avvio dell’istanza del role. Normalmente questi task permettono di creare una configurazione iniziale, lanciare vari tipi di script, incluso powershell, ed installare del nuovo software. 

 

Tralasciando l’attributo priority che è ad uso interno di Windows Azure, l’elemento Task rappresenta i singoli task attivabili mentre i suoi attributi hanno il seguente significato: commandline (obbligatorio) specifica il file da eseguire, executionContext (obbligatorio) definisce il livello di sicurezza con cui lo script deve girare esprimibile tramite limited, ovvero come standard user oppure elevated con privilegi amministrativi NT AUTHORITY\SYSTEM, quindi, mi raccomando, da usare con estrema cautela perchè più potente anche di Administrator!

L’attributo taskType (obbligatorio) rappresenta il comportamento del task rispetto a tutto il role. Infatti con simple, che è il default, il sistema aspetta che il task abbia terminato l’esecuzione prima di lanciare quelli successivi mentre con background il sistema non aspetta la fine del task corrente. Infine, foreground, è molto simile a background tranne nel caso di restart del role che non avverrà fino a quando tutti i foreground task non verranno terminati.

A questo punto è necessaria una precisazione importante sull’uso del taskType: poichè simple è il deafult e blocca tutte le attività del role fino al suo termine bisogna prestare mooolta attenzione nel caso in cui il comando del task vada in loop per qualche motivo. Infatti, in questo scenario anche la semplice connessione Remote Desktop per capire cosa succede non sarebbe disponibile perchè si attiva dopo gli Startup Tasks! Quindi, per debuggare questo scenario è necessario impostare il valore di taskType a background (maggiori info al paragrafo sul troubleshooting).

L’elemento Environment non è specifico dell’elemento Startup e rappresenta una collezione di variabili d’ambiente che ogni istanza renderà disponibile ai programmi.

Quindi, ad esempio, questo semplice codice XML ci permetterà di eseguire tutto il contenuto presente in mystartup.cmd:

<Startup>

  <Task commandLine="mystartup.cmd" executionContext="elevated" />

</Startup>

Come ultima nota, ricordo di impostare sempre il proprio file di startup all’interno del progetto in Visual Studio come “Copy to Output Directory” per assicurarsi che il batch file venga copiato nella cartella bin del ruolo su Windows Azure.

 

Eseguire codice ASP in un Web Role

Come descrive Steve Marx nel suo blog gli startup tasks possono essere usati per abilitare scenari che prima della versione 1.3 dell’ SDK erano di difficile attuazione come ad esempio abilitare l’engine ASP su alcune istanze di Web Role.

Infatti, se nel nostro esempio di prima, definiamo il nostro mystartup.cmd con il seguente contenuto: start /w pkgmgr /iu:IIS-ASP ecco che il nostro Web Role sarà in grado di eseguire un’applicazione ASP come questa:

Un po' di Troubleshooting

Come si fa debugging di uno startup task? Beh, diciamo che oltre ad alcune tecniche attuali (vedi quella del tasktype descritta prima) essendo un .cmd o .bat sono ancora valide molte di quelle tecniche che si usavano nel millennio passato come ad esempio il logging su file con append (>>), redirezione su file (in questo caso log.txt) ed eventuale intercettazione di tutti gli errori ritornati da Windows su un file separato(2>>error.txt):

D:
cd windows >>log.txt 2>>error.txt
dir >>log.txt 2>>error.txt

Attenzione alle trappole però! Il seguente, all’apparenza innocuo, comando di cancellazione farà bloccare inesorabilmente il nostro Startup Task:

del *.* >>a.txt

infatti, alla richiesta di cancellazione, il sistema chiederà una conferma alla quale non potremo mai rispondere! Di conseguenza avremo un blocco del task che se girerà con taskType impostato a Simple renderà la nostra istanza pending senza speranza! Per queste attività sarà necessario automatizzare la risposta al comando con echo e pipe (|)

echo Y|del *.* >>c:\temp\a.txt 2>>c:\temp\e.txt

Il debug può essere fatto in locale simulando dei breakpoint inserendo dopo ogni comando start /w cmd(come descritto sempre da Steve nel suo post dedicato ai trucchetti degli Startup Tasks) oppure tramite redirection dell’output per poi analizzarlo o via RDP (Remote Desktop) oppure copiando i log files sul blob storage di Windows Azure.

Per chi volesse ripassare o studiare per la prima volta il curioso mondo dei batch files può dare un’occhiata a questo sito che ho trovato molto interessante.

Che dire... ringrazio il team di Windows Azure per avermi dato l’occasione per un piacevole ritorno alla mia prima giovinezza...

--Mario