本文采用最小化安装方式,同时会阐述OpenRC和SystemD两种init环境安装区别。所以,镜像采用的是最小化minimal镜像+Stage3(OpenRC/SystemD),整个过程需要有公网访问能力,因此Stage3镜像不用下载到本地,直接在Live系统中wget即可。镜像可在国内清华Gentoo镜像站下载。
访问OpenRC下载地址,下载minimal镜像:
以及同目录下的OpenRC Stage3镜像:
可选步骤,这里只要清楚需要哪几个镜像即可,Stage3不用下载到本地。
访问SystemD下载地址,SystemD作为init系统时,Stage3镜像则为:
minimal镜像还是没有变:
OpenRC是Gentoo的原生init系统,核心部份处理依赖管理和init脚本分析,通过扫描运行级别,建造依赖图,接着启动需要的服务脚本来工作,启动方式为rc-service <service> <action>
或者/etc/init.d/<service> <action>
:
SystemD,由Fedora 15引入,相对OpenRC较新的init系统,也是当今最流行的init系统,集成了各类工具以便更好的管理系统,目前在各大Linux发行版基本都能见到,绝大部分默认都是以SystemD作为init系统,启动速度比OpenRC快很多,启动方式为systemctl [Option] [Unit]
:
OpenRC是Gentoo的默认Init系统,Gentoo官网整个安装步骤也是围绕此展开讨论,SystemD是Gentoo添加上去的支持,因此安装SystemD需要一些额外的步骤,但个人建议是选用SystemD集大成者,除非你清晰知道OpenRC更适合你的需求场景。
将minimal镜像上传到ESXi后,接下来可开始创建虚拟机,已有相关经验的可跳过这一步。
注:这里是用vCenter作为操作平台,界面展示上和ESXi有所区别,但实际就是操纵ESXi。
这里理解为将Gentoo安装到哪一台ESXi上面,如果你直接在ESXi操作则没有此步骤。
选择集群机器,101则为ESXi地址:
这里将Gentoo安装到16TB的硬盘里:
选默认最高版本即可,这里用的是ESXi 7.0:
操作系统版本:Linux
客户机操作系统版本:其他5.x或更高版本的Linux(64位)
根据主机性能酌情分配,并挂载好minimal镜像。Gentoo安装软件默认都会把源码拉下来编译,性能可以尽量给高点,提升安装效率,编译内核速度也会更快。
虚拟机选项-->引导选项,这里选择BIOS:
打开虚拟机后,默认第一个LiveCD选项进入系统:
如果你在【自定义硬件】步骤选用的网络适配器能上公网,那么此步骤可忽略。
使用ifconfig
或ip addr
查看网卡名:
可以看到Live系统默认已经从DHCP地址池中获取到了IP,一般这一步都没有太大问题。
测试公网连通性及DNS解析也没有问题:
如果没网,可以考虑使用net-setup
来配置,比如上面网卡是enp11s0,那么命令则为:net-setup enp11s0
,输出为下面的dialog界面,按照界面提示选择网络环境即可:
配置网络部分不做赘述,可参考官方文档。
设置一个密码,并开启sshd来远程登录,这样直接方便复制操纵一些文本:
通过终端ssh进入到live系统后的效果:
以100G磁盘为例,分区方案可以如下作为参考:
| 分区 | 大小 | 描述 |
| --------- | -------- | ------------------------------------------------------------ |
| /dev/sda1 | 256M | /boot分区 |
| /dev/sda2 | 2G | 交换(swap)分区,一般为内存的两倍,内存足够大可以考虑适量给。 |
| /dev/sda3 | 剩余部分 | 根分区 |
选择parted也没啥问题,大于2T的硬盘用不了fdisk。
使用如下命令开始分区硬盘:
fdisk /dev/sda
如果你用的是SSD,那么硬盘名称形如/dev/nvme0n1
。
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-209715199, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-209715199, default 209715199): +256M
Created a new partition 1 of type 'Linux' and of size 256 MiB.
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-209715199, default 526336):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (526336-209715199, default 209715199): +2G
Created a new partition 2 of type 'Linux' and of size 2 GiB.
Command (m for help): t
Partition number (1,2, default 2):
Hex code or alias (type L to list all): 82
Changed type of partition 'Linux' to 'Linux swap / Solaris'.
Command (m for help): n
Partition type
p primary (2 primary, 0 extended, 2 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (3,4, default 3):
First sector (4720640-209715199, default 4720640):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (4720640-209715199, default 209715199):
Created a new partition 3 of type 'Linux' and of size 97.7 GiB.
Command (m for help): p
Disk /dev/sda: 100 GiB, 107374182400 bytes, 209715200 sectors
Disk model: Virtual disk
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: 0xaf2138c5
Device Boot Start End Sectors Size Id Type
/dev/sda1 2048 526335 524288 256M 83 Linux
/dev/sda2 526336 4720639 4194304 2G 82 Linux swap / Solaris
/dev/sda3 4720640 209715199 204994560 97.7G 83 Linux
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
比如,在示例分区结构中,有使用FAT32的引导分区(/dev/sda1)和使用Ext4的根分区(/dev/sda3),则使用下面的命令:
mkfs.vfat -F 32 /dev/sda1
mkfs.ext4 /dev/sda3
激活并初始化swap分区:
mkswap /dev/sda2
swapon /dev/sda2
使用mount命令将根分区挂载到目录下面:
mount /dev/sda3 /mnt/gentoo
建议和UTC
时区保持一致,注意不是UTC+8
,Gentoo网络基础服务使用了安全证书,如果系统时间差的离谱,可能无法下载安装文件,后面步骤会设置为正确的时区。
可以使用内置的ntpd命令和ntp服务器同步:
ntpd -q -g
或者你也可以手动设置,比如设置时间为2023年1月16日18:00,则为:
date 011618002023
进入Gentoo的根挂载点:
cd /mnt/gentoo
下载OpenRC Stage3包文件:
wget https://mirrors.tuna.tsinghua.edu.cn/gentoo/releases/amd64/autobuilds/20230108T161708Z/stage3-amd64-openrc-20230108T161708Z.tar.xz
wget https://mirrors.tuna.tsinghua.edu.cn/gentoo/releases/amd64/autobuilds/20230108T161708Z/stage3-amd64-openrc-20230108T161708Z.tar.xz.CONTENTS.gz
wget https://mirrors.tuna.tsinghua.edu.cn/gentoo/releases/amd64/autobuilds/20230108T161708Z/stage3-amd64-openrc-20230108T161708Z.tar.xz.DIGESTS
wget https://mirrors.tuna.tsinghua.edu.cn/gentoo/releases/amd64/autobuilds/20230108T161708Z/stage3-amd64-openrc-20230108T161708Z.tar.xz.asc
wget https://mirrors.tuna.tsinghua.edu.cn/gentoo/releases/amd64/autobuilds/20230108T161708Z/stage3-amd64-openrc-20230108T161708Z.tar.xz.sha256
验证文件下载是否完整,避免文件下载不完全导致后面步骤白做,比如使用SHA512校验:
openssl dgst -r -sha512 stage3-amd64-openrc-20230108T161708Z.tar.xz
cat stage3-amd64-openrc-20230108T161708Z.tar.xz.DIGESTS
确保完全一致即可。
进入Gentoo的根挂载点:
cd /mnt/gentoo
下载SystemD Stage3包文件:
wget https://mirrors.tuna.tsinghua.edu.cn/gentoo/releases/amd64/autobuilds/20230108T161708Z/stage3-amd64-systemd-20230108T161708Z.tar.xz
wget https://mirrors.tuna.tsinghua.edu.cn/gentoo/releases/amd64/autobuilds/20230108T161708Z/stage3-amd64-systemd-20230108T161708Z.tar.xz.CONTENTS.gz
wget https://mirrors.tuna.tsinghua.edu.cn/gentoo/releases/amd64/autobuilds/20230108T161708Z/stage3-amd64-systemd-20230108T161708Z.tar.xz.DIGESTS
wget https://mirrors.tuna.tsinghua.edu.cn/gentoo/releases/amd64/autobuilds/20230108T161708Z/stage3-amd64-systemd-20230108T161708Z.tar.xz.asc
wget https://mirrors.tuna.tsinghua.edu.cn/gentoo/releases/amd64/autobuilds/20230108T161708Z/stage3-amd64-systemd-20230108T161708Z.tar.xz.sha256
使用SHA256校验文件是否完整:
openssl dgst -r -sha256 stage3-amd64-systemd-20230108T161708Z.tar.xz
cat stage3-amd64-systemd-20230108T161708Z.tar.xz.sha256
可以看到完全一致。
tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner
--numeric-owner
被用于确保从tarball中提取的文件的用户和组ID与Gentoo发布工程团队预期的保持一致。
编辑make.conf文件,优化编译参数:
nano -w /mnt/gentoo/etc/portage/make.conf
改成如下内容:
# These settings were set by the catalyst build script that automatically
# built this stage.
# Please consult /usr/share/portage/config/make.conf.example for a more
# detailed example.
COMMON_FLAGS="-march=native -O2 -pipe"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
FCFLAGS="${COMMON_FLAGS}"
FFLAGS="${COMMON_FLAGS}"
MAKEOPTS="-j16"
# NOTE: This stage was built with the bindist Use flag enabled
# This sets the language of build output to English.
# Please keep this setting intact when reporting bugs.
LC_MESSAGES=C
其中MAKEOPTS
表示编译时使用的线程数量,官方的建议是在CPU的线程数和整个系统的内存 / 2GiB 中选择小的那个比较好,我这里设置为16。
Gentoo默认配置的是官方源,跨境传输速度较慢,这里建议配置为国内源,比如选择清华源或阿里、网易等多个软件源。
mirrorselect -i -o >> /mnt/gentoo/etc/portage/make.conf
空格勾选即可:
Portage为Gentoo的包管理器,这里需要创建Portage配置目录,并将Gentoo镜像的配置文件复制到创建的repos.conf目录:
mkdir --parents /mnt/gentoo/etc/portage/repos.conf
cp /mnt/gentoo/usr/share/portage/config/repos.conf /mnt/gentoo/etc/portage/repos.conf/gentoo.conf
验证是否成功,可以看下文件内容:
cat /mnt/gentoo/etc/portage/repos.conf/gentoo.conf
cp --dereference /etc/resolv.conf /mnt/gentoo/etc/
--dereference
,可以保障如果/etc/resolv.conf是一个符号链接的话,复制的是resolv.conf的目标文件而不是这个链接文件。
想要确保新环境(/mnt/gentoo)能正常工作,需要把Live系统的一些文件系统挂载到/mnt/gentoo,才能确保能正常使用。
mount --types proc /proc /mnt/gentoo/proc
mount --rbind /sys /mnt/gentoo/sys
mount --make-rslave /mnt/gentoo/sys
mount --rbind /dev /mnt/gentoo/dev
mount --make-rslave /mnt/gentoo/dev
mount --bind /run /mnt/gentoo/run
mount --make-slave /mnt/gentoo/run
使用chroot
命令进入到Gentoo环境:
chroot /mnt/gentoo /bin/bash #进入到gentoo基础系统,并且使用bash解释器
source /etc/profile #是配置文件重新生效
export PS1="(chroot) ${PS1}" #修改PS1,帮助我们记忆这是在chroot环境
安装内核及引导程序时需用到boot分区,因此需要提前挂载:
mount /dev/sda1 /boot
emerge-webrsync
上一步已经建立数据库快照了并且更新ebuild为了最新版本,如果距离上一步有停顿一段时间(几个小时或者一天),可以使用下面命令保持为最新:
emerge --sync
当更新Portage ebuild数据库后,Portage可能会输出类似下面的信息:
* IMPORTANT: 9 news items need reading for repository 'gentoo'.
* Use eselect news read to view new items.
一般都是推送的重要消息,可以使用eselect命令来阅读,不然每次emerge安装软件时都会在最后提示此信息。
eselect news list
eselect news read
使用如下命令查看目前选择的profile:
eselect profile list
最后面*号表示当前选的配置文件。选的时候不能跨版本选择,比如17.1就选17.1的profile,不要17.0、17.1都包含。
因为我们使用最小化安装,这里默认就行,系统已经帮我们选好,如果是OpenRC Stage3包则默认会选OpenRC的profile(序列号1)。
比如选择OpenRC:
eselect profile set 1
@world集合是Gentoo所有软件、配置的集合,进行构建系统之前,更新一下@world集合是必要的:
emerge --ask --verbose --update --deep --newuse @world
USE变量可以在编译时选择编译或者不编译某些可选的支持、扩展包,简单理解为启用或禁用主程序某些其他功能,这样可以做到按需安装,只安装我们想要的包,更加精简化。
比如有以下需求:需要安装nmap,但是nmap的USE变量默认没有nping、ncat子命令,我们需要把它们一并安装上。
每个包的USE定义都可以在/etc/portage/package.use目录下设置,它可能也是一个文件,不管是哪一种,语法都是一样。
比如基于如上需求,需要安装nping、ncat子命令,那么USE变量可以是:
net-analyzer/nmap ipv6 nse ssl -libssh2 ncat nping -symlink (-system-lua) -verify-sig
要看nmap支持哪些USE标记,通过emerge -pv nmap
即可查看:
emerge -pv nmap
因为配置了nmap的USE设置,所以默认会读取设置后的USE变量:
-
开头表示不安装,比如libssh2
不安装libssh2
库文件。
默认的USE设置在make.defaults文件中,可以使用如下命令查看当前USE标记:
emerge --info |grep ^USE
如果对USE不了解,这里建议保持默认。
同时可以在/var/db/repos/gentoo/profiles/use.desc
中找到可用的USE标记的完整描述:
less /var/db/repos/gentoo/profiles/use.desc
以下8、9点根据当前init系统做对应操作,后续操作步骤会多次用到文本编辑器,如果不习惯内置的nano可以通过emerge --ask vim
安装vim命令。
ln -sf /proc/self/mounts /etc/mtab
上游仅支持/etc/mtab,如果不建立此软连接,则会导致mount、df命令出现bug(#434090和##477240)。
创建一个随机机器ID:
systemd-machine-id-setup
hostnamectl set-hostname <HOSTNAME>
时区列表在/usr/share/zoneinfo目录下,查到对应可用的时区后,软链到/etc/localtime。
比如我们要设置到上海时区:
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
vim /etc/locale.conf
习惯使用英文环境,修改成LANG="en_US.utf8"
即可。
依然以上海为例:
echo 'Asia/Shanghai' > /etc/timezone
重新配置timezone-data:
emerge --config sys-libs/timezone-data
将会基于/etc/timezone去更新/etc/localtime文件,/etc/localtime会让系统的C类库知道系统在什么时区。
完整的locale支持列表可以在/usr/share/i18n/SUPPORTED文件找到。系统支持的locale必须在/etc/local.gen定义。
修改/etc/locale.gen文件,将前面的注释去掉,启用US字符格式:
en_US.UTF-8 UTF-8
运行locale-gen
,将会生成/etc/locale.gen文件中指定的地区:
locale-gen
可以使用locale -a
验证当前选择的locale:
通过如下命令显示可用的配置:
eselect locale list
可以看到,系统默认已经帮我们选择了en_US.utf8
,如果不符合预期,可通过eselect locale set <NUMBER>
选择正确的区域设置,比如选择POSIX,可以是:
eselect locale set 3
完成上述选择后,重新加载环境:
env-update && source /etc/profile && export PS1="(chroot) ${PS1}"
以下内核安装方式二选一进行,ESXi上运行则更建议使用第一种。
ESXi安装方式最推荐使用二进制内核,如果你不厌其烦要从源码编译内核,那就需要把vmware虚拟化、相关驱动等诸多内核配置查找出来并勾选,费时费力,最后还不一定能完美兼容。
使用如下命令安装二进制内核:
emerge --ask sys-kernel/gentoo-kernel-bin
可以看到当前源里面最新stable版本为5.15.85-r1,且默认USE了initramfs
。
安装成功后,可以通过eselect
命令看到当前版本:
eselect kernel list
emerge --ask sys-kernel/gentoo-sources
列出已安装的内核:
eselect kernel list
可以看到一共有两个内核,第一个是从源码安装的版本,第二个是刚安装的二进制版本。
如果没有进行二进制内核安装,这里只会看到一个内核,不需要做额外操作。因为这里有两个内核,且第一是源码安装的内核版本,我们选择第一个:
eselect kernel set 1
可以看到,设置为第一个时,其实就是创建一个/usr/src/linux
的链接指向内核目录。
首先可以安装sys-apps/pciutils
包,通过lspci命令来收集硬件信息:
emerge --ask sys-apps/pciutils
lspci
因为下一步配置需要把每个必要的内核模块勾选。
接下来进入内核源码,开始配置内核:
cd /usr/src/linux
make menuconfig
一如既往的dialog视图:
接下来就是最繁琐的步骤,勾选必要的内核模块(空格勾选,*代表勾选上):
Gentoo Linux --->
Generic Driver Options --->
[*] Gentoo Linux support
[*] Linux dynamic and persistent device naming (userspace devfs) support
[*] Select options required by Portage features
Support for init systems, system and service managers --->
[*] OpenRC, runit and other script based systems and managers
[*] systemd
Device Drivers --->
Generic Driver Options --->
[*] Maintain a devtmpfs filesystem to mount at /dev
[*] Automount devtmpfs at /dev, after the kernel mounted the rootfs
Device Drivers --->
SCSI device support --->
<*> SCSI disk support
验证SCSI磁盘支持是否已激活(CONFIG_BLK_DEV_SD
),可以通过/
,来搜索CONFIG_BLK_DEV_SD
,这样不用一个个子选项去找,可以看到默认已经勾选:
File systems --->
<*> Second extended fs support
<*> The Extended 3 (ext3) filesystem
<*> The Extended 4 (ext4) filesystem
<*> Reiserfs support
<*> JFS filesystem support
<*> XFS filesystem support
<*> Btrfs filesystem support
DOS/FAT/NT Filesystems --->
<*> MSDOS fs support
<*> VFAT (Windows-95) fs support
Pseudo Filesystems --->
[*] /proc file system support
[*] Tmpfs virtual memory file system support (former shm fs)
CPU多核需要用到,配置名为:CONFIG_SMP
,这里默认也是勾选的,可以检查一遍:
Processor type and features --->
[*] Symmetric multi-processing support
如果在分区时使用GPT分区,则需要启用它(CONFIG_PARTITION_ADVANCED
,CONFIG_EFI_PARTITION
):
-*- Enable the block layer --->
Partition Types --->
[*] Advanced partition selection
[*] EFI GUID Partition support
如果你用的是UEFI引导,则需要启用EFI stub支持(CONFIG_EFI
,CONFIG_EFI_STUB
,CONFIG_EFI_MIXED
,CONFIG_EFI_VARS
,CONFIG_EFI_FB
)
Processor type and features --->
[*] EFI runtime service support
[*] EFI stub support
[*] EFI mixed-mode support
Device Drivers
Firmware Drivers --->
EFI (Extensible Firmware Interface) Support --->
<*> EFI Variable Support via sysfs
Graphics support --->
Frame buffer Devices --->
<*> Support for frame buffer devices --->
[*] EFI-based Framebuffer Support
针对ESXi,官方给出了需要勾选的内核模块列表:
[*] Networking support --->
Networking options --->
<*> Virtual Socket protocol
<*> VMware VMCI transport for Virtual Sockets
Device Drivers --->
[*] Fusion MPT device support --->
<*> Fusion MPT ScsiHost drivers for SPI
Misc devices --->
<*> VMware Balloon Driver
<*> VMware VMCI Driver
SCSI device support --->
[*] SCSI low-level drivers --->
<*> VMware PVSCSI driver support
[*] Network device support --->
[*] Ethernet driver support --->
[*] AMD devices
<*> AMD 8111 (new PCI LANCE) support
<*> AMD PCnet32 PCI support
[*] Intel devices
<*> Intel(R) PRO/1000 Gigabit Ethernet support
<*> Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support
<*> VMware VMXNET3 ethernet driver
Input device support --->
[*] Keyboards --->
<*> AT keyboard
File systems --->
<*> FUSE (Filesystem in Userspace) support
配置文件名:
同时可以考虑安装vm-tools工具:
emerge --ask app-emulation/open-vm-tools
make && make modules_install
无需用-j指定线程数,默认从我们前面的/etc/portage/make.conf
读取MAKEOPTS
指定的线程数。
编译完成后,使用如下命令完成安装,将会复制内核镜像到/boot目录:
make install
安装前线安装dracut,用它来生成initramfs:
emerge --ask sys-kernel/dracut
dracut --kver=5.15.80-gentoo
成功后,可以在/boot目录下看到initramfs开头的文件:
可以通过blkid
命令查看磁盘UUID:
blkid
拿到UUID后,写入到fstab里面:
vim /etc/fstab
vim默认没装,可以使用
emerge --ask app-editors/vim
安装,要么就用nano命令。
比如如上UUID,写入为:
UUID=C8D9-EEED /boot vfat defaults,noatime 0 2
UUID=e483307b-a5ce-44d2-94d6-d88b0584b5e0 none swap sw 0 0
UUID=7a05ddf2-b16c-4b4f-a70b-50288aededa8 / ext4 noatime 0 1
nano -w /etc/conf.d/hostname
比如将主机名设置为gentoo:
hostnamectl hostname gentoo
安装dhcpcd:
emerge --ask net-misc/dhcpcd
如果是OpenRC,默认启用此服务,让它开机自启动:
rc-update add dhcpcd default
rc-service dhcpcd start
SystemD则为:
systemctl enable dhcpcd
不要忘了给系统设置一个密码,不然无法登录进去:
passwd
OpenRC无需执行此步骤,保持默认即可。
SystemD则需要通过如下两条命令,从Live环境平滑过渡到安装后的首次启动:
systemd-firstboot --prompt --setup-machine-id
systemctl preset-all
OpenRC可以安装它,如果是SystemD则不需要安装:
emerge --ask app-admin/sysklogd
在OpenRC上添加自启动:
rc-update add sysklogd default
emerge --ask sys-process/dcron
OpenRC上添加自启动
rc-update add dcron default
SystemD上添加自启动
systemctl enable dcron
初始化
crontab /etc/crontab
即locate工具,安装命令如下:
emerge --ask sys-apps/mlocate
sshd服务默认已经内置,我们只需要把它设置为开机自启动服务即可。
OpenRC
rc-update add sshd default
SystemD
systemctl enable sshd
需要注意,默认sshd_config禁用了root登录,可以考虑修改成允许:
sed -ir 's|^#(Permit.*) (pro.*)|\1 yes|g' /etc/ssh/sshd_config
之后重启sshd服务即可。
使用NTP协议进行时钟同步的软件很多,比如ntpd或者chrony,这里建议使用后者:
emerge --ask net-misc/chrony
OpenRC
rc-update add chronyd default
SystemD
systemctl enable chronyd
/dev/sda1
和/dev/sda3
我们分别使用了FAT32和EXT4两个文件系统,所以至少需要安装这两个工具:
emerge --ask sys-fs/dosfstools sys-fs/e2fsprogs
以下选项根据实际引导对应选择
当使用BIOS引导时,无需其他配置直接安装GRUB:
emerge --ask --verbose sys-boot/grub
在/etc/default/grub
添加两行:
GRUB_CMDLINE_LINUX="init=/lib/systemd/systemd"
GRUB_DISABLE_OS_PROBER=false
安装grub到第一块盘:
grub-install /dev/sda
生成grub.cfg配置文件:
grub-mkconfig -o /boot/grub/grub.cfg
同理,先安装grub:
emerge --ask --verbose sys-boot/grub
在将grub安装到引导分区:
grub-install --target=x86_64-efi --efi-directory=/boot
生成grub.cfg
配置文件:
grub-mkconfig -o /boot/grub/grub.cfg
以上步骤安装完成后,可以退出chroot环境,并使用umount取消挂载,最后重启系统:
(chroot) (none) / # exit
exit
(none) ~ # umount -l /mnt/gentoo/dev{/shm,/pts,}
(none) ~ # umount -R /mnt/gentoo
(none) ~ # reboot
重启后,可以正常进入系统,说明已经成功:
进入系统后,stage3包我们已经不需要了,可以把它们删除掉:
rm /stage3-*.tar.*
同时可以安装neofetch
工具看下系统概览:
emerge --ask app-misc/neofetch
到此,整个系统已经全部安装结束。
附上PDF版本:
在dotnet可以使用Take获取指定数量的元素,获取顺序是从前向后,而获取到的数量是小于等于传入的指定数量。如数组中元素的数量小于传入的指定数量,则返回数组中的所有元素。如果数组中元素的数量大于等于传入的数量,则按照数组或列表顺序返回指定数量的元素在使用Take方法之前,请引用命名空间usingSystem.Linq;复制获取的时候通过在枚举类添加Take方法传入获取数量就可以返回小于或等于指定数量的元素varlist=newList<int>(); for(inti=0;i<10;i++) { list.Add(i); } foreach(vartempinlist.Take(100)) { Console.WriteLine(temp); }复制如上面代码,传入的获取数量是100而数组里面只有10个元素,那么将返回10个元素一些细节如下:如果传入的Count值小于等于0那么将会返回空列表因为用的是延迟加载,所以没有枚举是不会执行逻辑如果是列表将会返回ListPartition实例,但这是一个内部类ListPartition更多请看Enumerable.Take
useState使用useState的用法很简单,返回一个数组,数组的值为当前state和更新state的函数;useState的参数是变量、对象或者是函数,变量或者对象会作为state的初始值,如果是函数,函数的返回值会作为初始值。批量更新functionCount(){ let[count,setCount]=useState(0) consthandleAdd=function(){ setCount(count+1) setCount(count+1) } return( <div> <p>{count}</p> /*每次点击加1*/ <buttononClick={handleAdd}>加一</button> </div> ) } 复制在同一个事件中并不会因为调用了两次setCount而让count增加两次,试想如果在同一个事件中每次调用setCount都生效,那么每调用一次setCount组件就会重新渲染一次,这无疑使非常影响性能的;实际上如果修改的state是同一个,最后一个setCount函数中的新
很多同学好奇:总说互联网数据分析,到底啥是互联网数据分析?和传统企业有啥区别?今天系统讲解下。典型的传统企业典型的传统企业,以制造业为代表的,商业模式是:1、进原料,生产成产品2、通过经销商,卖到全国3、承担产品的售后、服务工作因此,其部门划分通常如下,分为:供应、研发、营运、营销、销售五大板块。这五大板块,也带来了相应的数据分析需求(如下图)。传统企业之间也有差异,主要在于供应链。比如汽车、地产、家电、家具等重资产的传统企业,生产线、原料、装配、库存都是大工程。因此分析任务很重,不但要监控质量,控制成本,还得考虑合理分配任务,控制库存,等等问题。在销售端,随着渠道形式的不同,也有分析差异。自营门店、电话销售、业务员跑单,是三种典型的销售方式,分析思路略有区别(如下图)。不过,随着互联网+的深入,传统企业也没有那么传统化了,有很多方面在向互联网看齐。互联网+以后的传统企业互联网对传统企业最大的改造在于销售和营销端。在销售端,传统企业也能自建电商APP/小程序,直接做toC的生意。也能入驻电商平台,通过平台销售。在营销端,现在传统企业也很流行做自媒体矩阵,在各个新媒体平台上建账号,搞运营
文章目录项目概述模块划分通用模块数据备份模块前端模版搭建前台模块商家模块超级管理员模块技术选型环境参数开发环境搭建Step1新建MavenWeb项目Step2构建的项目中出现的错误调整问题一Error:Thesuperclass"javax.servlet.http.HttpServlet"wasnotfoundontheJavaBuildPathindex.jsp/o2o/src/main/webappline1问题二Warining:BuildpathspecifiesexecutionenvironmentJ2SE-1.5.TherearenoJREsinstalledintheworkspacethatarestrictlycompatiblewiththisenvironment.Step3class输出路径检查Step4DynamicWebModule检查以及web.xml调整Step5工程编码检查Step6运行基础环境ProjectfacetJavaversion1.8isnotsupported.Github托管附-ServletTomcatJDK对
视频讲解:https://www.yuque.com/chudi/tzqav9/ny150b#aalY8 importtensorflowastf fromtensorflowimportkeras fromutilsimport* EPOCH=10 BATCH_SIZE=32 VEC_DIM=10 DNN_LAYERS=[64,128,64] DROPOUT_RATE=0.5 base,test=loadData() #所有的特征各个类别值个数之和 FEAT_CATE_NUM=base.shape[1]-1 K=tf.keras.backend defrun(): #将所有的特征的各个类别值统一id化。x中每行为各特征的类别值的id val_x,val_y=getAllData(test) train_x,train_y=getAllData(base) cate_num=val_x[0].shape[0] sub_emb_arr=[] product_list=[] inputs=keras.Input((cate_num,)) emb=keras.layers.Embe
1.背景SpringBoot默认使用Logback框架作为日志框架。最近有个想法“由于配置了多环境,比如开发环境,测试环境等,想根据不同环境指定日志文件的存储位置”2.行动分下面几个步骤:第一步:配置多环境第二步:配置不同环境下的参数第三步:配置logback的配置文件第四步:配置appender2.1第一步:配置多环境我已经配置好了多环境,如下:application-dev.ymlapplication-test.ymlapplication-release.yml参考:https://www.jianshu.com/p/61758ef6b5132.2第二步:配置不同环境下的参数开发时,是在mac环境下 在application-dev.yml下配置:logging: path:/Users/zhangyunfei/Downloads ....复制下面是线上环境的配置,它在linux系统下 在application-release.yml下配置:logging: path:/data/logs ....复制2.3第三步:配置logback的配置文件打开logback的配置文件log
作者:Jimmychow,人在中国香港。在通信行业二十余年,除了销售以外的工作,几乎全都做过,包括教育,研发,营销,管理,咨询等,设备商运营商学校都呆过,固网移动也全干了一遍,全球高端点的运营商前20位CxO级别的,过半有过交流吹嘘,而且以前主要的工作就是干这些吹牛的事情.如今,已年老色衰,所有的工作均为自由状态,保持着行业的联系,以及更多的时间照顾孩子家人。有配置中国香港保险找他。以下全文。文章不代表边缘计算社区观点。 5月6-8日,美国的Big5GEvent在Denver举办,这是北美业界的一个最大的论坛/展会,该来的都来了,设备商则为赞助伙伴,包括Cisco,Ericsson,Huawei,Qualcomm,Intel,等一个都不少. 与4G时代的类似专业论坛不一样,以前主要是电信运营商及諷设备商参加,外加一些产业链上的小伙伴.现在的5G时代,除了他们以外,互联网的各路神仙也都积极参与,不管是每年的MWC,还是其它的区域展会/论坛.LightReading的一则关于移动边缘计算MEC(MobileEdgeComputing)我觉得可以仔细研究一下. 仔细看看,问题也没啥!在这个
传说的像素眼,也就是可以快速分辨出1px以上差异的双眼,往往由资深设计师所get√,小鸡君本人是个苦逼程序员,但小鸡君的像素眼也不比任何一个设计师差。 当然了,距离真正的像素眼神人还是有很大差距的,比如下面这种游戏,小鸡君还真是玩不起:不过对于平常的工作来说,比如还原个视觉稿什么的,小鸡君的双眼还是绰绰有余的(不是指个数)。那么传说的像素眼真的有那么神奇?1px的差异真的那么隐蔽吗?当然不是。想要练就一双迷人的像素眼,除了常年累月的经验之外,还是有些技巧可以快速掌握的。下面小鸡君就来分享一下这些容易被像素眼发现的重灾区,只要你用心观察,一定是可以看出差距的。不同字号对齐大小字号搭配,是最容易分清主次信息的手法了。在页面的具体实现过程中,也很容易忽略这里的对齐问题。所以,这里往往是展示你像素眼技能的好地方。比如下面这张图,底边有1px没有对齐,左侧下沉了一点:我们把截图放到PS里面看一下,为了清晰,我把参考线调成了黑色:可以看到,左侧的销售价三个字的底部已经有1px在参考线以下了。所以下次,作为一个追求极致的设计师,再看到页面时就可以先关注一下这种地方,一定会有意想不到的收获。图片与文字
RealmRealm是一个MVCC(多版本并发控制)数据库,由YCombinator公司在2014年7月发布一款支持运行在手机、平板和可穿戴设备上的嵌入式数据库,目标是取代SQLite。 Realm本质上是一个嵌入式数据库,他并不是基于SQLite所构建的。它拥有自己的数据库存储引擎,可以高效且快速地完成数据库的构建操作。和SQLite不同,它允许你在持久层直接和数据对象工作。在它之上是一个函数式风格的查询api,众多的努力让它比传统的SQLite操作更快查看官网介绍:https://realm.io/cn/Realm的优点简单易用速度快跨平台高级功能可视化开源接入根目录build.gradle进行以下配置:buildscript{ repositories{ jcenter() } dependencies{ ... classpath"io.realm:realm-gradle-plugin:3.1.1" ... } }复制工程目录build.gradle依赖插件:applyplugin:'realm-android'复制Applicat
我们官网后台有访客防火墙,为了统计用户的登录信息,由于网站做了全站的CDN,所以防火墙默认获取到的ip全是CDN的ip。 这样就不便于我们做安全工作了,只好剔除CDN的ip,只获取访客的真是ip。 由于CDN商家一般不会提供header头,就只能依靠nginx的模块来支持了。 一:安装realip模块 nginx-V看看有没有安装,没有就单独编译安装下,有就直接修改nginx的配置即可。如果没有,就进nginx文件夹去编译:—with–http_realip_module./configure--user=www--group=www--prefix=/usr/local/nginx--with-http_stub_status_module--with-http_ssl_module--with-http_v2_module--with-http_gzip_static_module--with-ipv6--with-http_sub_module--with-openssl=/root/lnmp1.4/src/openssl-1.0.2l--with-http_geoip_modu
渗透测试人员其实都知道,只要能够直接接触到目标设备,并且选对了工具,那么任何设备都会成为“待宰的羔羊”。早在2005年,Hak5就已经研发出了一款简单又暴力的渗透测试工具。随着BashBunny的问世,渗透测试可能又更进了一步。组合各种USB设备的攻击方式按照Hak5自己的说法,这款设备是“世界上最先进的USB攻击工具”。我们就来看看这款工具究竟有哪些本领。这款设备“打开”的攻击面的确比先前的设备大了很多。渗透测试攻击和IT自动化工作,对BashBunny而言几秒内就能完成。通过各种USB设备——像以太网卡、串口设备、闪存、键盘等,BashBunny就能够从计算机中获取数据、文档,给计算机安装后门还有各种exploit了。设备采用简单的脚本语言,用记事本之类的工具就能编写。各种paylaod代码就包含在一个库(GitHub)中,要找到相应的攻击方式还是很容易的。发动BashBunny攻击,只需要将开关切换到武器模式(armingmode),复制一份payload文件——使用过程几乎和普通U盘没什么差别。发动多种payload应该是这款设备的一大特色。将开关切换到相应payload选择(
WPF截图控件之移除控件(九)「仿微信」 WPF截图控件之移除控件(九)「仿微信」 作者:WPFDevelopersOrg 原文链接:https://github.com/WPFDevelopersOrg/WPFDevelopers 框架使用大于等于.NET40; VisualStudio2022; 项目使用MIT开源许可协议; 截图控件暂时更新到此,未实现功能如下 Hook快捷打开截图。 添加操作还不能移动和更改大小 获取根据当前坐标返回进程的大小Rect。 获取鼠标区域RGB。 1.WPF实现截屏「仿微信」 2.WPF实现截屏控件之移动(二)「仿微信」 3.WPF截图控件之伸缩(三)「仿微信」 4.WPF截图控件之绘制方框与椭圆(四)「仿微信」 5.WPF截图控件之绘制箭头(五)「仿微信」 6.WPF截图控件之绘制箭头(六)「仿微信」 7.WPF截图控件之文字(七)「仿微信」 8.WPF截图控件之画笔(八)「仿微信」 正文 一、前几篇实现了添加方框、椭圆、箭头此时需要删除所添加的操作和撤销上次操作。 1)选中操作 在添加方框、椭圆、箭头、画笔、文字的同时需
前言 最近这两天刚刚接触Spine,研究了一下UnityMecanimAnimator如何控制Spine,在此分享记录一下,如有不当之处,请留言指出,欢迎讨论。 Unity&Spine 想要在Unity中使用Spine动画,目前有三种方式。第一种,利用SkeletonAnimation,这是Spine提供的原生方式,支持所有Spine功能。第二种,利用Mecanim(orSkeletonAnimator),使用此方式Spine-unity会将SkeletonData中的动画转换为一系列AnimationClips,并生成一个UnityAnimatorController。SkeletonAnimator 组件关联UnityAnimator和SpineAnimation,并利用SpineAnimation APIMix和Aplly方法控制动画。这允许我们使用Unity的原有流程控制动画。但是可能有些副作用关于attachmentkeyframes,可能很难追踪问题。attachmentkeyframes目前我还没有研究到。第三种,利用Baking,这个不推荐,这个是专门
从今天起,本人将会展开对Redis源码的学习,Redis的代码规模比较小,非常适合学习,是一份非常不错的学习资料,数了一下大概100个文件左右的样子,用的是C语言写的。希望最终能把他啃完吧,C语言好久不用,快忘光了。分析源码的第一步,先别急着想着从哪开始看起,先浏览一下源码结构,可以模块式的渐入,不过比较坑爹的是,Redis的源码全部放在在里面的src目录里,一下90多个文件统统在里面了,所以我选择了拆分,按功能拆分,有些文件你看名字就知道那是干什么的。我拆分好后的而结果如下: 11个包,这样每个包中的文件就比较可接受了,但是分出这个类别,我也是花了一定时间,思考了下,Redis下的主要的一些文件的特征,最后定的,应该算是比较全的了。 下面开始一个包一个包的介绍: test:(测试) 1.memtest.c内存检测 2.redis_benchmark.c用于redis性能测试的实现。 3.redis_check_aof.c用于更新日志检查的实现。 4.redis_check_dump.c用于本地数据库检查的实现
快速阅读 如何在winform程序中,让界面不再卡死。关于委托和AsyncCallback的使用。 界面卡死的原因是因为耗时任务的计算占用了主线程,导致主界面没有办法进行其它操作,比如拖动。造成界面卡死的现象。我们只需要把耗时任务放在子线程中执行就可以了。 子线程的计算结果要更新到界面中,怎么更新呢,因为不能操作主线程,所以要用委托来实现。 我们来看个例子。 场景 界面上一个按钮加一人richbox,点击以后获得当前所在年份 代码实现 定义一个委托实现子线程更新主线程 publicdelegatevoidUpdateText(stringmessage); publicvoidUpdateTextMehod(stringmessage) { richTextBox1.Text+=message+"\r\n"; richTextBox1.ScrollToCaret(); } 复制 按钮的点击事件 func委托:表示模拟一个耗时的操作(2s),然后返回一个结果。 Asynccallback:表示在相应异步操作完成时调用的方法。在这个方法中,获取异步执行的结果。 要获取异步执行的结果
文中图片摘自腾讯文化网:www.cal.qq.com1.Abstract 生活本就是平淡的,如同真理一般寂静。平时生活中不经意的瞬间,也有它本来的美丽。下面一组图是上上个世纪到上个世纪末一个画家的作品,通过绘画的手法将平凡人生活中的一些习以为常的动作刻画下来。绘画的技艺高超只有通过看画才更能体会到,作品中充融入了太多作者的细腻情感,自然而然地勾勒出了美源自于生活,美源自于平凡,美就在我们身边的主题。2.ContentFIG2.1讲故事 值得注意的是仔细看看小女孩陶醉的眼神,还有就是大手牵小手的温暖细节。FIG2.2品花香 FIG2.3专注FIG2.4削苹果 这张值得说一点的是,注意坐姿的悠闲,即使削下的果皮落到裙上也无伤大雅,右边桌上还有需要做的面粉团,一片闲下来时惬意感。FIG2.5修女与采花贼 花儿的美丽每个人都不会拒绝去欣赏,即使在清净之地,也忍不住险身试试,强烈的羞怯紧张氛围。FIG2.
GNS3的安装 1.先安装workstation 2.安装GNS3创建一些VMWARE的口 GNS3-1.4.4 solarwind/QMU/VPC不需要,其他的应该都要装。 选择localserver,本地的GNS3,选择一个个自己装IOU. IOU一般是一些交换机的个别的特性。 3.添加IOS镜像,一般有3个:36(80%是用这个的)/72-AD(特殊的命令)/72-AD-15.14/ASA842 4.GNS3网口的选择 0/0 0/11/02/03/0 本地的GNS360%的实验环境就搭建完了 改一下GNS3中开机的预配:startup-config ! service timestamps debug datetime msec service timestamps log datetime msec no service password-encryption ! hostname %
廚房水槽的使用非常頻繁。水槽主要分為單水槽和雙水槽。很多人不知道如何選擇,這也與檯面的尺寸有關。那麼,廚房的水槽是單水槽還是雙水槽?廚房的水槽多少錢合適?而且我們發現廚房下沉一段時間後,水會越來越慢,甚至堵塞。那麼,如何疏通廚房的下水道呢?讓我們看看下麵。 1、廚房水槽用單水槽或雙水槽 首先,廚房的水槽應該能够容納清**鍋碗瓢盆,否則水肯定會溢出來,到時候地面會潮濕。但如果檯面空間本來就小,不需要考慮雙槽,直接選擇單槽。囙此,如果檯面空間足够*,可以完全放下雙水槽,那麼就選擇雙水槽。 其次是清潔習慣。每個人的清潔習慣都不一樣。如果你*蔬菜和水果,你寧願直接在水槽裏*,或者把其他的盆放進水槽裏。如果是前者,選擇雙水箱,這樣水就不會到處流;如果你習慣了後者,選擇單水箱。 我們通常用兩個罐子,一個用來*油膩的東西,另一個用來提神。單罐與罐混合。 兩罐:既貴又好用。這兩個罐可以分類清*,很麻煩。兩個水箱有兩個污水,所以污水的管理會比較複雜,所以發生壞事的幾
第三章CSS网页布局与定位 3.1div 几乎XHTML中的任何标签都可以用于浮动与定位,而div首当其冲。对于其他标签而言,往往有它自身存在的目的,而div元素存在的目的就是为了浮动与定位。 3.1.1div是什么 div是XHTML中制定的、专门用于布局设计的容器对象。在传统表格式布局中,之所以能够进行页面的排版布局设计,完全依赖于表格对象table。如今,接触另一种布局方式——CSS布局。div正是这种布局方式的核心对象。仅从div的使用上说,做一个简单的布局只需要依赖两样东西:div与CSS。因此有人称CSS布局为div+css布局。 3.1.2如何使用div 只需要应用<div></div>标签,将内容放置其中,便可以应用div标签。但是,div标签之声一个标识,作用是把内容标识成一个块区域,并不负责其他事情。 div标签中除了直接放入文本外,也可以放入其他标签,还可以多个div进行嵌套使用,最终目的是合理地标识出内容区域。 在使用div标签时,可以加入一些属性,比如id、class、align、style等。在CSS布局方法,为了
懒汉单例的实现步骤: 1定义一个类,把构造器私有。 2定义一个静态变量存储一个对象。 3提供一个返回单例对象的方法。 子类不可以继承父类的构造器,子类有自己的构造器,父类构造器用于初始化父类对象。 子类可以继承父类的私有成员,但是不能直接访问。 子类可以继承父类的静态成员: 1有争议的知识点。 2子类可以直接使用父类的静态成员(共享)。 3但个人认为:子类不能继承父亲的静态成员(共享并非继承)。 子类为何不支持多继承 继承的特点: 1子类可以继承父类的属性和行为,但是子类不能继承父类的构造器。 2java是单继承模式:一个类只能继承一个直接父类 3java不支持多继承,但是支持多层继承 4java中所有的类都是object类的子类。 在子类方法中访问成员(成员变量,成员方法)满足就近原则 方法的重写 子类继承父类后构造器的特点:子类中所有的构造器默认都会先访问父类中无参构造器,再执行自己。 super调用父类构造器的作用:通过调用父类有参数构造器来初始化继承来自父类的数据。
CxClientSocket的使用如下(以某个叫做CSomeClass的类的相关代码为例): 一、声明客户端套接字对象实例。 CxClientSocketm_csRemoteHost;复制 二、设置客户端套接字事件通知方式。消息响应或回调函数,任选其一。客户端套接字事件有:缓冲区有数据可读取、与远程主机的连接被断开。 voidCSomeClass::PreSubclassWindow() { //TODO:Addyourspecializedcodehereand/orcallthebaseclass HWNDhwnd=GetSafeHwnd(); MSGmsg={hwnd,WM_SOCKET_EVENT}; m_usRemoteHost.SetWindowMessage(&msg); m_csRemoteHost.SetWindowMessage(&msg); m_ssLocalHost.SetWindowMessage(&msg); if(m_btCSMode==CSM_SERVER) ListenRemoteHost(); CStatic::Pr