Scripting

執行我的程序的可啟動 U 盤

  • April 26, 2020

我正在開發一個 Python 程序並想創建一個可啟動的 USB 記憶棒來執行我的程序

要求:

  1. USB 記憶棒應該執行 Linux,包括一些標準依賴項(LAN/WLAN 訪問、GUI、連接到投影儀的可能性)
  2. 我應該能夠為我的程序安裝依賴項(數據庫、一些 python 依賴項等)
  3. 我想避免任何手動設置:我需要一個生成 U 盤的腳本,包括我的程序、任何依賴項和所需的驅動程序(理想情況下,想想docker

實現這一目標的最簡單方法是什麼?


我考慮過創建一個可啟動的 Ubuntu並手動安裝我的程序和任何依賴項。這解決了 1-2,但不是 3。自動自定義可啟動的 Ubuntu 似乎並非易事……

在askubuntu的幫助下,我想出了一個適用於我的特定於 Ubuntu 的解決方案

  1. 在快閃記憶體驅動器上安裝 Ubuntu/Lubuntu ==============================

這些說明鬆散地遵循這個答案

(準備)

  • 創建實時 USB 或 DVD。
  • 關閉並拔下電腦。
  • 從您的電腦上拔下所有硬碟驅動器。
  • 重新插入電腦。
  • 在 UEFI 設置中禁用安全啟動和快速啟動(具體步驟取決於供應商)

(執行安裝程序)

  • 插入 Live USB 或 Live DVD。
  • 啟動電腦,USB/DVD 應該會啟動。
  • 選擇安裝 Ubuntu。
  • 插入新的目標驅動器以安裝 Ubuntu。
  • 按照說明進行操作。
  • 不要安裝“第三方軟體”,因為它可能無法在其他機器上執行。
  • 在“安裝類型”中選擇“其他”。
  • 選擇“繼續”。
  • 選擇目標驅動器(在我的情況下是 /dev/sdb)
  • 選擇“新建分區表”和“繼續”。

(EFI 分區)

  • 點擊“可用空間”和“+”。
  • “大小”:100 MB
  • 選擇“主要”
  • “位置”:“這個空間的開始”
  • “用作”:“EFI 系統分區”
  • 選擇“確定”

(/ 分割)

  • 點擊“可用空間”,然後點擊“+”。
  • “大小”:7800 MB(或其他)
  • 選擇“主要”
  • “位置”:“這個空間的開始”
  • “用作”:“Ext4”
  • 掛載點:“/”
  • 選擇“確定”

(重要的)

  • 確保“用於引導載入程序安裝的設備”指向快閃記憶體驅動器的根目錄(在我的例子中是 /dev/sdb)。
  • 點擊“立即安裝”和“繼續”。
  • 按照說明進行操作。
  • 等到安裝完成。

(包起來)

  • 關閉電腦並插入硬碟。

2.保存生成的快閃記憶體驅動器

接下來,將生成的圖像保存到您的機器上。我寫了一個腳本來處理這一步。

#!/bin/bash
#
# Saves flash drive partitions to disk
#
# Example Usage:
# ./copy.sh /dev/sde ./images

# enable bash strict mode
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
set -euo pipefail
IFS=$'\n\t'

##########
# INPUTS #
##########

# Checking inputs
if [ $# -ne 2 ]; then
 echo "USAGE: ./copy.sh DEVICE OUTPUTDIR"
 echo "Available devices:"
 sudo lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL,UUID,MODEL
 exit
fi

# parse inputs
DEVICE=$1
OUTPUTDIR=$2
EFIFILE=$OUTPUTDIR/ubuntu-efi.img
ROOTFILE=$OUTPUTDIR/ubuntu-root.img
PARTITIONFILE=$OUTPUTDIR/partitions.txt

# Display helpful information
echo "Saving device $DEVICE to $OUTPUTDIR:"
sudo lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL,UUID,MODEL $DEVICE

# Confirm
read -r -p "Continue? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then
   echo "Start copying (this could take a long time)..."
else
   echo "Aborting" >&2
   exit
fi

mkdir -p "$OUTPUTDIR"

########
# SAVE #
########

# record sizes
sudo fdisk -l | grep ${DEVICE} | sed "s#${DEVICE}#/dev/sdX#g" > $PARTITIONFILE

# dd: copy and convert
# if: source disk
# bs: sector size value from fdisk output
# count: last "end" sector from fdisk output incremented by one
# conv=sync,noerror: sync I/O and don't stop in case of errors on the source disk
sudo dd if=${DEVICE}1 conv=sync,noerror of=$EFIFILE
sudo dd if=${DEVICE}2 conv=sync,noerror of=$ROOTFILE

3.安裝到新驅動器

最後,將保存的映像安裝到新的快閃記憶體驅動器。同樣,我編寫了一個腳本來處理這一步。

#!/bin/bash
#
# Installs Ubuntu/Lubuntu to flash drive
#
# Example Usage:
# ./copy.sh /dev/sde ./images

###########
# HELPERS #
###########

# enable bash strict mode
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
set -euo pipefail
IFS=$'\n\t'

# directory containing this script
BASEDIR="$( dirname "$0")"

# run commands at the end of the script (even on errors)
EXIT=""
function addExit {
   # call the argument before ending the script
   EXIT="$@ ; $EXIT"
   trap "echo 'Final tasks before exit...' ; $EXIT" EXIT HUP TERM INT QUIT
}

##########
# INPUTS #
##########

# Checking inputs
if [ $# -ne 2 ]; then
 echo "USAGE: ./copy.sh DEVICE SOURCEDIR"
 echo "Available devices:"
 sudo lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL,UUID,MODEL
 exit
fi

# parse inputs
DEVICE="$1"
SOURCEDIR="$2"
MNT=/mnt

# Display helpful information
echo "Installing to device $DEVICE:"
sudo lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL,UUID,MODEL $DEVICE

# Confirm
read -r -p "Continue? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then
   echo "Preparing partitions..."
else
   echo "Aborting" >&2
   exit
fi

# record sizes
PARTITIONFILE="$SOURCEDIR/partitions.txt"
EFISTART=$( cat "$PARTITIONFILE" | grep /dev/sdX1 | awk -F" "  '{ print $2 }')
EFIEND=$(   cat "$PARTITIONFILE" | grep /dev/sdX1 | awk -F" "  '{ print $3 }')
ROOTSTART=$(cat "$PARTITIONFILE" | grep /dev/sdX2 | awk -F" "  '{ print $2 }')
ROOTEND=$(  cat "$PARTITIONFILE" | grep /dev/sdX2 | awk -F" "  '{ print $3 }')

#######################
# COPY TO FLASH DRIVE #
#######################

# umount all paritions of this device
echo "Unmounting all partitions of $DEVICE..."
sudo umount $DEVICE?* || true

# create partition table
sudo wipefs --all $DEVICE
sudo parted $DEVICE mklabel gpt

# efi partition
sudo parted $DEVICE mkpart primary fat32 ${EFISTART}s ${EFIEND}s
sudo parted $DEVICE set 1 boot on
sudo parted $DEVICE set 1 esp on

echo "Start copying efi..."
EFIFILE="$SOURCEDIR/ubuntu-efi.img"
sudo dd if="$EFIFILE" of=${DEVICE}1

# root partition
sudo parted $DEVICE mkpart primary ext4 ${ROOTSTART}s ${ROOTEND}s
# sudo parted $DEVICE name 2 UbuntuUSB

echo "Start copying root (this could take a long time)..."
ROOTFILE="$SOURCEDIR/ubuntu-root.img"
sudo dd if="$ROOTFILE" of=${DEVICE}2

##################
# PREPARE CHROOT #
##################
# prepare running command in root directory of new installation

sudo mount ${DEVICE}2 $MNT
addExit "sudo umount $MNT"

sudo mount ${DEVICE}1 $MNT/boot/efi
addExit "sudo umount $MNT/boot/efi"

for i in /dev /dev/pts /proc /sys; do
   sudo mount -B $i ${MNT}$i
   addExit "sudo umount ${MNT}$i"
done
sudo cp /etc/resolv.conf $MNT/etc/
modprobe efivars

########
# GRUB #
########

# update grub
sudo chroot $MNT grub-install -d /usr/lib/grub/x86_64-efi --efi-directory=/boot/efi/ --removable ${DEVICE}

#############
# CUSTOMIZE #
#############

# prepare scripts
sudo cp -r "${BASEDIR}/customize" "$MNT/opt/customize"

# install software
sudo chroot $MNT "/opt/customize/software.sh"

此腳本還使用以下腳本安裝其他自定義軟體./customize/software.sh

#!/bin/bash

# enable bash strict mode
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
set -euo pipefail
IFS=$'\n\t'

###########
# PREPARE #
###########

# avoid locale issues and in order to import GPG keys
export HOME=/root
export LC_ALL=C

#######
# APT #
#######

apt-get update -y
apt-get clean
apt-get -y autoremove --purge

####################
# INSTALL SOFTWARE #
####################

# -y: auto-confirm
# -qq: quiet installation
apt-get install -y -qq \
   htop \
   gparted \
   build-essential

這種方法應該有效,我認為這很容易

  • 使用工具mkusb從 Ubuntu iso 文件創建永久實時驅動器。
  • 然後安裝您需要的工具並進行調整。
  • 之後,您可以創建該驅動器的映像。
  • 最後從映像複製到其他 USB 驅動器(至少與原始系統的 USB 驅動器一樣大)。您可以將這些複製的驅動器分發給系統的最終使用者。

也可以讓最終使用者下載圖像的壓縮版本並將其解壓縮到他們自己的 USB 驅動器中。mkusb 可以直接從使用gzip(faster) 和xz(better compression) 壓縮的圖像中完成,但也可以使用其他工具完成,如果需要,也可以在 Windows 中完成。

引用自:https://unix.stackexchange.com/questions/558941