2018年5月

在树莓派Zero W上安装alpine linux系统

树莓派Zero W

PI-Zero-W.jpg

Raspberry Pi Zero 系列是我见过的最小的电脑系统。Zero W 是 Zero 之后发布的升级版本,它有一个支持硬件浮点运算的ARM架构1GHz 单核 CPU,512MB 的 RAM ,一个 Mini HDMI 接口,一个 USB OTG 接口,使用 Micro USB 供电。相比 Zero , Zero W 加入了 WiFi 和蓝牙模块,让连网变得更加方便。

Alpine Linux

Alpine Linux 是一款面向专业用户的 Linux 发行版,以小巧、简单、安全为主要特点。它使用 musl libc 和 busybox 构建,相比其它 Linux 发行版,它的核心只有 8MB ,安装之后也只有大约 130M。非常适合用在性能有限的设备上。

开始前的准备

在安装之前,先需要准备好必要的设备:

  • Micro SD 卡(树莓派没有内置存储空间, SD 卡相当于它的硬盘)
  • Micro SD 读卡器(用于在 PC 上写入树莓派的系统镜像)
  • 支持 HDMI 接口的显示器(其它接口也可以但需要转接线)
  • Mini HDMI 转 HDMI 转接头
  • USB 键盘
  • USB OTG 线
  • 5V 2A 的 USB 电源适配器(普通 Android 手机充电器就可以)
  • Micro USB 电源线( USB Type-C 的线用不了)

下载 Alpine Linux 镜像

在 Alpine Linux 的下载页有树莓派专用镜像,选择下载 armhf 版本。 armhf 是带硬件浮点运算支持的 ARM 架构 CPU,除梅莓派一代之外,其它机型的 CPU 都带有 hf 支持。

磁盘分区

我们需要将 Micro SD 卡分成两个磁盘分区:一个 256MB 的 FAT32 格式启动分区,树莓派只能识别 FAT32 ,不支持最新的 exFAT;一个 ext4 的 Linux 分区占用剩余的空间,我们将把 Alpine Linux 安装到这里。

我的 PC 上装的是 Ubuntu Linux 系统,我将使用 fdisk 命令进行磁盘分区。如果你使用 Windows 或者 Mac 系统,可以先用磁盘管理器创建一个 256MB 的 FAT32 的分区用于放置启动文件,ext4 格式的分区可以在安装过程中创建。

在插上读卡器之前,先用ls命令查看一个现在的硬盘分区都有哪些:

# ls /dev/sd*
/dev/sda  /dev/sda1 /dev/sdb /dev/sdb1 /dev/sdb2

我的电脑上有两块硬盘,一块 SSD 和一块机械硬盘,分别是sdasdb。然后将 Micro SD 卡插入读卡器,连接到 PC 上。再次用ls命令查看硬盘分区:

# ls /dev/sd*
/dev/sda /dev/sda1 /dev/sdb /dev/sdb1 /dev/sdb2 /dev/sdc /dev/sdc1

于是sdc应该就是新接上的 SD 卡无疑了。用fdisk命令对它进行分区:

# fdisk /dev/sdc

先用p命令打印一下现有的分区,千万不要搞错磁盘,不然会丢数据。


Welcome to fdisk (util-linux 2.27.1). Changes will remain in memory only, until you decide to write them. Be careful before using the write command. Command (m for help): p Disk /dev/sdc: 7.4 GiB, 7948206080 bytes, 15523840 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x00000000 Device Boot Start End Sectors Size Id Type /dev/sdc1 8192 15523839 15515648 7.4G b W95 FAT32

我用的是一张 8GB 的 SD 卡,可以看到出厂的时候已经分好了一个 FAT32 的分区。我会重新创建分区表,并划分分区。用o命令重新创建一个全新的 MSDOS 分区表。

Command (m for help): o
Created a new DOS disklabel with disk identifier 0xa159d333.

然后用n命令创建分区,选择p主要分区,编号1,容量+256MB

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p):

Using default response p.
Partition number (1-4, default 1):
First sector (2048-15523839, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-15523839, default 15523839): +256M

Created a new partition 1 of type 'Linux' and of size 256 MiB.

默认创建出来的分区类型是 Linux 类型,需要再自己修改分区类型。用t命令修改分区类型,L查看所有类型列表, FAT32 的分区类型码是c W95 FAT32 (LBA)。

Command (m for help): t
Selected partition 1
Partition type (type L to list all types): L

 0  Empty           24  NEC DOS         81  Minix / old Lin bf  Solaris
 1  FAT12           27  Hidden NTFS Win 82  Linux swap / So c1  DRDOS/sec (FAT-
 2  XENIX root      39  Plan 9          83  Linux           c4  DRDOS/sec (FAT-
 3  XENIX usr       3c  PartitionMagic  84  OS/2 hidden or  c6  DRDOS/sec (FAT-
 4  FAT16 <32M      40  Venix 80286     85  Linux extended  c7  Syrinx
 5  Extended        41  PPC PReP Boot   86  NTFS volume set da  Non-FS data
 6  FAT16           42  SFS             87  NTFS volume set db  CP/M / CTOS / .
 7  HPFS/NTFS/exFAT 4d  QNX4.x          88  Linux plaintext de  Dell Utility
 8  AIX             4e  QNX4.x 2nd part 8e  Linux LVM       df  BootIt
 9  AIX bootable    4f  QNX4.x 3rd part 93  Amoeba          e1  DOS access
 a  OS/2 Boot Manag 50  OnTrack DM      94  Amoeba BBT      e3  DOS R/O
 b  W95 FAT32       51  OnTrack DM6 Aux 9f  BSD/OS          e4  SpeedStor
 c  W95 FAT32 (LBA) 52  CP/M            a0  IBM Thinkpad hi ea  Rufus alignment
 e  W95 FAT16 (LBA) 53  OnTrack DM6 Aux a5  FreeBSD         eb  BeOS fs
 f  W95 Ext'd (LBA) 54  OnTrackDM6      a6  OpenBSD         ee  GPT
10  OPUS            55  EZ-Drive        a7  NeXTSTEP        ef  EFI (FAT-12/16/
11  Hidden FAT12    56  Golden Bow      a8  Darwin UFS      f0  Linux/PA-RISC b
12  Compaq diagnost 5c  Priam Edisk     a9  NetBSD          f1  SpeedStor
14  Hidden FAT16 <3 61  SpeedStor       ab  Darwin boot     f4  SpeedStor
16  Hidden FAT16    63  GNU HURD or Sys af  HFS / HFS+      f2  DOS secondary
17  Hidden HPFS/NTF 64  Novell Netware  b7  BSDI fs         fb  VMware VMFS
18  AST SmartSleep  65  Novell Netware  b8  BSDI swap       fc  VMware VMKCORE
1b  Hidden W95 FAT3 70  DiskSecure Mult bb  Boot Wizard hid fd  Linux raid auto
1c  Hidden W95 FAT3 75  PC/IX           bc  Acronis FAT32 L fe  LANstep
1e  Hidden W95 FAT1 80  Old Minix       be  Solaris boot    ff  BBT
Partition type (type L to list all types): c
Changed type of partition 'Linux' to 'W95 FAT32 (LBA)'.

将分区1标记为可启动:

Command (m for help): a
Selected partition 1
The bootable flag on partition 1 is enabled now.

创建第二块分区, Linux 类型,占用剩余所有空间:

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2):
First sector (526336-15523839, default 526336):
Last sector, +sectors or +size{K,M,G,T,P} (526336-15523839, default 15523839):

Created a new partition 2 of type 'Linux' and of size 7.2 GiB.

可以再用p命令看看分区是否正确:

Command (m for help): p
Disk /dev/sdc: 7.4 GiB, 7948206080 bytes, 15523840 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xa159d333

Device     Boot  Start      End  Sectors  Size Id Type
/dev/sdc1  *      2048   526335   524288  256M  c W95 FAT32 (LBA)
/dev/sdc2       526336 15523839 14997504  7.2G 83 Linux

一个 256MB 的可启动 FAT32 分区,一个 7.2GB 的 Linux 分区,没有问题按w保存分区表并退出。

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

mkfs命令格式化磁盘,将分区1格式化为 vfat 格式,分区2格式化为 ext4 格式:

# mkfs -t vfat /dev/sdc1
mkfs.fat 3.0.28 (2015-05-16)
# mkfs -t ext4 /dev/sdc2
mke2fs 1.42.13 (17-May-2015)
Creating filesystem with 1874688 4k blocks and 469568 inodes
Filesystem UUID: 7dca0553-48b1-4c5e-96af-c1e84d995648
Superblock backups stored on blocks:
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632

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

释放下载好的镜像

创建一个用于挂载新分区的目录/mnt/c,并将格式化好的 FAT32 分区挂载到其中:

# mkdir /mnt/c
# mount -t vfat /dev/sdc1 /mnt/c

将下载好的树莓派 armhf 镜像释放到/mnt/c下:

# cd /mnt/c
# tar xzf ~/Download/alpine-rpi-3.7.0-armhf.tar.gz

释放过程中会看到许Cannot change ownership to uid 1000, gid 1000: Operation not permitted这样的错误信息,这是因为 FAT32 文件系统不支持用户所有权属性导致的,直接无视它们就好。

然后需要在 FAT32 分区里添加一个usercfg.txt的配置文件,并在其中写入一行enable_uart=1,否则树莓派启动后,控制台会不停输出提示Can't open /dev/ttyS0

# echo 'enable_uart=1' > /mnt/c/usercfg.txt

下载 WiFi 驱动

默认 Alpine Linux 的树莓派镜像不是为 Zero W 型号设计的,所以没有加入 WiFi 模块的固件。然而我们在安装过程中还是会需要联网下载最新的软件包,所以我们需要自己下载安装。从Github项目中下载固件文件,放在 FAT32 分区的firmware/brcm目录下。

# mkdir -p /mnt/c/firmware/brcm
# cd /mnt/c/firmware/brcm
# wget https://github.com/RPi-Distro/firmware-nonfree/raw/master/brcm/brcmfmac43430-sdio.bin
# wget https://github.com/RPi-Distro/firmware-nonfree/raw/master/brcm/brcmfmac43430-sdio.txt

下载好 WiFi 模块的固件之后,即可卸载 SD 卡开始安装了。

# cd /
# umount /mnt/c

启动树莓派

将 SD 卡插入树莓派,连上显示器和键盘,通电点亮树莓派。稍候即可看到 OpenRC 的启动界面, OpenRC 是 Alpine Linux 使用的服务启动管理器。看到登录提示之后,输入用户名root,安装时无需输入密码。

安装 WiFi 工具

在启动安装脚本之前,我们需要先安装 WiFi 工具,这样才能在安装过程中设置无线网络。

# apk add wireless-tools wpa_supplicant

装好之后运行iwconfig命令可以看到wlan0网卡的信息,此时应该是关闭的状态。

# iwconfig
lo        no wireless extensions.
wlan0     IEEE 802.11bgn  ESSID:off/any
          Mode:Managed  Access Point: Not-Associated   Tx-Power=14 dBm
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Encryption key:off
          Power Management:off

安装脚本

现在可以运行安装脚本,安装系统了。

# setup-alpine

在安装的过程中,会提示你设置键盘布局、设置 WiFi 网络、设置时区、设置时间同步程序、设置apk软件源,设置root密码等等,按向导提示安装即可。

如果是普通安装,Alpine Linux 将会把整个系统安装到 FAT32 启动分区中,每次启动电脑的时候,会自动创建一个内存盘作为根分区。这种默认的安装方式比较简单,但却让 Zero W 本来就有限的内存显得更加捉襟见肘。

sys 模式

于是我选择了另一种安装方式—— sys 模式——将整个系统安装到一个 ext4 分区中。这样不需要内存盘作为根分区,可以节省出保贵的内存,也能让系统更可靠。请注意使用这种安装方式,在安装向导中需在save configsave cache步骤的提示中输入none

走完setup-alpine脚本之后,我们还需要安装 ext4 文件系统的支持,这部分需要联网下载安装。

# apk update
# apk add e2fsprogs

如果使用 Windows 或者 Mac 系统做的初始分区,可以在此时创建第二块分区,并格式化。

将格式化好的 ext4 分区挂载到/mnt下,注意树莓派上的设备是以mmcblk为前缀命名的。

# mount /dev/mmcblk0p2 /mnt

运行setup-disk命令将系统安装到另一分区。因为setup-disk脚本还不太完善,安装过程中可能会提示一些错误,忽略即可。

# setup-disk -m sys /mnt

重新挂载当前 FAT32 分区为可写模式:

# mount -o remount,rw /dev/mmcblk0p1

清理旧的,已经用不着的启动文件:

# rm -f /media/mmcblk0p1/boot/*  
# cd /mnt       # 切换到 ext4 分区
# rm boot/boot  # 删除无用的符号链接

将启动镜像和 Alpine Linux 的init ram移动到 FAT32 分区中的正确位置:

# mv boot/* /media/mmcblk0p1/boot/
# rm -Rf boot # 删除 ext4 分区中的 boot 目录
# mkdir media/mmcblk0p1   # 下次重启后 FAT32 分区的新挂载点

建立一个软链,这样以后升级系统后无需人工复制到 FAT32 分区中。不用担心错误提示:

# ln -s media/mmcblk0p1/boot boot

更新/etc/fstab分区挂载配置:

# echo "/dev/mmcblk0p1 /media/mmcblk0p1 vfat defaults 0 0" >> etc/fstab
# sed -i '/cdrom/d' etc/fstab   # 显示树莓派上没有光驱
# sed -i '/floppy/d' etc/fstab  # 也没有软驱

如果你要使用开源社区维护的软件,比如vim、php、nginx等等,修改etc/apk/repositories 中的配置,开启community软件源。

修改 FAT32 分区上记录的启动配置,将 root 分区改为 ext4 分区:

# cd /media/mmcblk0p1
# sed -i 's/^/root=\/dev\/mmcblk0p2 /' cmdline.txt

最后重启系统:

# reboot

安装之后

你可能发现重启之后 WiFi 断了,这是因为 wpa_supplicant 没有自动启动导致的。

先手动启动它:

# service wpa_supplicant start

然后设置它自动启动:

# rc-update add wpa_supplicant boot

由于树莓派上没有用于保持时钟的电池,我们需要调整设置使用软件时钟,以及使用网络授时。

# rc-update del hwclock boot
# rc-update add swclock boot
# service hwclock stop
# service swclock start

你可能想马上升级一下系统:

# apk update
# apk upgrade

一般来说,常用的软件也可以装一下:

# apk add vim htop openssl curl

至此树莓派 Zero W 已经安装好Alpine Linux 了,如果想要更安全的 ssh 方案,可以考虑用密钥登录或者创建限权账号,并安装sudo

参考资料

  • https://wiki.alpinelinux.org/wiki/Raspberry_Pi
  • https://wiki.alpinelinux.org/wiki/Classic_install_or_sys_mode_on_Raspberry_Pi
  • https://wiki.alpinelinux.org/wiki/Connecting_to_a_wireless_access_point#Broadcom_Wi-Fi_Chipset_Users
  • https://bugs.alpinelinux.org/issues/6959