2011-03-02 9 views
14

Sto sviluppando un'appliance basata su Linux utilizzando un alix 2d13.Firmware basato su Linux, come implementare un buon metodo di aggiornamento?

Ho sviluppato uno script che si occupa della creazione di un file immagine, della creazione delle partizioni, dell'installazione del boot loader (syslinux), del kernel e dell'initrd e, che si occupa di mettere i file del filesystem di root nella partizione corretta .

I file di configurazione sono sul filesystem tmpfs e vengono creati all'avvio del sistema da un software che legge un file XML che risiede su una propria partizione.

che sto cercando un modo per aggiornare il file system e ho considerato due soluzioni:

  • l'aggiornamento del firmware è un file compresso che potrebbe contenere il kernel, initrd e/o la partizione rootfs, in questo modo, al riavvio, initrd si prenderà cura di dd l'immagine rootfs nella partizione corretta;
  • l'aggiornamento del firmware è un file compresso che può contenere due archivi tar, uno per l'avvio e uno per il filesystem di root.

Ogni soluzione ha i suoi vantaggi: - un'immagine del filesystem mi permette di eliminare tutti i file inutilizzati, ma ha bisogno di un sacco di tempo e ucciderà la memoria compact flash velocemente; - un archivio è più piccolo, ha bisogno di meno tempo per l'aggiornamento, ma avrò il caos sul filesystem di root in breve tempo.

Una soluzione alternativa potrebbe essere quella di inserire un elenco di file e di inserire uno script pre/post update nell'archivio tar, in modo tale che qualsiasi file che non risiede nell'elenco dei file verrà eliminato.

Cosa ne pensi?

risposta

16

Ho utilizzato il seguente approccio. Era in qualche modo basato sul documento "Sistemi Linux embedded compatibili con la costruzione Murphy", disponibile here. Ho usato la versione versions.conf descritta in quella carta, non la roba di cfgsh.

  • Utilizzare un kernel di avvio il cui compito è eseguire il loopback del sistema di file radice "principale". Se hai bisogno di un kernel più recente, esegui kexec nel kernel più recente subito dopo averlo riavviato. Ho scelto di mettere l'init completo del kernel di avvio in initramfs, insieme a busybox e kexec (entrambi collegati staticamente), e il mio init era un semplice script di shell che ho scritto.
  • Uno o più file system di root "main OS" esistono in un file system "Immagine OS" come file immagine disco. Il kernel di avvio sceglie uno di questi basato su un file versions.conf. Mantengo solo due file immagine principali del sistema operativo, il file corrente e quello di fallback. Se quello corrente fallisce (più tardi sul rilevamento degli errori), il kernel di avvio avvia il fallback. Se entrambi falliscono o non c'è fall-back, il kernel di avvio fornisce una shell.
  • La configurazione del sistema si trova su una partizione separata. Normalmente non è aggiornato, ma non c'è motivo per cui non possa essere.
  • Esistono quattro partizioni totali: avvio, immagine del sistema operativo, configurazione e dati. La partizione dati è per le applicazioni utente destinate alla scrittura frequente. boot non viene mai montato leggere/scrivere. L'immagine del SO è solo (ri) montata in lettura/scrittura durante gli aggiornamenti. config è montato solo in lettura/scrittura quando le cose di configurazione devono cambiare (si spera mai). i dati sono sempre montati in lettura/scrittura.
  • I file di immagine del disco contengono ciascuno un sistema Linux completo, inclusi un kernel, script di init, programmi utente (ad esempio busybox, applicazioni di prodotto) e una configurazione predefinita copiata nella partizione di configurazione al primo avvio. I file sono di qualsiasi dimensione necessaria per adattarsi a qualsiasi cosa al loro interno. Per quanto tempo ho lasciato spazio sufficiente per la crescita in modo che la partizione dell'immagine del sistema operativo sia sempre abbastanza grande da contenere tre file immagine principali del sistema operativo (durante un aggiornamento, non elimino il vecchio fallback fino a quando non viene estratto il nuovo), posso consentire all'immagine del sistema operativo principale di crescere secondo le necessità. Questi file di immagine sono sempre (loop-back) montati in sola lettura. L'utilizzo di questi file elimina anche il problema di gestire i problemi di aggiornamento dei singoli file all'interno di un rootfs.
  • Gli aggiornamenti vengono effettuati trasferendo un tarball autoestraente in un tmpfs. L'inizio di questo script rimonta l'immagine del sistema operativo in lettura/scrittura, quindi estrae la nuova immagine del sistema operativo principale nel file system dell'immagine del sistema operativo, quindi aggiorna il file versions.conf (utilizzando il metodo di rinomina descritto nel documento "murphy"). Al termine, tocco un file di timbro che indica che è stato eseguito un aggiornamento, quindi riavvia.
  • Il kernel di avvio cerca questo file di francobolli. Se lo trova, lo sposta in un altro file di timbro, quindi avvia il nuovo file di immagine del sistema operativo principale. Si prevede che il file di immagine del sistema operativo principale rimuova il file del timbro quando viene avviato correttamente. In caso contrario, il watchdog attiverà il riavvio, quindi il kernel di avvio lo vedrà e rileverà un errore.
  • Si noterà che ci sono alcuni possibili punti di errore durante un aggiornamento: sincronizzazione di versions.conf durante l'aggiornamento e spostamento/rimozione dei file di timbri (tre istanze). Non sono riuscito a trovare un modo per ridurli ulteriormente e ottenere tutto ciò che volevo. Se qualcuno ha un suggerimento migliore, mi piacerebbe sentirlo. Potrebbero verificarsi anche errori del file system o interruzioni dell'alimentazione durante la scrittura dell'immagine del sistema operativo, ma spero che il file system ext3 fornisca alcune possibilità di sopravvivere in quel caso.
+1

mi piace molto la tua soluzione, alla fine ho fatto qualcosa di molto simile ma senza rilevamento errori di avvio, ma penso che implementerò qualcosa di simile: - riserverò un settore per la scrittura del rilevamento errori di avvio utilizzando le operazioni dirette io e sincronizzazione - il kernel di avvio avvierà un initrd che segnalerà un tentativo di avvio, con timestamp e montare l'immagine os - durante il processo di avvio, il nuovo initrd riporterà, passo dopo passo con i timestamp, le fasi di avvio per identificare i problemi - alla fine segnalerà nel settore di rilevamento degli errori di avvio "tutto fatto" –

+0

Per l'aggiornamento preferisco scaricare il tarball in la partizione dati e, al riavvio, se il primo initrd rileva il tarball di aggiornamento, gestirà il tarball (potrebbe essere tu Seful aggiunge due file speciali per identificare i file da eliminare e per eseguire uno script di aggiornamento). Dopo l'aggiornamento, il primo initrd eseguirà kexec nel nuovo kernel, riportando l'avvio come aggiornamento (in modo che il tarball possa essere eliminato). Il tarball, per motivi di sicurezza, deve essere firmato con una chiave privata. Per segnalare errori potrebbe utilizzare il precedente settore del disco (rilevamento errori di avvio), è sufficiente eseguire la sincronizzazione di scrittura per evitare problemi –

+0

Mi piace l'idea del "settore stato". Almeno sposta alcuni dei punti di errore in una singola posizione del disco, e se quel settore fallisce, si potrebbe probabilmente avere settori di riserva e si potrebbe tentare un ripristino, o almeno offrire una "modalità di ripristino." – Patrick

0

È possibile formattare rapidamente le partizioni prima di estrarre i file tar. Oppure vai con la soluzione immagine ma usa l'immagine più piccola possibile e dopo dd fai un ridimensionamento del filesystem (anche se non è necessario per l'archiviazione di sola lettura)

+0

mmm, se faccio un dd non ho davvero bisogno di fare un ridimensionamento perché il file system dovrebbe sapere che è la dimensione ... quello che davvero avrei bisogno è di ridimensionare la partizione in MB. In ogni caso posso evitare di ridimensionare la partizione più grande (in realtà ho bisogno di meno di 30mb quindi una partizione da 64 MB andrebbe bene). Vado per il + tar + pre/post script di aggiornamento + soluzione elenco file probabilmente –

2

Puoi avere una partizione separata per l'aggiornamento (dire Side1/Side2). Il kernel esistente, rootfs è in Side1, quindi inserire l'aggiornamento in Side2 e passare. Grazie a ciò è possibile ridurre il livellamento dell'usura e aumentare la vita ma il dispositivo diventa più costoso.

Problemi correlati