Skip to content

Instantly share code, notes, and snippets.

@Knogle
Last active April 10, 2024 22:36
Show Gist options
  • Save Knogle/fc1ee304ed6f1d76876157acbd659ed6 to your computer and use it in GitHub Desktop.
Save Knogle/fc1ee304ed6f1d76876157acbd659ed6 to your computer and use it in GitHub Desktop.
EXPLAIN: This Bash script provides functionality to set up and mount loop devices in Linux. It supports creating loop devices for existing files or generating new files with specified or random sizes to be used as loop devices.
#!/bin/bash
# Function to display help message
show_help() {
echo "Usage: $0 [OPTION]... [FILE]"
echo "Set up and mount loop devices for a given file, create new files of specified or random size and mount them, or create a ramdisk of specified size and mount it."
echo ""
echo " --help display this help and exit"
echo " automount <Size> automatically create a file of specified size, set up and mount it."
echo " polymount <Size> <N> create N files of specified size, set up and mount them."
echo " polymount rand <N> <MinSize> <MaxSize> create N files with random sizes between MinSize and MaxSize, set up and mount them."
echo " tmpfsmount <Size> create and mount a ramdisk of specified size as a loop device."
echo " <FilePath> path to the existing file to set up and mount"
echo ""
echo "Examples:"
echo " $0 /path/to/your/file.img Set up an existing file as a loop device."
echo " $0 automount 1M Create a 1M-sized file and set it up as a loop device."
echo " $0 polymount 1M 5 Create 5 1M-sized files and set them up as loop devices."
echo " $0 polymount rand 3 10M 100M Create 3 files with random sizes between 10M and 100M, and set them up as loop devices."
echo " $0 tmpfsmount 1G Create a 1G ramdisk and set it up as a loop device."
echo ""
echo "Note: Run this script with root permissions or using sudo."
}
# Other function definitions remain unchanged
# New function to create and mount a ramdisk as a loop device
tmpfsmount() {
RAMDISK_SIZE=$1
SIZE_VALUE=$(echo $RAMDISK_SIZE | sed -E 's/[^0-9]//g')
SIZE_UNIT=$(echo $RAMDISK_SIZE | sed -E 's/[0-9]//g' | tr '[a-z]' '[A-Z]')
case $SIZE_UNIT in
G) BYTE_SIZE=$(($SIZE_VALUE * 1024 * 1024 * 1024)) ;;
M) BYTE_SIZE=$(($SIZE_VALUE * 1024 * 1024)) ;;
*) echo "Unknown size unit: $SIZE_UNIT" >&2; exit 1 ;;
esac
TMPDIR=$(mktemp -d)
if [ ! -d "$TMPDIR" ]; then
echo "Failed to create temporary directory."
exit 1
fi
sudo mount -t tmpfs -o size=$BYTE_SIZE tmpfs $TMPDIR
echo "Ramdisk mounted at $TMPDIR"
FILEPATH="${TMPDIR}/ramdisk.img"
dd if=/dev/zero of="$FILEPATH" bs=1$SIZE_UNIT count=$SIZE_VALUE status=progress
setup_and_mount "$FILEPATH"
}
# Function to automatically create a file of a specified size and set up and mount it as a loop device
automount() {
GUID=$(uuidgen) # Generate a unique identifier for the filename
FILENAME="${GUID}.img" # Create a filename with the .img extension
FILEPATH="/tmp/${FILENAME}" # Define the full path in /tmp directory
FILESIZE=$1 # The size of the file to be created, passed as an argument
# Extract the numeric value and the unit (G,M) from the file size argument
SIZE_VALUE=$(echo $FILESIZE | sed -E 's/[^0-9]//g')
SIZE_UNIT=$(echo $FILESIZE | sed -E 's/[0-9]//g')
# Create a file of specified size using dd
dd if=/dev/zero of="$FILEPATH" bs=1$SIZE_UNIT count=$SIZE_VALUE status=progress
# Call function to set up and mount the file as a loop device
setup_and_mount "$FILEPATH"
}
# Convert size specification to bytes
convert_size_to_bytes() {
SIZE=$1
NUMBER=$(echo $SIZE | sed -E 's/[^0-9]//g')
UNIT=$(echo $SIZE | sed -E 's/[0-9]//g' | tr '[a-z]' '[A-Z]')
case $UNIT in
G) BYTE_SIZE=$(($NUMBER * 1024 * 1024 * 1024)) ;;
M) BYTE_SIZE=$(($NUMBER * 1024 * 1024)) ;;
*) echo "Unknown size unit: $UNIT" >&2; exit 1 ;;
esac
echo $BYTE_SIZE
}
# Generate a random size within specified range
generate_random_size() {
MIN_SIZE_BYTES=$1
MAX_SIZE_BYTES=$2
RANGE=$(($MAX_SIZE_BYTES - $MIN_SIZE_BYTES + 1))
RANDOM_BYTES=$(awk -v min=$MIN_SIZE_BYTES -v range=$RANGE 'BEGIN{srand(); print int(min+rand()*range)}')
echo $RANDOM_BYTES
}
# Create and mount loop devices with files of specified or random sizes
polymount() {
N=$1
SIZE_TYPE=$2
declare -a LOOPDEVICES
declare -a FILEPATHS
if [ "$SIZE_TYPE" == "rand" ]; then
MIN_SIZE=$(convert_size_to_bytes $3)
MAX_SIZE=$(convert_size_to_bytes $4)
fi
for ((i=1; i<=N; i++)); do
if [ "$SIZE_TYPE" == "rand" ]; then
SIZE_BYTES=$(generate_random_size $MIN_SIZE $MAX_SIZE)
SIZE_VALUE_MB=$(($SIZE_BYTES / 1024 / 1024))
FILESIZE="${SIZE_VALUE_MB}M"
else
SIZE_VALUE_MB=$(echo $SIZE_TYPE | sed -E 's/[^0-9]//g')
FILESIZE="${SIZE_VALUE_MB}M"
fi
GUID=$(uuidgen)
FILENAME="${GUID}.img"
FILEPATH="/tmp/${FILENAME}"
dd if=/dev/zero of="$FILEPATH" bs=1M count=$SIZE_VALUE_MB status=progress
LOOPDEVICE=$(sudo losetup -fP --show "$FILEPATH")
if [ -z "$LOOPDEVICE" ]; then
echo "Error creating loop device for $FILEPATH."
continue
fi
echo "Loop device set up: $LOOPDEVICE"
LOOPDEVICES+=("$LOOPDEVICE")
FILEPATHS+=("$FILEPATH")
done
echo "All loop devices set up. Press [Enter] to detach all loop devices."
read
for LOOPDEVICE in "${LOOPDEVICES[@]}"; do
sudo losetup -d "$LOOPDEVICE"
echo "Loop device detached: $LOOPDEVICE"
done
for FILEPATH in "${FILEPATHS[@]}"; do
rm -f "$FILEPATH"
echo "Temporary file deleted: $FILEPATH"
done
}
# Function to set up and mount the loop device
setup_and_mount() {
FILEPATH="$1"
LOOPDEVICE=$(sudo losetup -fP --show "$FILEPATH")
if [ -z "$LOOPDEVICE" ]; then
echo "Error creating the loop device."
exit 1
fi
echo "Loop device set up: $LOOPDEVICE"
read -p "Press [Enter] to detach the loop device."
cleanup "$LOOPDEVICE" "$FILEPATH"
}
# Function for cleanup: detaching the loop device, and deleting the file
cleanup() {
LOOPDEVICE=$1
FILEPATH=$2
sudo losetup -d "$LOOPDEVICE"
echo "Loop device detached: $LOOPDEVICE"
if [[ "$FILEPATH" == /tmp/*.img ]]; then
rm -f "$FILEPATH"
echo "Temporary file deleted: $FILEPATH"
fi
}
# Main logic
case "$1" in
--help)
show_help
;;
automount)
if [ "$#" -ne 2 ]; then
echo "Usage: $0 automount <Size>"
exit 1
fi
automount $2
;;
polymount)
if [ "$2" == "rand" ] && [ "$#" -ne 5 ]; then
echo "Usage: $0 polymount rand <N> <MinSize> <MaxSize>"
exit 1
elif [ "$#" -ne 3 ] && [ "$2" != "rand" ]; then
echo "Usage: $0 polymount <Size> <N>"
exit 1
fi
polymount $3 $2 $4 $5
;;
tmpfsmount)
if [ "$#" -ne 2 ]; then
echo "Usage: $0 tmpfsmount <Size>"
exit 1
fi
tmpfsmount $2
;;
*)
if [ "$#" -ne 1 ]; then
show_help
exit 1
fi
setup_and_mount $1
;;
esac
@PartialVolume
Copy link

Very nice, I'll give that a try. Thanks.

@Knogle
Copy link
Author

Knogle commented Apr 10, 2024

Very nice, I'll give that a try. Thanks.

I've created a new version. Now with tmpfsmount you can specifiy a size, and mount a loop device as ramdisk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment