# Creating GPT partitions easily on the command line

## Incentives

I’ve long been enjoying using sfdisk to manipulate my disk partitions. I always use it to,

When my disks are over 2T in size, I can’t use MBR and therefore can’t use sfdisk anymore. I have to use GPT instead. My first GPT partitions was created using GUI tools, but I really hate GUI tools. So this time when I need to partition GPT again, I look for the command line alternative instead.

## The problem

There is a command line tool, sgdisk, to create GPT partitions, but its command line interface is inhuman, if not insane. Here is the example given by the sgdisk author, from Creating Scripts for Partition Manipulation:

#!/bin/bash
sgdisk -og $1 sgdisk -n 1:2048:4095 -c 1:"BIOS Boot Partition" -t 1:ef02$1
sgdisk -n 2:4096:413695 -c 2:"EFI System Partition" -t 2:ef00 $1 sgdisk -n 3:413696:823295 -c 3:"Linux /boot" -t 3:8300$1
ENDSECTOR=sgdisk -E $1 sgdisk -n 4:823296:$ENDSECTOR -c 4:"Linux LVM" -t 4:8e00 $1 sgdisk -p$1


As the comparison, to create disk partitions using sfdisk, here are two examples:

• Three primary partitions: two of size 50MB and the rest:

sfdisk /dev/hda -uM << EOF
,50
,50
;
EOF

• A 1MB OS2 Boot Manager partition, a 50MB DOS partition, and three extended partitions (DOS D:, Linux swap, Linux):

sfdisk /dev/hda -uM << EOF
,1,a
,50,6
,,E
;
,20,4
,16,S
;
EOF


As you can see, it is so simple. Coming from the simple sfdisk and landed at the complicated sgdisk, on looking at the above example, I realize that there is no way I can write the above sgdisk code by hand, i.e., I need a tool to write it for me. Of course, the first tool that came into mind is the universal code generator, easygen. After poking around here and there, I made it.

## The solution

So to use the universal code generator, easygen to create GPT partitions, first we need to define our partitions layout in an easy format as the following:

Disk: /dev/sdb

# Common Partitions Types
#
# 8300 Linux filesystem
# 8200 linux swap
# fd00 linux raid
# ef02 BIOS boot
# 0700 Microsoft basic data
#
# For more GPT Partitions Types,
# echo L | gdisk /dev/sdb

Partitions:
- Name: bios_boot
Type: ef02
Size: +200M

- Name: linux_boot
Type: 8300
Size: +20G

- Name: windows
Type: "0700"
Size: +30G

- Name: linux_swap
Type: 8200
Size: +10G

- Name: os1
Type: 8300
Size: +12G

- Name: os2
Type: 8300
Size: +12G

- Name: os3
Type: 8300
Size: +12G

- Name: data
Type: 8300
Size: "0"


I.e., for each partition, we need to give its name, type and size. For your convenient, I’ve put the mostly used GPT types in the comment, as shown above.

That’s the hardest part, the rest are simple and straightforward, to generate partition creation code:

easygen test/sgdisk | tee test/sgdisk.sh


The result:

 # format /dev/sdb as GPT, GUID Partition Table
sgdisk -Z /dev/sdb

sgdisk -n 0:0:+200M -t 0:ef02 -c 0:"bios_boot" /dev/sdb
sgdisk -n 0:0:+20G -t 0:8300 -c 0:"linux_boot" /dev/sdb
sgdisk -n 0:0:+30G -t 0:0700 -c 0:"windows" /dev/sdb
sgdisk -n 0:0:+10G -t 0:8200 -c 0:"linux_swap" /dev/sdb
sgdisk -n 0:0:+12G -t 0:8300 -c 0:"os1" /dev/sdb
sgdisk -n 0:0:+12G -t 0:8300 -c 0:"os2" /dev/sdb
sgdisk -n 0:0:+12G -t 0:8300 -c 0:"os3" /dev/sdb
sgdisk -n 0:0:0 -t 0:8300 -c 0:"data" /dev/sdb

sgdisk -p /dev/sdb

# inform the OS of partition table changes
partprobe /dev/sdb
fdisk -l /dev/sdb


After carefully read sgdisk’s man page, I found it is not that insane or inhuman, but just powerful after all.

The result will be exactly as we are expecting:

sgdisk -p /dev/sdb Disk /dev/sdb: 732558336 sectors, 2.7 TiB Logical sector size: 4096 bytes Disk identifier (GUID): C4426321-9726-4022-BB20-2EF00B490465 Partition table holds up to 128 entries First usable sector is 6, last usable sector is 732558330 Partitions will be aligned on 256-sector boundaries Total free space is 250 sectors (1000.0 KiB) Number Start (sector) End (sector) Size Code Name 1 256 51455 200.0 MiB EF02 bios_boot 2 51456 5294335 20.0 GiB 8300 linux_boot 3 5294336 13158655 30.0 GiB 0700 windows 4 13158656 15780095 10.0 GiB 8200 linux_swap 5 15780096 18925823 12.0 GiB 8300 os1 6 18925824 22071551 12.0 GiB 8300 os2 7 22071552 25217279 12.0 GiB 8300 os3 8 25217280 732558330 2.6 TiB 8300 data fdisk -l /dev/sdb

Disk /dev/sdb: 2.7 TiB, 3000558944256 bytes, 732558336 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: C4426321-9726-4022-BB20-2EF00B490465

Device        Start       End   Sectors  Size Type
/dev/sdb1       256     51455     51200  200M BIOS boot
/dev/sdb2     51456   5294335   5242880   20G Linux filesystem
/dev/sdb3   5294336  13158655   7864320   30G Microsoft basic data
/dev/sdb4  13158656  15780095   2621440   10G Linux swap
/dev/sdb5  15780096  18925823   3145728   12G Linux filesystem
/dev/sdb6  18925824  22071551   3145728   12G Linux filesystem
/dev/sdb7  22071552  25217279   3145728   12G Linux filesystem
/dev/sdb8  25217280 732558330 707341051  2.7T Linux filesystem


## Is it better?

I know most GUI lovers would laugh at my silly action. I just know them so well that I can imagine exactly what the conversion would be, as follows (T stands for “they”, whereas M stands for me):

T
“Ha, you are making this more complicated”
M
No, I think I’m making it simpler. For example, the data definition (.yaml) file not only serves the purpose of generating the partition-creation code, but also serves the purpose of documentation as well.
T
You are just kidding me, the best way to document is to take a screenshot
M
Well, I disagree. What if you want to do it again?
T
That’s so simple. I just need to find out where I store my screenshot, and I can easily redo it again
M
From the GUI, doing the clicking all over again?
T
Definitely. Who want to learn or use your silly way?

Oh, well, my tools is definitely not for them, no matter how hard I’d like to try. I think that it is the mentality conflicting between the two camps, the Microsoft spoiled dummies, and die-hard text-everything Unix fans. Personally, I view WYSIWYG GUI tools as carving stones with chisels, and text-based/command-line tools as operating CNC machines. Yes, sure there are strict rules and steep learning curves regarding the CNC machines, but once you are over that fear and hurdle, the benefits or possibilities are endless.

Talking about partition creation, let alone doing it again on a different machine, even on the same machine, I need to do it several times, because nobody can achieve the perfect score with a single shot without any prior practices. I can’t. Doing the clicking over and over again will wear me out very fast, and I most probably would end up with a less optimal setting that I’ll be regretting since. Using the .yaml file and code generation, it’ll be nearly “zero cost”, I can do it over and over again until I’m fully satisfied.

Let alone doing it several times, even just doing it once can be simplified by the .yaml file as well. Here is a piece of my actual GPT partition definition:

  - Name: os1p
Type: 8300
Size: +12G

- Name: os1s
Type: 8300
Size: +12G

- Name: os11
Type: 8300
Size: +8G

- Name: os12
Type: 8300
Size: +8G

- Name: os13
Type: 8300
Size: +8G

- Name: os2p
Type: 8300
Size: +12G

- Name: os2s
Type: 8300
Size: +12G

- Name: os21
Type: 8300
Size: +8G

- Name: os22
Type: 8300
Size: +8G

- Name: os23
Type: 8300
Size: +8G


I’d like to keep a lot of OS partitions for me to try new things or keeping the old systems so that I can go back to them any time. In the above listing, I have two sets of OS partitions, os1x and os2x, each with two big partitions (12G), primary and secondary, and three smaller partitions (8G). Using a text editor, I can quickly duplicate the first entry into the first full set, then into both the two sets, without too much trouble. Doing from GUI, not a single chiseling I can save. Err, I meant clicking.

The .yaml file and code generation will

• serve both the purpose of action and documentation.
• make it very simple to redo/reuse, regardless to different machines, or to the same machines; many times, or just once.
• give me a clearer content. Instead of the exact sgdisk commands, i.e., the implementation details, the file contains only each partition’s name, type and size. Clear and straight to the point. No trivial details are in the way.
• of course, it also gives the benefit of coding and documenting at the same place. More reasons can be documented in the .yaml file, the same way as comments make code-purpose clearer.

Here is the bonus, once the data definition (.yaml) file is in place, you can do all sorts of other things you want.

E.g., how about managing the mount-points?

\$ easygen -tf test/sgdisk-mp test/sgdisk

mkdir /mnt/bios_boot
mkdir /mnt/linux_boot
mkdir /mnt/windows
mkdir /mnt/linux_swap
mkdir /mnt/os1
mkdir /mnt/os2
mkdir /mnt/os3
mkdir /mnt/data

mount LABEL=bios_boot /mnt/bios_boot
mount LABEL=linux_boot /mnt/linux_boot
mount LABEL=windows /mnt/windows
mount LABEL=linux_swap /mnt/linux_swap
mount LABEL=os1 /mnt/os1
mount LABEL=os2 /mnt/os2
mount LABEL=os3 /mnt/os3
mount LABEL=data /mnt/data


Generating the fstab entries are as simple as above as well. Or, how about using mkfs to format each partition? Simple as well.

I’ll explain more on the easy to use universal code/text generator easygen next. Meanwhile, you can check out what we have covered already before, including mock-up generation.

Stay tuned.