changed a year ago
Published Linked with GitHub

如何
在外接式儲存裝置中
安裝可保留作業狀態的 Ubuntu 作業系統

https://hackmd.io/@brlin/portable-ubuntu-howto

尚未完成,歡迎分身伐樹


Powered by HackMD
「感恩HackMD!讚嘆HackMD!」
這是一個基於Markdown的HackMD簡報



歡迎於授權範圍內自由使用本作品
點此查看本簡報的來源碼


免責聲明

  • 以下全為個人經驗整理,不保證正確性
  • 對任何第三方的論述全為主觀論點,僅供參考且不應當作事實看待

基本知識


快閃記憶體(flash memory)儲存裝置的
可用性問題

  • 快閃記憶體的原理是透過電壓變更將電荷束縛入釋放出半導體電路組成的晶格(cell)來儲存資料
  • 每次的寫入操作都會破壞晶格束縛電荷能力,故快閃記憶體寫入次數有限,寫多了就會壞掉
  • 請避免在其中保存重要資料,壞了不保證能救回來

快閃記憶體(flash memory)儲存裝置的
笑能問題

  • 快閃記憶體隨身碟的讀寫效能主要由其使用的記憶體顆粒記憶體控制器能力決定
    • 說什麼 USB3.0(5000Mbps) 比 USB2.0(480Mbps) 快十倍的都是在講幹話
  • 效能依據分為連續讀取、連續寫入、隨機讀取、隨機寫入、每秒讀寫操作數、讀寫延遲等
    • 但是絕大多數都不會印在包裝上,
      因為要 costdown 騙你以為你買到好東西

快閃記憶體(flash memory)儲存裝置的
分區對齊問題

  • 記憶體分頁(page)是快閃記憶體能夠讀寫的最小單位(大小 2KiB~32KiB 不等)
  • 分頁寫入資料了之後必須經過抹除(erase)才能再寫入新的資料,抹除區塊(erase block)是快閃記憶體理論上能夠抹除的最小單位(大小 128KiB~2MiB 不等)
  • 多個抹除區塊組合為一個抹除區段(erase segment),這是實務上控制器抹除的最小單位(大小通常為 4MiB)

快閃記憶體(flash memory)儲存裝置的
分區對齊問題

  • 分頁、抹除區塊、抹除區段的大小可以用讀寫測試的方式猜出來
  • 取最小公倍數作為分區邊界起點較不會有不對齊造成的問題(4MiB是個安全值)

產品選購參考

強烈主觀意見,僅供參考


爛爛的便宜貨

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

老實但是還是一樣爛爛的便宜貨

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

國防布
(包裝上完全看不出來,碰運氣)


好的好野人

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →


不過CP值都比不上

固態硬碟+外接硬碟盒


目標

  • 支援舊式PC韌體(唸作BIOS)開機程序
  • 支援新式PC韌體(唸作UEFI)開機程序
  • 支援 UEFI SecureBoot

免責聲明

  • 很多電腦製造商韌體設計很爛,開不了請找他們算帳
  • 不保證你的隨身碟可以繼續長長久久的用下去
  • 絕對不幫忙救資料,這邊有幾家資料救援公司好便宜的

需要什麼工具

  • 一台電腦
  • 一個Debian系的GNU+Linux作業系統散佈版本
  • 網際網路存取能力
  • 一個外接式USB匯流排儲存裝置
    • 快閃記憶體隨身碟
    • 快閃記憶體固態硬碟 + 外接硬碟盒
    • 傳統磁盤轉動式硬碟 + 外接硬碟盒

Ubiquity 作業系統安裝程式

  • 很殘念地不支援UEFI規範內的可移除式磁碟開機程序,跳過

安裝媒體 Live 系統 + Persistence

還在學QAQ


Debootstrap土法煉鋼

  • 能夠在Debian系系統下佈署另一個Debian系系統的工具
  • 直接用它在隨身碟中建一個Ubuntu作業系統出來

桌面環境選擇

  • 都已經要到處插別人電腦了還是選輕量的吧
    • XFCE
    • LXDE
    • MATE

儲存空間分區
Partitioning

  • Microsoft Windows只支援存取可移除式磁碟的第一分區
  • Microsoft Windows的安裝程式只支援FAT、NTFS與ExFAT等(如果還有)檔案系統的安裝媒體
  • UEFI規範只保證主板韌體一定支援FAT檔案系統(其他的檔案系統要看有沒有驅動)
    • 有解,如Rufus開發者開發的UEFI:NTFS驅動

檔案系統選用

  • 有日誌(journaling)的檔案系統會增加讀寫負擔,不建議使用
  • 針對Flash儲存裝置設計的檔案系統較佳,但有系統、bootloader支援度的問題
    • Flash-Friendly File System(F2FS)
  • 什麼是Flash Translation Layer(FTL)?

檔案系統選用


分區參考1(EXT2)

# parted /dev/sdX --script unit MiB print
型號:JetFlash Transcend 64GB (scsi)
磁碟 /dev/sdX:60160MiB
磁區大小 (邏輯/物理):512B/512B # 假的
分割區:msdos
磁碟旗標: # 不需要 boot 旗標,會需要的你的主板韌體有問題

編號  起始點   結束點    大小      類型     檔案系統  旗標
 1    4.00MiB  5120MiB   5116MiB   primary  fat32     lba
 2    5120MiB  60160MiB  55040MiB  primary  ext2

分區參考2(F2FS)

# parted /dev/sdX --script unit MiB print
型號:JetFlash Transcend 64GB (scsi)
磁碟 /dev/sdX:60160MiB
磁區大小 (邏輯/物理):512B/512B
分割區:msdos
磁碟旗標:

編號  起始點   結束點    大小      類型     檔案系統  旗標
 1    4.00MiB  5004MiB   5000MiB   primary  fat32
 2    5004MiB  6004MiB   1000MiB   primary  ext2
 3    6004MiB  60160MiB  54156MiB  primary

檔案系統初始化

  • FAT檔案系統的標籤長度最多11個位元組
  • EXT檔案系統的標籤長度最多16個位元組

Debootstrap安裝基本系統

$ sudo mkdir --parents /mnt/debootstrap/rootfs
$ cd /mnt/debootstrap
$ sudo mount /dev/sdX3 rootfs
# debootstrap [OPTION]... <suite> <target> [<mirror> [<script>]]
$ sudo debootstrap xenial rootfs http://tw.archive.ubuntu.com/ubuntu

把其他檔案系統掛載在正確的位置

$ sudo mount /dev/sdX2 rootfs/boot
$ sudo mkdir rootfs/boot/efi
$ sudo mount /dev/sdX1 rootfs/boot/efi

變更根目錄(chroot)以取得該系統的 Root Shell

  • 程序太麻煩了,直接偷用 ArchLinux 的 arch-chroot 腳本吧
$ sudo arch-chroot rootfs

自訂主機名稱

由於是異機可用系統所以沒「主機」名稱可設,選個自己好記的吧:

$ sudo printf 'MY-USB\n' >/etc/hostname

主機名稱→網路地址映射設定也要新增對應的項目:

$ sudo printf '127.0.1.1\tMY-USB\n' >>/etc/hosts
$ sudo hostname -f /etc/hostname
$ bash

參考資料

  • hostname(5) 的使用手冊頁面(manpage)
  • hosts(5) 的使用手冊頁面
  • hostname(1) 的使用手冊頁面

WORKAROUND
修正 APT 軟體來源清單

Debootstrap 預設給的軟體來源清單是不完整的,弄一個相對完整的給它

$ sudo apt install nano # 或是你慣用的純文字文件編輯器
$ sudo cp --force /usr/share/doc/apt/examples/sources.list /etc/apt/sources.list
$ sudo apt edit-sources # 注意目前 Ubuntu 16.04 提供的範本使用的是 14.04(trusty) 的軟體來源,請手動修正

全系統升級

由於使用的 suite 是 xenial 而非 xenial-updates 故需要如此

$ sudo apt update # 更新本地軟體來源快取資料
$ sudo apt full-upgrade

初始化語系設定

$ sudo dpkg-reconfigure locales

# 勾選 `zh_TW UTF-8 UTF-8`、`zh_HK UTF-8 UTF-8` 跟 `zh_CN UTF-8 UTF-8`
# 預設語系選 zh_TW.UTF-8

$ sudo update-locale LANGUAGE=zh_TW:zh_HK:zh:en


安裝 Linux 作業系統核心

基本系統預設是沒有作業系統核心的(因為某些情境其實不需要)

$ sudo apt install linux-signed-generic
# 安裝舊式PC開機支援的 GRUB 的提問,選擇根裝置(/dev/sdX)而非底下的分區裝置(/dev/sdXN)

這邊直接安裝簽好 SecureBoot 的版本(-signed)


安裝 GRUB 開機載入程式
(舊式PC開機支援)

一樣,基本系統預設是沒有開機載入程式(bootloader)的(因為某些情境不需要),這個步驟實際上已在上個步驟進行

$ sudo apt install grub-pc-bin grub2-common 
$ sudo grub-install --verbose /dev/sdX
  • 故意不裝 grub-pc 軟體包,因為會跟等一下安裝的 grub-efi-amd64-signed 軟體包衝突
  • 有 30KiB 附近大小的 core.img 程式被寫進MBR跟第一分區間的間隙

停用 GRUB 其他系統開機選單自動產生

$ sudo chmod a-x /etc/grub.d/30_os-prober
$ sudo update-grub

新式PC開機支援
(含Secureboot簽章)

$ sudo apt install grub-efi-amd64-signed shim-signed grub-efi-ia32-bin
$ sudo grub-install --target=x86_64-efi --uefi-secure-boot --removable --verbose
$ sudo grub-install --target=i386-efi --removable --verbose
$ sudo sh -c 'mkdir --parents /boot/.disk && touch /boot/.disk/info' # 讓有簽章的 GRUB 能找到 /boot 分區的 workaround
  • grub-efi-ia32-bin 提供 Intel 32位元處理器架構的UEFI韌體(但沒有Secureboot簽章)
  • 目前預設只支援內接磁碟開機方式,外接式的要自己修

新式PC開機支援
(含Secureboot簽章)

/boot/efi
└── EFI
    ├── BOOT
    │   ├── BOOTIA32.EFI # 沒有簽章的 Intel 32位元處理器架構 GRUB 開機載入程式
    │   ├── BOOTX64.EFI # 有簽 Microsoft 簽章的 Intel 64位元處理器架構 SHIM 開機載入程式,可驗證 Canonical 簽章
    │   ├── grub.cfg # 實際上這個不會被讀到
    │   ├── grub.efi # 跟 BOOTIA32.EFI 一樣,因軟體缺陷冗餘生出來的檔案?
    │   ├── grubx64.efi # 有簽 Canonical 簽章的 GRUB 開機載入程式
    │   └── mmx64.efi # 自簽章需要
    └── ubuntu # 完全用不到但因為 GRUB 的軟體缺陷會自動安裝
        ├── fw
        ├── fwupx64.efi
        ├── grub.cfg
        ├── grubx64.efi
        ├── mmx64.efi
        └── shimx64.efi

WORKAROUND
修正 GRUB 沒有將 root 核心參數設定為 UUID 的問題

  • 由於 GNU GRUB 的軟體缺陷,可被Linux作業系統核心識別 UUID 的 F2FS 根目錄系統被判定為無法識別而汰退為保存對異機使用不友善的相對路徑(如 /dev/sdX3),此問題修正前需要手動解決才不會開機時無法掛載根目錄檔案系統
# sudo mkdir /etc/default/grub.d
$ sudo nano /etc/default/grub.d/10-local-force-to-use-uuid-for-rootfs-device-specification.cfg
# 在 GRUB_CMDLINE_LINUX_DEFAULT 的值後面加上 `root=UUID=〈根目錄檔案系統的UUID,查閱 `blkid` 命令的輸出〉` 其會覆越掉前面自動插入的 root 核心參數設定
$ sudo update-grub # 重新產生開機選單

WORKAROUND
強制作業系統核心以文字模式啟動

在部份的硬體配置下早期的開機訊息將無法顯示在螢幕上,此法可以迴避此問題

printf "# Force boot in text mode to avoid blank screen during early boot stages.\nGRUB_GFXPAYLOAD_LINUX=text\n" > /etc/default/grub.d/10-local-force-text-mode.cfg

撰寫檔案系統掛載設定
(/etc/fstab)

參閱 fstab(5) 的 manpage 使用手冊頁面

$ sudoedit /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>

撰寫檔案系統掛載設定
(/etc/fstab)

  • file system 欄位建議使用 UUID
  • FAT 檔案系統的 type 為 vfat,且 options 須填入 utf8=1 以支援 Unicode 檔名
  • options 如果沒有已知的就填 defaults
  • dump 欄位都設定 0
  • pass 欄位根目錄檔案系統設定為 1,其他的設定為 2

安裝 F2FS 的使用者空間工具以讓 F2FS 檔案系統在開機時可以被檢查

$ sudo apt install f2fs-tools
# 檢查有沒有包入initramfs
$ lsinitramfs /boot/initrd* | grep 'fsck\.f2fs'
sbin/fsck.f2fs

將 F2FS 檔案系統驅動核心模組打包入作業系統初始化時期運行記憶體檔案系統(initramfs)中

這樣系統才能成功掛載根目錄檔案系統

注意:理論上應該要自動包入才對,可能是個軟體缺陷


將 F2FS 檔案系統驅動核心模組打包入作業系統初始化時期運行記憶體檔案系統(initramfs)中

$ printf '# F2FS根目錄檔案系統掛載支援\nf2fs\n\n' \
     | sudo tee --append /etc/initramfs-tools/modules
# F2FS根目錄檔案系統掛載支援
f2fs

$ update-initramfs -k all -uv
# 檢查有沒有包入核心模組
$ lsinitramfs /boot/initrd* | grep 'f2fs\.ko'

WORKAROUND
迴避F2FS沒有依賴crc32模組的問題
Linux作業系統核心第187471號軟體缺陷

$ printf '# WORKAROUND: 迴避F2FS沒有依賴crc32模組的問題\n# https://bugzilla.kernel.org/show_bug.cgi?id=187471\ncrypto-crc32\n\n' \
     | sudo tee --append /etc/initramfs-tools/modules
# WORKAROUND: 迴避F2FS沒有依賴crc32模組的問題
# https://bugzilla.kernel.org/show_bug.cgi?id=187471
crypto-crc32

$ update-initramfs -k all -uv

(選用)加快F2FS乾淨檔案系統的檢查速度

如果開機的時候一直卡在呼叫 fsck.f2fs 的話可以將 fastboot 參數加入 Linux 作業系統核心參數列中

$ sudoedit /etc/fstab
# 在 / 項目的掛載選項中加入 `fastboot`

新增一般使用者帳號

記得給他 sudo 的使用權限

$ sudo adduser _user_name_
$ sudo gpasswd --add _user_name_ sudo

安裝 Xubuntu 桌面版

# apt install xubuntu-desktop

注意:如果設定軟體途中在 blueman 軟體包發生錯誤,此為 blueman 軟體包打包的已知缺陷:#878814 - fails to install in a chroot - Debian Bug report logs


搞定收工!

# exit
$ sudo umount --recursive rootfs
$ udisksctl power-off --block-device /dev/sdX
# 可以拔儲存裝置了

參考資料
快閃記憶體基本知識方面


參考資料
開機相關


參考資料
系統設定


參考資料
其他

  • update-grub-gfxpayload(8) 使用手冊頁面:
	‘GRUB_GFXPAYLOAD_LINUX’

	Set to ‘text’ to force the Linux kernel to boot in normal text mode, ‘keep’ to preserve the graphics mode set using ‘GRUB_GFXMODE’, ‘widthxheight’\[‘xdepth’\] to set a particular graphics mode, or a sequence of these separated by commas or semicolons to try several modes in sequence. See [gfxpayload](https://www.gnu.org/software/grub/manual/grub/grub.html#gfxpayload).

	Depending on your kernel, your distribution, your graphics card, and the phase of the moon, note that using this option may cause GNU/Linux to suffer from various display problems, particularly during the early part of the boot sequence. If you have problems, set this option to ‘text’ and GRUB will tell Linux to boot in normal text mode.
Select a repo