Flag, output e codici di uscita
Queste regole valgono per ogni comando ironflock, e uno script può farci affidamento. La pagina di ciascun comando indica solo ciò che il comando aggiunge.
Una riga di comando ha una di queste due forme:
ironflock <group> <verb> [flags] ironflock agent install -c device.flock
ironflock <verb> [flags] ironflock versionIl gruppo è il prodotto: agent per l’agente del dispositivo, appliance per l’IronFlock Appliance, os per IronFlockOS. Un verbo ha lo stesso significato in ogni gruppo. I comandi che riguardano la macchina nel suo insieme non hanno un gruppo. ironflock e ironflock <group> senza verbo stampano il loro aiuto. Nessun comando accetta argomenti posizionali, salvo dove la sua pagina lo indica; tutto il resto è un flag. login e device sono nomi riservati: rispondono che sono riservati, con il codice di uscita 2.
Flag globali
Ogni comando accetta questi flag. Tutti tranne --help possono stare prima o dopo il nome del comando: ironflock --json version e ironflock version --json sono equivalenti.
| Flag | Significato |
|---|---|
--download-base <url> | URL di base dei download. Predefinito: il cloud IronFlock, https://instance-registry.ironflock.com/dl; per un dispositivo di un IronFlock Appliance, alcuni comandi usano prima il mirror dell’Appliance. Vedi Base di download. |
--host [user@]machine | Esegue il comando su quella macchina via SSH invece che qui. Indicalo più volte per più macchine. Vedi Macchine remote via SSH. |
--hosts <file> | Esegue il comando su ogni macchina indicata nel file, un [user@]machine per riga. Vedi Il file degli host. |
--parallel <n> | Elabora al massimo n macchine di --host e --hosts contemporaneamente. Predefinito 10, da 1 a 100. |
--json | Scrive il risultato su stdout come un unico oggetto JSON e non chiede nulla. |
--yes | Risponde sì alla domanda del comando. Non annulla mai un rifiuto. |
-h, --help | Stampa l’aiuto del comando. |
Flag con nomi fissi
Il nome di un flag ha lo stesso significato in ogni comando che lo prevede. -c e -d sono gli unici flag brevi oltre a -h.
| Flag | Significato | Comandi |
|---|---|---|
-c, --config <file> | il file .flock del dispositivo | agent install, agent configure, doctor, os flash, os install, os reset |
-d, --drive <drive> | l’unità su cui scrive un comando | os flash |
--disk <disk> | il disco da cui si è avviato il sistema in esecuzione, che il comando sostituisce | os install |
--output <file> | il file che un comando scrive al posto di un’unità | os flash |
--http-proxy, --https-proxy, --no-proxy | il proxy aziendale | agent install, agent configure, os install |
--proxy-password-file <file> | un file o una pipe la cui unica riga è la password dell’utente indicato negli URL del proxy | agent install, agent configure, os install |
Base di download e proxy
La base di download viene da --download-base, poi dalla variabile d’ambiente IRONFLOCK_DL_BASE, altrimenti è https://instance-registry.ironflock.com/dl. Senza nessuno dei due, agent install, doctor, os install e os update usano, prima del cloud, il mirror di download dell’Appliance indicato dal file .flock del dispositivo (Dispositivi di un IronFlock Appliance).
Il proxy viene dai flag, poi da HTTP_PROXY, HTTPS_PROXY e NO_PROXY (o dalle loro forme in minuscolo). agent configure fa eccezione: modifica il proxy del dispositivo solo con i propri flag, e l’ambiente del comando lì non cambia nulla. Un URL di proxy ha la forma http://proxy.example.com:3128; funzionano anche https:// e socks5://, e un URL senza schema vale come http://. Quando il proxy richiede un login, l’URL indica l’utente, come in http://[email protected]:3128, e --proxy-password-file fornisce la password (vedi Segreti). Per i dispositivi dietro un proxy, vedi Dietro un Proxy Aziendale.
Output e JSON
stdout contiene il risultato e nient’altro. Si tratta di un breve testo per una persona oppure, con --json, esattamente un oggetto JSON su una riga. Anche --help va su stdout. L’unica eccezione è agent logs, il cui risultato è il log: con --json scrive un oggetto JSON per ogni riga del log.
stderr contiene tutto il resto: avanzamento, output degli strumenti che un comando esegue (apt, l’installer di Docker), avvisi, domande ed errori.
Così un reindirizzamento o una sostituzione di comando ottiene solo il risultato, e uno script che non vuole messaggi reindirizza stderr:
# Il risultato come testo in un file; avanzamento e avvisi restano visibili sul terminale
ironflock status > result.txt
# Il risultato come JSON in una variabile della shell, senza i messaggi su stderr
result=$(ironflock status --json 2>/dev/null)I nomi dei campi JSON sono in snake_case. Un risultato ha il campo action quando il comando ha modificato qualcosa, ad esempio "installed", "configured" o "removed". Nel tempo si aggiungono campi, e nessuno viene rinominato o rimosso all’interno di una versione major. Un programma che legge un risultato ignora i campi che non conosce. Con più macchine, --json scrive invece una riga per macchina (vedi Macchine remote via SSH).
Avanzamento
Un passo lungo mostra su stderr a che punto è: una barra su un terminale, altrimenti una riga a ogni 10%. Con --json, stdout riceve comunque esattamente un oggetto JSON, il risultato, e stderr riceve l’avanzamento come eventi, un oggetto JSON per riga:
{"event":"progress","phase":"writing","done":104857600,"total":412345678}| Campo | Significato |
|---|---|
event | progress |
phase | downloading: download di un file immagine o di una release; checking: verifica del suo SHA-256 rispetto al catalogo; preparing: preparazione della scrittura di os install dall’immagine; writing: scrittura sull’unità (o nel file di --output); verifying: verifica dell’unità (o del file) tramite rilettura; installing: installazione di una release nell’altro slot (os update) |
done, total | Byte: del file immagine per downloading, checking, preparing e writing, dell’immagine scritta per verifying. Per installing, percentuale: total è 100. |
os install legge il file immagine due volte prima del riavvio: checking confronta il suo SHA-256 con il catalogo firmato, e preparing decomprime l’immagine una volta per trovarne la partizione IRONFLOCKOS, inserirvi il file .flock del dispositivo e le impostazioni di rete, e calcolare i checksum di ciò che la scrittura mette sul disco. Su un terminale compaiono come Checking e Preparing.
Un evento arriva quando una fase inizia (done è 0), ogni volta che cambia la percentuale intera e quando la fase è completa (done è uguale a total). Un download che riprende salta ai byte che ha già. Le altre righe su stderr, tra cui gli avvisi, sono testo per una persona: un programma prende le righe che si possono interpretare come oggetti JSON e ignora le altre.
Domande e conferma
Un comando che modifica la macchina dice prima cosa farà, poi chiede:
- Un comando che rimuove o sovrascrive qualcosa dice prima cosa va perso. Un comando che installa dice prima cosa installerà.
agent stopdice prima che cosa si interrompe quando l’agente si arresta. --yesrisponde sì a ogni domanda del comando e sceglie il valore predefinito dove il comando offre una scelta.- Al terminale, una domanda ha «Yes» preselezionato, quindi basta premere Invio per proseguire. Tre domande hanno «No» preselezionato, quindi Invio da solo non cancella e non rimuove nulla:
os flashprima di cancellare un’unità,os flashprima di sostituire il file di--output, eagent remove. os resetti chiede di digitare il nome del dispositivo, eos installil nome host della macchina. Qualsiasi altra cosa, anche Invio da solo, vale come no.- Ciò che hai digitato prima che comparisse una domanda viene scartato. Si risponde a una domanda dopo aver letto ciò che il comando dice.
- Esc risponde no: il comando non modifica nulla e termina con il codice di uscita 4. Ctrl-C a una domanda non dà alcuna risposta, nemmeno quella preselezionata: il comando non modifica nulla e termina con il codice di uscita 130.
Una domanda richiede un terminale sia su stdin sia su stderr. Senza terminale (una pipe, la CI, uno script cloud-init), il comando non attende e non tira a indovinare: termina con il codice di uscita 4 e dice che --yes conferma. Lo stesso vale con --json, che non chiede nulla. Per questo gli script indicano --yes insieme a --json.
--yes non annulla mai un rifiuto. Quando un comando rifiuta (codice di uscita 3, o un controllo fallito), nessun flag lo fa proseguire. La pagina di ciascun comando elenca ciò che rifiuta. L’unica eccezione è un disco interno, che os flash --allow-internal scrive quando --drive lo indica.
Con --host, le domande ti raggiungono quando esegui il comando a un terminale. Su più macchine contemporaneamente non viene chiesto nulla a nessuno, quindi un comando che pone domande viene eseguito lì solo con --yes (vedi Macchine remote via SSH).
Privilegi di root
Un comando che modifica il sistema richiede root. Senza root termina con il codice di uscita 3 e lo dice. Non chiama sudo da solo; lo fa solo --host, sull’altra macchina. In quel caso os flash indica la riga di comando da digitare, con sudo davanti.
| Comandi | Root |
|---|---|
version, completion, os images, os drives, ogni --help | non necessario |
status, doctor | non necessario. Senza root, status indica unknown (needs root) per ciò che non riesce a leggere, e doctor segna questi controlli come skipped. Con sudo leggono anche questo. |
agent install, agent configure, agent update, agent remove, agent restart, agent stop, agent start | necessario |
agent logs | necessario: legge soltanto, ma ciò che legge è accessibile solo a root |
os flash | necessario per scrivere un’unità. Non necessario con --output. Su macOS, un utente che può scrivere sul dispositivo raw dell’unità non ha bisogno di root. |
os install, os update, os rollback, os reset | necessario |
self-update | accesso in scrittura alla cartella del binario, ed essere il proprietario del binario e membro del suo gruppo, oppure root. Per /usr/local/bin/ironflock significa root |
Con --host, un comando che richiede root viene eseguito tramite sudo sull’altra macchina quando l’utente di login non è root.
Segreti
Nessun comando stampa un segreto: né il segreto di un file .flock, né una passphrase WiFi, né una password del proxy, né una chiave di licenza. Questo vale per stdout, stderr, --json e i messaggi di errore.
Un segreto non è mai il valore di un flag quando può contenerlo un file, perché le righe di comando compaiono in ps e nella cronologia della shell. Una password del proxy non fa eccezione:
- Un URL di proxy in un flag indica l’utente senza la password:
http://[email protected]:3128. - Un URL con password, come
http://user:password@proxy:3128, è una riga di comando errata (codice di uscita 2). Viene rifiutato prima che venga eseguito qualsiasi cosa, e con--hostprima che arrivi alla macchina. L’errore non lo ripete. - La password viene da
--proxy-password-file: un file, o una pipe (/dev/stdin), di una sola riga. - Le variabili proxy dell’ambiente, a cui
agent installricorre in mancanza dei flag, possono contenere una password: non compaiono su una riga di comando.
# La password da un file
sudo ironflock agent configure --https-proxy http://[email protected]:3128 --proxy-password-file proxy-password.txt
# La password tramite una pipe
sudo ironflock agent configure --proxy-password-file /dev/stdin --yes < proxy-password.txtSu un dispositivo configurato da agent install, la password del proxy si trova dove solo root può leggerla: in /etc/ironflock/proxy.env (modo 0600). I drop-in di docker.service e di ironflock-device-agent.service indicano quel file e non contengono impostazioni del proxy, quindi systemctl show rivela a ogni utente il nome del file e nulla del suo contenuto.
Con --host, un file .flock, un file con la passphrase WiFi o un file con la password del proxy indicato in un flag arriva all’altra macchina tramite la connessione SSH, mai su una riga di comando (vedi Macchine remote via SSH). Una base di download che contiene credenziali di login termina con il codice di uscita 2 prima che venga raggiunta qualsiasi macchina.
Codici di uscita
| Codice | Tipo | Significato |
|---|---|---|
| 0 | completato | |
| 1 | failed | il comando è partito e non è riuscito a terminare |
| 2 | usage | la riga di comando è errata: un comando o un flag sconosciuto, un flag mancante, un nome riservato. Non è stato toccato nulla. |
| 3 | precondition | la macchina non è nello stato richiesto dal comando: non root, nessun agente installato, un agente già installato, un sistema su cui il comando non funziona. Non è stato toccato nulla. |
| 4 | declined | alla domanda è stato risposto no, oppure non è stato possibile porla e --yes non era indicato |
| 130 | interrupted | interrotto (Ctrl-C) prima che il comando terminasse; con --host anche un comando sull’altra macchina terminato per un hangup, un’interruzione o un segnale di terminazione |
| 255 | ssh | la connessione SSH di --host non è riuscita: la macchina non è stata raggiunta, o la connessione si è interrotta |
Un errore è una riga su stderr, Error: seguito dal messaggio. Un errore di utilizzo è seguito da una riga che indica il --help da leggere. Con --json l’errore è il risultato: stdout riceve un oggetto errore, e stderr non riceve alcuna riga di errore. kind è uno dei tipi della tabella.
{"error":{"kind":"precondition","message":"the agent is not installed on this machine"}}Due comandi scrivono il loro risultato e terminano comunque con il codice di uscita 1. agent update lo fa quando l’agente resta alla sua versione: il risultato dice perché, e stderr riceve la riga Error:. doctor lo fa quando un controllo è fallito: il risultato dice quale, e non segue alcuna riga di errore. Con --json, in questi casi nessuno dei due scrive un oggetto errore: stdout contiene il risultato.
Con --help, un comando sconosciuto non è un errore: ironflock os nosuch --help stampa l’aiuto di ironflock os, con il codice di uscita 0. Su più macchine, il comando termina con il codice di uscita peggiore tra quelli delle macchine (vedi Macchine remote via SSH).
Interruzioni
Ctrl-C, SIGTERM e SIGHUP (quando il terminale o la sessione SSH scompare) terminano subito la maggior parte dei comandi, come terminano qualsiasi programma, senza una riga di errore; la shell vede 130 (143 dopo SIGTERM, 129 dopo SIGHUP). Alcuni passi li gestiscono:
os flashmentre scarica, scrive o rilegge un’immagine, eos updatementre scarica e verifica un bundle, si fermano al blocco successivo. Dicono cosa hanno lasciato, come errore di tipointerrupted, e terminano con 130; in questo casoos updatenon installa nulla. Quandoos flashha riletto l’ultimo blocco, completa i passi finali e termina con 0. Un secondo Ctrl-C termina subito il processo; con--outputpuò restare il file.part.agent logs --followsegue il log fino a un segnale di questo tipo, poi termina con 0.agent updatesmette di seguire l’aggiornamento con 130; l’agente prosegue da solo.os reset, mentre scrive la sua richiesta, la ritira, termina con 130 e il dispositivo non si riavvia.agent configure, una volta iniziata la modifica della macchina, non si ferma più per un terminale o una sessione SSH persi. Ctrl-C e SIGTERM lo terminano comunque subito.os installsi comporta diversamente prima e dopo la sua domanda; vediironflock os install.
Codici di uscita in uno script
Uno script indica --yes affinché il comando non si fermi alla sua domanda, --json per un risultato leggibile, e controlla il codice di uscita:
#!/bin/sh
# Fa aggiornare l'agente da solo; conserva il risultato JSON, scarta l'avanzamento su stderr.
result=$(sudo ironflock agent update --yes --json 2>/dev/null)
code=$?
case $code in
0) echo "agent is current: $result" ;;
1) echo "agent update failed: $result" ;;
3) echo "agent update refused on this machine: $result" ;;
*) echo "agent update ended with exit code $code: $result" ;;
esacCon il codice di uscita 0, $result contiene il risultato, il cui outcome è updated o current. Con il codice di uscita 1, contiene il risultato, il cui outcome e reason dicono perché l’agente resta alla sua versione, oppure un oggetto errore. Con il codice di uscita 3, contiene l’oggetto errore.