Salta al contenuto principale

fdisk: vedere e modificare le partizioni di un disco

Inviato da tuxsa il

Un disco nuovo non serve a niente finché non lo si divide in partizioni: una per il sistema, una per i dati, magari una di swap. Un disco già in uso può avere bisogno di una partizione in più, o di capire come è fatto prima di intervenire. Lo strumento classico per tutto questo è fdisk: si usa a riga di comando, in modo interattivo, ed è presente praticamente ovunque.

Cos'è

fdisk (fixed disk) fa parte del pacchetto util-linux, lo stesso di lsblk, mount e lscpu (su Ubuntu recente il programma sta nel pacchetto separato fdisk, che comprende anche sfdisk e cfdisk; se manca, sudo apt install fdisk: vedi l'articolo su apt). Lavora sulla tabella delle partizioni, cioè l'elenco, scritto all'inizio del disco, che dice dove comincia e dove finisce ogni partizione e di che tipo è. Conosce i due formati più diffusi: MBR (chiamato anche DOS, il vecchio formato) e GPT (il formato moderno, richiesto dall'UEFI e necessario per i dischi sopra i 2 TiB).

Cosa fa

Mostra le partizioni di un disco, ne crea di nuove, le elimina, ne cambia il tipo e scrive la tabella sul disco. Non crea il file system: una partizione appena creata è uno spazio vuoto, che si prepara poi con mkfs (vedi mount e lsblk per la parte successiva). Le modifiche restano in memoria finché non si dà il comando di scrittura: è una rete di sicurezza importante.

Come si usa

$ sudo fdisk -l [disco]
$ sudo fdisk disco

Come ho fatto le prove. Nella macchina virtuale di prova il sistema non permette di toccare i dischi (anche come amministratore dà Permission denied o Operation not permitted), ma fdisk funziona benissimo anche su un file immagine: un normale file che si comporta come un disco. Ho quindi creato un file da 2 GiB (truncate -s 2G disco.img, che non occupa spazio finché non si scrive) e ci ho lavorato come su un disco vero. Gli output che vedi con disco.img sono perciò reali (fdisk 2.39.3), con gli identificativi generati lì; i nomi come /dev/sda sono quelli che vedresti su web01, il server degli articoli precedenti. È anche un ottimo modo per fare pratica senza rischi: prova tutto su un file immagine, prima di toccare un disco vero.

Esempio 1: elencare le partizioni

$ sudo fdisk -l /dev/sda
$ sudo fdisk -l
$ fdisk -l disco.img
Disk disco.img: 2 GiB, 2147483648 bytes, 4194304 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 07876C22-41D1-471D-8D64-CDBBA506E00E

Device       Start     End Sectors  Size Type
disco.img1    2048 1050623 1048576  512M EFI System
disco.img2 1050624 3147775 2097152    1G Linux swap
disco.img3 3147776 4192255 1044480  510M Linux filesystem

fdisk -l (list) mostra le partizioni e esce: non modifica niente, ed è la prima cosa da fare. Senza il nome del disco elenca tutti i dischi del sistema (nel sandbox non mostra niente, perché non può accedere ai dischi). Prima c'è l'intestazione del disco: la dimensione, la dimensione dei settori (512 bytes, o 4096 sui dischi più recenti), il Disklabel type (gpt o dos) e l'identificativo. Poi la tabella: Start e End sono il primo e l'ultimo settore, Sectors quanti sono, Size la dimensione e Type il tipo. Nota che la prima partizione comincia al settore 2048, cioè a 1 MiB dall'inizio: è l'allineamento che fdisk sceglie da solo, giusto anche per i dischi con settori da 4 KiB e per gli SSD. Per riconoscere a colpo d'occhio dischi e partizioni, anche già montate, c'è lsblk (vedi l'articolo relativo).

Esempio 2: più dettagli e altre unità

$ fdisk -x disco.img | sed -n 7,12p
First usable LBA: 2048
Last usable LBA: 4194270
Alternative LBA: 4194303
Partition entries starting LBA: 2
Allocated partition entries: 128
Partition entries ending LBA: 33
$ fdisk -l -o Device,Start,Size,Type disco.img | tail -n 3
disco.img1    2048  512M EFI System
disco.img2 1050624    1G Linux swap
disco.img3 3147776  510M Linux filesystem
$ fdisk -l --bytes disco.img | tail -n 3
disco.img1    2048 1050623 1048576  536870912 EFI System
disco.img2 1050624 3147775 2097152 1073741824 Linux swap
disco.img3 3147776 4192255 1044480  534773760 Linux filesystem

Con -x (details) si vedono i dettagli della tabella (nell'esempio, i dati interni della tabella GPT, e per ogni partizione l'identificativo del tipo e quello unico della partizione, utile per i file /etc/fstab con UUID=: vedi l'articolo su mount). Con -o si scelgono le colonne (l'elenco è nell'aiuto: fdisk -h), e con --bytes le dimensioni escono in byte esatti, comodi negli script. Una nota: sull'output di un MBR le colonne sono diverse (compaiono Boot e Id: vedi l'esempio 4).

Esempio 3: creare una tabella GPT e tre partizioni

$ sudo fdisk /dev/sdb
Command (m for help): g
Created a new GPT disklabel (GUID: 07876C22-41D1-471D-8D64-CDBBA506E00E).
Command (m for help): n
Partition number (1-128, default 1):
First sector (2048-4194270, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-4194270, default 4192255): +512M
Created a new partition 1 of type 'Linux filesystem' and of size 512 MiB.
Command (m for help): t
Selected partition 1
Partition type or alias (type L to list all): uefi
Changed type of partition 'Linux filesystem' to 'EFI System'.
Command (m for help): n
Partition number (2-128, default 2):
First sector (1050624-4194270, default 1050624):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (1050624-4194270, default 4192255): +1G
Created a new partition 2 of type 'Linux filesystem' and of size 1 GiB.
Command (m for help): t
Partition number (1,2, default 2):
Partition type or alias (type L to list all): swap
Changed type of partition 'Linux filesystem' to 'Linux swap'.
Command (m for help): n
(Invio a tutte le domande: la terza partizione occupa lo spazio rimasto)
Created a new partition 3 of type 'Linux filesystem' and of size 510 MiB.
Command (m for help): p
Command (m for help): v
No errors detected.
Command (m for help): w
The partition table has been altered.
Syncing disks.

Il programma si guida con comandi di una lettera, che si scrivono dopo il prompt Command (m for help): (m mostra il menù). Il blocco è la sessione reale su disco.img, riassunta: ho tolto qualche riga vuota, e dove il programma propone un valore predefinito l'utente preme Invio (le risposte vuote dopo default). I comandi usati: g crea una nuova tabella GPT vuota (o per una MBR); n (new) crea una partizione, chiedendo numero, primo settore e ultimo; l'ultimo si può dare come dimensione (+512M, +1G) e se si preme Invio prende tutto lo spazio rimasto. t (type) cambia il tipo, e si può dare con un alias (uefi, swap, linux, lvm, raid: li ho provati) o con il numero della lista che mostra l; p stampa la tabella (come nell'esempio 1), v la verifica, w la scrive ed esce, q esce senza salvare. Prima della w il disco non è stato toccato: all'apertura fdisk dice Changes will remain in memory only. Se il disco è vuoto, all'avvio crea in memoria una tabella MBR predefinita (Created a new DOS (MBR) disklabel): se vuoi una GPT, il primo comando è g.

Esempio 4: la tabella MBR, con partizioni estese e logiche

Command (m for help): o
Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
...
Command (m for help): a
Selected partition 1
The bootable flag on partition 1 is enabled now.
...
Command (m for help): n
All space for primary partitions is in use.
Adding logical partition 5
$ fdisk -l mbr.img | tail -n 6
Device     Boot   Start     End Sectors  Size Id Type
mbr.img1   *       2048 1050623 1048576  512M 83 Linux
mbr.img2        1050624 3147775 2097152    1G 82 Linux swap / Solaris
mbr.img3        3147776 4194303 1046528  511M  5 Extended
mbr.img5        3149824 3764223  614400  300M 83 Linux
mbr.img6        3766272 4194303  428032  209M 83 Linux

Il formato MBR ha un limite storico: al massimo quattro partizioni primarie. Per averne di più, una delle quattro diventa estesa (il tipo 5 Extended dell'esempio) e fa da contenitore per un numero qualsiasi di partizioni logiche, che hanno numeri da 5 in su (mbr.img5, mbr.img6): quando le primarie sono finite fdisk lo dice (All space for primary partitions is in use. Adding logical partition 5) e prosegue da solo. Con a si attiva il flag boot (* nella colonna Boot), che i vecchi BIOS usano per sapere da quale partizione avviarsi. Nel tipo, con MBR si usano codici in esadecimale (83 Linux, 82 swap, 8e LVM, fd RAID, ef EFI), e fdisk accetta in alternativa gli alias. Il MBR non gestisce dischi oltre i 2 TiB (gli indirizzi sono a 32 bit): per i dischi grandi serve la GPT.

Esempio 5: eliminare, spazio libero, informazioni

Command (m for help): F
Unpartitioned space disco.img: 0 B, 0 bytes, 0 sectors
Command (m for help): d
Partition number (1-3, default 3): 3
Partition 3 has been deleted.
Command (m for help): F
Unpartitioned space disco.img: 510.98 MiB, 535805440 bytes, 1046495 sectors
  Start     End Sectors  Size
3147776 4194270 1046495  511M
Command (m for help): i
Partition number (1-3, default 3): 2
         Device: disco.img2
          Start: 1050624
            End: 3147775
        Sectors: 2097152
           Size: 1G
           Type: Linux swap
      Type-UUID: 0657FD6D-A4AB-43C4-84E5-0933C84B4F4F
           UUID: 789EF033-3062-4AC4-880C-648F0897714C
Command (m for help): q

F mostra lo spazio libero non partizionato (come nell'esempio: prima della cancellazione 0, dopo circa 511 MiB); d (delete) elimina una partizione, i (info) mostra i dettagli di una (compreso l'identificativo unico, quello che si usa in fstab). Nell'esempio ho chiuso con q, per non salvare: la cancellazione c'è stata solo in memoria. Importante: d toglie la partizione dalla tabella, non cancella i dati contenuti. Ma senza la tabella il sistema non sa più dove sono, e il recupero non è garantito (vedi "Attenzione a"). Vale la regola: prima della w si può sempre tornare indietro con q; dopo la w no.

Esempio 6: gli errori più frequenti

$ fdisk -l /dev/nonesiste
fdisk: cannot open /dev/nonesiste: No such file or directory
$ fdisk -l /dev/sda
fdisk: cannot open /dev/sda: Permission denied
Command (m for help): n
Partition number (4-128, default 4): 1
Value out of range.
Partition number (4-128, default 4): 99999999
Value out of range.
Partition number (4-128, default 4):
No enough free sectors available.
Command (m for help): L
L: unknown command

I messaggi da riconoscere. cannot open ...: No such file or directory: il disco non esiste (controlla il nome con lsblk). Permission denied: servono i privilegi, quindi sudo (il secondo l'ho visto con un utente senza privilegi sul disco del sandbox). Value out of range: il numero o il settore indicato non è tra quelli ammessi (nell'esempio, il numero 1 è già usato), e il programma lo richiede. No enough free sectors available (il testo ha davvero questo errore di grammatica): non c'è più spazio libero per una nuova partizione. L'ultimo mostra una confusione frequente: al prompt principale l'elenco dei tipi si chiede con l (minuscola); la L maiuscola funziona solo dentro il comando t.

Esempio 7: salvare e ripetere una tabella con sfdisk

$ sfdisk -d disco.img > tabella.txt
$ cat tabella.txt
label: gpt
label-id: 07876C22-41D1-471D-8D64-CDBBA506E00E
device: disco.img
unit: sectors
first-lba: 2048
last-lba: 4194270
sector-size: 512

disco.img1 : start=        2048, size=     1048576, type=C12A7328-..., uuid=BC77F0D1-...
disco.img2 : start=     1050624, size=     2097152, type=0657FD6D-..., uuid=789EF033-...
disco.img3 : start=     3147776, size=     1044480, type=0FC63DAF-..., uuid=94FF9AAC-...
$ sfdisk nuovo.img < tabella.txt
$ printf 'label: gpt\n,512M,U\n,1G,S\n,,L\n' | sfdisk nuovo.img
nuovo.img1: Created a new partition 1 of type 'EFI System' and of size 512 MiB.
nuovo.img2: Created a new partition 2 of type 'Linux swap' and of size 1 GiB.
nuovo.img3: Created a new partition 3 of type 'Linux filesystem' and of size 510 MiB.
nuovo.img4: Done.

sfdisk (stesso pacchetto) è il fratello non interattivo di fdisk: legge la tabella da un testo, perciò è adatto agli script. Con -d (dump) salva la tabella di un disco in un file, che si può conservare come copia di sicurezza prima di un intervento (è anche l'unica copia leggibile da una persona) e poi riapplicare con sfdisk disco < file. L'ultimo comando crea una tabella nuova da una descrizione scritta a mano: una riga per partizione, con dimensione e tipo abbreviato (U = EFI, S = swap, L = Linux; senza dimensione, la partizione prende tutto lo spazio che resta). Nell'esempio le tre righe uuid le ho accorciate. Attenzione: sfdisk con un dump riapplicato su un altro disco gli assegna gli stessi identificativi del disco originale (l'ho verificato: il disco copiato ha lo stesso GUID): se i due dischi stanno nello stesso computer il sistema può confondersi. Per cambiare l'identificativo del disco si usa il menù degli esperti (x, poi i) o sfdisk --disk-id.

Esempio 8: uso negli script

#!/bin/bash
# Mostra il tipo di tabella e il numero di partizioni di un disco
DISCO=${1:?indicare il disco, per esempio /dev/sda}
TIPO=$(fdisk -l "$DISCO" 2>/dev/null | awk -F': ' '/^Disklabel type/ {print $2}')
if [ -z "$TIPO" ]; then
    echo "$DISCO: nessuna tabella delle partizioni (o disco non leggibile)" >&2
    exit 1
fi
N=$(fdisk -l "$DISCO" | grep -c "^$DISCO")
echo "$DISCO: tabella $TIPO, $N partizioni"

Lo script prende il nome di un disco come argomento (${1:?...} si ferma con un messaggio se manca), legge dal listato di fdisk -l il tipo di tabella e conta le righe che cominciano con il nome del disco (le partizioni). L'ho provato sui miei file immagine: disco.img risponde tabella gpt, 3 partizioni e mbr.img tabella dos, 5 partizioni; su un disco vuoto o inesistente dà l'errore e il codice 1; senza argomento si ferma subito con il messaggio. Il conteggio funziona per /dev/sda (partizioni /dev/sda1...) e anche per i dischi NVMe (/dev/nvme0n1p1), perché in entrambi i casi il nome delle partizioni comincia con quello del disco. Si lancia con sudo. Una riga come fdisk -l disco è sicura da usare in uno script; i comandi che scrivono, invece, vanno inseriti con molta più cautela, e di norma conviene sfdisk (esempio 7).

Opzioni utili

  • fdisk -l [disco]: elenco delle partizioni; -x: più dettagli; -o colonne: scelta delle colonne; --bytes: dimensioni in byte.
  • Nel programma: m menù; p stampa; n nuova; d elimina; t tipo; F spazio libero; i informazioni; v verifica; l elenco dei tipi; a flag di avvio (MBR); w scrive; q esce senza salvare.
  • g, o: crea una tabella nuova vuota (GPT, MBR); I, O: carica o salva un file di descrizione come quelli di sfdisk.
  • -w auto|always|never: cancella o no le firme di vecchi file system; -b dimensione: forza la dimensione dei settori.
  • sfdisk -d disco: salva la tabella; sfdisk disco < file: la ripristina; cfdisk: la stessa cosa con un menù a tutto schermo.
  • lsblk, blkid, mount, df: dispositivi, identificativi, montaggi, spazio. mkfs.ext4, mkswap: preparano la partizione dopo fdisk. partprobe: avvisa il sistema di una nuova tabella.

Attenzione a

  • Il disco sbagliato è l'errore più grave: fdisk /dev/sda invece di /dev/sdb può cancellare il sistema. Controlla sempre con lsblk (modello, dimensione, punti di montaggio) e con fdisk -l prima di scrivere; i nomi sda e sdb possono scambiarsi da un avvio all'altro, perciò verifica anche la dimensione e il modello.
  • Dopo la w non si torna indietro: prima di scrivere ricontrolla con p e v, e se sei in dubbio premi q. Su un disco con dati salva prima la tabella (sfdisk -d disco > copia.txt) e i dati stessi (vedi rsync e tar).
  • Non toccare partizioni montate: smonta prima i file system (vedi mount). Se il disco è in uso, dopo la scrittura il sistema può non rileggere la tabella (Re-reading the partition table failed): in quel caso sudo partprobe o un riavvio. Non ho potuto provarlo nel sandbox, che non lo permette sui dischi.
  • Eliminare e ricreare una partizione non cancella i dati, ma è rischioso: se la nuova partizione comincia esattamente allo stesso settore, il file system sopra è di solito ancora leggibile; se no, i dati sono persi di fatto. Per questo i dischi con dati importanti si ridimensionano con strumenti dedicati (growpart, parted, resize2fs), che aggiornano insieme tabella e file system. fdisk non ridimensiona.
  • Creare la partizione non basta: serve poi il file system (mkfs.ext4 /dev/sdb1, mkswap per lo swap), il montaggio e, per renderlo permanente, la riga in /etc/fstab. Un mkfs sulla partizione sbagliata cancella davvero i dati.
  • MBR o GPT: per macchine nuove con UEFI si usa la GPT, con una partizione EFI System (di solito 100-512 MiB) per l'avvio; la MBR serve ai vecchi BIOS e non gestisce i dischi oltre i 2 TiB. Scegliere male rende il sistema non avviabile.
  • Dischi ingranditi nel cloud o in una macchina virtuale: se il disco è stato ingrandito dal fornitore, la partizione va allargata con growpart (o con la procedura del fornitore), e poi il file system con resize2fs (ext4) o xfs_growfs (XFS). Questi passaggi li ho solo citati, non provati.
  • I nomi dei tipi e gli alias dipendono dalla versione: gli alias uefi, swap, lvm, raid li ho provati con la 2.39.3; su versioni più vecchie può servire il numero o il codice esadecimale (l mostra l'elenco della tua).

Riepilogo

ComandoCosa fa
sudo fdisk -lElenca le partizioni di tutti i dischi
sudo fdisk -l /dev/sdaElenca quelle di un solo disco
sudo fdisk -x /dev/sdaElenco con più dettagli
sudo fdisk /dev/sdbApre il disco per modificare la tabella (in memoria)
g / oNuova tabella vuota GPT / MBR
n, d, tNuova partizione, elimina, cambia il tipo
p, F, i, vStampa, spazio libero, informazioni, verifica
w / qScrive ed esce / esce senza salvare
sfdisk -d /dev/sda > tabella.txtSalva la tabella in un file
sudo sfdisk /dev/sdb < tabella.txtApplica una tabella salvata
truncate -s 2G disco.imgCrea un file immagine con cui esercitarsi