x230i作为办公用的笔记本,今天完成了它的使命,正式退役。鉴于曾经的树莓派性能已经不能满足现在需求,x230i开始逐步取代树莓派,成为家中主力服务器的角色。
安装系统
我接触的过的Linux发型版主要有以下几个:
-
Slackware
,这个发型版是我的入门Linux,通过这个发型版深入地学到了很多系统的本质问题,但是这个系统相对来说比较小众,目前已基本不再接触。 -
CentOS
,工作中一直用的发型版,以稳定著称,但是个人非常不喜欢这个发型版,很多应用太过老旧,包管理也非常难用,其它还有很多问题,反正用了这么多年一直也没能习惯。 -
Arch
,系统很简洁,没有任何多余的东西,一切都根据自己的需要来定制,除了更新太频繁外,其它的理念都非常符合我的口胃。作为工作机,更新频繁还是很好的,做为服务器来用,还是有点风险,或者说经常更新还是太麻烦。 -
Ubuntu
,这大概是当前最流行的发型版了,不过总觉得这个发型版本有点怪,但又是说不了来哪里不舒服。 -
Manjaro
,这个发型版印象中作为桌面系统还是不错的,师承Arch,作为服务器也同样有更新频繁的问题。 -
Debian
,这个发型版目前是我最喜欢的一个了,适用平台相当广范,系统组件简洁,占用内存小,更新也不像Arch
那么频繁,作为服务器来说,我觉得非常不错的选择。
经常这些版本试用比较,我目前倾向于用 Debian
作为主要服务器系统,如果需要作为桌面系统,我的选择可以是 Debain
、 Manjaro
、 Arch
。
当前 Debian
的最新版是 Debian 11 bullseye
,那么就以这个版本为来作为我的服务器系统了。
安装过程非常简单,下载 debian-11.0.0-amd64-netinst.iso
,通过 Rufus
制作U盘安装盘,通过U盘启动,安装即可。过程不在详述。
安装包源配置
由于某些原因,在国内,Debian默入的安装包源比较慢,所以装安装完系统后,需要将软件包源替换成国内的镜像源。
leen@x230i:~$ cat /etc/apt/sources.list
# deb cdrom:[Debian GNU/Linux 11.0.0 _Bullseye_ - Official amd64 NETINST 20210814-10:07]/ bullseye main
#deb cdrom:[Debian GNU/Linux 11.0.0 _Bullseye_ - Official amd64 NETINST 20210814-10:07]/ bullseye main
deb http://mirrors.ustc.edu.cn/debian/ bullseye main
deb-src http://mirrors.ustc.edu.cn/debian/ bullseye main
deb http://security.debian.org/debian-security bullseye-security main
deb-src http://security.debian.org/debian-security bullseye-security main
# bullseye-updates, to get updates before a point release is made;
# see https://www.debian.org/doc/manuals/debian-reference/ch02.en.html#_updates_and_backports
deb http://mirrors.ustc.edu.cn/debian/ bullseye-updates main
deb-src http://mirrors.ustc.edu.cn/debian/ bullseye-updates main
常用软件安装
-
apt install sudo
-
apt install vim
-
apt install htop
-
apt install git
-
apt install tree
-
apt install samba
-
apt install tmux
-
apt install lrzsz
-
apt install tcpdump
-
apt install ethtool
-
apt install build-essential
-
apt install flex bison
USB磁盘挂载配置
debian系统默情况下没有自动将USB磁盘自动挂载到某个目录的动作。需要自己编写脚本来实现监控。
-
首先需要在
/etc/udev/rules.d/
目录中新增一个文件11-usb-auto-mount.rules
,内容如下:KERNEL=="sd[a-z][0-9]", SUBSYSTEMS=="usb", ACTION=="add", RUN+="/bin/systemctl start usb-mount@%k.service" KERNEL=="sd[a-z][0-9]", SUBSYSTEMS=="usb", ACTION=="remove", RUN+="/bin/systemctl stop usb-mount@%k.service"
-
在
/etc/systmed/system
目录中新增一个服务文件usb-mount@.service
, 内容如下:[Unit] Description=Mount USB Drive on %i [Service] Type=oneshot RemainAfterExit=true ExecStart=/usr/local/bin/usb-mount.sh add %i ExecStop=/usr/local/bin/usb-mount.sh remove %i
-
在
/usr/local/bin
目录中新增一个脚本文件usb-mount.sh
, 内容如下:#!/bin/bash # This script is called from our systemd unit file to mount or unmount # a USB drive. usage() { echo "Usage: $0 {add|remove} device_name (e.g. sdb1)" exit 1 } if [[ $# -ne 2 ]]; then usage fi ACTION=$1 DEVBASE=$2 DEVICE="/dev/${DEVBASE}" # See if this drive is already mounted, and if so where MOUNT_POINT=$(/bin/mount | /bin/grep ${DEVICE} | /usr/bin/awk '{ print $3 }') do_mount() { if [[ -n ${MOUNT_POINT} ]]; then echo "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}" exit 1 fi # Get info for this drive: $ID_FS_LABEL, $ID_FS_UUID, and $ID_FS_TYPE eval $(/sbin/blkid -o udev ${DEVICE}) # Figure out a mount point to use LABEL=${ID_FS_LABEL} if [[ -z "${LABEL}" ]]; then LABEL=${DEVBASE} elif /bin/grep -q " /media/${LABEL} " /etc/mtab; then # Already in use, make a unique one LABEL+="-${DEVBASE}" fi MOUNT_POINT="/media/${LABEL}" echo "Mount point: ${MOUNT_POINT}" /bin/mkdir -p ${MOUNT_POINT} # Global mount options OPTS="rw,relatime" # File system type specific mount options if [[ ${ID_FS_TYPE} == "vfat" ]]; then OPTS+=",users,gid=100,umask=000,shortname=mixed,utf8=1,flush" fi if ! /bin/mount -o ${OPTS} ${DEVICE} ${MOUNT_POINT}; then echo "Error mounting ${DEVICE} (status = $?)" /bin/rmdir ${MOUNT_POINT} exit 1 fi echo "**** Mounted ${DEVICE} at ${MOUNT_POINT} ****" } do_unmount() { if [[ -z ${MOUNT_POINT} ]]; then echo "Warning: ${DEVICE} is not mounted" else /bin/umount -l ${DEVICE} echo "**** Unmounted ${DEVICE}" fi # Delete all empty dirs in /media that aren't being used as mount # points. This is kind of overkill, but if the drive was unmounted # prior to removal we no longer know its mount point, and we don't # want to leave it orphaned... for f in /media/* ; do if [[ -n $(/usr/bin/find "$f" -maxdepth 0 -type d -empty) ]]; then if ! /bin/grep -q " $f " /etc/mtab; then echo "**** Removing mount point $f" /bin/rmdir "$f" fi fi done } case "${ACTION}" in add) do_mount ;; remove) do_unmount ;; ,*) ;; esac
-
udevadm control –reload-rules
-
systemctl daemon-reload
上面的步骤看起来比繁琐,最初搜索如何挂载USB磁盘的时候,还有一个更简洁的方案(https://www.axllent.org/docs/auto-mounting-usb-storage/):
-
vim /etc/udev/rules.d/11-media-by-label-auto-mount.rules
KERNEL!="sd[a-z][0-9]", GOTO="media_by_label_auto_mount_end" # Import FS infos IMPORT{program}="/sbin/blkid -o udev -p %N" # Get a label if present, otherwise specify one ENV{ID_FS_LABEL}!="", ENV{dir_name}="%E{ID_FS_LABEL}" ENV{ID_FS_LABEL}=="", ENV{dir_name}="usbhd-%k" # Global mount options ACTION=="add", ENV{mount_options}="relatime" # Filesystem-specific mount options ACTION=="add", ENV{ID_FS_TYPE}=="vfat|ntfs", ENV{mount_options}="$env{mount_options},utf8,gid=100,umask=002" # Mount the device ACTION=="add", RUN+="/bin/mkdir -p /media/%E{dir_name}", RUN+="/bin/mount -o $env{mount_options} /dev/%k /media/%E{dir_name}" # Clean up after removal ACTION=="remove", ENV{dir_name}!="", RUN+="/bin/umount -l /media/%E{dir_name}", RUN+="/bin/rmdir /media/%E{dir_name}" # Exit LABEL="media_by_label_auto_mount_end"
-
udevadm control –reload-rules
但是偿试这个方案的时候发现有个问题就是,指定的目录看不到挂载的磁盘内容,同时脚执行过程也没有任何报错,后来才明白这是因为 namespace
导致的问题。虽然可以解决这个问题,也 不建议 直接在 udev
rule中直接用mount命令(详见:https://wiki.archlinux.org/title/udev)。
断电延迟关机配置
笔记本有自带电池,可以确保在突然断电后,系统仍然在运行,电力最多也只能支撑两个小时左右。当然断电后继续运行的意义也不大,这个时候应该进行优雅的关机操作,以确保相应的数据都能存入磁盘。如果很短时间的断电,那么就不需要关机了。所以我希望实现一个功能就是在断电后的半个小时内,如果还没有通电那么笔记本就自动关机,如果在半小时内又通电了,就什么都不做。另外因为笔记本设定了通电开机,所以在关机后,如果通电了,那么笔记本会自动开机。
实现延时关机的功能需要以下几个方面的参于:
-
vim /dev/udev/rules.d/99-delayed-poweroff.rules
, 这文件用来感知电源变化SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="0", RUN+="/usr/bin/systemctl start delayed-poweroff.timer" SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="1", RUN+="/usr/bin/systemctl stop delayed-poweroff.timer"
-
vim /etc/systemd/system/delayed-poweroff.timer
, 这个文件用来配置延时定时器[Unit] Description=Delayed Poweroff when AC unplugin [Timer] OnActiveSec=30min [Install] WantedBy=timers.target
-
vim /etc/systemd/system/delayed-poweroff.service
, 这个文件用来执行关机命令[Unit] Description=Delayed poweroff service when AC unplugin [Service] Type=simple ExecStart=/usr/sbin/poweroff