Any way to create a file and make it emulate a real block device?

As the title says, I would like to

  • create a file
  • have that file emulate a real block device
  • run bash commands to perform operations on that file and have that file emulate the exact behaviours of a real block device, without having a physical device.

Specifically, I want to run all commands such as

  • parted
  • mkfs
  • mkswap
  • fsck
  • etc.

Is there a way to do that?

Is there a tool (free?) to offers that capability?



Tool I am working on to automate a disk partitioning to specification defined in a config file.

Script: 001__PreInstallDiskPartitionningAndFormatting.sh

#!/bin/bash

#################################################################################################
#################################################################################################

echo="echo -e"


testForDisk()
{
	testRoot=$( df -h / | grep '^/' | awk '{ print $1 }' | sed 's+[0-9]*++g' )
	testTarget=$( lsblk --paths | grep '^'${DISK} | awk '{ print $1 }' )

	if [ -z "${testTarget}" ]
	then
		${echo} "\n\t ABORT.  Specified disk does not exist.\n" ; exit 1
	fi

	if [ "${testRoot}" = "${testTarget}" ]
	then
		${echo} "\n\t ABORT.  Specified disk is system ROOT.\n" ; exit 1
	fi
} #testForDisk()


testForSwap()
{
	sudo swapoff ${DISK}?*
	testSwaps=$( sudo swapon | grep ${DISK} )

	if [ -n "${testSwaps}" ]
	then
		${echo} "\n\t ABORT.  Specified disk has active SWAP.  Was unable to turn that off!\n" ; exit 1
	else
		${echo} "\tConfirmed any active SWAP was disabled ..."
	fi
} #testForSwap()


unMountDisk()
{
	sudo umount ${DISK}?*
	testMounts=$( sudo mount | grep ${DISK} )

	if [ -n "${testMounts}" ]
	then
		${echo} "\n\t ABORT.  Specified disk has active mounts.  Was unable to unmount partitions!\n" ; exit 1
	else
		${echo} "\tConfirmed ${DISK} is not mounted ..."
	fi
} #unMountDisk()


transient_PartitionSpecificationDefinition()
{
	###
	###	IMPORTANT:  NOT meant to be part of permanent script logic
	###

###
${echo} "\nCapture Partition Specifications (from command-line or config file) ..."
###
###	Guidance:
###		- Hibernate target should be system's primary swap to
###		  minimize delay from copying from swap to hibernate image
###		- Hibernate target should be 1.5 to 2 times size of RAM
###

###
###	FUTURES:
###		- Calculate size of HIBERNATE swap space based on installed RAM
###		- Calculate start and end point of each partition based
###		  size specification for each partition
###		- Create fstab entries using UUIDs the resulting disk layout
###

cat >"${specifications}" <<EnDoFfIlE
# partNum:partFsType:partStart:partEnd:partName:partMount
1	swap	4MiB	8GiB	HIBERNATE	none
2	ext4	8GiB	12GiB	BOOT		/boot
3	ext4	12GiB	200GiB	DB007_F1	/
4	ext4	200GiB	100%	DB007_F2	/DB007_F2
EnDoFfIlE

} #transient_PartitionSpecificationDefinition()


demoSetup()
{
	###
	###	Call function to create sample partitioning specification
	###
	transient_PartitionSpecificationDefinition

	###
	###	
	###
}

#################################################################################################
#################################################################################################


doit=0
doDemo=1

while [ $# -ne 0 ]
do
	case "${1}" in
		--demo )
			doDemo=1
			doit=0
			shift
			;;
		--layout )
			specifications="${2}"
			shift ; shift
			;;
		--device )
			DISK="${2}"
			doDemo=0
			shift ; shift
			;;
		--apply )
			doit=1
			shift ;
			;;
	esac
done

if [ ${doDemo} -eq 1 ]
then
	###
	###	Specify/Select value for target disk
	###
	DISK="/dev/sdg"

	###
	###	Specify/Select value for partitioning specifications file
	###
	specifications="./partitions_sdg_specs.conf"

	###
	###	Initialize demo processing session
	###
	demoSetup
fi

if [ -z "${specifications}" ]
then
	echo "\n\t ERROR:  File containing specs for device partitioning must be identified using '--layout' flag.\n" ; exit 1
fi

if [ -z "${DISK}" ]
then
	echo "\n\t ERROR:  Specification of device fullpath required using '--device' flag.\n" ; exit 1
fi



###
${echo} "\nVerifying the specified disk is recognized and accessible ..."
###
CMD="testForDisk"
test ${doit} -eq 1 && { ${CMD} ; }
test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }


##################################
##########   PHASE  I   ##########
##################################

###
${echo} "\nEnsuring that the disk has no active dependancy for swap ..."
###
CMD="testForSwap"
test ${doit} -eq 1 && { ${CMD} ; }
test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }


###
${echo} "\nEnsuring that the disk is not busy or mounted ..."
###
CMD="unMountDisk"
test ${doit} -eq 1 && { ${CMD} ; }
test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }


###
${echo} "\nScanning '${DISK}' for badblocks before continuing ..."
###
CMD="sudo badblocks -nsv ${DISK}"
test ${doit} -eq 1 && { ${CMD} ; }
test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }


##################################
##########   PHASE II   ##########
##################################

${echo} "\nStarting Process of Partitioning and Formatting '${DISK}' ..."

###
${echo} "\nCreate new GPT-type partition table ..."
###
CMD="sudo parted --script ${DISK} mklabel gpt"
test ${doit} -eq 1 && { ${CMD} ; }
test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }






#IFSorig="${IFS}"

#declare -a specsArray=()
specsArray=()

indx=0

grep -v '^#' "${specifications}" |
while [ true ]
do
	read specsArray[${indx}]

	if [ $? -ne 0 ] ; then break ; fi

	${echo} "	specsArray[${indx}] = ${specsArray[${indx}]} "

	###
	###	Parse partition values from command line or configuration file
	###

	###
	${echo} "\nExtract partition data from next entry in specifications array ..."
	###

	#IFS=':'
	#read partNum partFsType partStart partEnd partName partMount <<< "1	swap	4MiB	8GiB	HIBERNATE	none"
	read partNum partFsType partStart partEnd partName partMount <<< "${specsArray[${indx}]}"

	${echo} "\n	partNum		= ${partNum}
	partFsType	= ${partFsType}
	partStart	= ${partStart}
	partEnd		= ${partEnd}
	partName	= ${partName}
	partMount	= ${partMount}"

	###
	${echo} "\nCreate a partition to specifications ..."
	###
	CMD="sudo parted --script --align optimal ${DISK} mkpart primary ${partFsType} ${partStart} ${partEnd}"
	test ${doit} -eq 1 && { ${CMD} ; }
	test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }

	###
	${echo} "\nUpdate OS awareness of the disk's new structure ..."
	###
	CMD="sudo partprobe ${DISK}"
	test ${doit} -eq 1 && { ${CMD} ; }
	test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }

	###
	${echo} "\nEnsure device node creation is complete ..."
	###
	CMD="sleep 2 ; udevadm settle"
	test ${doit} -eq 1 && { ${CMD} ; }
	test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }

	PARTITION="${DISK}${partNum}"

	###
	${echo} "\nFormat partition to specification ..."
	###
	case ${partFsType} in
		swap )
			CMD="sudo mkswap ${PARTITION} -L '${partName}'"
			test ${doit} -eq 1 && { ${CMD} ; }
			test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }
			;;
		* )
			CMD="sudo mkfs.${partFsType} ${PARTITION} -L '${partName}'"
			test ${doit} -eq 1 && { ${CMD} ; }
			test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }
			;;
	esac

	${echo} "\n\t Hit return to continue ...\c" ; read k <&2

	indx=$( expr ${indx} + 1 )
done

#IFS="${IFSorig}"


###
${echo} "\nReport final state of disk partitioning ..."
###
CMD="parted --script ${DISK} print"
test ${doit} -eq 1 && { ${CMD} ; }
test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }

echo ""
CMD="sudo lsblk --list -o NAME,FSTYPE,PARTLABEL,UUID,SIZE,MOUNTPOINT,SUBSYSTEMS '${DEVICE}' "
test ${doit} -eq 1 && { ${CMD} ; }
test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }


###
${echo} "\nReload the updated fstab ..."
###
CMD="sudo systemctl daemon-reload"
test ${doit} -eq 1 && { ${CMD} ; }
test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }


exit 0
exit 0
exit 0
1 Like

Yes, it is possible. You can use mount command with -o loop option for the purpose. Or you may prefer losetup command.

Man pages and/or Internet search will definitely provide useful details on these commands usage.

Good luck!

5 Likes

Thank you, Eugene. I will give you credit for that. I had looked at that before, but I guess I hadn't dug in deep enough.

Following your prompting, I looked deeper into it and got it to work ... somewhat ... but apparently not completely. :frowning:



Firstly, GParted does not report any devices created using losetup! That is a BIG disappointment.

Funny part is that ... parted itself ... does !!!

Report final state of disk partitioning ...
Model: Loopback device (loopback)
Disk /dev/loop33: 2147MB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: 

Number  Start   End     Size    File system     Name     Flags
 1      4194kB  67.1MB  62.9MB  linux-swap(v1)  primary  swap
 2      67.1MB  268MB   201MB   ext4            primary
 3      268MB   1074MB  805MB   ext4            primary
 4      1074MB  2146MB  1073MB  ext4            primary

...(previously posted section deleted)...

CORRECTION:
I have mounted the partitions and they are behaving as expected per the lsblk report:

loop33                                                               2G                               block
loop35p1 swap     HIBERNATE  82f37040-c8cb-42fe-9d69-a0206eee17cf    60M                               block
loop35p2 ext4     BOOT       cc2929fe-61cb-437a-9e0e-e00577bc6ad0   192M /altboot                      block
loop35p3 ext4     DB008_F1   b587613e-7876-49d8-a303-eb8f57a6a5fc   768M /altroot                      block
loop35p4 ext4     DB008_F2   e383d184-3d3d-445c-a480-2893da0652f3  1023M /DB008_F2                     block

:slight_smile:

1 Like

So, here is what I have come up with. I am a "qualified" happy with that, but hope others have feedback on where I may have overlooked something.

Purpose/Intent:

  • from Live ISO terminal session, perform partitionning and formatting of a target disk BEFORE starting the installation process, to simplify the activities which the ISO install encompasses.

  • intended as first step of a 3-step process involving
            [1] disk formatting (this script),
            [2] install of Ubuntu Server, and
            [3] use another script which prompts interractively for all User-specified Applications from a list of the most used/cherished Applications available from the Ubuntu distribution repository.



The script offers an option to visually confirm the sequence that will be performed for each line entry in a "layout specification file", before committing to applying that specification to the intended target installation drive.

Everything seems to work fine but, for "partition 4", where I create the partition intended for "root", it reports

parted: invalid token: root

I don't know if that is because an actual root was already mounted, or the fact that the mountpoint path was identified as "/altroot", rather than "/".

Would I get that same error if I was running from a Live Session or not, pre-install of Ubuntu Server setup?



File:     partitions_sdc_specs.conf

# partNum:partFsType:partStart:partEnd:partName:partMount:partFlag
1	linux-swap	24KB	4MiB	GRUB		none		null
2	linux-swap	4MiB	64MiB	HIBERNATE	none		swap
3	ext4		64MiB	256MiB	BOOT		/altboot	boot
4	ext4		256MiB	1GiB	DB008_F1	/altroot	root
5	ext4		1GiB	100%	DB008_F2	/DB008_F2	null


The following is a session log of the actual formatting of the drive:

ericthered @ OasisMega1 : /DB001_F4/00__18__DISTRO__Build/001__DiskPartsAndFormats
$ ./001__PreInstallDiskPartitionningAndFormatting.sh --layout "./partitions_sdc_specs.conf" --device "/dev/sdc" --apply


Verifying the specified disk is recognized and accessible ...

Ensuring that the disk has no active dependancy for swap ...
[sudo] password for ericthered: 
	Confirmed any active SWAP was disabled ...

Ensuring that the disk is not busy or mounted ...
	Confirmed /dev/sdc is not mounted ...

Scanning '/dev/sdc' for badblocks before continuing ...

Starting Process of Partitioning and Formatting '/dev/sdc' ...

Create new GPT-type partition table ...

Extract partition data from next entry in specifications array ...

	partNum		= 1
	partFsType	= linux-swap
	partStart	= 24KB
	partEnd		= 4MiB
	partName	= GRUB
	partMount	= none
	partFlag	= null

Create a partition to specifications using 'parted mkpart ...' ...
Warning: The resulting partition is not properly aligned for best performance: 46s % 2048s != 0s

Update OS awareness of the disk's new structure using 'partprobe' ...

Ensure device node (udev) creation is complete ...

Format partition to specification ...
Setting up swapspace version 1, size = 4 MiB (4165632 bytes)
LABEL='GRUB', UUID=71db8ca8-2ca4-4926-925d-3c378ebe8f1d

	/dev/sdc1   8:33   1   4M  0 part 

	 Hit return to continue ...

Extract partition data from next entry in specifications array ...

	partNum		= 2
	partFsType	= linux-swap
	partStart	= 4MiB
	partEnd		= 64MiB
	partName	= HIBERNATE
	partMount	= none
	partFlag	= swap

Create a partition to specifications using 'parted mkpart ...' ...

Update OS awareness of the disk's new structure using 'partprobe' ...

Ensure device node (udev) creation is complete ...

Format partition to specification ...
mkswap: /dev/sdc2: warning: wiping old swap signature.
Setting up swapspace version 1, size = 60 MiB (62910464 bytes)
LABEL='HIBERNATE', UUID=cb8c2a02-a871-46d9-b455-1095d8435c99

	/dev/sdc2   8:34   1  60M  0 part 

	 Hit return to continue ...

Extract partition data from next entry in specifications array ...

	partNum		= 3
	partFsType	= ext4
	partStart	= 64MiB
	partEnd		= 256MiB
	partName	= BOOT
	partMount	= /altboot
	partFlag	= boot

Create a partition to specifications using 'parted mkpart ...' ...

Update OS awareness of the disk's new structure using 'partprobe' ...

Ensure device node (udev) creation is complete ...

Format partition to specification ...
mke2fs 1.46.5 (30-Dec-2021)
Creating filesystem with 49152 4k blocks and 49152 inodes
Filesystem UUID: ae44c502-de89-41c7-bf9e-7b58611d40c3
Superblock backups stored on blocks: 
	32768

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done


	/dev/sdc3   8:35   1  192M  0 part /altboot

	 Hit return to continue ...

Extract partition data from next entry in specifications array ...

	partNum		= 4
	partFsType	= ext4
	partStart	= 256MiB
	partEnd		= 1GiB
	partName	= DB008_F1
	partMount	= /altroot
	partFlag	= root

Create a partition to specifications using 'parted mkpart ...' ...
parted: invalid token: root

Update OS awareness of the disk's new structure using 'partprobe' ...

Ensure device node (udev) creation is complete ...

Format partition to specification ...
mke2fs 1.46.5 (30-Dec-2021)
Creating filesystem with 196608 4k blocks and 49152 inodes
Filesystem UUID: 2af8b0d6-3788-4dd8-95c2-e7399529091c
Superblock backups stored on blocks: 
	32768, 98304, 163840

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done


	/dev/sdc4   8:36   1  768M  0 part /altroot

	 Hit return to continue ...

Extract partition data from next entry in specifications array ...

	partNum		= 5
	partFsType	= ext4
	partStart	= 1GiB
	partEnd		= 100%
	partName	= DB008_F2
	partMount	= /DB008_F2
	partFlag	= null

Create a partition to specifications using 'parted mkpart ...' ...

Update OS awareness of the disk's new structure using 'partprobe' ...

Ensure device node (udev) creation is complete ...

Format partition to specification ...
mke2fs 1.46.5 (30-Dec-2021)
Creating filesystem with 3527936 4k blocks and 883008 inodes
Filesystem UUID: d835a150-ffb7-44c7-b2ed-a8dbc0d04599
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done   


	/dev/sdc5   8:37   1 13.5G  0 part /DB008_F2

	 Hit return to continue ...

Report final state of disk partitioning ...

	Model:  USB DISK 2.0 (scsi)
	Disk /dev/sdc: 15.5GB
	Sector size (logical/physical): 512B/512B
	Partition Table: gpt
	Disk Flags: 
	
	Number  Start   End     Size    File system     Name       Flags
	 1      23.6kB  4194kB  4171kB  linux-swap(v1)  GRUB       swap
	 2      4194kB  67.1MB  62.9MB  linux-swap(v1)  HIBERNATE  swap
	 3      67.1MB  268MB   201MB   ext4            BOOT       boot, esp
	 4      268MB   1074MB  805MB   ext4            DB008_F1
	 5      1074MB  15.5GB  14.5GB  ext4            DB008_F2
	

	/dev/sdc                                                             14.5G                               block:scsi:usb:pci
	/dev/sdc1   swap     GRUB      71db8ca8-2ca4-4926-925d-3c378ebe8f1d     4M                               block:scsi:usb:pci
	/dev/sdc2   swap     HIBERNATE cb8c2a02-a871-46d9-b455-1095d8435c99    60M                               block:scsi:usb:pci
	/dev/sdc3   ext4     BOOT      ae44c502-de89-41c7-bf9e-7b58611d40c3   192M /altboot                      block:scsi:usb:pci
	/dev/sdc4   ext4     DB008_F1  2af8b0d6-3788-4dd8-95c2-e7399529091c   768M /altroot                      block:scsi:usb:pci
	/dev/sdc5   ext4     DB008_F2  d835a150-ffb7-44c7-b2ed-a8dbc0d04599  13.5G /DB008_F2                     block:scsi:usb:pci

Reload the updated fstab ...

ericthered @ OasisMega1 : /DB001_F4/00__18__DISTRO__Build/001__DiskPartsAndFormats
$ 


File:     001__PreInstallDiskPartitionningAndFormatting.sh

        (Beta Test version of script (looking for feedback)

#!/bin/bash
# SPDX-License-Identifier: GPLv3-or-later
# SPDX-FileCopyrightText: © 2026 Eric Marceau <[email protected]>
#
# For the full text of the GNU General Public License version 3.0 (a.k.a. GPLv3)
# 	please visit:	https://spdx.org/licenses/GPL-3.0-or-later.html
#
#################################################################################################
#################################################################################################
###
###	Purpose/Intent:
###
###		* from Live ISO terminal session, perform partitionning and formatting 
###		  of a target disk **BEFORE** starting the installation process, 
###		  to simplify the activities which the ISO install encompasses.
###
###		* intended as first step of a 3-step process involving 
###		    [1] disk formatting (this script), 
###		    [2] install of Ubuntu Server, and 
###		    [3] use another script which prompts interractively for all User-specified
###		        Applications from a list of the most used/cherished Applications
###		        available from the Ubuntu distribution repository.
###
###	Version:
###		March 27 2026  -  Eric Marceau  -  v0.8 Beta Test
###
#################################################################################################
#################################################################################################


echo="echo -e"


testForDisk()
{
	testRoot=$( df -h / | grep '^/' | awk '{ print $1 }' | sed 's+[0-9]*++g' )
	testTarget=$( lsblk --paths | grep '^'${DISK} | awk '{ print $1 }' )

	test ${doDemo} -eq 1 && ${echo} "\tDEMO:  testTarget = '${testTarget}' ..."
	if [ -z "${testTarget}" ]
	then
		${echo} "\n\t ABORT.  Specified disk does not exist.\n" ; exit 1
	fi

	if [ "${testRoot}" = "${testTarget}" ]
	then
		${echo} "\n\t ABORT.  Specified disk is system ROOT.\n" ; exit 1
	fi
} #testForDisk()


testForSwap()
{
	sudo swapoff ${DISK}?* 2>>/dev/null
	testSwaps=$( sudo swapon | grep ${DISK} )

	if [ -n "${testSwaps}" ]
	then
		${echo} "\n\t ABORT.  Specified disk has active SWAP.  Was unable to turn that off!\n" ; exit 1
	else
		${echo} "\tConfirmed any active SWAP was disabled ..."
	fi
} #testForSwap()


unMountDisk()
{
	sudo umount ${DISK}?* 2>>/dev/null
	testMounts=$( sudo mount | grep ${DISK} )

	if [ -n "${testMounts}" ]
	then
		${echo} "\n\t ABORT.  Specified disk has active mounts.  Was unable to unmount partitions!\n" ; exit 1
	else
		${echo} "\tConfirmed ${DISK} is not mounted ..."
	fi
} #unMountDisk()


transient_PartitionSpecificationDefinition()
{
	###
	###	IMPORTANT:  NOT meant to be part of permanent script logic
	###

	###
	${echo} "\nCapture Partition Specifications (from command-line or config file) ..."
	###
	###	Guidance:
	###		- Hibernate target should be system's primary swap to
	###		  minimize delay from copying from swap to hibernate image
	###		- Hibernate target should be 1.5 to 2 times size of RAM
	###

	###
	###	FUTURES:
	###		- Calculate size of HIBERNATE swap space based on installed RAM
	###		- Calculate start and end point of each partition based
	###		  size specification for each partition
	###		- Create fstab entries using UUIDs the resulting disk layout
	###

	#cat >"${specifications}" <<EnDoFfIlE
	## partNum:partFsType:partStart:partEnd:partName:partMount
	#1	core	8KB	4MiB	GRUB	none
	#2	swap	4MiB	8GiB	HIBERNATE	none
	#3	ext4	8GiB	12GiB	BOOT		/boot
	#4	ext4	12GiB	200GiB	DB007_F1	/
	#5	ext4	200GiB	100%	DB007_F2	/DB007_F2
	#EnDoFfIlE

	#cat >"${specifications}" <<EnDoFfIlE
	## partNum:partFsType:partStart:partEnd:partName:partMount
	#1	linux-swap	4MiB	64MiB	HIBERNATE	none
	#2	ext4	64MiB	256MiB	BOOT		/altboot
	#3	ext4	256MiB	1GiB	DB008_F1	/altroot
	#4	ext4	1GiB	100%	DB008_F2	/DB008_F2
	#EnDoFfIlE

	cat >"${specifications}" <<EnDoFfIlE
# partNum:partFsType:partStart:partEnd:partName:partMount:partFlag
1	linux-swap	24KB	4MiB	GRUB	none	null
2	linux-swap	4MiB	64MiB	HIBERNATE	none	swap
3	ext4	64MiB	256MiB	BOOT		/altboot	boot
4	ext4	256MiB	1GiB	DB008_F1	/altroot	root
5	ext4	1GiB	100%	DB008_F2	/DB008_F2	null
EnDoFfIlE

	if [ ! -s "${specifications}" ]
	then
		${echo} "\tABORT - unable to create '${specifications}' for demo run.\n" >&2 ; exit 1
	fi
} #transient_PartitionSpecificationDefinition()


demoSetup()
{
	###
	###	Call function to create sample partitioning specification
	###
	transient_PartitionSpecificationDefinition

	###
	###	Create file that will behave as device
	###
	devFile="/site/DB007_F1/tmp/demo.img"

	locn="$(dirname ${devFile} )"
	if [ ! -d "${locn}" ]
	then
		${echo} "\tABORT - unable to access '${locn}/' for demo run.\n" >&2 ; exit 1
	fi

	${echo} "\n	DEMO:  Creating '${devFile}' to be used as device file ..."
	{
		sudo truncate --size 2G ${devFile}
		if [ ! -f "${devFile}" ]
		then
			${echo} "\tABORT - unable to create '${devFile}' for demo run.\n" >&2 ; exit 1
		fi
		ls -ld ${devFile}
	} | awk '{ printf("\t\t%s\n", $0 ) ; }'

	###
	###	Assign first available 'loop' device
	###
	DISK=$(sudo losetup --verbose --find --partscan --show ${devFile} )
	${echo} "\n	DEMO:  Created simulated drive using loop device '${DISK}' ..."
	{
		ls -ld ${DISK}
		echo ""
		df -h -a ${DISK}
		#echo "split--"
		#mount --verbose | grep ${DISK}
	} | awk '{ printf("\t\t%s\n", $0 ) ; }'
}

cleanup()
{
	if [ ${doDemo} -eq 1 ]
	then
		${echo} "\nPurging all elements of demo device ..."
		if [ -n "${mounts}" ]
		then
			#sudo umount --verbose /altboot /altroot /DB008_F2
			for mount in $(echo ${mounts} )
			do
				sudo umount --verbose ${mount}
			done
		fi

		test -n "${DISK}" && { sudo losetup --verbose --detach ${DISK} ; ${echo} "${DISK} detached ..." ; }

		test -n "${devFile}" && { sudo rm --verbose --force ${devFile} ; }
		${echo} "\tPurged.\n"
	fi
}


#################################################################################################
#################################################################################################


trap cleanup EXIT INT TERM

doit=0
doDemo=0

while [ $# -ne 0 ]
do
	case "${1}" in
		--demo )
			doDemo=1
			doit=1
			shift
			;;
		--layout )
			specifications="${2}"
			shift ; shift
			;;
		--device )
			doDemo=0
			DISK="${2}"
			shift ; shift
			;;
		--apply )
			doit=1
			shift ;
			;;
	esac
done

if [ ${doDemo} -eq 1 ]
then
	###
	###	Specify/Select value for partitioning specifications file
	###
	specifications="./partitions_demo_specs.conf"

	###
	###	Initialize demo processing session
	###
	demoSetup
fi



if [ -z "${specifications}" ]
then
	echo "\n\t ERROR:  File containing specs for device partitioning must be identified using '--layout' flag.\n" ; exit 1
fi

if [ -z "${DISK}" ]
then
	echo "\n\t ERROR:  Specification of device fullpath required using '--device' flag.\n" ; exit 1
fi



###
${echo} "\nVerifying the specified disk is recognized and accessible ..."
###
CMD="testForDisk"
test ${doit} -eq 1 && { ${CMD} ; }
test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }


##################################
##########   PHASE  I   ##########
##################################

###
${echo} "\nEnsuring that the disk has no active dependancy for swap ..."
###
CMD="testForSwap"
test ${doit} -eq 1 && { ${CMD} ; }
test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }


###
${echo} "\nEnsuring that the disk is not busy or mounted ..."
###
CMD="unMountDisk"
test ${doit} -eq 1 && { ${CMD} ; }
test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }


if [ -n "$(echo ${DISK} | grep -v 'loop' )" ]
then
	###
	${echo} "\nScanning '${DISK}' for badblocks before continuing ..."
	###
	CMD="sudo badblocks -nsv ${DISK}"
	#test ${doit} -eq 1 && { ${CMD} ; }
	test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }
else
	${echo} "\n\tDEMO:  Skipping badblocks scan for demo device ..."
fi


##################################
##########   PHASE II   ##########
##################################

${echo} "\nStarting Process of Partitioning and Formatting '${DISK}' ..."

###
${echo} "\nCreate new GPT-type partition table ..."
###
CMD="sudo parted --script ${DISK} mklabel gpt"
test ${doit} -eq 1 && { ${CMD} ; }
test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }






#IFSorig="${IFS}"

specsArray=()

export mount=""
indx=0

grep -v '^#' "${specifications}" |
while [ true ]
do
	read specsArray[${indx}]

	if [ $? -ne 0 ] ; then break ; fi

	test ${doDemo} -eq 1 && { ${echo} "\nINPUT:   specsArray[${indx}] = ${specsArray[${indx}]} " ; }

	###
	###	Parse partition values from command line or configuration file
	###

	###
	${echo} "\nExtract partition data from next entry in specifications array ..."
	###

	#IFS=':'
	read partNum partFsType partStart partEnd partName partMount partFlag <<< "${specsArray[${indx}]}"

	${echo} "\n	partNum		= ${partNum}
	partFsType	= ${partFsType}
	partStart	= ${partStart}
	partEnd		= ${partEnd}
	partName	= ${partName}
	partMount	= ${partMount}
	partFlag	= ${partFlag}"

	###
	${echo} "\nCreate a partition to specifications using 'parted mkpart ...' ..."
	###
	if [ "${partFlag}" = "null" ]
	then
		#echo "track1"
		CMD="sudo parted --script --align optimal ${DISK} mkpart ${partName} ${partFsType} ${partStart} ${partEnd}"
		test ${doit} -eq 1 && { ${CMD} ; }
		test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }
	else
		#echo "track2"
		CMD="sudo parted --script --align optimal ${DISK} mkpart ${partName} ${partFsType} ${partStart} ${partEnd} set ${partNum} ${partFlag} on"
		test ${doit} -eq 1 && { ${CMD} ; }
		test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }
	fi

	###
	${echo} "\nUpdate OS awareness of the disk's new structure using 'partprobe' ..."
	###
	CMD="sudo partprobe ${DISK}"
	test ${doit} -eq 1 && { ${CMD} ; }
	test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }

	sleep 2

	###
	${echo} "\nEnsure device node (udev) creation is complete ..."
	###
	CMD="udevadm settle"
	test ${doit} -eq 1 && { ${CMD} ; }
	test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }

	case ${DISK} in
		*loop* )
			PARTITION="${DISK}p${partNum}"
			;;
		/dev/sd* )
			PARTITION="${DISK}${partNum}"
			;;
		* )
			PARTITION="${DISK}${partNum}"
			;;
	esac

	###
	${echo} "\nFormat partition to specification ..."
	###
	case ${partFsType} in
		core )
			;;
		linux-swap )
			CMD="sudo mkswap ${PARTITION} -L '${partName}'"
			test ${doit} -eq 1 && { ${CMD} ; }
			test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }
			;;
		* )
			CMD="sudo mkfs.${partFsType} ${PARTITION} -L '${partName}'"
			test ${doit} -eq 1 && { ${CMD} ; }
			test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }
			;;
	esac

	if [ "${partMount}" != "none" ]
	then
		if [ ! -d "${partMount}" ]
		then
			CMD="sudo mkdir ${partMount}"
			test ${doit} -eq 1 && { ${CMD} ; }
			test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }
			if [ ! -d "${partMount}" ]
			then
				${echo} "\tABORT:  Failed to create '${partMount}'.\n" ; exit 1
			fi
		fi

		CMD="sudo mount -t ${partFsType} ${PARTITION} ${partMount}"
		RC=0
		test ${doit} -eq 1 && { ${CMD} ; RC=$? ; }
		test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }
		if [ ${RC} -eq 0 ]
		then
			mounts="${mounts} ${partMount}"
		else
			${echo} "\tABORT:  Failed to mount '${PARTITION}' at '${partMount}'.\n" ; exit 1
		fi
	fi

	${echo} "\n\t$(lsblk --paths ${PARTITION} | grep '/dev' )" ;

	${echo} "\n\t Hit return to continue ...\c" ; read k <&2

	indx=$( expr ${indx} + 1 )


done

#IFS="${IFSorig}"


###
${echo} "\nReport final state of disk partitioning ...\n"
###
CMD="sudo parted --script ${DISK} print"
test ${doit} -eq 1 && { ${CMD} | awk '{ printf("\t%s\n", $0 ) }' ; }
test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }

echo ""
CMD="sudo lsblk --list --path -o NAME,FSTYPE,PARTLABEL,UUID,SIZE,MOUNTPOINT,SUBSYSTEMS"
test ${doit} -eq 1 && { ${CMD} | grep ${DISK} | awk '{ printf("\t%s\n", $0 ) }' ; }
test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }


###
${echo} "\nReload the updated fstab ..."
###
CMD="sudo systemctl daemon-reload"
test ${doit} -eq 1 && { ${CMD} ; }
test ${doit} -eq 0 && { echo "DEFERRED:  ${CMD}" ; }


exit 0
exit 0
exit 0

I am also hoping that the Ubuntu Server install will place the correct "grub2 core.img" in that first partition labelled "GRUB". Can anyone confirm if that will be the case?


May I solicit feedback from the following individuals?
(Order in which names are listed has no significance.)

1 Like