1 lang
1.1 path
01.Java
a.安装
mv jdk-8u191-linux-x64.tar.gz /usr/local
cd /usr/local
tar -zxvf jdk-8u191-linux-x64.tar.gz
rm -r jdk-8u191-linux-x64.tar.gz
mv jdk1.8.0_191 jdk-1.8.0_191
b.环境变量
gedit /root/.bashrc
export JAVA_HOME=/usr/local/jdk-1.8.0_191
export CLASSPATH=$JAVA_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$PATH
source /root/.bashrc
c.测试
java -version
02.Maven
a.安装
mv apache-maven-3.6.3-bin.tar.gz /usr/local
cd /usr/local
tar -zxvf apache-maven-3.6.3-bin.tar.gz
rm -r apache-maven-3.6.3-bin.tar.gz
b.环境变量
gedit /root/.bashrc
export MAVEN_HOME=/usr/local/apache-maven-3.6.3
export PATH=$MAVEN_HOME/bin:$PATH
source /root/.bashrc
c.测试
mvn -V
03.Tomcat
a.安装
mv apache-tomcat-9.0.78.tar.gz /usr/local
cd /usr/local
tar -zxvf apache-tomcat-9.0.78.tar.gz
rm -r apache-tomcat-9.0.78.tar.gz
b.环境变量
gedit /root/.bashrc
export MAVEN_HOME=/usr/local/apache-tomcat-9.0.78
export PATH=$MAVEN_HOME/bin:$PATH
source /root/.bashrc
c.测试
startup.sh
04.Nodejs-14.21.1,【不支持】npm安装pnpm
a.安装
mv node-v14.21.1-linux-x64 /usr/local
cd /usr/local
tar -zxvf node-v14.21.1-linux-x64
rm -r node-v14.21.1-linux-x64
mv node-v14.21.1 node-14.21.1
b.环境变量
gedit /root/.bashrc
export NODE_HOME=/usr/local/node-14.21.1
export PATH=$NODE_HOME:$NODE_HOME/bin:$NODE_HOME/node-global:$PATH
source /root/.bashrc
c.配置
npm config set prefix "/usr/local/node-14.21.1/node-global"
npm config set cache "/usr/local/node-14.21.1/node-cache"
npm config ls
d.测试
npm -v
node -v
05.Nodejs-16.20.1,【不支持】npm安装pnpm
a.安装
mv node-v16.20.1-linux-x64.tar /usr/local
cd /usr/local
tar -zxvf node-v16.20.1-linux-x64.tar
rm -r node-v16.20.1-linux-x64.tar
mv node-v16.20.1 node-16.20.1
b.环境变量
gedit /root/.bashrc
export NODE_HOME=/usr/local/node-16.20.1
export PATH=$NODE_HOME:$NODE_HOME/bin:$NODE_HOME/node-global:$PATH
source /root/.bashrc
c.配置
npm config set prefix "/usr/local/node-16.20.1/node-global"
npm config set cache "/usr/local/node-16.20.1/node-cache"
npm config ls
d.测试
npm -v
node -v
06.Nodejs-20.18.0,【支持】npm安装pnpm
a.安装
mv node-v20.18.0-linux-x64.tar.gz /usr/local
cd /usr/local
tar -zxvf node-v20.18.0-linux-x64.tar.gz
rm -r node-v20.18.0-linux-x64.tar.gz
mv node-v20.18.0 node-20.18.0
b.环境变量
gedit /root/.bashrc
export NODE_HOME=/usr/local/node-20.18.0
export PATH=$NODE_HOME:$NODE_HOME/bin:$NODE_HOME/node-global/bin:$PATH
source /root/.bashrc
c.配置
npm config set prefix "/usr/local/node-20.18.0/node-global"
npm config set cache "/usr/local/node-20.18.0/node-cache"
npm config ls
d.测试
npm -v
node -v
e.安装
npm install -g pnpm
pnpm set registry http://172.17.8.54/
pnpm set registry https://registry.npmmirror.com
pnpm adduser --registry http://172.17.8.54/
pnpm profile set password --registry http://172.17.8.54/
-----------------------------------------------------------------------------------------------------
pnpm login
j057240
qwER159263
-----------------------------------------------------------------------------------------------------
pnpm c get
pnpm i --registry https://registry.npmmirror.com
07.Navicat
a.权限
mkdir /usr/local/navicat
cd /Ubuntu/software/SQL/Navicat/
mv navicat15-premium-cs.AppImage /usr/local/navicat/navicat15-premium-cs.AppImage
mv navicat.jpg /usr/local/navicat/navicat.jpg
cd /usr/local/navicat/
chmod +x navicat15-premium-cs.AppImage
b.创建Navicat.desktop
gedit /usr/share/applications/Navicat.desktop
c.编辑pycharm.desktop
[Desktop Entry]
Version=1.0
Type=Application
Name=Navicat
Icon=/usr/local/navicat/navicat.jpg
Exec=/usr/local/navicat/navicat15-premium-cs.AppImage
MimeType=application/x-py;
Name[en_US]=Navicat
1.2 debian
00.Debian13包含了超过14,100个新软件包,总数达到近70,000个
a.系统与内核
Linux Kernel: 6.12 LTS 系列
Systemd: 257
GNU C Library: 2.41
b.编译器与工具链
GCC: 14.2
LLVM/Clang: 19 (默认), 17, 18 可选
Python: 3.13
Perl: 5.40
PHP: 8.4
Rustc: 1.85
OpenJDK: 21
c.服务与数据库
Apache: 2.4.64
Nginx: 1.26
MariaDB: 11.8
PostgreSQL: 17
Samba: 4.22
OpenSSH: 10.0p1
OpenSSL: 3.5
d.桌面环境与应用
GNOME: 48
KDE Plasma: 6.3
Xfce: 4.20
LibreOffice: 25.2
GIMP: 3.0.4
Inkscape: 1.4
01.开机设置一:介绍
a.Debian10(Buster)
引入新的Debian 10的主题 “FuturePrototype”
新版本的电脑桌面环境GNOME 3.30、Cinnamon 3.8、KDE Plasma 5.14、MATE 1.20、Xfce 4.12
长期支持版内核4.19.0-4
新的Python 3 (3.7.2)、Perl 5.28、PHP 7.3
iptables替换为 nftables
更新LibreOffice 6.1、GIMP 2.10.8
更新OpenJDK 11、MariaDB 10.3 和 Apache 2.4.38
更新Chromium 73.0、Firefox 60.7
b.默认账号
User(osboxes、osboxes.org)(myslayers、4023615)
Root(root、osboxes.org)(root、4023615)
c.切换root
su -
osboxes.org
d.用户sudo权限
sudo vi /etc/sudoers
osboxes ALL=(ALL:ALL) ALL --打开osboxes全部权限
myslayers ALL=(ALL:ALL) ALL --打开myslayers全部权限
e.安装Vmware Tools
tar -zxvf VMwareTools-10.0.0-2977863.tar.gz
sudo ./vmware-install.pl -y
f.Settings
Privacy -> Off(ScreenLock、LocationServices、Usage&History、PurgeTrash&TemporaryFiles)
Power -> PowerSaving(Never)、Suspend&PowerButton(Off)
KeyboardShortcuts -> HomeFolder(Win+E)、Settings(Win+I)、Browser(Win+1)
KeyboardShortcuts -> add -> 名称(Terminal)、命令(gnome-terminal)、快捷键(Win+R)
Account -> User(myslayers)、Password(40236155)
02.开机设置二:更新工具
a.默认vi-tiny
a.解决默认vi-tiny无法使用“删除键”、“方向键”
sudo vi /etc/vim/vimrc.tiny
set nocompatible --将compatible变nocompatible(方向)
set backspace=2 --末行增加set backspace=2(删除键)
b.将默认vi-tiny替换为vim
apt-get update && apt-get -y remove vim-common && apt-get -y install vim*
b.国内镜像源
a.备份默认镜像源
sudo cp /etc/apt/sources.list /etc/apt/sources.list_bak
a.切换tsinghua镜像源
sudo apt install apt-transport-https ca-certificates
b.查看tsinghua镜像源
vi /etc/apt/sources.list
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-updates main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-backports main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian-security buster/updates main contrib non-free
c.tasksel命令
a.tasksel一键搭建LAMP服务器、邮件服务器、DNS服务器
sudo tasksel install lamp-server
sudo tasksel install mail-server
sudo tasksel install dns-server
b.切换桌面
sudo tasksel -> KDE Plasma、GNOME、Xfce、Cinnamon、web server、print server、SSH server -> 空格选
update-alternatives --config x-session-manager --切换桌面系统
d.IPv4+DNS
a.修改网卡配置:dhcp,vi /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface
allow-hotplug ens33
iface ens33 inet dhcp
b.修改网卡配置:vi /etc/network/interfaces,假设网卡名为eth33
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface
auto ens33
iface ens33 inet static
address 192.168.2.138
netmask 255.255.255.0
gateway 192.168.2.1
dns-nameservers 192.168.2.1
c.配置DNS解析
vi /etc/NetworkManager/NetworkManager.conf --在[main]后追加dns=none
vi /etc/resolv.conf --设置DNS解析
nameserver 192.168.2.1
d.重启网卡
systemctl restart networking --Ubuntu/Debian:重启网络
systemctl status networking --Ubuntu/Debian:查看状态
e.auto与allow-hotplug区别
auto:不管有无网线,网卡都会启用,运行/etc/init.d/networking restart之后,网卡能自动重启
allow-hotplug:只会在开机时启动插网线的网卡,运行/etc/init.d/networking restart之后,网卡不能自动重启
DNS优先级:/etc/hosts文件 > /etc/network/interfaces中DNS > /etc/resolv.conf中DNS
修改主机名:/etc/hostname -> debian01
e.映射 vi /etc/hosts 或 C:\Windows\System32\drivers\etc\hosts
192.168.2.128 bigdata01
192.168.2.129 bigdata02
192.168.2.130 bigdata03
192.168.2.131 bigdata04
192.168.2.132 bigdata05
192.168.2.138 debian01
192.168.2.2 bigdata
03.开机设置三:配置root用户(图形界面)
a.配置一:root用户密码修改
sudo passwd root --修改root密码
su --切换root用户
sudo whoami --查看用户是否具有sudo权限
b.配置二:root用户登陆图像界面
vi /etc/gdm3/daemon.conf
AutomaticLoginEnable = true --以root自动登录
AutomaticLogin = root --以root自动登录
[security]
AllowRoot=true --允许root登录
c.配置三:root用户登陆图像界面
vi /etc/pam.d/gdm-autologin
auth required pam_success_if.so user!=root quiet_success --注释该行
d.配置四:root用户登陆图像界面
vi /etc/pam.d/gdm-password
auth required pam_success_if.so user!=root quiet_success --注释该行
e.配置五:root用户图形界面登陆错误
vi /root/.profile
tty -s && mesg n || true --修改内容
04.开机设置四:配置root用户(SSH界面)
a.安装openssh-server
yum list installed | grep openssh-server --检测是否安装
yum install openssh-server --如果未安装,则安装openssh-server
yum install -y glibc libgcc libstdc++ python ca-certificates tar openssh-server bash curl
b.配置
vi /etc/ssh/sshd_config
Port 22 --监听端口
ListenAddress 0.0.0.0 --监听地址
ListenAddress :: --监听地址
PermitRootLogin yes --开启远程访问(SSH,root用户登录)
--------------------------
PubkeyAuthentication yes --开启密钥验证(SSH,pubkey登录)
AuthorizedKeysFile .ssh/authorized_keys --开启密钥验证(SSH,pubkey登录)
--------------------------
PasswordAuthentication yes --开启密码验证(SSH,密码验证)
c.开启服务
systemctl start sshd --开启服务
systemctl enable sshd --开机自启
systemctl restart sshd --重启服务
ps -e | grep sshd --检查sshd服务是否已经开启
systemctl list-unit-files | grep sshd --检查sshd服务是否开机自启
yum check-update && yum install code -y --远程机器安装VScode
d.ssh免密钥登录(Remote-SSH只提供使用RSA秘钥远程登录,SSH不支持命令行-p输入明文密码)(默认aes256-cbc类型)
a.win10生成密钥
ssh-keygen -t rsa
b.将Win10中的公钥id_rsa.pub -> 手动放到Centos7中的authorized_keys
chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys
c.win10远程访问(C:\Windows\System32\OpenSSH)
ssh [email protected]
ssh [email protected] -i "C:\Users\mysla\.ssh\id_rsa.ppk" -P 22
ssh [email protected] -i "C:\Users\mysla\.ssh\id_rsa.ppk" -P 22
d.putty远程访问(D:\software\Java\putty-0.74)
connection -> SSH -> Auth -> Browse -> 选中putty密钥(id_rsa.ppk)
session -> IP(192.168.2.128)、Port(22)、Saved(bigdata01) -> 连接
1.3 ubuntu
00.Ubuntu 24.04 LTS 是一个里程碑式的版本
a.系统与内核 (System & Kernel)
Linux Kernel: 6.8,带来了最新的硬件支持,并增强了性能调度与网络功能。
Systemd: 255,提供了更完善的系统和服务管理能力。
GNU C Library: 2.39,基础C库更新,提升了兼容性和安全性。
Netplan: 1.0,网络配置工具迎来重要更新,支持更复杂的网络场景。
b.编译器与工具链 (Compilers & Toolchain)
GCC: 14 (可选, 默认 13.2),提供了对最新C++标准的支持和更强的编译优化能力。
LLVM/Clang: 18
Python: 3.12,默认版本,带来了性能改进和新的语言特性。
Perl: 5.38
PHP: 8.3
Rustc: 1.75
Go: 1.22
OpenJDK: 21 (默认), 17, 11 可选,全面支持最新的Java LTS版本。
c.服务与数据库 (Services & Databases)
Apache: 2.4.58
Nginx: 1.24
MariaDB: 10.11
PostgreSQL: 16
Samba: 4.19
OpenSSH: 9.6p1,增强了安全性,默认禁用较弱的RSA/SHA1签名。
OpenSSL: 3.2
d.桌面环境与核心应用 (Desktop Environment & Core Applications)
GNOME: 46,带来了全局搜索的重大改进、更高效的文件管理、可变刷新率(VRR)的实验性支持以及优化的设置面板。
KDE Plasma: 5.27.11 (Kubuntu),Kubuntu 24.04 LTS 仍然使用 Plasma 5.27,以保证稳定性。
Installer: Subiquity,采用了全新的基于Flutter构建的桌面安装程序,支持如ZFS、自动安装等高级功能,界面更现代化。
App Center: 新的应用中心,替代了原有的 "Ubuntu Software",提供更流畅的Snap应用浏览和管理体验。
LibreOffice: 24.2
GIMP: 2.10.36
Inkscape: 1.3.2
01.开机设置一:安装
a.空白分区
此电脑 -> 管理 -> 磁盘管理 -> D盘 -> 压缩 -> 307200MB
b.手动分区,将EFI系统分区作为系统启动引导器
4096MB 逻辑分区 空间起始位置 EFI文件系统
32768MB 逻辑分区 空间起始位置 SWAP交换空间
4096MB 逻辑分区 空间起始位置 Ext4日志文件系统 /tmp
4096MB 逻辑分区 空间起始位置 Ext4日志文件系统 /boot
108544MB 逻辑分区 空间起始位置 Ext4日志文件系统 /home
153600MB 主分区 空间起始位置 Ext4日志文件系统 /
c.使用Ubuntu双系统
a.设置Bios
F2 -> Security -> Secure Boot -> Disabled --关闭安全防护
F2 -> Boot -> Legacy support -> Boot priority -> Windows --默认启动windows
b.切换系统
F12
d.关闭AOMEI OneKey Recovery
a.设置Bios
F2 -> Security -> Secure Boot -> Enabled --开启安全防护
F2 -> Boot -> Legacy support -> Boot priority -> Windows --默认启动windows
b.切换系统
F12
c.系统设置
msconfig -> 常规(选择性启动:加载系统服务、加载启动项)、引导(删除AOMEI OneKey Recovery)-> 应用
e.删除分区(Windows系统)
diskpart --进入分区命令
list disk --查看当前磁盘列表
select disk 0 --选中操作的磁盘
list partition --查看该磁盘下的分区
select partition X --选择操作的分区
delete partition override --强制删除该分区
f.安装Vmware Tools
tar -zxvf VMwareTools-10.0.0-2977863.tar.gz
sudo ./vmware-install.pl -y
g.常见的镜像源
http://mirrors.aliyun.com/ubuntu-releases/16.04/
http://mirrors.zju.edu.cn/ubuntu-releases/16.04/
http://mirrors.melbourne.co.uk/ubuntu-releases/
http://mirrors.ustc.edu.cn/ubuntu-releases/16.04/
02.开机设置二:配置root用户
a.配置一:root用户密码修改
sudo passwd root --修改root密码
su --切换root用户
sudo whoami --查看用户是否具有sudo权限
b.配置二:root用户登陆图像界面
gedit /usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf
greeter-show-manual-login=true --追加内容
all-guest=false --追加内容
c.配置三:root用户登陆图像界面
gedit /etc/pam.d/gdm-autologin
auth required pam_success_if.so user!=root quiet_success --注释该行
d.配置四:root用户登陆图像界面
gedit /etc/pam.d/gdm-password
auth required pam_success_if.so user!=root quiet_success --注释该行
e.配置五:root用户图形界面登陆错误
gedit /root/.profile
tty -s && mesg n || true --修改内容
03.开机设置三:网卡
a.配置:卸载ideapad_laptop模块,启用无线网卡,打开文件权限
gedit /etc/modprobe.d/ideapad.conf
blacklist ideapad_laptop --追加内容
b.终端
sudo chmod 777 /etc/modprobe.d/ideapad.conf --打开文件权限
sudo modprobe -r ideapad_laptop --卸载ideapad模块
04.开机设置四:声卡
a.配置:root用户使用音频设备
gedit /etc/profile
pulseaudio --start --log-target=syslog --追加内容
b.终端
alsamixer -> HDA Intel PCH -> M --允许音频输出
05.开机设置五:显卡
a.配置:root用户亮度调节
gedit /etc/default/grub
quiet splash acpi_backlight=vendor acpi_osi=Linux --修改内容
b.终端
sudo update-grub --更新grub
06.开机设置六:进程
a.查看
ps -a --查看当前所有程序
top --查看当前活跃程序
q --返回终端
b.终止
kill [PID] --终止PID
kill 37788 --示例
pkill [ProcessName] --终止进程
pkill gnome-software --示例
killall [ProcessName] --终止程序所有实例
killall gedit --示例
c.snap
snap changes
sudo snap abort 7
07.开机设置七:更换数据源
a.配置文件
cd /etc/apt
cp sources.list sources.list.bak
vim sources.list
b.配置内容
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
c.更新配置
sudo apt-get update
sudo apt-get upgrade
1.4 machine1
01.CUDA
a.禁止自带nouveau驱动
a.卸载已安装的nvidia驱动
sudo apt-get remove --purge nvidia*
sudo apt-get purge nvidia*
sudo apt-get autoremove
sudo ./NIVIDIA-Linux-X86_64-384.59.run --uninstall
b.禁用自带nouveau驱动
gedit /etc/modprobe.d/blacklist-nouveau.conf
blacklist nouveau
blacklist lbm-nouveau
options nouveau modeset=0
alias nouveau off
alias lbm-nouveau off
c.更新内核
sudo update-initramfs -u --更新内核
d.重启
reboot
e.测试
lsmod | grep nouveau
b.安装依赖
a.获取build-essential、 gcc-multilib、dkms
sudo apt-get install build-essential gcc-multilib dkms
sudo apt install make
sudo apt install gcc
sudo apt install g++
b.获取kernel source
apt-get install linux-source
apt-get install linux-headers-$(uname -r)
c.降低内核版本
uname -r
sudo apt-get remove linux-image-4.4.0-140-generic
sudo apt-get remove linux-image-$(uname -r)
d.内核相关命令
a.查看内核列表
sudo dpkg --get-selections |grep linux-image
b.查看当前使用的内核
uname -r
c.升级/安装内核
sudo apt-get install linux-image-4.4.0-75-generic
d.删除内核
sudo apt-get remove linux-image-4.4.0-75-generic
c.安装NVIDIA驱动
a.查看系统信息
lspci | grep -i nvidia --查看GPU型号
sudo dpkg --list | grep nvidia-* --查看NVIDIA驱动版本
lspci | grep -i vga --查看显卡型号
http://pci-ids.ucw.cz/mods/PC/10de?action=help?help=pci --电脑显卡型号:2191
nvidia-smi --具体显卡型号
nvcc -V --查看cuda版本
b.卸载已安装的nvidia驱动
sudo apt-get remove --purge nvidia*
c.关闭图形界面
sudo apt-get install lightdm
sudo service lightdm stop --停止服务
d.安装NVIDIA驱动
sudo chomd a+x NVIDIA-Linux-x86_64-430.09.run
sudo NVIDIA-Linux-x86_64-430.09.run -no-x-check -no-nouveau-check -no-opengl-files
-no-x-check:安装驱动时关闭X服务
-no-nouveau-check:安装驱动时禁用nouveau
-no-opengl-files:只安装驱动文件,不安装OpenGL文件
-Z, --disable-nouveau:禁用nouveau,此参数非必需,之前已经手动禁用nouveau
-A:查看更多高级选项
e.安装过程中一些选项
The distribution-provided pre-install script failed! Are you sure you want to continue? 选择 yes 继续
Would you like to register the kernel module souces with DKMS? This will allow DKMS to automatically build a new module, if you install a different kernel later? 选择 No 继续
Nvidia's 32-bit compatibility libraries? 选择 No 继续
Would you like to run the nvidia-xconfigutility to automatically update your x configuration so that the NVIDIA x driver will be used when you restart x? Any pre-existing x confile will be backed up. 选择Yes 继续
f.挂载Nvidia驱动
modprobe nvidia
g.重启图形界面
sudo service lightdm start --开启服务
h.验证驱动是否安装成功
nvidia-smi
nvidia-settings
d.安装CUDA9.0
a.关闭图形界面
sudo service lightdm stop --停止服务
b.安装CUDA9.0
sudo chmod a+x cuda_9.0.176_384.81_linux.run
sudo ./cuda_9.0.176_384.81_linux.run --no-opengl-libs
--no-opengl-libs:只安装驱动文件,不安装OpenGL文件,必需参数,注意不是-no-opengl-files
c.安装过程中一些选项
阅读声明:一直按D,然后Accept
选项install nvidia accelerated Graphics Driver:选择N(已安装了NVIDIA驱动)
选项install the OpenGL libraries:选择N(双显卡),选择Y(单显卡)
后面选项:都可以选择Y
最后一个选项:选择N(不复制Samples,因为安装目录下有samples)
Driver :Installed
Toolkit :Installed in /usr/local/cuda-9.0
Samples :Installed in /home/vincent
d.环境变量
export CUDA_HOME=/usr/local/cuda-9.0
export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64:$LD_LIBRARY_PATH
export PATH=/usr/local/cuda-9.0/bin:$PATH
e.重启图形界面
sudo service lightdm start --开启服务
f.验证cuda是否安装成功
nvcc -V
g.两个测试均为Result = PASS,说明CUDA安装成功
cd /usr/local/cuda-9.0/samples/1_Utilities/deviceQuery --测试1:编译并测试设备 deviceQuery
sudo make
./deviceQuery
cd ../bandwidthTest --测试2:编译并测试带宽 bandwidthTest
sudo make
./bandwidthTest
h.若上述测试不通过,则有有可能是缺少依赖
sudo apt-get install freeglut3-dev \
build-essential \
libx11-dev \
libxmu-dev \
libxi-dev \
libgl1-mesa-glx \
libglu1-mesa \
libglu1-mesa-dev
i.重启
重启黑屏,在grub界面进入linux的选择上按e键,找到quiet splash,在后面加nouveau.modeset=0,然后按F10启动
j.卸载
sudo /usr/local/cuda-9.2/bin/uninstall_cuda-9.2.pl --卸载CUDA
sudo /usr/bin/nvidia-uninstall --卸载NVIDIA
e.安装CUDNN7.0.5
a.安装:Debian File形式
sudo dpkg -i libcudnn7_7.0.5.15-1+cuda9.0_amd64.deb
sudo dpkg -i libcudnn7-dev_7.0.5.15-1+cuda9.0_amd64.deb
sudo dpkg -i libcudnn7-doc_7.0.5.15-1+cuda9.0_amd64.deb
b.安装:Tar File形式
tar -xzvf cudnn-9.0-linux-x64-v7.tgz
sudo cp cuda/include/cudnn.h /usr/local/cuda/include
sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64
sudo chmod a+r /usr/local/cuda/include/cudnn.h
sudo chmod a+r /usr/local/cuda/lib64/libcudnn*
c.验证Debian File形式,在/usr/src/cudnn_samples_v7有一些cudnn示例,编译mnistCUDNN sample进行验证
cp -r /usr/src/cudnn_samples_v7/ $HOME
cd $HOME/cudnn_samples_v7/mnistCUDNN
make clean && make
./mnistCUDNN
d.验证CUDNN是否安装成功
cat /usr/local/cuda/version.txt
cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2
f.其他方式
a.方式一:使用标准Ubuntu仓库进行自动安装
sudo apt-get update
sudo ubuntu-drivers devices --显示可安装NVIDIA驱动
sudo ubuntu-drivers autoinstall --安装
b.方式二:使用图形驱动程序PPA存储库安装NVIDIA beta驱动程序
sudo add-apt-repository ppa:graphics-drivers/ppa --添加ppa库到系统中
sudo apt-get update --更新
sudo ubuntu-drivers devices --显示可安装NVIDIA驱动
sudo apt-get install nvidia-xxx --xxx代表版本号
02.Anaconda
a.安装Anaconda3
sh /Ubuntu/software/JetBrains/Anaconda3/Anaconda3-2019.10-Linux-x86_64.sh
[/root/anaconda3] >>> /usr/local/anaconda3
mv /Ubuntu/software/JetBrains/Anaconda3/.condarc /root/.condarc
mkdir /root/pip
mv /Ubuntu/software/JetBrains/Anaconda3/pip/pip.ini /root/pip/pip.ini
b.环境变量
gedit /root/.bashrc
export PATH=$PATH:/usr/local/anaconda3/bin
source /root/.bashrc
c.conda测试
a.命令
conda info
conda info --envs
conda create -n tf2 tensorflow-gpu python=3.6
conda activate tf2
conda deactivate
conda remove -n tf2 --all
conda install scipy
conda remove scipy
conda list
conda --version
conda update -n base -c defaults conda
b.镜像源(/root/.condarc)
channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/menpo/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/bioconda/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
show_channel_urls: true
ssl_verify: true
c.查看配置信息
conda info
d.python测试
a.命令
pip3 --version
pip3 install --upgrade pip
python3 --version
python3 -m site
python3 -m site -help
pip freeze > requirements.txt
pip install -r requirements.txt
pip unistall -r requirements.txt
https://pypi.tuna.tsinghua.edu.cn/simple
b.镜像源(/root/pip/pip.ini)
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple/
c.修改pip默认下载位置(/usr/lib/python3.6/site.py,第87行附近)
USER_SITE = "/root/.local"
USER_BASE = "/root/.local/lib/python3.6/site-packages"
d.查看配置信息
python3 -m site
e.快捷方式
a.创建anaconda.desktop
gedit /usr/share/applications/anaconda.desktop
b.编辑anaconda.desktop
[Desktop Entry]
Version=1.0
Name=Anaconda
Type=Application
GenericName=Anaconda
Comment=Scientific Python Development Environment - Python3
Categories=Development;Science;IDE;Qt;Education;
Exec=/usr/local/anaconda3/bin/anaconda-navigator
Icon=/usr/local/anaconda3/lib/python3.7/site-packages/anaconda_navigator/static/images/anaconda-icon-256x256.png
Terminal=false
StartupNotify=true
MimeType=text/x-python;
03.Pytorch 1.2.0
a.创建Pytorch新环境,并指定python版本为3.7.9
conda create -n pytorch python=3.7.9
b.列举conda当前全部环境
conda env list
c.激活Pytorch新环境
conda activate pytorch
d.安装Pytorch(conda方式,可以判断所有安装包的版本间的兼容性,各种必备包自动安装),管理员方式启动
a.升级conda
conda update -n base -c defaults conda
b.安装Pytorch的GPU版本(注意一定去掉-c pytorch,才可以使用国内镜像加速)
conda install pytorch==1.2.0 torchvision==0.4.0 cudatoolkit=10.0
c.安装Pytorch的CPU版本
conda install pytorch torchvision cpuonly
e.测试Pytorch
import torch
print(torch.__version__)
print('gpu:', torch.cuda.is_available())
04.TensorFlow 2.0.0
a.创建TensorFlow新环境,并指定python版本为3.7.9
conda create -n tf2 tensorflow-gpu python=3.7.9
b.列举conda当前全部环境
conda env list
c.激活TensorFlow新环境
conda activate tf2
d.安装TensorFlow(conda方式,可以判断所有安装包的版本间的兼容性,各种必备包自动安装),管理员方式启动
a.升级conda
conda update -n base -c defaults conda
b.安装TensorFlow的GPU版本
conda search tensorflow-gpu
conda install tensorflow-gpu=2.0.0
c.安装TensorFlow的CPU版本
conda search tensorflow
conda install tensorflow=2.0.0
e.测试TensorFlow
import tensorflow as tf
tf.compat.v1.disable_eager_execution()
sess = tf.compat.v1.Session()
a=tf.constant(1)
b=tf.constant(2)
print(sess.run(a+b))
print(tf.test.is_gpu_available())
f.解决报错
pip uninstall tensorflow
pip install tensorflow==2.0.0
g.tensorflow-gpu==1.8.0只支持gcc4.9
a.报错:
软件包gcc还没有可供安装的候选者
b.解决
a.添加源
sudo gedit /etc/apt/sources.list
deb http://dk.archive.ubuntu.com/ubuntu/ xenial main
deb http://dk.archive.ubuntu.com/ubuntu/ xenial universe
b.更新源
sudo apt update
c.安装
sudo apt install g++-4.9
sudo apt install gcc-4.9
c.用update-alternatives来为整个系统更改gcc版本
a.设置优先级
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 40
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 55
update-alternatives --install /usr/bin/gcc gcc /usr/local/bin/gcc 54
b.列出可用的gcc替代版本
update-alternatives --list gcc
c.选择可用的Python替代版本
update-alternatives --config gcc
d.查看版本
gcc -v
05.Jupyter Notebook
a.常见错误
a.命令
jupyter notebook --generate-config
b.报错
ImportError: DLL load failed: 找不到指定的模块
ModuleNotFoundError: No module named 'pysqlite2'
c.解决
https://www.pianshen.com/article/56211259074/
去sqlite3官网下载对应64位的插件,将sqlite3.def、sqlite3.dll复制到../Anaconda/DLLs目录
b.默认路径
a.打开文件
gedit /root/.jupyter/jupyter_notebook_config.py
b.修改jupyter_notebook_config.py
## The directory to use for notebooks and kernels.
c.NotebookApp.notebook_dir = '/Ubuntu/software_ware/workspace_conda'
c.运行
jupyter notebook --allow-root
1.5 machine2
01.常见工具
a.VScode
sudo dpkg -i /Ubuntu/software/JetBrains/VScode/code_1.50.1-1602600906_amd64.deb
b.Chorme
sudo dpkg -i /Ubuntu/document/Office/Chorme/google-chrome-stable_current_amd64.deb
c.CloudMusic
sudo dpkg -i /Ubuntu/document/CloudMusic/netease-cloud-music_1.2.1_amd64_ubuntu_20190428.deb
d.QQ
sudo dpkg -i /Ubuntu/document/Tencent/QQ/linuxqq_2.0.0-b2-1084_amd64.deb
e.software
electronic-wechat
Telegram Desktop
Gnome Tweaks
09.搜狗输入法
a.安装
sogoupinyin_2.3.2.07_amd64-831.deb
b.卸载
Language Support -> fcitx修改为IBus --修改输入法
sudo dpkg -l sog* --查找
sudo dpkg -P sogoupinyin --卸载
sudo apt-get purge fcitx --彻底删除fcitx
sudo apt-get autoremove --删除多余的依赖
10.火狐浏览器
a.安装国内版
tar jxvf Firefox-latest-x86_64.tar.bz2
cd Firefox-latest-x86_64
sudo mv firefox /usr/lib/
b.快捷方式
gedit /usr/share/applications/firefox.desktop
[Desktop Entry]
Name=firefox
Name[zh_CN]=火狐浏览器
Comment=火狐浏览器
Exec=/usr/lib/firefox/firefox
Icon=/usr/lib/firefox/browser/chrome/icons/default/default128.png
Terminal=false
Type=Application
Categories=Appliction;
Encoding=UTF-8
StartupNotify=true
d.Flash
tar -zxvf flash_player_npapi_linux.x86_64.tar.gz
mv libflashplayer.so /usr/lib/mozilla/plugins
chmod 777 /usr/lib/mozilla/plugins/libflashplayer.so
11.Typora
a.下载
wget -qO - https://typora.io/linux/public-key.asc | sudo apt-key add -
b.仓库
sudo add-apt-repository 'deb https://typora.io/linux ./'
sudo apt-get update
c.安装
sudo apt-get install typora
d.图标
usr/share/application -> Typora -> 属性 -> 命令:Exec=typora %U --no-sandbox
e.解压
/Ubuntu/document/Office/Typora
tar -zxvf Typora-linux-x64.tar.gz
cd Typora-linux-x64
mv /bin/Typora-linux-x64 /usr/local
f.创建pycharm.desktop
gedit /usr/share/applications/Typora.desktop
g.编辑pycharm.desktop
[Desktop Entry]
Name=Typora
GenericName=Editorubuntu / linux
Comment=Typroa - a markdown editor
Exec="/usr/local/Typora-linux-x64/Typora" %U --no-sandbox
Icon=/usr/local/Typora-linux-x64/resources/app/asserts/icon/icon_256x256.png
Terminal=false
Categories=Markdown;ux
StartupNotify=false
Type=Application
12.宝塔面板
a.升级openssl版本为1.1.1
cd /Ubuntu/software/Linux/BaoTa/
tar -zxvf openssl-1.1.1g.tar.gz
cd openssl-1.1.1g
./config
make && make install
echo "export LD_LIBRARY_PATH=/usr/local/lib" >> ~/.bashrc --添加环境
export LD_LIBRARY_PATH=/usr/local/lib --添加环境
openssl version --查看版本
b.安装
wget -O install.sh http://download.bt.cn/install/install-ubuntu_6.0.sh && sudo bash install.sh f2dec8
c.登录
外网面板地址: http://192.168.3.102:8888/9a6bf9a9
内网面板地址: http://192.168.3.102:8888/9a6bf9a9
username: myslayers
password: XXXXXXXX
d.设置
bt
/etc/init.d/bt default
13.Pycharm
a.安装
cd /Ubuntu/software/JetBrains/Pycharm/
tar -zxvf pycharm-professional-2019.2.6.tar.gz
mv pycharm-2019.2.6 /usr/local/pycharm
b.环境变量
gedit /root/.bashrc
export PATH=$PATH:/usr/local/pycharm/bin
source /root/.bashrc
c.快捷方式
a.创建pycharm.desktop
gedit /usr/share/applications/pycharm.desktop
b.编辑pycharm.desktop
[Desktop Entry]
Version=1.0
Type=Application
Name=PyCharm
Icon=/usr/local/pycharm/bin/pycharm.svg
Exec=sh /usr/local/pycharm/bin/pycharm.sh
MimeType=application/x-py;
Name[en_US]=pycharm
14.IntelliJ IDEA
a.安装
cd /Ubuntu/software/JetBrains/IDEA
tar -zxvf ideaIU-2019.3.5.tar.gz
mv idea-IU-193.7288.26 /usr/local/idea
b.环境变量
gedit /root/.bashrc
export PATH=$PATH:/usr/local/idea/bin
source /root/.bashrc
c.快捷方式
a.创建idea.desktop
gedit /usr/share/applications/idea.desktop
b.编辑idea.desktop
[Desktop Entry]
Version=1.0
Type=Application
Name=IntelliJ IDEA
Icon=/usr/local/idea/bin/idea.svg
Exec=sh /usr/local/idea/bin/idea.sh
MimeType=application/x-py;
Name[en_US]=IntelliJ IDEA
15.WebStorm
a.安装
cd /Ubuntu/software/JetBrains/WebStorm
tar -zxvf WebStorm-2019.3.5.tar.gz
mv WebStorm-193.7288.28 /usr/local/webstorm
b.环境变量
gedit /root/.bashrc
export PATH=$PATH:/usr/local/webstorm/bin
source /root/.bashrc
c.快捷方式
a.创建webstorm.desktop
gedit /usr/share/applications/webstorm.desktop
b.编辑webstorm.desktop
[Desktop Entry]
Version=1.0
Type=Application
Name=WebStorm
Icon=/usr/local/webstorm/bin/webstorm.svg
Exec=sh /usr/local/webstorm/bin/webstorm.sh
MimeType=application/x-py;
Name[en_US]=WebStorm
16.Datagrip
a.安装
cd /Ubuntu/software/JetBrains/Datagrip
tar -zxvf datagrip-2019.3.5.tar.gz
mv DataGrip-2019.3.5 /usr/local/datagrip
b.环境变量
gedit /root/.bashrc
export PATH=$PATH:/usr/local/datagrip/bin
source /root/.bashrc
c.快捷方式
a.创建datagrip.desktop
gedit /usr/share/applications/datagrip.desktop
b.编辑datagrip.desktop
[Desktop Entry]
Version=1.0
Type=Application
Name=Datagrip
Icon=/usr/local/datagrip/bin/datagrip.svg
Exec=sh /usr/local/datagrip/bin/datagrip.sh
MimeType=application/x-py;
Name[en_US]=Datagrip
2 mysql
2.1 mock
01.windows
a.Node
a.环境变量
NODE_HOME:D:\software\JavaScript\Nodejs
path:%NODE_HOME%
%NOED_HOME%\node_modules
D:\software\Repository\Repository_Npm
b.测试
node -v
c.配置
npm config set prefix "D:\software\Repository\Repository_Npm" --设置本地仓库
npm config set cache "D:\software\Repository\Repository_Npm_Cache" --设置缓存位置
npm config ls --查看是否修改成功
b.MongoDB
a.环境变量
MongoDB_HOME:D:\software\SQL\MongoDB
path:%MongoDB_HOME%\bin
b.测试
mongod --dbpath=D:\software_ware\workspace_mongo\data --port=27017 --logpath=D:\software_ware\workspace_mongo\log\mongo.log --install --serviceName "MongoDB"
net start MongoDB --启动服务
mongo --启动
c.Redis
a.环境变量
Redis_HOME:D:\software\SQL\Redis
path:%Redis_HOME%
b.测试
redis-server.exe redis.windows.conf --服务端
redis-cli.exe -h 127.0.0.1 -p 6379 --客户端
d.Easymock
a.下载git
yum install -y git
b.克隆项目
git clone https://github.com/easy-mock/easy-mock.git
c.安装npm
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install(如果无法使用npm,刷新环境变量source /etc/profile)
d.启动
npm run dev
e.测试
http://127.0.0.1:7300
f.部署阶段
a.编译easy-mock文件
npm run build
b.启动
pm2 start app.js -i 4 -n Easymock --启动
pm2 save --保存NodeJS服务
pm2 list --查看列表
pm2 startup --创建开机启动
127.0.0.1:7300 --访问
02.linux
a.nodejs
a.下载
wget https://nodejs.org/dist/v8.9.1/node-v8.9.1-linux-x64.tar.xz
b.解压
tar -xvJf node-v8.9.1-linux-x64.tar.xz
c.重命名
mv node-v8.9.1-linux-x64 node
d.配置环境变量
vi /etc/profile
export PATH=$JAVA_HOME/bin:/apps/node/bin:/apps/mongodb/bin:$PATH
source /etc/profile
b.MongoDB
a.下载
curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.6.4.tgz
b.解压
tar -zxvf mongodb-linux-x86_64-3.6.4.tgz
c.重命名
mv mongodb-linux-x86_64-3.6.4 mongodb
d.配置环境变量
vi /etc/profile
export PATH=$JAVA_HOME/bin:/apps/node/bin:/apps/mongodb/bin:$PATH
source /etc/profile
e.配置存储数据、日志
cd mongodb/
mkdir data
touch logs
f.启动
bin/mongod --dbpath=/apps/mongodb/data --logpath=/apps/mongodb/logs --port=27017 &
c.redis
a.下载
wget http://download.redis.io/releases/redis-4.0.0.tar.gz
b.解压
tar -zxvf redis-4.0.0.tar.gz
c.重命名
mv redis-4.0.0 redis
d.编译
cd redis/
yum install gcc-c++
make MALLOC=libc
e.配置redis.conf
daemonize yes
f.启动
src/redis-server redis.conf &
src/redis-cli -p 6379
d.easymock
a.下载git
yum install -y git
b.克隆项目
git clone https://github.com/easy-mock/easy-mock.git
c.安装npm
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install(如果无法使用npm,刷新环境变量source /etc/profile)
d.启动
npm run dev
e.测试
http://192.168.2.128:7300
2.2 yearning
01.下载
http://yearning.io/
02.配置
[Mysql]
Db = "Yearning"
Host = "127.0.0.1"
Port = "3306"
Password = "xxxx"
User = "root"
[General] #数据库加解密key,只可更改一次。
SecretKey = "dbcjqheupqjsuwsm"
03.初始化数据结构
./Yearning -m
04.启动
./Yearning -s
05.测试
192.168.2.128:8000
admin / Yearning_admin
2.3 activemq
01.下载
wget https://mirrors.tuna.tsinghua.edu.cn/apache/activemq/5.15.13/apache-activemq-5.15.13-bin.tar.gz
tar -zxvf apache-activemq-5.15.13-bin.tar.gz
02.启动
cd apache-activemq-5.15.13
bin/activemq start
03.测试
192.168.2.128:8161 --测试(用户名:admin 密码:admin)
2.4 rabbitmq
01.安装erlang
a.安装依赖
yum -y install gcc glibc-devel make ncurses-devel openssl-devel xmlto perl wget gtk2-devel binutils-devel
b.下载
wget http://erlang.org/download/otp_src_22.0.tar.gz
http://file.zhaobl.com/common/otp_src_22.0.tar.gz --速度过慢,切换地址直接下载
c.解压
tar -zxvf otp_src_22.0.tar.gz
d.移走
mv otp_src_22.0 /usr/local/
e.切换目录
cd /usr/local/otp_src_22.0/
f.创建即将安装的目录
mkdir ../erlang
g.配置安装路径
./configure --prefix=/usr/local/erlang
h.安装
make install
i.查看是否安装成功
ll /usr/local/erlang/bin
j.添加环境变量
echo 'export PATH=$PATH:/usr/local/erlang/bin' >> /etc/profile
k.刷新环境变量
source /etc/profile
l.测试命令
erl
02.安装RabbitMQ
a.下载
wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.7.15/rabbitmq-server-generic-unix-3.7.15.tar.xz
b.解压
yum install -y xz --解压tar.xz格式
/bin/xz -d rabbitmq-server-generic-unix-3.7.15.tar.xz --第一次解压
tar -xvf rabbitmq-server-generic-unix-3.7.15.tar --第二次解压
c.移走
mv rabbitmq_server-3.7.15/ /usr/local/
d.改名
mv /usr/local/rabbitmq_server-3.7.15 rabbitmq
e.配置环境变量
echo 'export PATH=$PATH:/usr/local/rabbitmq/sbin' >> /etc/profile
f.刷新环境变量
source /etc/profile
g.创建配置目录
mkdir /etc/rabbitmq
h.启动命令
rabbitmq-server -detached --启动
rabbitmqctl stop --停止
rabbitmqctl status --状态
i.WEB管理
rabbitmq-plugins enable rabbitmq_management --开启WEB插件
http://127.0.0.1:15672/ --用户名guest、密码guest
j.用户管理
rabbitmqctl list_users --查看所有用户
rabbitmqctl add_user myslayers 4023615 --添加一个用户
rabbitmqctl set_permissions -p "/" zhaobl ".*" ".*" ".*" --配置权限
rabbitmqctl list_user_permissions myslayers --查看用户权限
rabbitmqctl set_user_tags zhaobl administrator --设置tag
rabbitmqctl delete_user guest --删除用户
2.5 mysql-5.5.58
01.清理Centos7自带mariadb
rpm -qa |grep -i mysql
rpm -qa |grep -i mariadb
yum remove mariadb-libs-5.5.56-2.el7.x86_64
02.rpm安装MySQL
a.安装
rpm -ivh MySQL-server-5.5.58-1.el6.x86_64.rpm --force --nodeps
rpm -ivh MySQL-client-5.5.58-1.el6.x86_64.rpm --force --nodeps
b.验证
mysqladmin --version
03.配置MySQL
a.启动MySQL服务
service mysql start
b.查看MySQL状态
service mysql status
c.设置密码
/usr/bin/mysqladmin -u root password root
d.登录MySQL
mysql -uroot -p
e.开启MySQL远程访问
mysql> grant all privileges on *.* to 'root'@'%' identified by 'root' with grant option;
mysql> flush privileges;
mysql> exit
f.Windows远程访问
mysql -uroot -proot -h192.168.2.128 -P3306
04.常见命令
a.启动命令
service mysql start
b.关闭命令
service mysql stop
c.重启命令
service mysql restart
d.查看服务状态
service mysql status
e.查看MySQL系统配置
cat /etc/my.cnf
05.MySQL服务:常见报错/var/lib/mysql/mysql.sock不存在
a.手动启动服务
/etc/init.d/mysql start
b.开机自启
chkconfig mysql on
c.关闭开机自启
chkconfig mysql off
d.检查开机自启
ntsysv
2.6 mysql-5.7.17
01.清理Centos7自带mariadb
rpm -qa |grep -i mysql
rpm -qa |grep -i mariadb
yum remove mariadb-libs-5.5.56-2.el7.x86_64
02.安装MySQL
a.下载
wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm
b.解压
rpm -ivh mysql57-community-release-el7-10.noarch.rpm
c.安装
yum install mysql-community-server
03.修改密码
a.启动MySQL服务
systemctl start mysqld.service
b.查看MySQL状态
systemctl status mysqld.service
c.从日志中获取临时密码
grep "password" /var/log/mysqld.log
d.登录MySQL
mysql -uroot -p
e.修改密码
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123456';
04.远程访问
a.开启MySQL远程访问
mysql> grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option;
mysql> flush privileges;
mysql> exit;
b.firewalld添加开放端口
firewall-cmd --zone=public --add-port=3306/tcp --permanent --mysql端口3306
firewall-cmd --zone=public --add-port=8080/tcp --permanent --Tomcat端口8080
firewall-cmd --reload --重启防火墙
systemctl stop firewalld --关闭防火墙
systemctl disable firewalld --禁止开机自启
c.远程cmd登录MySQL
mysql -uroot -proot -h192.168.2.128 -P3306 -Dtest
mysql -u用户名 -p密码 -h远程数据库IP地址 -P端口 -D数据库名(可以不用指定具体的数据库名)
05.修改编码
a.查看字符编码
mysql> status
mysql> show variables like '%char%' ;
b.修改配置文件,vi /etc/my.cnf
[client] --添加第一行
default-character-set=utf8 --添加第二行
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
character-set-server=utf8 --添加第三行
collation-server=utf8_general_ci --添加第四行
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
c.保存更改后的my.cnf文件后,重启下mysql
systemctl restart mysqld.service
06.创建新的MySQL用户,并授权
a.创建用户
create user 'testuser'@'%' identified with mysql_native_password by '123456';
b.授权
grant all privileges on *.* to 'testuser'@'%' with grant option;
c.修改密码过期规则
alter user 'testuser'@'%' identified by '123456' password expire never;
d.立即生效
flush privileges;
07.binlog功能
a.修改配置文件,vi /etc/my.cnf
[client]
default-character-set=utf8
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
character-set-server=utf8
collation-server=utf8_general_ci
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
log-bin=mysql-bin --文件目录
binlog-format=ROW --选择row模式
server_id=1 --canal和slaveId不重复
b.验证是否开启
show master logs; --查看所有日志文件
show master status; --查看正在写入的日志文件
show binlog events; --查看当前binlog文件内容
show binlog events in 'my-bin.000001'; --指定日志文件查看
flush logs; --结束正在写入日志文件
reset master; --删除所有日志,重新记录
c.二进制日志文件导出
mysqlbinlog binlog.000001 >1.sql --导出为sql格式
mysqlbinlog --start-datetime="2018-03-20 11:25:56" --stop-datetime="2018-03-20 14:20:10" mysql-bin.000001 > /data/test01.log --按时间点导出
mysqlbinlog --start-position=5786 --stop-position=6254 mysql-bin.000001 > /data/test02.log --按事件位置导出
08.如何确定MySQL服务已经启动?
a.chkconfig命令
chkconfig --list
b.查询端口
netstat -tulpn
c.查询进程
ps -ef | grep mysqld
ps -ef | grep mysqld_safe
09.MySQL服务:常见报错/var/lib/mysql/mysql.sock不存在
a.手动启动服务
/etc/init.d/mysqld start
b.开机自启
systemctl enable mysqld.service
c.关闭开机自启
systemctl disable mysqld.service
d.检查开机自启
ntsysv
10.彻底卸载MySQL
a.查看是否有安装的MySQL:
rpm -qa | grep -i mysql
yum list install mysql*
b.卸载MySQL安装包
yum remove mysql mysql-server mysql-libs compat-mysql51
yum remove mysql-community-release、
rpm -e --nodeps mysql-community-libs-5.7.22-1.el7.x86_64
rpm -e –nodeps mysql57-community-release-el7-11.noarch
c.删除残留的MySQL目录或文件
i.残留的MySQL目录
whereis mysql
ii.残留的MySQL文件
find / -name mysql
iii.删除
rm -rf xxx
d.删除MySQL配置文件
rm –rf /usr/my.cnf
rm -rf /root/.mysql_sercret
e.删除MySQL开机自启服务
chkconfig --list | grep -i mysql
chkconfig --del mysqld
11.免密码登录MySQL
a.停止MySQL服务
systemctl stop mysqld.service
b.以不检查权限的方式启动mysqld,root身份运行
mysqld --user=root --skip-grant-tables &
c.免密码登录MySQL
mysql -u root
d.设置密码
UPDATE mysql.user SET authentication_string=PASSWORD('密码') where USER='root';
ALTER USER 'root'@'localhost' IDENTIFIED BY '密码';
SET PASSWORD FOR root=PASSWORD('密码');
12.数据库存放目录
a.数据库目录
datadir=/var/lib/mysql
b.pid文件目录
pid-file=/var/lib/mysql/bigdata01.pid
c.MySQL核心目录
/var/lib/mysql 安装目录
/usr/share/mysql 配置文件
/usr/bin 命令目录(mysqladmin、mysqldump等)
/etc/init.d/mysql 启停脚本
d.MySQL配置文件
my-huge.cnf 高端服务器 1-2G内存
my-large.cnf 中等规模
my-medium.cnf 一般
my-small.cnf 较小
但是,以上配置文件mysql默认不能识别,默认只能识别 /etc/my.cnf
若采用 my-huge.cnf,通过命令:#cp /usr/share/mysql/my-huge.cnf /etc/my.cnf
e.注意
MySQL5.5:默认配置文件/etc/my.cnf
MySQL5.6:默认配置文件/etc/mysql-default.cnf
2.7 mysql-8.0.21
01.清理Centos7自带mariadb
rpm -qa |grep -i mysql
rpm -qa |grep -i mariadb
yum remove mariadb-libs-5.5.56-2.el7.x86_64
02.安装MySQL
a.下载
wget https://dev.mysql.com/downloads/file/?id=496950
b.解压
tar -xvf mysql-8.0.21-1.el7.x86_64.rpm-bundle.tar
c.依次安装common、libs、client、server
rpm -ivh mysql-community-common-8.0.21-1.el7.x86_64.rpm --force --nodeps
rpm -ivh mysql-community-libs-8.0.21-1.el7.x86_64.rpm --force --nodeps
rpm -ivh mysql-community-client-8.0.21-1.el7.x86_64.rpm --force --nodeps
rpm -ivh mysql-community-server-8.0.21-1.el7.x86_64.rpm --force --nodeps
d.验证
mysqladmin --version
03.修改密码
a.用户授权:初始化时,如果不存在,会创建它;如果存在,而且该目录里有数据,会报错并终止初始化
vi /etc/my.cnf
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
chmod -R 777 /var/lib/mysql --文件权限
rm -rf /var/lib/mysql/* --删除文件,防止报错
b.初始化数据
mysqld --initialize
c.开启服务
systemctl start mysqld.service
d.启用数据
systemctl enable mysqld
e.从日志中获取临时密码
grep "password" /var/log/mysqld.log
f.登录MySQL
mysql -uroot -p
g.修改密码
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456';
04.远程访问
a.开启MySQL远程访问
mysql> use mysql;
mysql> select host, user, authentication_string, plugin from user;
mysql> update user set host='%' where user='root';
mysql> flush privileges;
mysql> exit;
b.firewalld添加开放端口
firewall-cmd --zone=public --add-port=3306/tcp --permanent --mysql端口3306
firewall-cmd --zone=public --add-port=8080/tcp --permanent --Tomcat端口8080
firewall-cmd --reload --重启防火墙
systemctl stop firewalld --关闭防火墙
systemctl disable firewalld --禁止开机自启
c.远程cmd登录MySQL
mysql -uroot -proot -h192.168.2.128 -P3306 -Dtest
mysql -u用户名 -p密码 -h远程数据库IP地址 -P端口 -D数据库名(可以不用指定具体的数据库名)
3 fastdfs
3.1 tracker
01.gcc环境
yum install gcc-c++
02.下载Tracker依赖库 -> libevent库
yum -y install libevent
03.下载Tracker依赖库 -> libfastcommon库
a.下载
cd /usr/local
wget https://github.com/happyfish100/libfastcommon/archive/V1.0.43.tar.gz
tar -zxvf libfastcommon-1.0.43.tar.gz
b.编译
cd /usr/local/libfastcommon-1.0.43/
./make.sh
./make.sh install
04.安装Tracker
a.下载
cd /usr/local
https://github.com/happyfish100/fastdfs/archive/V6.06.tar.gz
tar -zxvf fastdfs-6.06.tar.gz
b.编译
cd /usr/local/fastdfs-6.06/
./make.sh
./make.sh install
c.将conf目录下的配置文件拷贝到/etc/fdfs目录下
cd /usr/local/fastdfs-6.06/conf/
cp ./* /etc/fdfs/
d.配置tracker.conf
mkdir /home/myslayers/fastdfs --创建元数据存储目录
vi /etc/fdfs/tracker.conf --打开tracker.conf
port = 22122 --默认端口
base_path = /home/myslayers/fastdfs --元数据存储目录必须存在
e.启动
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start --启动Tracker
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf stop --关闭Tracker
3.2 storage
01.gcc环境
yum install gcc-c++
02.下载Tracker、Storage依赖库 -> libevent库
yum -y install libevent
03.下载Tracker、Storage依赖库 -> libfastcommon库
a.下载
cd /usr/local
wget https://github.com/happyfish100/libfastcommon/archive/V1.0.43.tar.gz
tar -zxvf libfastcommon-1.0.43.tar.gz
b.编译
cd /usr/local/libfastcommon-1.0.43/
./make.sh
./make.sh install
04.安装Storage
a.下载
cd /usr/local
https://github.com/happyfish100/fastdfs/archive/V6.06.tar.gz
tar -zxvf fastdfs-6.06.tar.gz
b.编译
cd /usr/local/fastdfs-6.06/
./make.sh
./make.sh install
c.将conf目录下的配置文件拷贝到/etc/fdfs目录下
cd /usr/local/fastdfs-6.06/conf/
cp ./* /etc/fdfs/
d.配置storage.conf
mkdir /home/myslayers/fastdfs --创建元数据存储目录
vi /etc/fdfs/storage.conf --打开storage.conf
base_path = /home/myslayers/fastdfs
store_path0 = /home/myslayers/fastdfs
tracker_server = 192.168.2.128.:22122 --不能是127.0.0.1
#tracker_server = 192.168.209.122:22122 --注释掉另一个不用的地址
e.启动
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf start --启动Storage
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf stop --关闭Storage
3.3 nginx_fastdfs_module
01.fastdfs-nginx-module:重定向文件连接到源服务器取文件,避免客户端由于复制延迟导致的文件无法访问错误
a.下载
cd /usr/local
https://github.com/happyfish100/fastdfs-nginx-module/archive/V1.22.tar.gz
tar -zxvf fastdfs-nginx-module-1.22.tar.gz
b.将/usr/local/fastdfs-nginx-module-1.22/src/mod_fastdfs.conf拷贝到/etc/fdfs/目录下
cp /usr/local/fastdfs-nginx-module-1.22/src/mod_fastdfs.conf /etc/fdfs/
c.配置mod_fastdfs.conf
mkdir /home/myslayers/fastdfs --创建元数据存储目录
vi /etc/fdfs/mod_fastdfs.conf --打开mod_fastdfs.conf
base_path = /home/myslayers/fastdfs
store_path0 = /home/myslayers/fastdfs
tracker_server = 192.168.2.128:22122
url_have_group_name = true
02.Nginx编译时,--add-module
a.下载
cd /usr/local
wget https://nginx.org/download/nginx-1.14.0.tar.gz
tar -zxvf nginx-1.14.0.tar.gz
b.依赖
yum install -y gcc pcre pcre-devel
yum install -y openssl openssl-devel
c.编译
cd /usr/local/nginx-1.14.0/
./configure --add-module=/usr/local/fastdfs-nginx-module-1.22/src
make
make install
d.配置,请求转发
vi /usr/local/nginx/conf/nginx.conf
user root; --解决权限
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location ~/group[0-9]/ {
ngx_fastdfs_module;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
/usr/local/nginx/sbin/nginx -s reload --重启nginx
e.启动
/usr/local/nginx/sbin/nginx --启动Nginx
/usr/local/nginx/sbin/nginx -s stop --停止Nginx
03.开机自启
vi /etc/rc.local --打开文件
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart --追加
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart --追加
/usr/local/nginx/sbin/nginx --追加
chmod 755 /etc/rc.local --设置文件权限
3.4 upload download
01.pom.xml
<dependency>
<groupId>cn.bestwu</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27</version>
</dependency>
02.fastdfs-client.properties
fastdfs.connect_timeout_in_seconds = 5
fastdfs.network_timeout_in_seconds = 30
fastdfs.charset = UTF-8
fastdfs.http_anti_steal_token = false
fastdfs.http_secret_key = FastDFS1234567890
fastdfs.http_tracker_http_port = 80
fastdfs.tracker_servers = 192.168.2.128:22122
fastdfs.connection_pool.enabled = true
fastdfs.connection_pool.max_count_per_entry = 500
default value is 3600
fastdfs.connection_pool.max_idle_time = 3600
millisecond, default value is 1000
fastdfs.connection_pool.max_wait_time_in_ms = 1000
03.文件上传
@Test
void testUpload() throws IOException, MyException {
//创建StorageClient1
ClientGlobal.initByProperties("fastdfs-client.properties");
TrackerClient trackerClient = new TrackerClient();
TrackerServer trackerServer = trackerClient.getConnection();
StorageServer storageServer = null;
StorageClient1 client1 = new StorageClient1(trackerServer, storageServer);
//NameValuePair保存的是文件的元数据信息
NameValuePair pairs[] = null;
String filePath = client1.upload_file1("D:\\document\\Background\\2.jpg", "jpg", pairs);
System.out.println(filePath);
}
04.文件下载
@Test
void testDownload() throws IOException, MyException {
ClientGlobal.initByProperties("fastdfs-client.properties");
TrackerClient tracker = new TrackerClient();
TrackerServer trackerServer = tracker.getConnection();
StorageServer storageServer = null;
StorageClient1 client = new StorageClient1(trackerServer, storageServer);
byte[] bytes = client.download_file1("group1/M00/00/00/wKgCgF-FtTuAW7D5ABOZB_BKrKk977.jpg");
FileOutputStream fos = new FileOutputStream(new File("D:\\test.png"));
fos.write(bytes);
fos.close();
}
3.5 token check
01.开启令牌校验
vi /etc/fdfs/http.conf
http.anti_steal.check_token = true --开启校验
http.anti_steal.secret_key = FastDFS1234567890 --密钥
http.anti_steal.token_check_fail = /home/yuqing/fastdfs/conf/anti-steal.jpg
02.重启服务器
/usr/local/nginx/sbin/nginx -s stop --停止Nginx
/usr/local/nginx/sbin/nginx --启动Nginx
03.获取令牌
@Test
public void getToken() throws Exception {
int ts = (int) Instant.now().getEpochSecond();
//第一个参数:访问的文件,注意不包含 group
//第二个参数:时间戳
//第三个参数:密钥
String token = ProtoCommon.getToken("M00/00/00/wKgCgF-FtTuAW7D5ABOZB_BKrKk977.jpg", ts, "FastDFS1234567890");
StringBuilder sb = new StringBuilder();
sb.append("?token=").append(token);
sb.append("&ts=").append(ts);
System.out.println(sb.toString());
}
04.携带令牌访问
http://192.168.2.128/group1/M00/00/00/wKgCgF-FtTuAW7D5ABOZB_BKrKk977.jpg?token=5f4b1976727a3ba439fc2d8874945581&ts=1602603800
4 service
4.1 aria2
01.安装(一是命令行下载模式,二是RPC模式+网页管理)
将https://github.com/aria2/aria2/releases/tag/release-1.35.0替代文件夹中的“aria2c.exe” -> 启动aria2.exe
02.配置(aria2.conf)
a.修改默认下载目录
#文件的保存路径(可使用绝对路径或相对路径),默认: 当前启动位置
dir=D:\Download
b.修改服务器默认连接数
#同一服务器连接数,添加时可指定,默认:1,默认编译windows可设置的最大连接数为16
max-connection-per-server=16
c.开启BT下列设置
enable-dht=true
bt-enable-lpd=true
enable-peer-exchange=true
d.添加trackers,逗号隔开,获取https://github.com/XIU2/TrackersListCollection/blob/master/best_aria2.txt
bt-tracker=udp://tracker.coppersurfer.tk:6969/announce,
03.实现开机无cmd窗口启动
a.方式一:编辑HideRunAria2.vbs文件(普遍写法)
CreateObject("WScript.Shell").Run "D:\software\Linux\Window\Aria2\aria2c.exe --conf-path=aria2.conf",0
b.方式二:编辑HideRunAria2.vbs文件(防止多开)
Set wmi=GetObject("winmgmts:\\.\root\cimv2")
Set list=wmi.ExecQuery("select * from win32_process where name='aria2c.exe'")
If list.count=0 Then
Set objShell = CreateObject("Wscript.Shell")
objShell.Run "D:\software\Linux\Window\Aria2\aria2c.exe --conf-path=aria2.conf",0
End If
c.开机启动
HideRunAria2.vbs.快捷方式 -> C:\Users\13514\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
d: && cd D:\software\Linux\Window\Aria2 && nssm install Aria2 && net start Aria2
04.测试
a.命令行管理
aria2c http://example.org/mylinux.iso --下载网络文件
aria2c http://a/f.iso ftp://b/f.iso --下载多个文件
aria2c -x2 http://a/f.iso --下载时每个host使用两个连接
aria2c http://example.org/mylinux.torrent --使用BitTorrent协议下载
aria2c 'magnet:?xt=urn:btih:248D0A1CD08284299DE78D5C1ED359BB46717D8C' --使用磁力链接下载
aria2c http://example.org/mylinux.metalink --Metalink
aria2c -i uris.txt --下载text文本文件中的链接
b.网页管理(Motrix WebExtension、百度网盘助手、BaiduExporter)
Aria2 for Chrome
YAAW for Chrome
http://aria2c.com/
http://localhost:6800/jsonrpc --AriaNg设置 -> RPC地址
05.Motrix
a.安装
https://motrix.app/
b.插件
集装箱 -> 右键 -> 使用Motrix下载
c.进阶设置
Tracker 服务器 -> 自动更新
RPC 授权密钥(生成密钥、2ZMAiC7r3gqr、保存)-> Motrix Chrome Extension(2ZMAiC7r3gqr、Set Key)
4.2 seafile
01.直接编译(Seafile会自动配置 MariaDB,Memcached,WebDAV,Ngnix 和开机自动启动脚本)
a.安装
yum install wget -y
wget https://raw.githubusercontent.com/haiwen/seafile-server-installer-cn/master/seafile-server-centos-7-amd64-http
bash seafile-server-centos-7-amd64-http 6.3.3
b.运行(配置SERVICE_URL、FILE_SERVER_ROOT)
Server Address: http:/127.0.0.1
Seafile Admin:[email protected]
Admin Password:oDoac0xe
02.Docker
a.镜像
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce -y
b.配置(右边的端口号一定不要改,左边端口号的含义是Seafile占用的端口,例如修改为1234:80)
docker run -d --name seafile \
-e SEAFILE_SERVER_HOSTNAME=seafile.example.com \
-e [email protected] \
-e SEAFILE_ADMIN_PASSWORD=password \
-v /opt/seafile-data:/shared \
-p 80:80 \
seafileltd/seafile:latest
c.运行(配置SERVICE_URL、FILE_SERVER_ROOT)
systemctl enable docker
docker update --restart=always seafile
01.Telegram
a.创建机器人
@BotFather -> /start -> /newbot -> RssBot、Bilihotbot
b.创建命令
rss - 显示当前订阅的 RSS 列表,加 raw 参数显示链接
sub - 订阅一个 RSS: /sub http://example.com/feed.xml
unsub - 退订一个 RSS: /unsub http://example.com/feed.xml
unsubthis - 使用此命令回复想要退订的 RSS 消息即可退订, 不支持 Channel
export - 导出为 OPML
c.机器人对应的Token
1513156079:AAG6RWpm_YbgaW1Nxq44_ukTwTzilPUf9gc
1759838027:AAG2GdOOhDMeGsWOZbFnVMz7pycWNs2oo_Y TELEGRAMBOTTOKEN
d.Server酱·Turbo版
SCT158050TEyUSPpKA2iMlpBtQGkVWKygC SendKey
02.安装RSSBot
a.安装,DATAFILE为数据库保存路径,TELEGRAM-BOT-TOKEN对应创建的机器人对应的Token
apt install unzip
wget https://github.com/iovxw/rssbot/releases/download/v1.4.3/rssbot-v1.4.3-linux.zip
unzip rssbot-v1.4.3-linux.zip
./rssbot DATAFILE TELEGRAM-BOT-TOKEN
b.配置
vi /etc/systemd/system/rssbot.service
[Unit]
Description=A RSS Bot
After=network.target
Wants=network.target
[Service]
Type=simple
WorkingDirectory=/home/rss
ExecStart=/home/rss/rssbot DATAFILE TELEGRAM-BOT-TOKEN
Restart=on-failure
RestartSec=10
User=rss
[Install]
WantedBy=multi-user.target
c.执行
systemctl daemon-reload
systemctl enable rssbot
systemctl start rssbot
03.Bot命令示例
个人订阅:/sub
频道订阅:/sub @channelname
查看个人订阅列表:/rss
查看个人订阅列表并显示订阅链接:/rss raw
如果需要把机器人加入频道,则机器人的身份需要为管理员
4.4 coolify
01.介绍
Coolify 开源自托管的 Heroku/Netlify/Vercel 替代方案
02.特点
自主托管:Coolify 允许部署资源到几乎任何服务器上,包括个人的服务器、树莓派等。只需要 SSH 连接,就能管理自己硬件资源。
多语言多框架支持:Coolify 与各种编程语言、框架兼容,可以部署和管理各种类型的应用程序。不论静态网站、API 后端服务还是数据库,Coolify 都能提供强大的支持。
SSL 证书和安全性:Coolify 会自动为自定义域名设置和更新 Let’s Encrypt 证书,确保应用程序的安全和加密连接。用户不需要担心证书繁琐设置和更新,Coolify 会自动处理这些问题。
监控、通知:Coolify 会监控部署、服务器磁盘使用情况等,并在发生任何问题时通过电子邮件等渠道通知。
03.安装脚本
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
注意:Coolify 支持通过源码及 Docker 等方式部署,上面是来自官方的一键部署脚本,可使用与生产环境。
04.运行要求
a.支持操作系统
基于 Debian 的 Linux 发行版(Debian/Ubuntu 等)
基于 Redhat 的 Linux 发行版(CentOS/Fedora/Red Hat/AlmaLinux/Rocky 等)
基于 SUSE 的 Linux 发行版(SLES/SUSE/openSUSE 等)
b.支持系统架构
AMD64 位架构
ARM64 位架构
c.所需的最低服务器配置
2cpu
2gb内存
30+GB的存储空间
4.5 hugging
01.介绍
a.You can create a repository from the CLI (skip if you created a repo from the website)
$ pip install huggingface_hub
# You already have it if you installed transformers or datasets
$ huggingface-cli login
# Log in using a token from huggingface.co/settings/tokens
# Create a model or dataset repo from the CLI if needed
$ huggingface-cli repo create repo_name --type {model, dataset, space}
b.Clone your model, dataset or Space locally
# Make sure you have git-lfs installed
# (https://git-lfs.github.com)
$ git lfs install
$ git clone https://huggingface.co/username/repo_name
c.Then add, commit and push any file you want, including larges files
# save files via `.save_pretrained()` or move them here
$ git add .
$ git commit -m "commit from $USER"
$ git push
d.In most cases, if you're using one of the compatible libraries, your repo will then be accessible from code, through its identifier: username/repo_name
For example for a transformers model, anyone can load it with:
tokenizer = AutoTokenizer.from_pretrained("username/repo_name")
model = AutoModel.from_pretrained("username/repo_name")
4.6 oneinstack
01.安装
a.使用镜像下载oneinstack文件
yum -y install wget screen curl python #for CentOS/Redhat
# apt-get -y install wget screen curl python #for Debian/Ubuntu
wget http://aliyun-oss.linuxeye.com/oneinstack-full.tar.gz #阿里云经典网络下载
wget http://mirrors.linuxeye.com/oneinstack-full.tar.gz #包含源码,国内外均可下载
wget http://mirrors.linuxeye.com/oneinstack.tar.gz #不包含源码,建议仅国外主机下载
b.解压并安装
tar xzf oneinstack-full.tar.gz
cd oneinstack #如果需要修改目录(安装、数据存储、Nginx日志),请修改options.conf文件
screen -S oneinstack #如果网路出现中断,可以执行命令`screen -R oneinstack`重新连接安装窗口
./install.sh #注:请勿sh install.sh或者bash install.sh这样执行
c.一键配置
a.更改ssh端口号,建议默认22,过程出现Default可直接回车
22
b.是否开启iptables,如果安全组开启,可关闭
N
c.是否安装Nginx、Apache、Tomcat(推荐:PHP使用LNMP模式,JAVA使用LNMT模式)
LNMP:安装Nginx、不安装Apache、Tomcat
(系统运行php-fpm进程)
LAMP:安装Apache、不安装Nginx、Tomcat
(无php-fpm进程,php以模块形式加载在Apache中)
LNMPA:安装Nginx、Apache,不安装Tomcat
(静态资源由Nginx处理,PHP由Apache处理,无php-fpm进程,php以模块形式加载在Apache中)
LNMT:安装Nginx、Tomcat,不安装Apache
(静态资源由Nginx处理,JAVA由Tomcat处理,可安装PHP,支持多语言环境,同时可运行PHP、JAVA)
d.是否安装数据库
Y
02.命令
./addons.sh --添加附加组件
./vhost.sh --添加虚拟主机
./vhost.sh del --删除虚拟主机
./pureftpd_vhost.sh --管理FTP账号
./backup_setup.sh --备份
./upgrade.sh --更新
./uninstall.sh --卸载
03.管理服务
a.Nginx/Tengine/OpenResty
service nginx {start|stop|status|restart|reload|configtest}
b.MySQL/MariaDB/Percona
service mysqld {start|stop|restart|reload|status}
c.PostgreSQL
service postgresql {start|stop|restart|status}
d.MongoDB
service mongod {start|stop|status|restart|reload}
e.PHP
service php-fpm {start|stop|restart|reload|status}
f.HHVM
service supervisord {start|stop|status|restart|reload}
g.Apache
service httpd {start|restart|stop}
h.Tomcat
service tomcat {start|stop|status|restart}
i.Pure-Ftpd:
service pureftpd {start|stop|restart|status}
j.Redis
service redis-server {start|stop|status|restart|reload}
k.Memcached
service memcached {start|stop|status|restart|reload}
04.ftp权限问题
a.报错
创建ftp账户后,远程连接出现550错误,提示没有权限。
b.解决:网站根目录权限遵循:文件644、文件夹755、权限用户和用户组www
chown -R www.www /data/wwwroot/
find /data/wwwroot/ -type d -exec chmod 755 {} \;
find /data/wwwroot/ -type f -exec chmod 644 {} \;
05.LNMT模式部署JAVA应用
a.采用lnmt模式,即安装nginx、mysql、tomcat
默认Nginx处理静态资源,Tomcat处理动态资源
b.域名
默认(未绑定域名)对应网站根目录/data/wwwroot/default(不是webapps),
部署代码时建议将war包解压(比如example.war,解压命令:jar xf example.war ,注意权限必须为www),将其中代码放到对应网站根目录:
如果上传代码之后目录结构为:/data/wwwroot/default/WEB-INF,访问地址为:http://IP
如果上传代码之后目录结构为:/data/wwwroot/default/example/WEB-INF,访问网站地址为:http://IP/example
c.war包
war包也可以不解压即上传到对应网站根目录,但必须注意访问路径和静态资源目录问题。
如果访问网站时,静态资源加载不了,可能是原因是做了动静分离静态资源直接有nginx处理,
请确认nginx是否能找到相关静态资源(nginx网站根目录:/data/wwwroot/default)
d.虚拟主机
如果vhost.sh绑定了域名,如www.example.com,工具会自动生成对应根目录:/data/wwwroot/www.example.com ,请将代码放入此目录
06.切换php版本
./uninstall.sh php #卸载
./install.sh #php选择y,其余选择n,即可
07.配置MySQL远程连接
a.开启iptables中3306端口
a.Centos7
iptables -I INPUT 4 -p tcp -m state --state NEW -m tcp --dport 3306 -j ACCEPT
service iptables save #保存iptables规则
b.Ubuntu/Debian
iptables -I INPUT 4 -p tcp -m state --state NEW -m tcp --dport 3306 -j ACCEPT
iptables-save > /etc/iptables.up.rules #保存iptables规则
b.授权数据库
远程连接新建一个帐号(帐号名不能为root)
如:添加一个用户名为db_user,密码为db_pass,授权为%,对db_name数据库所有权限,命令如下:
# mysql -uroot -p
MySQL [(none)]> grant all privileges on db_name.* to db_user@’%’ identified by ‘db_pass’;
MySQL [(none)]> flush privileges;
MySQL [(none)]> exit;
4.7 vaultwarden
01.VaultWarden
a.安装docker
yum update -y && yum install docker -y && systemctl start docker && systemctl enable docker && service docker status
b.安装docker-compose
curl -L "https://github.com/docker/compose/releases/download/1.26.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose
c.配置docker-compose.yml
cd / && mkdir www && cd www && mkdir vaultwarden && cd /www/vaultwarden && vi docker-compose.yml
version: "3"
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: always
ports:
- "127.0.0.1:6666:80" #将宿主机6666端口映射到docker的80端口
- "127.0.0.1:3012:3012"
volumes:
- ./vw-data:/data
environment:
DOMAIN: 'https://myslayers.cn/'
WEBSOCKET_ENABLED: "true" #是否开启WebSocket
SIGNUPS_ALLOWED: "true" #是否开启注册,自用的话自己搭建好注册后改成false
WEB_VAULT_ENABLED: "true" #是否开启Web客户端
#ADMIN_TOKEN: "xxxxxx" #后台登陆密码,建议openssl rand -base64 48 生成ADMIN_TOKEN确保安全
d.启动docker-compose
cd /www/vaultwarden
docker-compose up -d --启动服务
docker-compose down --关闭服务
docker-compose restart --重启服务
docker-compose down && docker pull vaultwarden/server:latest --更新镜像,需要先停止服务
docker ps -a --查看运行
docker rm -f 80576e5ea74a --移除容器
docker images --查看镜像
docker rmi -f d55229deb03e --移除镜像
docker start 80576e5ea74a --启动容器
docker stop 80576e5ea74a --停止容器
docker restart 80576e5ea74a --重启容器
docker rm 80576e5ea74a --移除容器
docker logs 80576e5ea74a --查看日志
docker exec -it vaultwarden /bin/bash --内部环境
e.数据备份
yum install sqlite-devel -y && sqlite3 -version && sqlite3 /www/vaultwarden/vm-data/d.sqlite3 ".backup '/root/db-$(date '+%Y%m%d-%H%M').sqlite3'"
02.Let’s Encrypt
a.安装
curl https://get.acme.sh | sh && chmod -R 777 /root/.acme.sh/
b.自动续签,开启自动同步更新
cd /root/.acme.sh && alias acme.sh=~/.acme.sh/acme.sh && echo 'alias acme.sh=~/.acme.sh/acme.sh' >>/etc/profile
00 00 * * * root /root/.acme.sh/acme.sh --cron --home /root/.acme.sh &>/var/log/acme.sh.logs
/root/.acme.sh/acme.sh --upgrade --auto-upgrade
c.申请证书
export xxxxx="xxxxxxxxxxxxxxxxxxxxxxxxxx"
export xxxxx="xxxxxxxxxxxxxxxxxxxxxxxxxxx"
acme.sh --issue --dns dns_ali -d myslayers.cn -d www.myslayers.cn
d.申请证书(Nginx创建ssl文件夹,生成dhparam.pem文件,acme将证书克隆到ssl文件夹)
yum update -y && yum install -y epel-release && yum install -y nginx && cat /etc/nginx/nginx.conf && mkdir /etc/nginx/ssl && openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048 && acme.sh --installcert -d myslayers.cn --key-file /etc/nginx/ssl/myslayers.cn.key --fullchain-file /etc/nginx/ssl/fullchain.cer --reloadcmd "service nginx force-reload"
03.Nginx
a.配置(cat /etc/nginx/nginx.conf)
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name myslayers.cn www.myslayers.cn;
root /usr/share/nginx/html;
ssl_certificate "/etc/nginx/ssl/fullchain.cer";
ssl_certificate_key "/etc/nginx/ssl/myslayers.cn.key";
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://127.0.0.1:6666;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
location /notifications/hub {
proxy_pass http://127.0.0.1:3012;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /notifications/hub/negotiate {
proxy_pass http://127.0.0.1:6666;
}
location /admin {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:6666;
}
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
b.启动
nginx --打开服务
nginx -v --查看版本
nginx -t --检查配置
nginx -p prefix --默认前缀(/usr/share/nginx/)
nginx -c filename --默认配置(/etc/nginx/nginx.conf)
nginx -s reopen --主进程发送信号(重启服务)
nginx -s reload --主进程发送信号(重载配置)
nginx -s stop --主进程发送信号(强制停止)
nginx -s quit --主进程发送信号(优雅退出)
ss -ntlp| grep -i nginx --查看软件是否正常运行
systemctl enable | start | stop | restart nginx --systemctl命令
04.启动
a.访问
https://myslayers.cn/
b.二次验证
https://myslayers.cn/admin -> SMTP Email Settings、Email 2FA Settings
Enabled Default: true(勾选)
Host smtp.163.com(填写)
Enable Secure SMTP Default: true(勾选)
Force TLS Default: false(勾选)
Port 465(填写)
From Address [email protected] (填写)
From Name Vaultwarden(填写)
Username [email protected] (填写)
Password RBMWIHQZJTMYOLNG
SMTP Auth mechanism 无
SMTP connection timeout 15
Server name sent during HELO 无
Enable SMTP debugging (Know the risks!) 无
Accept Invalid Certs (Know the risks!) 无
Accept Invalid Hostnames (Know the risks!) 无
Test SMTP [email protected] -> Send test mail
4.8 lookingglass
01.利用Oneinstack安装nginx、php7.2
wget -c http://mirrors.linuxeye.com/oneinstack-full.tar.gz && tar xzf oneinstack-full.tar.gz && ./oneinstack/install.sh --nginx_option 1 --php_option 7
02.由于LookingGlass需要PHP中某些禁用的函数,因此需要配置PHP
vi /usr/local/php/etc/php.ini
:set nu -> 311行 -> disable_functions代表禁用函数 -> 删除proc开头的函数,以及函数后面的逗号
service php-fpm restart
03.安装LookingGlass
a.下载
wget https://github.com/ILLKX/LookingGlass/archive/master.zip && unzip master.zip
b.运行脚本
rm -f /data/wwwroot/default/index.html
mv LookingGlass-master/* /data/wwwroot/default/
bash /data/wwwroot/default/LookingGlass/configure.sh
c.填写规范
如果项目放于Nginx目录下时,http://xxx.com(最后不要加"/")
如果项目放于Nginx目录下的某个文件夹时,http://xxx.com/xxx(最后不要加"/")
Enter your website name (Header/Logo) []: SpeedTest
Enter the public URL to this LG (including http://) []: http://halavah.buzz
Enter the servers location []: Tokyo, Japan
Enter the test IPv4 address []: 202.182.112.34
Enter the test IPv6 address (Re-enter everytime this script is run) []:
Enter the size of test files in MB (Example: 25 50MB 100) []: 100MB
Do you wish to enable rate limiting of network commands? (y/n): n
Enter the username of your webserver (E.g. www-data): root
Enter the user group of your webserver (E.g. www-data): root
04.测试
http://halavah.buzz
5 website
5.1 read
01.常见信息1
a.分类1
a.常用1
Vultr
RackNerd
甲骨文,永久
微软云,1年
亚马逊,3个月一换
谷歌云,3个月一换
谷歌One全家桶:Gmail、Drive、Docs、Sheets、Slides、Calendar、Meet、Chat、Sites、Forms
b.常用2
解绑 =/= 停用 =/= 释放 =/= 冻结
阿里(海外):云服务器(标准ECS)、轻量应用服务器(简化ECS)、COS对象存储
腾讯(海外):云服务器(标准CVM)、轻量应用服务器(简化ECS)、OSS对象存储
c.阿里云备案
在阿里云备案必须拥有阿里云中国内地节点服务器
事实上,不只是云服务器,阿里云很多云产品均支持备案
网站域名想要在阿里云备案,需要有一台中国大陆地域的云服务器,并且购买时长大于等于3个月
b.分类2
a.Lenny's Newsletter
一年175刀,价值1286.25人民币,送一堆软件年订阅,随便一个单独订阅都回本
https://www.lennysnewsletter.com/p/an-unbelievable-offer-now-get-one
-------------------------------------------------------------------------------------------------
Cursor:一年的 Pro 计划(价值 240 美元)
Bolt:一年的 Pro 计划(价值 240 美元)
Lovable:一年的入门计划(价值 240 美元)
Replit:一年核心计划(价值 240 美元)
v0:一年的高级计划(价值 240 美元)
Granola:为您和您的团队提供一年的商业计划 - 最多 100 个席位(价值 10,000 美元以上)
Notion:为您和您的团队提供一年的 Plus 计划(外加无限 AI)—最多 10 个席位(价值 2,000 美元以上)
Linear:一年的商业计划——两个席位(价值 336 美元)
Superhuman:一年的入门计划(价值 300 美元)
Perplexity:一年的 Pro 计划(价值 240 美元)
b.ClawCloud
ClawCloud 推出了永久免费容器,最高可获取4核心8G内存,推荐区域日本、新加坡。
不需要信用卡,需要 Github 注册日期大于 180 天,每个月都送 5 美金额度。
c.相关区域
US East (N. Virginia) - 美国东部(北弗吉尼亚)
US East (Ohio) - 美国东部(俄亥俄)
US West (Oregon) - 美国西部(俄勒冈)
c.分类3
a.Render
特点(现代化平台,易于使用)、限制(免费计划有一定的使用限制)、部署方式(Git 或 Docker)
核心额度,实例时长,每月750小时,未用完不结转,耗尽则暂停服务至次月重置。
资源配置,单服务限512MB内存,无持久化磁盘,支持自动重启。
流量存储,每月100GB出站流量,共享400小时免费构建时间。
-------------------------------------------------------------------------------------------------
服务数量,单实例部署,支持Web服务、静态站点、API、Cron Job等多类型服务。
运行规则,15分钟无请求自动休眠,冷启动约20-30秒;免费PostgreSQL创建后30天过期,过期后14天grace期未升级则删除数据。
附加功能,支持Docker、Git自动部署、自定义域名+免费HTTPS,含DDOS保护。
数据库权益,免费PostgreSQL(1GB存储)、Redis(25MB内存,50连接,无持久化)。
b.Album1
dokploy:容器管理+trafiek反向代理
Heroku:限制(免费账户有550小时/月的限制,30分钟不活动会休眠)、部署方式(Git 推送或 Docker)
ClawCloud 推出了永久免费容器,最高可获取4核心8G内存,推荐区域日本、新加坡。
-------------------------------------------------------------------------------------------------
Google App Engine:限制(每天有一定的免费配额)、部署方式(gcloud CLI 或 Maven 插件)
Oracle Cloud Free Tier:特点(提供两个免费的 VM,永久免费)、部署方式(SSH 或 Oracle Cloud CLI)
IBM Cloud Foundry:特点(支持多种编程语言和框架)、限制(免费账户有一定的资源限制)
c.Album2
OpenShift Online:特点(基于Kubernetes,适合容器化应用)、限制(免费版功能受限)、部署方式(Git 或 Docker 镜像)
AWS Free Tier:特点(提供多种服务的免费额度)、限制(有些服务只在第一年免费)、部署方式(多样,包括 Elastic Beanstalk, EC2 等)
Railway:特点(快速部署,开发者友好)、限制(免费计划有每月使用时间限制)、部署方式(Git 或 Docker)
02.常用信息2
a.分类1
a.db4free,替代sqlite
db4free.net - 免费的 MySQL 数据库
只提供MySQL服务
提供服务:基本最新版Mysql8.0服务
服务器地址:国外
优点:
1、无需注册,直接用邮箱申请
2、用户名称和密码可以自定义
缺点:
1、一个邮箱账号,只能绑定一个账号
2、不定期重置仓库大小超过200MB的仓库数据
b.sqlpub
SQLPub - 免费的MySQL数据库
只提供MySQL服务
提供服务:最新版Mysql8.0服务;最大36000次/小时的请求、同时30个连接和500M存储空间
服务器地址:国内
优点:
1、无需注册,直接用邮箱申请
2、仓库空间比较大
缺点:
1、一个邮箱账号,只能绑定一个账号
2、密码自动生成,比较复杂
c.ElephantSQL
ElephantSQL - PostgreSQL as a Service
提供PostgreSQL服务
服务器地址:由国内地址
提供服务:20MB免费
d.MongoDB Cloud
提供MongoDB数据库服务
服务器地址:有国内
提供服务:永久512MB免费
优点:
1、空间大且永久免费
2、有国内服务器地址
e.Redis Cloud
提供Redis服务
b.分类2
a.SVNCloud
专业SVN服务,代码托管,数据库托管,MYSQL服务(wsfdb.cn)
只提供MySQL服务
提供服务(免费版本):Mysql7.x;永久5MB(免费),可以升级vip扩展(存储容量);支持:在线备份、备份下载、导入备份、修改密码、实时开通、自动清理日志
服务器地址:国内
优点:
1、一个账号,可以无限创建仓库
2、用户名和密码可以自定义(用户名和仓库名一样)
缺点:
需要注册账号使用
注:这个公司同时提供svn云服务,免费的有80MB,同样不限制创建数量
b.MemFireDB
只提供PostgreSQL服务
服务器地址:国内
缺点:一个账号只能注册一个
c.Heroku
Cloud Application Platform | Heroku
提供PostgreSQL服务
服务器地址:国外
提供服务:1w行数据(小的可怜)
优点:可创建多个数据库
缺点:空间小、连接速度慢
d.RabbitMQ
CloudAMQP - Queue starts here.
提供RabbitMQ服务
-----------------------------------------------------------------------------------------------------
Little Lemur - For Development
Max 100 queues
Max 10 000 queued messages
Max idle queue time 28 days
e.Kafka
CloudKarafka
Apache Kafka Message streaming as a Service
提供Kafka服务
-----------------------------------------------------------------------------------------------------
付费
5.2 aliyun
01.阿里云
a.配置
名称:iZ2ze1rjl28spy91pf927wZ
地域:华北2(北京)
核心:2核2GB
带宽:3Mbps
系统:CentOS 7.9 64位
公网IP:101.42.36.187
公网密码:xxxxxxxxx
创建时间:2026年7月31日 23:59:59
到期时间:2024年7月31日 18:09:00
云服务器ECS:应用管理 -> 1panel运维面板社区版
提示:修改密码可执行命令:1pctl update password
-----------------------------------------------------------------------------------------------------
国内的带宽大概20块钱一个月1M,
不过这个200M也不是稳定200M,是共享池,但是最低有10M
b.重置密码
https://ecs.console.aliyun.com/ -> 简捷版本 -> 重置前,建议停止实例,采用【离线重置密码】
c.创建密钥对
https://ecs.console.aliyun.com/ -> 标准版本 -> 实例 -> 更多操作 -> 绑定密钥对 -> 生成halavah.pem(SSH密钥认证)
d.更改系统
https://ecs.console.aliyun.com/ -> 标准版本 -> 实例 -> 更多操作 -> 云盘与镜像:更换操作系统
e.安装1Panel
1-65535代表全部端口
方式1(成功):计算巢
方式2(失败):1Panel命令,报错:此Linux发行版(centos7)已终止使用,此脚本不再支持。
02.腾讯云
b.配置
地域:北京
核心:2核4GB
磁盘:60GB SSD
带宽:5Mbps,500GB/月
系统:1Panel Linux 面板 2.0.15
操作系统:Ubuntu Server 22.04 LTS 64bit
b.说明
公网IP:101.42.36.187
公网用户:ubuntu
公网密码:}S9Nxg,KAp2a+u
到期时间:20261230 22:02:53
服务密钥:ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEFJBdm8fLCdBVAR/JVrU4PNkyC8bLfBzQIyBlsHsmtL lqzx-server-deploy
c.说明
域名:myslayers.top
SSH连接:ssh [email protected]
SSH链接:su / su root
d.备案
晋ICP备2025068649号
主域名(只需要备案一次)、二级域名(不需要备案)
备案期间,需要关闭DNS解析,服务器裸IP的上线服务
03.部署情况
a.管理面板
a.1Panel
地址:http://101.42.36.187:8090/tencentcloud
用户:1nvyurf67r
密码:qwhl6dxf3y,旧
密码:qwhl6dxf4y,新
b.BaoTa
地址:http://101.42.36.187:8888/4023615
用户:xxxxxx
密码:xxxxxx
b.数据库
a.MySQL
地址:http://101.42.36.187:3306/
用户:halavah
密码:xhXDsEhjWyHn4Adh
b.PostgreSQL
地址:http://101.42.36.187:5432/
用户:halavah
密码:BB6K2pzsRYkBG7fE
c.Redis
地址:http://101.42.36.187:6379/
密码:5WB6GdZnYy5GT3yb
d.Mongo
端口:27017
用户名:mongo_EXnk8b
用户密码:mongo_AApFMA
c.常用服务
a.DDNS-GO
地址:http://101.42.36.187:9876/
用户:troyekk
密码:qwER159263
支持:阿里云、腾讯云、DnsPod、Cloudflare、华为云、Callback
支持:百度云、Porkbun、GoDaddy、Namecheap、NameSilo、Vercel
支持:Dynadot、火山引擎
b.Frps
服务端口:7000
Dashboard端口:7500
用户名:admin
密码:admin_MrDsz5
密钥:token123456
映射:82、3100、9994
示例:http://101.42.36.187:82/
d.常用服务
a.One API
地址:http://101.42.36.187:3000/
用户:troyekk
密码:qwER159263
b.new-api
地址:http://101.42.36.187:3000/
用户:root
密码:qwER159263
用户:troyekk
密码:qwER159263
-------------------------------------------------------------------------------------------------
# 使用 SQLite 的部署命令:
docker run --name new-api -d --restart always -p 3000:3000 -e TZ=Asia/Shanghai -v /home/ubuntu/data/new-api:/data calciumion/new-api:latest
# 使用 MySQL 的部署命令,在上面的基础上添加 `-e SQL_DSN="root:123456@tcp(localhost:3306)/oneapi"`,请自行修改数据库连接参数。
# 例如:
docker run --name new-api -d --restart always -p 3000:3000 -e SQL_DSN="root:123456@tcp(localhost:3306)/oneapi" -e TZ=Asia/Shanghai -v /home/ubuntu/data/new-api:/data calciumion/new-api:latest
-------------------------------------------------------------------------------------------------
最新版Docker镜像:calciumion/new-api:latest
默认账号root 密码123456
更新指令:docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower -cR
c.bitwarden
地址:http://101.42.36.187:40031/
用户:troyekk
密码:qwER159263
5.3 vercel
01.常见信息1
a.valut
Root Directory 空,代表根目录
-----------------------------------------------------------------------------------------------------
Framework Preset Other
-----------------------------------------------------------------------------------------------------
Build Command npm run vercel-build
Output Directory public
Install Command npm install
Environment Command 空
b.valut2
Root Directory 空,代表根目录
-----------------------------------------------------------------------------------------------------
Framework Preset Other
-----------------------------------------------------------------------------------------------------
Build Command npm run vercel-build
Output Directory public
Install Command npm install
Environment Command 空
c.valut3
Root Directory 空,代表根目录
-----------------------------------------------------------------------------------------------------
Framework Preset Other
-----------------------------------------------------------------------------------------------------
Build Command npm run vercel-build
Output Directory public
Install Command npm install
Environment Command 空
d.quartz-end
Root Directory 空,代表根目录
-----------------------------------------------------------------------------------------------------
Framework Preset Next.js
-----------------------------------------------------------------------------------------------------
Build Command 空,默认,'npm run build' or 'next build'
Output Directory 空,默认,Next.js default
Install Command 空,默认,'yarn install', 'pnpm install', 'npm install', or bun install'
Development Command 空,默认,next
02.常见信息2
a.picgo
Root Directory vuepress
-----------------------------------------------------------------------------------------------------
Framework Preset VuePress
-----------------------------------------------------------------------------------------------------
Build Command vuepress build vuepress
Output Directory ../docs
Install Command yarn add global vuepress
Development Command vuepress dev vuepress --port $PORT
b.pintree
Root Directory 空,代表根目录
-----------------------------------------------------------------------------------------------------
Framework Preset Next.js
-----------------------------------------------------------------------------------------------------
Build Command prisma generate && prisma db push && next build
Output Directory 空,默认,Next.js default
Install Command npm install
Development Command 空,默认,next
c.gitstars
Root Directory 空,代表根目录
-----------------------------------------------------------------------------------------------------
Framework Preset Vite
-----------------------------------------------------------------------------------------------------
Build Command 空,默认,'npm run build' or 'vite build'
Output Directory 空,默认,dist
Install Command 空,默认,'yarn install', 'pnpm install', 'npm install', or bun install'
Development Command 空,默认,vite
5.4 render
01.free
a.db4free.net
服务商: db4free.net
主机: db4free.net
位置: 德国(欧洲)
b.MongoDB Atlas
版本:8.0.17
地区:AWS / N. Virginia (us-east-1)
c.render
每个月1号,重置流量
https://dashboard.render.com/w/tea-d4vrlka4d50c7387bjk0/billing
-----------------------------------------------------------------------------------------------------
场景 延迟 影响
Render SG → db4free.net (德国) ~200-300ms 每次数据库查询都很慢
Render SG → MongoDB Atlas (美国) ~150-250ms 日志查询慢
Render SG → 新加坡数据库 ~5-20ms 快速响应
-----------------------------------------------------------------------------------------------------
在 Render Dashboard 配置这些变量(从 .env.prod 复制):
MYSQL_HOST、MYSQL_USER、MYSQL_PASSWORD、MYSQL_DATABASE、MONGODB_URI、JWT_SECRET、PORT 等
02.render-server
a.render-redis
Name render-redis
Maxmemory Policy allkeys-lru (recommended for caches)
Region Singapore
Runtime Valkey 8.1.4
-----------------------------------------------------------------------------------------------------
内部键值URL redis://red-d52ld0h5pdvs73fijkgg:6379
外部键值URL 不允许外部流量。请在“网络”部分添加 IP 地址
Valkey CLI 命令 不允许外部流量。请在“网络”部分添加 IP 地址
b.render-postgres
Name render-postgres
PostgreSQL Version 18
Region Singapore (Southeast Asia)
Storage 6.55% used out of 1 GB
-----------------------------------------------------------------------------------------------------
Hostname dpg-d52lcn56ubrc73a0ubhg-a
Port 5432
Database render_postgres_81qz
Username render_postgres_81qz_user
Password viNgZi0w26e39YX5lJAUIXW5ZIYxVadC
-----------------------------------------------------------------------------------------------------
内部键值URL postgresql://render_postgres_81qz_user:viNgZi0w26e39YX5lJAUIXW5ZIYxVadC@dpg-d52lcn56ubrc73a0ubhg-a/render_postgres_81qz
外部键值URL postgresql://render_postgres_81qz_user:viNgZi0w26e39YX5lJAUIXW5ZIYxVadC@dpg-d52lcn56ubrc73a0ubhg-a.singapore-postgres.render.com/render_postgres_81qz
PSQL CLI 命令 PGPASSWORD=viNgZi0w26e39YX5lJAUIXW5ZIYxVadC psql -h dpg-d52lcn56ubrc73a0ubhg-a.singapore-postgres.render.com -U render_postgres_81qz_user render_postgres_81qz
5.5 cloudflare
01.流程
a.第1步:仅DNS,是为了通过DNS记录,来验证vercel
使用https://vercel.com/halavahs-projects/valut2/settings/domains,查看解析情况
-----------------------------------------------------------------------------------------------------
类型 名称 内容 TTL 代理状态
CNAME valut cname.vercel-dns.com. 仅DNS 自动
CNAME valut2 cname.vercel-dns.com. 仅DNS 自动
CNAME valut3 cname.vercel-dns.com. 仅DNS 自动
CNAME valut-end cname.vercel-dns.com. 仅DNS 自动
CNAME picgo cname.vercel-dns.com. 仅DNS 自动
b.第2步:使用Fgaoxing提供的DNS线路
类型 名称 内容 TTL 代理状态
CNAME valut vercel.cdn.yt-blog.top 仅DNS 自动
CNAME valut2 vercel.cdn.yt-blog.top 仅DNS 自动
CNAME valut3 vercel.cdn.yt-blog.top 仅DNS 自动
CNAME valut-end vercel.cdn.yt-blog.top 仅DNS 自动
CNAME picgo vercel.cdn.yt-blog.top 仅DNS 自动
c.第3步:开启CDN代理
类型 名称 内容 TTL 代理状态
CNAME valut vercel.cdn.yt-blog.top 已代理 自动
CNAME valut2 vercel.cdn.yt-blog.top 已代理 自动
CNAME valut3 vercel.cdn.yt-blog.top 已代理 自动
CNAME valut-end vercel.cdn.yt-blog.top 已代理 自动
CNAME picgo vercel.cdn.yt-blog.top 已代理 自动
-----------------------------------------------------------------------------------------------------
SSL/TLS
完全(严格)
d.说明
如果使用 Cloudflare 代理(橙色云朵),需要在 Cloudflare 中专门设置端口转发
建议将代理状态设置为关闭(灰色云朵),这样可以直接访问原始端口
Cloudflare 免费版本只支持特定的端口(如 80、443 等),对于 28575 这样的非标准端口,需要关闭 Cloudflare 代理
e.测试
dig kiro-basket-client-captain.halavah.us
dig kiro-basket-client-resident.halavah.us
02.映射记录
a.分类1
类型 名称 内容 TTL 代理状态
CNAME valut vercel.cdn.yt-blog.top 已代理 自动
CNAME valut2 vercel.cdn.yt-blog.top 已代理 自动
CNAME valut3 vercel.cdn.yt-blog.top 已代理 自动
CNAME valut-end vercel.cdn.yt-blog.top 已代理 自动
b.分类2
类型 名称 内容 TTL 代理状态
CNAME tree vercel.cdn.yt-blog.top 已代理 自动
CNAME picgo vercel.cdn.yt-blog.top 已代理 自动
CNAME online vercel.cdn.yt-blog.top 已代理 自动
c.分类3
类型 名称 内容 TTL 代理状态
CNAME kiro-travel quartz-online.onrender.com 仅DNS 自动
CNAME kiro-online kiro-travel.onrender.com 仅DNS 自动
CNAME kiro-basket-client-captain kiro-basket.troyesivens.workers.dev 已代理 自动
CNAME kiro-basket-client-resident kiro-basket.troyesivens.workers.dev 已代理 自动
d.分类4
类型 名称 内容 TTL 代理状态
A test82 119.91.252.124 仅DNS 自动
A n8n 167.114.208.11 仅DNS 自动
03.flare-vmail
a.说明
CF_API_TOKEN Cloudflare API Token,用于授权 Wrangler 操作。请确保该 Token 具有编辑 Workers 和 D1 数据库的权限。
CF_ACCOUNT_ID 您的 Cloudflare 账户 ID,可以在 Cloudflare 控制台主页的右侧找到。
D1_DATABASE_ID 您的 D1 数据库 ID。
D1_DATABASE_NAME 您的 D1 数据库名称。
EMAIL_DOMAIN 您的邮箱域名,如果多个域名请用逗号隔开。
COOKIES_SECRET 用于加密 Cookie 的密钥,请设置为一个随机且足够复杂的字符串。
TURNSTILE_KEY Cloudflare Turnstile 网站密钥 (Site Key)。
TURNSTILE_SECRET Cloudflare Turnstile 密钥 (Secret Key)。
b.环境变量
https://github.com/halavah/flare-vmail/settings/secrets/actions
-----------------------------------------------------------------------------------------------------
CF_API_TOKEN f3-N6jyd7j1MkQSOKgkS6ehzFghD9-knBI26VXOp
CF_ACCOUNT_ID e63f38d1d4e56a0c22147ef38929b30b
D1_DATABASE_ID e08cf547-c9b1-44b3-8d3d-027b000eb050
D1_DATABASE_NAME flare-vmail
EMAIL_DOMAIN halavah.us
COOKIES_SECRET ixI3h548xqD2X
TURNSTILE_KEY 0x4AAAAAACH4gwB8FtSw0IDx
TURNSTILE_SECRET 0x4AAAAAACH4g4Ix7MbCRfC4t2r23dyz4og
-----------------------------------------------------------------------------------------------------
Global API Key 41e7dc9620373c9c2518d23327fa8510327c8,使用此key
c.域名映射
workers.dev vmail.troyesivens.workers.dev
Preview URLs *-vmail.troyesivens.workers.dev
Route vmail.halavah.us
d.DNS映射
| Record type | Hostname | Priority | Value
|-------------|--------------------------------|----------|------------------------------------------
| MX | halavah.us | 42 | route1.mx.cloudflare.net.
| MX | halavah.us | 42 | route1.mx.cloudflare.net.
| MX | halavah.us | 77 | route2.mx.cloudflare.net.
| MX | halavah.us | 81 | route3.mx.cloudflare.net.
| TXT | cf2024-1._domainkey.halavah.us | | "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiweykoi+o48IOGuP7GR3X0MOExCUDY/BCRHoWBnh3rChl7WhdyCxW3jgq1daEjPPqoi7sJvdg5hEQVsgVRQP4DcnQDVjGMbASQtrY4WmB1VebF+RPJB2ECPsEDTpeiI5ZyUAwJaVX7r6bznU67g7LvFq35yIo4sdlmtZGV+i0H4cpYH9+3JJ78km4KXwaf9xUJCWF6nxeD+qG6Fyruw1Qlbds2r85U9dkNDVAS3gioCvELryh1TxKGiVTkg4wqHTyHfWsp7KD3WQHYJn0RyfJJu6YEmL77zonn7p2SRMvTMP3ZEXibnC9gz3nnhR6wcYL8Q7zXypKTMD58bTixDSJwIDAQAB"
| TXT | halavah.us | | "v=spf1 include:_spf.mx.cloudflare.net ~all"
e.邮件路由
配置电子邮件路由 在您的 Cloudflare 域名管理界面,进入 Email -> Email Routing -> Routes,
设置一个 Catch-all 规则,将所有发送到您域名的邮件 Send to a Worker,选择您刚刚部署的 Worker。
5.6 firewall
00.端口规范(01、23、45、67、89)
a.quartz系列
a.动态0
quartz-memo 30100、30101、30102
b.静态1
quartz-flare 31100
quartz-online 31200
b.kiro系列
a.动态2
kiro-basket 32100、32101、32102
b.静态3
kiro-travel 33100
01.quartz系列
a.动态0
a.quartz-memo
项目 端口 说明
client-mini 无 微信小程序,在微信开发者工具中运行,无端口
client-vite 30101 Vite 开发服务器 (vite.config.js:23),代理到 localhost:30100
-------------------------------------------------------------------------------------------------
server 30100 Express,后端服务 (app-dev.js:136)
server-init 无 数据库初始化脚本,不监听端口
server-test 无 API 测试脚本,不监听端口
-------------------------------------------------------------------------------------------------
client-flare 30101 Vite 开发服务器,代理到 localhost:30100
server-flare 30100 Cloudflare Workers 开发服务器 (wrangler dev 默认端口)
b.quartz-time
项目 端口 说明
client-mini 无 微信小程序,在微信开发者工具中运行,无端口
client-vite 30201 Vite 开发服务器 (vite.config.js:23),代理到 localhost:30200
-------------------------------------------------------------------------------------------------
server 30200 Express,后端服务 (app-dev.js:136)
c.quartz-srytal
client-mini-memo 职途记
client-mini-srytal 知音匣
client-mini-time 相识线
b.静态1
a.quartz-flare,静态网站
项目 端口 说明
quartz-flare 31100 Cloudflare Pages 静态站点开发服务器
b.quartz-online,静态网站
项目 端口 说明
quartz-online 31200 Next.js 开发服务器
02.kiro系列
a.动态3
a.kiro-basket
项目 端口 说明
server 32100 Express 后端服务
client-captain 32101 团长端前端 Vite (vite.config.js:13)
client-resident 32102 居民端前端 Vite (vite.config.js:14)
-------------------------------------------------------------------------------------------------
server-init - 数据库初始化脚本
server-test - API 测试脚本
b.静态3
a.kiro-travel,静态网站
项目 端口 说明
kiro-travel 33100 Next.js 全栈应用 (.env.dev:5)
03.网段管理
来源 协议 端口 策略 备注
自定义 TCP 1-65535 允许 放开全部IP段
自定义 TCP 8090 允许 1Panel Linux 面板默认端口
HTTP (80) TCP 80 允许 Web服务HTTP (80),如 Apache、Nginx
HTTPS (443) TCP 443 允许 Web服务HTTPS (443),如 Apache、Nginx
Linux 登录(22) TCP 22 允许 Linux SSH登录
Windows登录(3389) TCP 3389 允许 Windows远程桌面登录
Windows登录优化(3389) UDP 3389 允许 Windows远程桌面登录优化
Ping ICMP ALL 允许 通过Ping测试网络连通性 (放通ALL ICMP)
04.防火墙管理
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" port protocol="tcp" port="1-65535" accept' --permanent
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" port protocol="udp" port="1-65535" accept' --permanent
firewall-cmd --reload
5.7 favorite
01.gemini-script
a.inbox
基础模版.go 卡牌盒
b.template1
EasyCode 生成 dto service
codehelper 使用 easycodeplus模版
c.template2
TestProductMapper 查看:1、2、3指令
TestProductMapper 导出:1、2、3指令
TestProductMapper 删除:逻辑删除、逻辑恢复
TestProductMapper DTOs、VOs
TestUserMapper DTOs、VOs
02.libra-boot-plus
a.libra-boot-mp
前后端集成
b.libra-framework/libra-common
CommonResult.java 对应 cn.myslayers.libra.module.system.dal.dataobject.permission.RoleMenuDO
src/main/java/cn/myslayers/libra/common/entity/IntegerKeyValue.java 合并、删除
src/main/java/cn/myslayers/libra/common/entity/KeyValue.java 合并、删除
c.libra-spring-boot-starter-redis
1个配置写1个文档
basic
cache
distributed-lock
rate-limiter
idempotent
d.libra-spring-boot-starter-security
security yml 按照模块来设计,配置过滤器链、配置白名单
websocket yml 按照模块来设计,配置过滤器链
RBAC SQL示例生成
cn.myslayers.libra.common.auth 移入进来
e.libra-spring-boot-starter-mybatis 测试
切换数据源
替换更新的用户
service内部类,日志
service填充日期、人
mapper调用底层实现标签
BlBaseServiceImpl.java
03.yudao-spring-boot
a.分类1
yudao-spring-boot-starter-biz-data-permission
yudao-spring-boot-starter-biz-tenant
yudao-spring-boot-starter-biz-ip 跳过
yudao-spring-boot-starter-excel
yudao-spring-boot-starter-job
yudao-spring-boot-starter-monitor
yudao-spring-boot-starter-mq
yudao-spring-boot-starter-mybatis
b.分类2
yudao-spring-boot-starter-protection 限流
yudao-spring-boot-starter-redis
yudao-spring-boot-starter-security
yudao-spring-boot-starter-test 跳过
yudao-spring-boot-starter-web
yudao-spring-boot-starter-websocket
5.8 workflow
01.核心概念
02.导入json
a.方法1:通过 n8n 界面导入
a.打开 n8n 界面
在浏览器访问你的 n8n 实例(通常是 http://localhost:5678)
登录到 n8n
b.导入工作流
点击右上角的 "+" 号按钮
选择 "From file"(从文件导入)
选择你的 n8n-workflow.json 文件
点击 "Import"(导入)
b.方法2:通过拖拽导入
a.直接拖拽
打开 n8n 界面
将 n8n-workflow.json 文件直接拖拽到浏览器窗口中
系统会自动识别并提示导入
c.方法3:通过命令行导入
a.使用 n8n 的 Docker 版本
docker exec -i <n8n_container_name> n8n import:workflow --file=/path/to/n8n-workflow.json
b.使用 n8n CLI
n8n import:workflow --file=/Volumes/Samsung/software_ware/04.Directory04/.claude/skills/ai-media-workflow/n8n/n8n-workflow.json
03.认证方式
a.方案A:API Key认证
a.生成API Key
登录 https://myslayers.app.n8n.cloud
点击右上角头像 → Settings
选择 API 标签
点击 Generate API Key
复制生成的API Key(格式类似:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...)
b.使用API Key访问
# 方法1:Header方式(推荐)
Authorization: Bearer <你的API_KEY>
# 方法2:查询参数方式
https://myslayers.app.n8n.cloud/api/v1/workflows/s3fR3PRWks0rzG4C/execute?api_key=<你的API_KEY>
b.方案B:Webhook认证
a.编辑Webhook触发器
打开你的工作流编辑页面
点击 Webhook 节点
在 Authentication 部分,选择认证类型:
b.三种认证方式选择
选项1:Basic Auth
Username: 你设置的用户名
Password: 你设置的密码
-------------------------------------------------------------------------------------------------
选项2:Header Auth
Header Name: Authorization
Header Value: Bearer <你的自定义Token>
-------------------------------------------------------------------------------------------------
选项3:Query Auth
Parameter Name: token (或其他参数名)
Parameter Value: 你的Token值
c.保存工作流后,Webhook URL会更新
# 如果设置了Basic Auth
https://myslayers.app.n8n.cloud/webhook/media-generator
# 调用时需要认证
curl -u username:password https://myslayers.app.n8n.cloud/webhook/media-generator
c.方案C:Session Cookie
先登录n8n获取session
使用session cookie访问
5.9 kiro-travel
01.render
a.Web Service:kiro-travel
Root Directory 空
-----------------------------------------------------------------------------------------------------
Build Command yarn --frozen-lockfile install; pnpm run build
Pre-Deploy CommandOptional 空
Start Command pnpm run start
Auto-Deploy On Commit
Deploy Hook https://api.render.com/deploy/srv-d501l7lactks73djtss0?key=1YtxExL0rtQ
-----------------------------------------------------------------------------------------------------
Custom Domains kiro-travel.halavah.us
5.10 kiro-basket
01.render
a.Web Service:kiro-basket-server
a.说明
Root Directory server
-------------------------------------------------------------------------------------------------
Build Command npm install
Pre-Deploy CommandOptional 空
Start Command npm run prod
Auto-Deploy On Commit
Deploy Hook https://api.render.com/deploy/srv-d52n14be5dus73ep40dg?key=8xjzTVkXbU4
-------------------------------------------------------------------------------------------------
Custom Domains https://kiro-basket-server.onrender.com
b.Static Site:kiro-basket-client-captain
a.说明
添加 Rewrite Rule,点击左侧 Redirects/Rewrites,点击 Add Rule,填写
Source /*
Destination /index.html
Action Rewrite
b.说明
Root Directory client-captain
-------------------------------------------------------------------------------------------------
Build Command npm install; npm run build
Publish Directory dist
Auto-Deploy On Commit
Deploy Hook https://api.render.com/deploy/srv-d52nrelactks73d7vd7g?key=XYVhFNgkkUA
-------------------------------------------------------------------------------------------------
Custom Domains https://kiro-basket-client-captain.onrender.com
c.Static Site:kiro-basket-client-resident
a.说明
添加 Rewrite Rule,点击左侧 Redirects/Rewrites,点击 Add Rule,填写
Source /*
Destination /index.html
Action Rewrite
b.说明
Root Directory client-resident
-------------------------------------------------------------------------------------------------
Build Command npm install; npm run build
Publish Directory dist
Auto-Deploy On Commit
Deploy Hook https://api.render.com/deploy/srv-d52nrelactks73d7vd7g?key=XYVhFNgkkUA
-------------------------------------------------------------------------------------------------
Custom Domains https://kiro-basket-client-resident.onrender.com
5.11 quartz-srytal
01.网站命名
a.命名1
选项 读音 寓意
遇知己 Yù Zhī Jǐ 遇到懂你的人,直白温暖
同频者 Tóng Pín Zhě 频率相同的人,现代感强
灵犀点 Líng Xī Diǎn 心有灵犀,文雅有韵味
缘来见 Yuán Lái Jiàn 缘分来了就相见
合拍遇 Hé Pāi Yù 遇到合拍的人,轻松活泼
b.命名2
选项 读音 寓意
知音匣 Zhī Yīn Xiá 收藏知音的盒子,文艺有质感
遇合拍 Yù Hé Pāi 遇到合拍的人,轻松活泼
同路人 Tóng Lù Rén 志同道合的人,稳重踏实
频率同 Pín Lǜ Tóng 频率相同,科技感强
心相印 Xīn Xiāng Yìn 心心相印,经典浪漫
c.命名3
灵犀遇 Líng Xī Yù 心有灵犀的相遇
缘来遇 Yuán Lái Yù 缘分来了就遇见
遇真我 Yù Zhēn Wǒ 遇见真实的自己与对方
知遇约 Zhī Yù Yuē 知遇之约,正式感
心相通 Xīn Xiāng Tōng 心灵相通
d.命名4
遇同频 Yù Tóng Pín 遇见同频的人
缘分簿 Yuán Fèn Bù 记载缘分的簿子,复古感
遇知音 Yù Zhī Yīn 遇见知音,简洁直接
同频匣 Tóng Pín Xiá 收藏同频人的盒子
心动约 Xīn Dòng Yuē 心动的约会,年轻化
02.最初需求
a.说明1
飞书表格
AI情感聊天助手
AI辅助沟通助手
b.说明2
问题1:B站/抖音/小红书/微博,各个占比多少?
问题2:淘宝/京东/拼多多/闲鱼/得物,各个占比多少?
问题3:微信好友量/是否喜欢群聊/是否经常看朋友圈
问题4:QQ飞车/LOL/CF/绝地求生/三角洲/其他
问题5:是否有强迫症/是否喜欢摆放整洁/是否喜欢专注
问题1-5为必答题,附带小作文(个人内心表达,字数不超100字)
c.说明3
星座、神佛
猫狗、听歌、象棋
鬼畜、COS、表情包
轻音乐:笛,萧、埙(xūn)
喜欢剧:怀旧,科技,动漫,玄幻
d.说明4
最高学历
专业排名
高考分数、数学成绩、英语成绩
e.说明5
体重、身高、工作
家里是否有房产,房贷,车
f.说明6
谈过几次恋爱,每个恋爱分手的原因
家里父母工作,兄弟姐妹几个,是否上学
工作是否主动发起话题,是否带有共同性
g.说明7
拜金女
筛选型人格
h.说明8
信息有偏差
沟通摩擦面
攻击人性上的弱点
03.功能设计
a.卡片1:社交媒体依赖度
考察维度:主要社交平台的使用频率/心智占用
收集项:Bilibili / 抖音 / 小红书 / 微博
评分等级:[从不,偶尔,有时,经常,总是](对应 0-100% 占比)
校验:必答,四项均需有值
b.卡片2:电商消费偏好
考察维度:购物平台的使用心智与消费习惯
收集项:淘宝 / 京东 / 拼多多 / 闲鱼 / 得物
评分等级:[从不,偶尔,有时,经常,总是]
校验:必答,五项均需有值
c.卡片3:微信社交习惯
考察维度:即时通讯中的封闭式社交态度
收集项1:微信好友量 [100人以内,100-300人,300-500人,500人以上]
收集项2:群聊参与度 [likes:超爱群聊,sometimes:偶尔参与,dislikes:能躲就躲]
收集项3:朋友圈刷新频率 [often:每天必刷,sometimes:偶尔看看,rarely:基本不看]
d.卡片4:移动游戏图谱
考察维度:竞技与沉浸式娱乐的审美交集
收集项:王者荣耀,和平精英,金铲铲,LOL手游,原神,永劫无间,CF手游,CF端游,使命召唤,第五人格
模式:多选(允许勾选多个,反映游戏圈层)
e.卡片5:性格切片测评
考察维度:基础性格特质与生活秩序感
收集项:强迫症,整洁控,专注型,拖延症,完美主义,计划控,敏感,乐观,悲观,淡定,情绪化,共情力,社恐,社牛,内向,外向等
模式:多选,至少选 1 项
f.卡片6:灵魂关键字
考察维度:用户对自我的核心定义标签
候选库:包含 30+ 关键词(如:温和,夜猫子,随性,电影,认真,务实,幽默,艺术感等)
模式:多选,要求选择 3 到 7 个精确画像
g.卡片7:文化消费偏好
考察维度:影视审美与沟通符号偏好
收集项:怀旧,玄幻,科幻,动漫,甜宠,悬疑,喜剧,历史,纪录片,综艺等
附加开关:是否喜欢抽象表情包 [abstractEmoji:Boolean]
h.卡片8:思维殿堂
考察维度:底层认知与逻辑模式
选项(单选):logic:逻辑建筑师,poet:感性诗人,maker:现实实干家,dreamer:未来梦想家
i.卡片9:能量补给站
考察维度:情感消耗后的恢复路径
选项(单选):solitude:独处充电,social:社交聚能,pets:猫狗双全,talk:深度倾诉
j.卡片10:生活切片价值观
考察维度:生活重心的选择
选项(单选):house:安身立命,travel:诗和远方,beauty:精致悦己,grow:自我投资
k.卡片11:个人独白
意图:非结构化数据的收集(对应小作文需求)
输入项:多行文本框
限制:字数不建议超过 100 字(反映个人内心表达)
l.卡片12:最终相处方案
考察维度:用户预设的两人社交边界
选项(单选):workplace:职场型,travel:旅游型,daily:日常型,online:网聊型
逻辑:最终收尾,驱动结果计算
5.12 quartz-online
01.vercel
a.quartz-online
Root Directory 空,代表根目录
-----------------------------------------------------------------------------------------------------
Framework Preset Next.js
-----------------------------------------------------------------------------------------------------
Build Command npm run build
Output Directory out
Install Command npm install
Development Command 空,默认,next
-----------------------------------------------------------------------------------------------------
Output Directory out
Install Command npm ci
Development Command npm run dev
02.render
a.Web Service:quartz-online
Root Directory 空
-----------------------------------------------------------------------------------------------------
Build Command npm install; npm run build
Pre-Deploy CommandOptional 空
Start Command npm run start
Auto-Deploy On Commit
Deploy Hook https://api.render.com/deploy/srv-d501n5pr0fns739vhkog?key=lU0wcId-qsg
-----------------------------------------------------------------------------------------------------
Custom Domains kiro-online.halavah.us
03.cloudflare
a.手动部署
项目名称 quartz-flare
构建命令 npm run build
部署命令 npm run build
非生产分支构建 取消勾选
-----------------------------------------------------------------------------------------------------
路径 /
API令牌 quartz-flare build token
变量名称 空
Variable value 空
b.参考命令
# 1.构建项目
npm run build
-----------------------------------------------------------------------------------------------------
# 2.部署到 Cloudflare Pages
npm run deploy
# 使用生产环境部署:
npm run deploy:prod
-----------------------------------------------------------------------------------------------------
# 3. 直接一条命令完成构建和部署
npm run build && npm run deploy
-----------------------------------------------------------------------------------------------------
npm run build 构建静态网站到 public/
npm run dev 本地开发服务器
npm run deploy 部署到 Cloudflare Pages
npm run deploy:prod 部署到生产环境
npm run clean 清理构建缓存
npm run preview 本地预览构建结果
5.13 quartz-memo
00.网站信息
a.说明1
a.分类1
http://localhost:5173
http://localhost:5173/door?token=sweet
http://localhost:5173/verify?token=Dh5mK6hL
b.分类2
http://localhost:5174
http://localhost:5174/door?token=sweet
http://localhost:5174/verify?token=Dh5mK6hL
c.分类3
http://101.42.36.187:7881
http://101.42.36.187:7881/verify?token=Dh5mK6hL
http://101.42.36.187:7881/verify?token=Dh5mK6hL
b.说明2
a.分类1
http://memo.halavah.us
http://memo.halavah.us/door?token=sweet
http://memo.halavah.us/verify?token=sweet
b.分类2
http://memo.myslayers.top
http://memo.myslayers.top/door?token=sweet
http://memo.myslayers.top/verify?token=sweet
c.说明3
a.分类1
sweet 管理员
Dh5mK9hL 亲友A
Zk5hG6jK 亲友B
Zm2nC9eR 访客C
Zp4bV7xW 访客D
Zs8dF3gT 访客E
b.分类2
首页,头像图片,点击5次,跳转简历
编年,任意卡片,点击5次,跳转碎碎念
c.分类3
PowerShell 5.1 的 BOM UTF-8 文件编码
文件编码问题(例如保存为了 UTF-8 无 BOM,而旧版 PowerShell 默认按系统 ANSI 读取导致中文乱码)
01.render
a.Web Service:quartz-memo-server
a.说明
Root Directory server
-------------------------------------------------------------------------------------------------
Build Command npm install
Pre-Deploy CommandOptional 空
Start Command npm run prod
Auto-Deploy On Commit
Deploy Hook https://api.render.com/deploy/srv-d52n14be5dus73ep40dg?key=8xjzTVkXbU4
-------------------------------------------------------------------------------------------------
Custom Domains https://quartz-memo-server.onrender.com
b.Static Site:quartz-memo-client-vite
a.说明
添加 Rewrite Rule,点击左侧 Redirects/Rewrites,点击 Add Rule,填写
Source /*
Destination /index.html
Action Rewrite
b.说明
Root Directory client-vite
-------------------------------------------------------------------------------------------------
Build Command npm install; npm run build
Publish Directory dist
Auto-Deploy On Commit
Deploy Hook https://api.render.com/deploy/srv-d52nrelactks73d7vd7g?key=XYVhFNgkkUA
-------------------------------------------------------------------------------------------------
Custom Domains https://quartz-memo-client-vite.onrender.com
02.cloudflare
a.网站部署
a.域名一致
情况1:move-car/nextjs,同一个应用,点击延迟低
情况2:server、client-vite,前后端,建议都绑定到【halavah】域名
b.quartz-memo-client-flare
域名 https://memo.halavah.us/
-------------------------------------------------------------------------------------------------
纯文本 D1_DATABASE_ID d0b8284f-619d-4126-ac57-88cba5d94905
纯文本 JWT_SECRET quartz_memo_secret_2025
纯文本 ONLY_ALLOW_CN true
纯文本 R2_BUCKET_NAME quartz-memo-assets
c.quartz-memo-server-flare
域名 https://memo-server.halavah.us/
-------------------------------------------------------------------------------------------------
纯文本 ONLY_ALLOW_CN true
纯文本 VITE_API_BASE_URL https://memo-server.halavah.us/api
b.加速CDN
a.源站优化 (Next.js)
移除第三方阻断资源 (Google Fonts)
强制静态生成 (SSG)
HTML 预加载 (Preload)
iframe 加载优化
b.CDN优化 (Cloudflare)
智能压缩 (Brotli/Gzip)
边缘缓存 (Edge Cache)
资源最小化 (Minify)
协议优化 (HTTP/3, 0-RTT)
c.路由优化 (可选)
Argo Smart Routing
智能负载均衡
多层缓存拓扑
c.仅允许CN地区
a.方法一:使用 WAF 规则(推荐)
1.进入 Cloudflare Dashboard → 你的域名
2.左侧菜单点击「Security」→「WAF」
3.点击「Create rule」
4.规则设置:
Rule name:`Block non-CN traffic`
If incoming requests match:`Country does not equal China`
Then:`Block`
5.点击「Deploy」
-------------------------------------------------------------------------------------------------
(http.host eq "memo.halavah.us" and ip.src.country ne "CN")
(http.host eq "memo-server.halavah.us" and ip.src.country ne "CN")
b.方法二:在 Worker 代码中过滤
// 只允许中国地区访问
const country = request.cf?.country;
if (country && country !== 'CN') {
return new Response('Access Denied', { status: 403 });
}
03.1panel
a.路径
a.默认规则
遵循 1Panel "静态网站" 和 "运行环境" 的默认行为。脚本自动识别,面板自动识别。
tencent-deploy-client.ps1 -> 上传到 /opt/1panel/www/sites/quartz-memo-client-vite/index
tencent-deploy-client.sh -> 上传到 /opt/1panel/www/sites/quartz-memo-client-vite/index
tencent-deploy-server.ps1 -> 上传到 /opt/1panel/www/sites/quartz-memo-server
tencent-deploy-server.sh -> 上传到 /opt/1panel/www/sites/quartz-memo-server
b.1panel默认是容器化的
User[开发者 (您)] -->|运行 tencent.sh| Script[自动化脚本]
subgraph Server [腾讯云 1Panel 服务器]
Script -->|1. 上传代码| StandardPath["标准目录 (/opt/1panel/www/sites/...)"]
Script -->|2. 重启指令| DockerEngine[Docker 引擎]
DockerEngine -->|运行| QuartzServer[后端容器 (Node.js)]
DockerEngine -->|运行| QuartzDB[数据库容器 (MySQL)]
DockerEngine -->|运行| OpenResty[网关/静态服务]
OpenResty -->|托管| StandardPath
OpenResty -->|反向代理 (/api -> :3000)| QuartzServer
end
b.部署服务
a.后端,Node.js
创建:“网站” -> “运行环境” -> “Node.js” -> “创建”
名称:quartz-memo-server --容器名称
应用:Node.js,24.5.0
项目目录:/opt/1panel/www/sites/quartz-memo-server --路径
-------------------------------------------------------------------------------------------------
启动命令:npm run prod --启动
容器名称:quartz-memo-server --容器名称
包管理器:npm
镜像源:https://registry.npmjs.org/
b.前端,静态网站
创建:“网站” -> “创建网站” -> “静态网站”
域名:101.42.36.187:30100 --解析DNS
域名:memo.myslayers.top,80端口 --解析DNS
代号:quartz-memo-client-vite --解析名称
对应主目录:/opt/1panel/www/sites/quartz-memo-client-vite/index --解析路径
-------------------------------------------------------------------------------------------------
反向代理 名称 前端请求路径 后端代理地址 后端域名
反向代理 api /api http://172.18.0.4:30100 $host
反向代理 api /content http://172.18.0.4:30100 $host
反向代理 api /uploads http://172.18.0.4:30100 $host
-------------------------------------------------------------------------------------------------
伪静态 location / {try_files $uri $uri/ /index.html;}
-------------------------------------------------------------------------------------------------
主域名 颁发组织 类型 Acme 账号 过期时间
memo.myslayers.top Let's Encrypt DNS 账号 [email protected] 2026-04-05
c.证书
主机记录:*
记录类型:A
线路类型:默认
记录值:101.42.36.187
TTL:600
-------------------------------------------------------------------------------------------------
主域名:*.myslayers.top
Acme账户:[email protected]
密钥算法:EC 256
验证方式:DNS账号
DNS账号:腾讯云 [Tencent Cloud]
自动续签:勾选
-------------------------------------------------------------------------------------------------
Windows:nslookup test.yourdomain.com
Linux/macOS:dig test.yourdomain.com 或 ping test.yourdomain.com
d.防火墙/安全组配置
来源 协议 端口 策略 备注
自定义 TCP 1-65535 允许 放开全部IP段
自定义 TCP 8090 允许 1Panel Linux 面板默认端口
HTTP (80) TCP 80 允许 Web服务HTTP (80),如 Apache、Nginx
HTTPS (443) TCP 443 允许 Web服务HTTPS (443),如 Apache、Nginx
Linux 登录(22) TCP 22 允许 Linux SSH登录
Windows登录(3389) TCP 3389 允许 Windows远程桌面登录
Windows登录优化(3389) UDP 3389 允许 Windows远程桌面登录优化
Ping ICMP ALL 允许 通过Ping测试网络连通性 (放通ALL ICMP)
-------------------------------------------------------------------------------------------------
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" port protocol="tcp" port="1-65535" accept' --permanent
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" port protocol="udp" port="1-65535" accept' --permanent
firewall-cmd --reload
04.script
a.kondo.sh
================================================================
项目空间清理工具 (POSIX sh 兼容版) v4.1
================================================================
ℹ️ 目标根目录: /Volumes/Samsung/software_xare/quartz-memo
🎯 将会查找并删除以下名称的目录: node_modules, target
----------------------------------------------------------------
⏳ 正在查找目标目录,请稍候...
🔍 已找到 8 个可清理的目录。
--- 将要删除以下目录 ---
./client-flare/node_modules
./client-mini/node_modules
./server/node_modules
./server/content/node_modules
./server-test/node_modules
./server-init/node_modules
./server-flare/node_modules
./client-vite/node_modules
--------------------------
⏳ 正在计算总大小...
💾 总计大小约为: 637M
b.manage.sh
═══════════════════════════════════════════════════════════
项目管理
═══════════════════════════════════════════════════════════
0. 🚢 部署到 Git (deploy.sh)
→ 自动提交并推送代码到远程仓库
1. 🧹 清理 Git 跟踪 (clear-ignore.sh)
→ 根据 .gitignore 移除已跟踪的文件
2. 🗜️ 压缩 Git 仓库 (clear-git.sh)
→ 优化 .git 目录,减小体积(保留所有历史)
3. 🧹 清理 Git 历史 (clear-history.sh)
→ 删除旧提交,仅保留最近 N 个(需谨慎)
═══════════════════════════════════════════════════════════
9. 🚪 退出
═══════════════════════════════════════════════════════════
请选择操作 [0-9] (默认: 0 - 部署):
c.start.sh
═══════════════════════════════════════════════════════════
快速启动 (职途记)
═══════════════════════════════════════════════════════════
1. 🚀 启动后端服务器 (start-server.sh)
→ 启动 Node.js 后端
2. 🌐 启动 Web 端 (start-vite.sh)
→ 启动 H5 移动端 (Client-Vite)
3. 📱 启动小程序前端 (start-mini.sh)
→ 启动小程序开发环境 (Client-Mini)
4. 🗄️ 初始化开发数据库 (server-init-dev.sh)
→ 初始化 MySQL 数据库(开发环境)
5. 🗄️ 初始化生产数据库 (server-init-prod.sh)
→ 初始化 MySQL 数据库(生产环境)
6. 🗄️ 初始化 Render 数据库 (server-init-render.sh)
→ 初始化 MySQL 数据库(Render 环境)
7. 🧪 运行 API 测试 (test-api.sh)
→ 执行服务端 API 自动化测试
═══════════════════════════════════════════════════════════
9. 🚪 退出
═══════════════════════════════════════════════════════════
请选择操作 [1-7, 9]:
d.docker.sh
═══════════════════════════════════════════════════════════
🐳 Docker 环境管理
═══════════════════════════════════════════════════════════
1. 🚀 启动 Docker Compose (docker-up.sh)
→ 一键启动完整容器化测试环境 (DB+Server+Redis)
2. 🧹 移除 Docker 环境 (docker-clean.sh)
→ 清除容器、卷和本地镜像 (Deep Clean)
═══════════════════════════════════════════════════════════
9. 🚪 退出
Select option [1-2, 9]:
e.flare.sh
═══════════════════════════════════════════════════════════
Flare 云端管理 (职途记)
═══════════════════════════════════════════════════════════
1. 🚀 启动 Flare 后端开发端 (Local Dev)
→ Hono Workers
2. 🌐 启动 Flare Web 开发端 (Local Dev)
→ Vite Pages
3. 🗄️ 初始化 Flare D1 数据库 (Migration)
→ 数据库迁移
4. 📦 同步本地资源到 R2 (Sync)
→ 将 content/ 同步到 Cloudflare R2
─── 部署选项 (自动配置) ───────────────────────────────────
5. 🌏 部署到 Cloudflare (CN 专线)
→ 自动开启 Geo-blocking (仅限 CN)
6. 🌍 部署到 Cloudflare (全球版)
→ 自动关闭限制 (允许全球访问)
═══════════════════════════════════════════════════════════
9. 🚪 退出
═══════════════════════════════════════════════════════════
请选择操作 [1-6, 9]:
f.tencent.sh
═══════════════════════════════════════════════════════════
腾讯云 1Panel 部署工具
═══════════════════════════════════════════════════════════
1. 🌐 部署前端 (Vue) (tencent-deploy-client.sh)
→ 自动构建并上传 Client-Vite
2. ⚙️ 部署后端 (Node) (tencent-deploy-server.sh)
→ 自动打包并上传 Server (自动重启容器)
═══════════════════════════════════════════════════════════
3. 🚀 部署全栈 (All)
→ 依次部署后端和前端
═══════════════════════════════════════════════════════════
9. 🚪 退出
═══════════════════════════════════════════════════════════
请选择操作 [1-3, 9]:
6 blogger
6.1 hexo
00.汇总
a.Gitee Pages
仅支持 Jekyll、Hugo、Hexo编译静态资源
-----------------------------------------------------------------------------------------------------
如何创建一个首页访问地址不带二级目录的 pages,如ipvb.gitee.io?
答:如果你想你的 pages 首页访问地址不带二级目录,如ipvb.gitee.io,你需要建立一个与自己个性地址同名的仓库,
如 https://gitee.com/ipvb 这个用户,想要创建一个自己的站点,但不想以子目录的方式访问,
想以ipvb.gitee.io直接访问,那么他就可以创建一个名字为ipvb的仓库 https://gitee.com/ipvb/ipvb 部署完成后,
就可以以 https://ipvb.gitee.io 进行访问了。
b.私有仓库支持性
Vercel Pages支持连接私有仓库
Netlify Pages支持连接私有仓库
Cloudflare Pages不能连接私有仓库
GitHub的私有仓库开启GitHub Pages需要升级为Pro用户($4/mon)
c.gihtub page
a.前提
必须仓库为公有public
b.不使用Action
settings -> pages -> Build and deployment -> Deploy from a branch -> master、/docs
c.使用Action
.github/workflows/deploy.yml,该文件指定构建目录,如public;指定构建分支,如master
settings -> pages -> Build and deployment -> GitHub Actions
GitHub Actions -> 查看构建情况
01.Hexo托管
a.托管方式(Gitee)-> 手动更新
名称:myslayers
描述:勿因喜而轻诺!
插件:d: && cd D:\software_ware\workspace_blog && cnpm install hexo-deployer-git --save
邮箱:git config --global user.email "[email protected] " && git config --global user.name "myslayers"
开启Gitee Pages服务:Branch(master)、整个目录
站点_config.yml文件:
title: 个人博客
subtitle: ''
description: '勿因喜而轻诺'
keywords:
author: myslayers
language: zh-CN
timezone: 'Asia/Shanghai'
----------------------------------------------------------------------
url: https://myslayers.gitee.io/
root: /
permalink: :title.html
----------------------------------------------------------------------
public_dir: public
----------------------------------------------------------------------
theme: keep
----------------------------------------------------------------------
deploy:
type: 'git'
repo: 'https://gitee.com/myslayers/myslayers.git'
branch: master
message:
b.托管方式(Github)-> 自动更新
名称:myslayers.github.io
描述:勿因喜而轻诺!
插件:d: && cd D:\software_ware\workspace_blog && cnpm install hexo-deployer-git --save
邮箱:git config --global user.email "[email protected] " && git config --global user.name "myslayers"
开启Github Pages服务:Branch(master)、docs目录
站点_config.yml文件:
title: Halavah's Blog
subtitle: ''
description: '勿因喜而轻诺!'
keywords:
author: Halavah
language: zh-CN
timezone: 'Asia/Shanghai'
----------------------------------------------------------------------
url: https://halavah.github.io/halavah
root: /halavah/
permalink: :title.html
----------------------------------------------------------------------
public_dir: docs
----------------------------------------------------------------------
theme: Chic
----------------------------------------------------------------------
deploy:
type: 'git'
repo: 'https://github.com/halavah/halavah.git'
branch: master
message:
c.自定义域名(Github)
a.Cloudflare
类型 名称 内容 TTL 代理状态
A @ 185.199.108.153 自动 仅限 DNS
A @ 185.199.109.153 自动 仅限 DNS
A @ 185.199.110.153 自动 仅限 DNS
A @ 185.199.111.153 自动 仅限 DNS
CNAME www halavah.github.io 自动 仅限 DNS
b.Settings
master /docs
halavah.tk
Enforce HTTPS Please allow 24 hours for this process to complete
c._config.yml
url: https://halavah.tk
root: /
d.防止删除CNAME文件
将CNAME文件放到source文件夹下,那么在hexo generate在编译时,也会将CNAME编译进docs文件夹中
e.docs放CNAME
https://halavah.github.io/halavah
02.Hexo部署
a.部署方式(git push)(每次提交需要add、commit、ppush,同时需要手动输入邮箱、密码)
a.创建本地仓库、远程仓库
git init --创建本地仓库
[email protected] :myslayers/myslayers.github.io.git--创建远程仓库
b.关联本地仓库与远程仓库地址
git remote add origin https://github.com/myslayers/myslayers.github.io.git
c.保留线上的readme文件(如果本地分支版本大于远程版本,则强制提交)
git pull origin master
d.关联本地分支与远程分支地址
git add .
git commit -m "my first commit"
git push origin master -f --强制提交:舍弃线上文件进行强制推送(不推荐)
git push origin master --正常提交:保留线上的readme文件
b.部署方式(hexo deploy)
hexo clean && hexo generate && hexo deploy
hexo clean && hexo generate && hexo s -p 9999
03.Hexo使用(NexT、Keep、目前Chic、yilia、Concise、Fluid、Flui、Inside)(Typecho-handsome)(Typecho)
a.环境(Nodejs、Git、hexo-cli)(在Disk中默认Nodejs编译cnpm、hexo-cli,默认Git,因此可以忽略此步骤)
D:\software\Linux\Window\Git
D:\software\JavaScript\Nodejs
npm install -g cnpm --registry=https://registry.npm.taobao.org && cnpm install -g hexo-cli
b.安装
d: && mkdir D:\software_ware\workspace_hexo --创建blog文件夹
d: && cd D:\software_ware\workspace_hexo && hexo init --初始化hexo框架
c.命令
hexo init [folder] --初始化命令,[folder]表示初始化的文件夹
hexo new [layout] <title> --新建文章或页面,[layout]表示页面, <title>表示标题
hexo s -p 9999 --本地查看网站
hexo generate --生成网站静态文件,网页默认保存在“public文件夹”
hexo clean --清空“public文件夹的内容”
hexo deploy --部署网站,将“public文件夹的内容”进行部署
hexo version --当前hexo版本号
d.启动
git clone [email protected] :halavah/PicGo.git workspace_hexo --第1步:克隆仓库
git pull --rebase --第2步:更新仓库
hexo clean && hexo generate && hexo s -p 9999 --第3步:查看本地(check.bat)(重新生成docs)
hexo clean && hexo generate && hexo deploy --第4步_无:远程部署(deploy.bat)(删除配置)
git add . && git commit -m 'v1.0' && git push --第5步:手动提交
git tag v1.0 && git push origin v1.0 --第6步:手动提交
e.Keep主题
a.功能
Post_top(文章顶置)
base_info(网站名称、作者昵称、网站域名)
style(网站主题色、文章内容页的图片排列位置、左侧TOC目录结构模块的宽度、设置鼠标悬浮时的样式、首屏模块)
social_contact(社交网络链接,仅在首屏下生效)
menu(导航菜单)
rss(订阅)
comment(Gitalk评论)
website_count(计数项)
local_search(本地搜索)
post_wordcount(文章字数统计和阅读时长统计功能)
home_article(首页文章块底部的显示设置)
code_copy(代码复制)
side_tools(右下角工具)
back2top(一键快速 回到顶部和到达底部)
toc(查看文章结构和跳转)
copyright_info(文章内容页的版权信息模块)
cdn(开启资源CDN加速)
footer(网站最底部的信息展示设置)
MathJax(数学公式)
lazyload(懒加载)
pjax(Ajax部分更新)
b.写作
---
title: 第一篇文章
date: 2020-04-07 21:55:14
tags: 标签一
categories: 分类一
comment: true --评论
mathjax: true --MathJax数学公式
sticky: 9999 --sticky值越大,顶置的文章越靠前
---
f.Chic主题
a.安装
cd your-blog/themes
git clone https://github.com/Siricee/hexo-theme-Chic.git Chic
hexo new page tag
hexo new page category
hexo new page about
b.写作
---
title: 第一篇文章
date: 2020-04-07 21:55:14
tags: 标签一
categories: 分类一
mathjax: true --MathJax数学公式
---
6.2 hugo
01.命令(PaperMod、Even、MemE、LoveIt)
hugo new site myslayers -f yml --初始化,文件夹myslayers,站点http://myslayers.com
hugo new --kind post archetypes/post.md --归档
hugo new --kind post tags/post.md --标签
hugo server -D --本地查看网站(http://localhost:1313/)
02.主题
https://themes.gohugo.io/hugo-papermod/
https://github.com/adityatelange/hugo-PaperMod
03.发布
a.第一次发布
cd public
git init
git remote add origin https://github.com/Showfom/showfom.github.io.git
git add .
git commit -m "first commit"
git push -u origin master
b.后续发布
cd public
git add .
git status
git commit -m "add blog post"
git push
6.3 picgo
01.GitHub
仓库名 halavah/PicGo
分支名 master
Token 5ef48dd7ead044453f7606442ce8d04ccc365c23
存储路径 avatar/ background/
自定义域名 https://halavah.buzz
02.默认路径
https://raw.githubusercontent.com/[username]/[仓库名]/[分支名]/[文件路径]
https://raw.githubusercontent.com/halavah/PinGo/master/background/22.jpg
03.加速路径
https://cdn.jsdelivr.net/gh/[username]/[仓库名]@[分支名]/[文件路径]
https://cdn.jsdelivr.net/gh/halavah/PinGo@master/background/22.jpg
04.域名路径
https://halavah.buzz/[文件路径]
https://halavah.buzz/background/22.jpg
6.4 quartz1
00.起源
a.分类1
TroyeKK小站
TroyeKK World
b.分类2
TroyeHub、TroyeVibe、KKZone、TroyeNest、KKSpot、TroyeWorld、TroyeBox、KKLink、TroyeX、TroyeHQ
c.World换个词
Realm、Horizon、Sphere、Domain、Territory、Kingdom、Vista、Universe、Oasis、Empire
d.版本说明
quartz-v0_没有防护码
quartz-v1_仅适配域名_如vercel_session:采用sessionStorage来实现,可以通过绕开验证,通过【会话存储】使用【verified】设置为【true】
quartz-v1_仅适配域名+仓库_如github_session:采用sessionStorage来实现,可以通过绕开验证,通过【会话存储】使用【verified】设置为【true】
quartz-v2_仅适配域名_如vercel_token:采用sessionStorage来实现,但是token分为3个部分,localStorage存储一部分、sessionStorage 存储另一部分、cookie存储第三部分,但是【ChatGPT】可推测出密码
quartz-v3_仅适配域名_如vercel_不可逆加密:采用sessionStorage来实现,但是token分为3个部分,localStorage存储一部分、sessionStorage 存储另一部分、cookie存储第三部分,但是【不可逆加密】,【ChatGPT】不能推测出密码
e.启动
$ npx quartz build --verbose ,构建到public,但不运行
$ npx quartz build --serve,默认监听在 8080 端口,支持热重载,但是不支持网络文件系统的热重载。
f.硬链接
mklink /d "D:\software_xare\workspace_open\quartz-pro_screen\content" "D:\software_ware\04.Directory04"
mklink /d "D:\software_ware\99.Directory01\content" "D:\software_ware\01.Directory01"
mklink /d "D:\software_ware\99.Directory02\content" "D:\software_ware\02.Directory02"
mklink /d "D:\software_ware\99.Directory03\content" "D:\software_ware\03.Directory03"
mklink /d "D:\software_ware\99.Directory04\content" "D:\software_ware\04.Directory04"
mklink /d "D:\software_ware\99.Directory05\content" "D:\software_ware\05.Directory05"
g.git检查Aliyun Key
搜索accessKey、secretKey、accessKeyId、accessKeySecret
00.project1
02.backend2
06.cangqiong
07.jiankang
01.使用
a.下载
https://github.com/jackyzha0/quartz
b.安装和初始化
[[quartz]] 支持利用 nodejs 直接部署,以及利用 docker 部署。
# nodejs 部署和初始化
$ git clone https://github.com/jackyzha0/quartz.git
$ cd quartz
$ npm i
$ npx quartz create
$ npx quartz build --serve
---------------------------------------------------------------------------------------------------------
# docker部署
$ git clone https://github.com/jackyzha0/quartz.git
$ docker run --rm -itp 8080:8080 $(docker build -q .)
c.配置quartz.config.ts 和quartz.layout.ts文件
quartz.config.ts 文件主要是配置网站信息,主题自定义以及插件系统,默认基本不用动,只需要更改一下网站信息即可,具体参考Configuration (jzhao.xyz)。
quartz.layout.ts 文件是配置布局,默认有 3 个布局样式可以自定义:
sharedPageComponents :这个是配置分享页面内容的,主要是配置页脚信息。
defaultContentPageLayout:这个是配置文档页面布局的,注意主页也属于文档。
defaultListPageLayout :这个是配置标签页和文件夹页面布局的。
布局参考:Layout (jzhao.xyz)
组件参考:Components (jzhao.xyz)
d.生成和预览
$ npx quartz build --verbose ,构建到public,但不运行
$ npx quartz build --serve,默认监听在 8080 端口,支持热重载,但是不支持网络文件系统的热重载。
e.同步内容
文档内容全部在content目录,该文件夹下应该有index.md 作为主页,content 中的文档结构会默认的渲染成路径。
f.启动脚本:start.bat
@echo off
:: Navigate to the directory where the script is located
cd /d "%~dp0"
:: Delete all contents in the "public" folder but keep the folder itself
if exist "public" (
echo Deleting all contents in the "public" folder...
del /q /f "public\*.*"
for /d i"
echo Deletion completed.
) else (
echo "The public folder does not exist."
)
npx quartz build --serve
g.命令说明
npx quartz build --serve
其中大多数都有合理的默认值,但如果您有自定义设置,则可以覆盖它们:
-d或--directory:内容文件夹。这通常只是content
-v或者--verbose:打印额外的日志信息
-o或--output:输出文件夹。这通常只是public
--serve:运行本地热重载服务器来预览你的 Quartz
--port:在哪个端口上运行本地预览服务器
--concurrency:解析笔记需要使用多少个线程
02.配置样式
a.根目录
a.网址:quartz.config.ts
a.11行
pageTitle: "TroyeKK小站",
pageTitle: "TroyeKK World",
pageTitle: "Halavah's Blog",
b.19行
baseUrl: "halavah.github.io",
ignorePatterns: ["private", "templates", ".obsidian", ".obsidian_android", ".trash", "_assets"],
c.20241220
import { QuartzConfig } from "./quartz/cfg"
import * as Plugin from "./quartz/plugins"
/**
* Quartz 4.0 Configuration
*
* See https://quartz.jzhao.xyz/configuration for more information.
*/
const config: QuartzConfig = {
configuration: {
pageTitle: "TroyeKK World",
pageTitleSuffix: "",
enableSPA: true,
enablePopovers: true,
analytics: {
provider: "plausible",
},
locale: "en-US",
baseUrl: "halavah.github.io",
ignorePatterns: ["private", "templates", ".obsidian", ".obsidian_android", ".trash", "_assets"],
defaultDateType: "created",
generateSocialImages: false,
theme: {
fontOrigin: "googleFonts",
cdnCaching: true,
typography: {
header: "Schibsted Grotesk",
body: "Source Sans Pro",
code: "IBM Plex Mono",
},
colors: {
lightMode: {
light: "#faf8f8",
lightgray: "#e5e5e5",
gray: "#b8b8b8",
darkgray: "#4e4e4e",
dark: "#2b2b2b",
secondary: "#284b63",
tertiary: "#84a59d",
highlight: "rgba(143, 159, 169, 0.15)",
textHighlight: "#fff23688",
},
darkMode: {
light: "#161618",
lightgray: "#393639",
gray: "#646464",
darkgray: "#d4d4d4",
dark: "#ebebec",
secondary: "#7b97aa",
tertiary: "#84a59d",
highlight: "rgba(143, 159, 169, 0.15)",
textHighlight: "#b3aa0288",
},
},
},
},
plugins: {
transformers: [
Plugin.FrontMatter(),
Plugin.CreatedModifiedDate({
priority: ["frontmatter", "filesystem"],
}),
Plugin.SyntaxHighlighting({
theme: {
light: "github-light",
dark: "github-dark",
},
keepBackground: false,
}),
Plugin.ObsidianFlavoredMarkdown({ enableInHtmlEmbed: false }),
Plugin.GitHubFlavoredMarkdown(),
Plugin.TableOfContents(),
Plugin.CrawlLinks({ markdownLinkResolution: "shortest" }),
Plugin.Description(),
Plugin.Latex({ renderEngine: "katex" }),
],
filters: [Plugin.RemoveDrafts()],
emitters: [
Plugin.AliasRedirects(),
Plugin.ComponentResources(),
Plugin.ContentPage(),
Plugin.FolderPage(),
Plugin.TagPage(),
Plugin.ContentIndex({
enableSiteMap: true,
enableRSS: true,
}),
Plugin.Assets(),
Plugin.Static(),
Plugin.NotFoundPage(),
],
},
}
export default confige
b.友链:quartz.layout.ts
a.11行
// GitHub: "https://github.com/halavah",
// BiliBili: "https://space.bilibili.com/71393128/",
b.32行
right: [
// Component.Graph(),
Component.DesktopOnly(Component.TableOfContents()),
// Component.Backlinks(),
],
c.20241220
import { PageLayout, SharedLayout } from "./quartz/cfg"
import * as Component from "./quartz/components"
// components shared across all pages
export const sharedPageComponents: SharedLayout = {
head: Component.Head(),
header: [],
afterBody: [],
footer: Component.Footer({
links: {
// GitHub: "https://github.com/halavah",
// BiliBili: "https://space.bilibili.com/71393128/",
},
}),
}
// components for pages that display a single page (e.g. a single note)
export const defaultContentPageLayout: PageLayout = {
beforeBody: [
Component.Breadcrumbs(),
Component.ArticleTitle(),
Component.ContentMeta(),
Component.TagList(),
Component.MobileOnly(Component.TableOfContents()),
],
left: [
Component.PageTitle(),
Component.MobileOnly(Component.Spacer()),
Component.Search(),
Component.DesktopOnly(Component.Explorer()),
Component.DesktopOnly(Component.About()),
Component.MobileOnly(Component.Darkmode()),
],
right: [
Component.Graph(),
Component.DesktopOnly(Component.TableOfContents()),
// Component.Backlinks(),
],
}
// components for pages that display lists of pages (e.g. tags or folders)
export const defaultListPageLayout: PageLayout = {
beforeBody: [
Component.Breadcrumbs(),
Component.ArticleTitle(),
Component.ContentMeta(),
],
left: [
Component.PageTitle(),
Component.MobileOnly(Component.Spacer()),
Component.Search(),
Component.DesktopOnly(Component.Explorer()),
Component.DesktopOnly(Component.About()),
Component.MobileOnly(Component.Darkmode()),
],
right: [
],
}
b.css
a.基础CSS:quartz/styles/base.scss
a.181行
& .sidebar {
gap: 2rem;
top: 0;
box-sizing: border-box;
padding: $topSpacing 2rem 2rem 2rem;
display: flex;
height: 100vh;
position: sticky;
}
b.546行
ul.overflow,
ol.overflow {
max-height: 100%;
//overflow-y: auto;
// clearfix
content: "";
clear: both;
& > li:last-of-type {
margin-bottom: 30px;
}
/*&:after {
pointer-events: none;
content: "";
width: 100%;
height: 50px;
position: absolute;
left: 0;
bottom: 0;
opacity: 1;
transition: opacity 0.3s ease;
background: linear-gradient(transparent 0px, var(--light));
}*/
}
c.229行
& .page-header,
& .page-footer {
margin-top: 1rem;
}
b.变量CSS:quartz/styles/variables.scss
a.18行
$sidePanelWidth: 280px; //380px;
b.19行
$topSpacing: 1rem;
c.21行
$semiBoldWeight: 470;
c.TroyeKK小站
a.quartz/components/PageTitle.tsx,16行
PageTitle.css = `
.page-title {
font-size: 1.75rem;
margin: 0;
}
`
d.搜索
a.quartz/components/Search.tsx,23行
前
<p>{i18n(cfg.locale).components.search.title}</p>
-------------------------------------------------------------------------------------------------
后
<p>搜索</p>
e.大纲
a.quartz/components/TableOfContents.tsx,36行
前
<h3>{i18n(cfg.locale).components.tableOfContents.title}</h3>
-------------------------------------------------------------------------------------------------
后
<h3>大纲</h3>
b.quartz/components/styles/toc.scss,3行
前
.toc {
display: flex;
flex-direction: column;
&.desktop-only {
max-height: 40%;
}
}
-------------------------------------------------------------------------------------------------
后
.toc {
display: flex;
flex-direction: column;
&.desktop-only {
max-height: 50%;
}
}
c.quartz/components/styles/toc.scss,45行
前:大纲滚动条
//#toc-content {
// list-style: none;
// overflow: hidden;
// overflow-y: auto;
// max-height: 100%;
// transition:
// max-height 0.35s ease,
// visibility 0s linear 0s;
// position: relative;
// visibility: visible;
//
// &.collapsed {
// max-height: 0;
// transition:
// max-height 0.35s ease,
// visibility 0s linear 0.35s;
// visibility: hidden;
// }
//
// &.collapsed > .overflow::after {
// opacity: 0;
// }
//
// & ul {
// list-style: none;
// margin: 0.5rem 0;
// padding: 0;
// & > li > a {
// color: var(--dark);
// opacity: 0.35;
// transition:
// 0.5s ease opacity,
// 0.3s ease color;
// &.in-view {
// opacity: 0.75;
// }
// }
// }
// > ul.overflow {
// max-height: none;
// width: 100%;
// }
//
// @for $i from 0 through 6 {
// & .depth-#{$i} {
// padding-left: calc(1rem * #{$i});
// }
// }
//}
-------------------------------------------------------------------------------------------------
后:大纲滚动条
#toc-content {
list-style: none;
overflow: hidden;
overflow-y: auto;
max-height: 100%;
transition:
max-height 0.35s ease,
visibility 0s linear 0s;
position: relative;
visibility: visible;
// 自定义滚动条样式
&::-webkit-scrollbar {
width: 6px; // 滚动条宽度
height: 6px; // 滚动条高度(对于横向滚动条)
}
&::-webkit-scrollbar-thumb {
background: var(--secondary); // 滚动条滑块颜色
border-radius: 3px; // 圆角滑块
}
&::-webkit-scrollbar-thumb:hover {
background: var(--tertiary); // 滑块悬停时颜色
}
&::-webkit-scrollbar-track {
background: var(--light); // 滚动条轨道颜色
border-radius: 3px; // 圆角轨道
}
&.collapsed {
max-height: 0;
transition:
max-height 0.35s ease,
visibility 0s linear 0.35s;
visibility: hidden;
}
&.collapsed > .overflow::after {
opacity: 0;
}
& ul {
list-style: none;
margin: 0.5rem 0;
padding: 0;
& > li > a {
color: var(--dark);
//opacity: 0.35;
transition:
0.5s ease opacity,
0.3s ease color;
&.in-view {
opacity: 0.75;
}
}
}
> ul.overflow {
max-height: none;
width: 100%;
}
@for $i from 0 through 6 {
& .depth-#{$i} {
padding-left: calc(1rem * #{$i});
}
}
}
f.目录
a.quartz/components/Explorer.tsx,99行
前
<h2>{opts.title ?? i18n(cfg.locale).components.explorer.title}</h2>
-------------------------------------------------------------------------------------------------
后
<h2>目录</h2>
b.quartz/components/styles/explorer.scss,67行
前
//#explorer-content {
// list-style: none;
// overflow: hidden;
// overflow-y: auto;
// max-height: 100%;
// transition:
// max-height 0.35s ease,
// visibility 0s linear 0s;
// margin-top: 0.5rem;
// visibility: visible;
//
// &.collapsed {
// max-height: 0;
// transition:
// max-height 0.35s ease,
// visibility 0s linear 0.35s;
// visibility: hidden;
// }
//
// & ul {
// list-style: none;
// margin: 0.08rem 0;
// padding: 0;
// transition:
// max-height 0.35s ease,
// transform 0.35s ease,
// opacity 0.2s ease;
// & li > a {
// color: var(--dark);
// opacity: 0.75;
// pointer-events: all;
// }
// }
// > #explorer-ul {
// max-height: none;
// }
//}
---------------------------------------------------------------------------------------------
后
#explorer-content {
list-style: none;
overflow: hidden;
overflow-y: auto;
max-height: 100%;
transition:
max-height 0.35s ease,
visibility 0s linear 0s;
margin-top: 0.5rem;
visibility: visible;
/* 自定义滚动条样式 */
&::-webkit-scrollbar {
width: 6px; /* 滚动条宽度 */
height: 6px; /* 滚动条高度(对于横向滚动条) */
}
&::-webkit-scrollbar-thumb {
background: var(--secondary); /* 滚动条滑块颜色 */
border-radius: 3px; /* 圆角滑块 */
}
&::-webkit-scrollbar-thumb:hover {
background: var(--tertiary); /* 滑块悬停时颜色 */
}
&::-webkit-scrollbar-track {
background: var(--light); /* 滚动条轨道颜色 */
border-radius: 3px; /* 圆角轨道 */
}
&.collapsed {
max-height: 0;
transition:
max-height 0.35s ease,
visibility 0s linear 0.35s;
visibility: hidden;
}
& ul {
list-style: none;
margin: 0.08rem 0;
padding: 0;
transition:
max-height 0.35s ease,
transform 0.35s ease,
opacity 0.2s ease;
& li > a {
color: var(--dark);
opacity: 0.75;
pointer-events: all;
}
}
> #explorer-ul {
max-height: none;
}
/* 深度缩进 */
@for $i from 0 through 6 {
& .depth-#{$i} {
padding-left: calc(1rem * #{$i});
}
}
}
g.关于我
a.quartz/components/About.tsx
// @ts-ignore: this is safe, we don't want to actually make darkmode.inline.ts a module as
// modules are automatically deferred and we don't want that to happen for critical beforeDOMLoads
// see: https://v8.dev/features/modules#defer
import darkmodeScript from "./scripts/darkmode.inline"
import styles from "./styles/about.scss"
import {QuartzComponent, QuartzComponentConstructor, QuartzComponentProps} from "./types"
import {i18n} from "../i18n"
import {classNames} from "../util/lang"
const About: QuartzComponent = ({displayClass, cfg}: QuartzComponentProps) => {
return (
<div className={classNames(displayClass, "about")}>
<div className="link-container">
<ul>
<li>
<a href="https://github.com/halavah" target="_blank">
<svg t="1734574903988" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1446" width="25" height="25">
<path d="M498.894518 100.608396c-211.824383 0-409.482115 189.041494-409.482115 422.192601 0 186.567139 127.312594 344.783581 295.065226 400.602887 21.13025 3.916193 32.039717-9.17701 32.039717-20.307512 0-10.101055 1.176802-43.343157 1.019213-78.596056-117.448946 25.564235-141.394311-49.835012-141.394311-49.835012-19.225877-48.805566-46.503127-61.793368-46.503127-61.793368-38.293141-26.233478 3.13848-25.611308 3.13848-25.611308 42.361807 2.933819 64.779376 43.443441 64.779376 43.443441 37.669948 64.574714 98.842169 45.865607 122.912377 35.094286 3.815909-27.262924 14.764262-45.918819 26.823925-56.431244-93.796246-10.665921-192.323237-46.90017-192.323237-208.673623 0-46.071292 16.498766-83.747379 43.449581-113.332185-4.379751-10.665921-18.805298-53.544497 4.076852-111.732757 0 0 35.46063-11.336186 116.16265 43.296085 33.653471-9.330506 69.783343-14.022365 105.654318-14.174837 35.869952 0.153496 72.046896 4.844332 105.753579 14.174837 80.606853-54.631248 116.00813-43.296085 116.00813-43.296085 22.935362 58.18826 8.559956 101.120049 4.180206 111.732757 27.052123 29.584806 43.443441 67.260893 43.443441 113.332185 0 162.137751-98.798167 197.850114-192.799074 208.262254 15.151072 13.088086 28.65155 38.804794 28.65155 78.17957 0 56.484456-0.459464 101.94381-0.459464 115.854635 0 11.235902 7.573489 24.381293 29.014824 20.2543C825.753867 867.330798 933.822165 709.10924 933.822165 522.700713c0-233.155201-224.12657-422.192601-434.927647-422.192601L498.894518 100.608396z" fill="#3F3F3F" p-id="1447"></path>
</svg>
<span style="position: relative; top: -5px;">GitHub</span>
</a>
</li>
<li>
<a href="https://space.bilibili.com/71393128/" target="_blank">
<svg t="1734575058981" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2445" width="25" height="25">
<path
d="M777.514667 131.669333a53.333333 53.333333 0 0 1 0 75.434667L728.746667 255.829333h49.92A160 160 0 0 1 938.666667 415.872v320a160 160 0 0 1-160 160H245.333333A160 160 0 0 1 85.333333 735.872v-320a160 160 0 0 1 160-160h49.749334L246.4 207.146667a53.333333 53.333333 0 0 1 75.392-75.434667l113.152 113.152c3.370667 3.370667 6.186667 7.04 8.448 10.965333h137.088c2.261333-3.925333 5.12-7.68 8.490667-11.008l113.109333-113.152a53.333333 53.333333 0 0 1 75.434667 0z m1.152 231.253334H245.333333a53.333333 53.333333 0 0 0-53.205333 49.365333l-0.128 4.010667v320c0 28.117333 21.76 51.114667 49.365333 53.162666l3.968 0.170667h533.333334a53.333333 53.333333 0 0 0 53.205333-49.365333l0.128-3.968v-320c0-29.44-23.893333-53.333333-53.333333-53.333334z m-426.666667 106.666666c29.44 0 53.333333 23.893333 53.333333 53.333334v53.333333a53.333333 53.333333 0 1 1-106.666666 0v-53.333333c0-29.44 23.893333-53.333333 53.333333-53.333334z m320 0c29.44 0 53.333333 23.893333 53.333333 53.333334v53.333333a53.333333 53.333333 0 1 1-106.666666 0v-53.333333c0-29.44 23.893333-53.333333 53.333333-53.333334z"
p-id="2446"></path>
</svg>
<span style="position: relative; top: -5px;">BiliBili</span>
</a>
</li>
</ul>
</div>
<div className="home-container">
<div className="about-container">
<a href="/">
<svg t="1734575352208" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3589" width="25" height="25">
<path
d="M452.266667 119.466667a99.555556 99.555556 0 0 1 119.466666 0l284.444445 213.333333c25.031111 18.773333 39.822222 48.355556 39.822222 79.644444v426.666667A99.555556 99.555556 0 0 1 796.444444 938.666667H227.555556a99.555556 99.555556 0 0 1-99.555556-99.555556v-426.666667c0-31.288889 14.791111-60.871111 39.822222-79.644444l284.444445-213.333333z m68.266666 68.266666a14.222222 14.222222 0 0 0-17.066666 0l-284.444445 213.333334a14.222222 14.222222 0 0 0-5.688889 11.377777v426.666667c0 7.850667 6.371556 14.222222 14.222223 14.222222h568.888888a14.222222 14.222222 0 0 0 14.222223-14.222222v-426.666667a14.222222 14.222222 0 0 0-5.688889-11.377777l-284.444445-213.333334z"
p-id="3590"></path>
<path d="M455.111111 668.444444a14.222222 14.222222 0 0 0-14.222222 14.222223v227.555555h-85.333333v-227.555555c0-54.954667 44.600889-99.555556 99.555555-99.555556h113.777778c54.954667 0 99.555556 44.600889 99.555555 99.555556v227.555555h-85.333333v-227.555555a14.222222 14.222222 0 0 0-14.222222-14.222223H455.111111z" p-id="3591"></path>
</svg>
<span style="position: relative; top: -5px;">Index</span>
</a>
</div>
<button class="changemode" id="changemode">
<svg
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
version="1.1"
id="dayIcon"
x="0px"
y="0px"
viewBox="0 0 35 35"
style="enable-background:new 0 0 35 35"
xmlSpace="preserve"
aria-label={i18n(cfg.locale).components.themeToggle.darkMode}
>
<title>{i18n(cfg.locale).components.themeToggle.darkMode}明/暗</title>
<path
d="M6,17.5C6,16.672,5.328,16,4.5,16h-3C0.672,16,0,16.672,0,17.5 S0.672,19,1.5,19h3C5.328,19,6,18.328,6,17.5z M7.5,26c-0.414,0-0.789,0.168-1.061,0.439l-2,2C4.168,28.711,4,29.086,4,29.5 C4,30.328,4.671,31,5.5,31c0.414,0,0.789-0.168,1.06-0.44l2-2C8.832,28.289,9,27.914,9,27.5C9,26.672,8.329,26,7.5,26z M17.5,6 C18.329,6,19,5.328,19,4.5v-3C19,0.672,18.329,0,17.5,0S16,0.672,16,1.5v3C16,5.328,16.671,6,17.5,6z M27.5,9 c0.414,0,0.789-0.168,1.06-0.439l2-2C30.832,6.289,31,5.914,31,5.5C31,4.672,30.329,4,29.5,4c-0.414,0-0.789,0.168-1.061,0.44 l-2,2C26.168,6.711,26,7.086,26,7.5C26,8.328,26.671,9,27.5,9z M6.439,8.561C6.711,8.832,7.086,9,7.5,9C8.328,9,9,8.328,9,7.5 c0-0.414-0.168-0.789-0.439-1.061l-2-2C6.289,4.168,5.914,4,5.5,4C4.672,4,4,4.672,4,5.5c0,0.414,0.168,0.789,0.439,1.06 L6.439,8.561z M33.5,16h-3c-0.828,0-1.5,0.672-1.5,1.5s0.672,1.5,1.5,1.5h3c0.828,0,1.5-0.672,1.5-1.5S34.328,16,33.5,16z M28.561,26.439C28.289,26.168,27.914,26,27.5,26c-0.828,0-1.5,0.672-1.5,1.5c0,0.414,0.168,0.789,0.439,1.06l2,2 C28.711,30.832,29.086,31,29.5,31c0.828,0,1.5-0.672,1.5-1.5c0-0.414-0.168-0.789-0.439-1.061L28.561,26.439z M17.5,29 c-0.829,0-1.5,0.672-1.5,1.5v3c0,0.828,0.671,1.5,1.5,1.5s1.5-0.672,1.5-1.5v-3C19,29.672,18.329,29,17.5,29z M17.5,7 C11.71,7,7,11.71,7,17.5S11.71,28,17.5,28S28,23.29,28,17.5S23.29,7,17.5,7z M17.5,25c-4.136,0-7.5-3.364-7.5-7.5 c0-4.136,3.364-7.5,7.5-7.5c4.136,0,7.5,3.364,7.5,7.5C25,21.636,21.636,25,17.5,25z"></path>
</svg>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
version="1.1"
id="nightIcon"
x="0px"
y="0px"
viewBox="0 0 100 100"
style="enable-background:new 0 0 100 100"
xmlSpace="preserve"
aria-label={i18n(cfg.locale).components.themeToggle.lightMode}
>
<title>{i18n(cfg.locale).components.themeToggle.lightMode}</title>
<path
d="M96.76,66.458c-0.853-0.852-2.15-1.064-3.23-0.534c-6.063,2.991-12.858,4.571-19.655,4.571 C62.022,70.495,50.88,65.88,42.5,57.5C29.043,44.043,25.658,23.536,34.076,6.47c0.532-1.08,0.318-2.379-0.534-3.23 c-0.851-0.852-2.15-1.064-3.23-0.534c-4.918,2.427-9.375,5.619-13.246,9.491c-9.447,9.447-14.65,22.008-14.65,35.369 c0,13.36,5.203,25.921,14.65,35.368s22.008,14.65,35.368,14.65c13.361,0,25.921-5.203,35.369-14.65 c3.872-3.871,7.064-8.328,9.491-13.246C97.826,68.608,97.611,67.309,96.76,66.458z"></path>
</svg>
<div className="text-container">
<a>Light/Dark</a>
</div>
</button>
</div>
</div>
)
}
About.beforeDOMLoaded = darkmodeScript
About.css = styles
export default (() => About) satisfies QuartzComponentConstructor
b.quartz/components/styles/about.scss
// div
.about {
position: absolute;
bottom: 0.8rem;
left: 0;
right: 0;
}
// link
.link-container {
text-align: left;
opacity: 0.7;
margin-bottom: 0.6rem;
ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: row;
gap: 1rem;
margin-top: -1rem;
li a {
text-decoration: none;
color: #4584a5;
&:hover {
opacity: 0.7;
}
}
}
}
// home
.home-container {
display: flex;
align-items: center;
justify-content: flex-start;
}
// about
.about-container {
margin-bottom: 2px;
margin-right: 25px;
a {
text-decoration: none;
color: #7B97AA;
&:hover {
opacity: 0.7;
}
}
}
// changemode
.changemode {
cursor: pointer;
padding: 0;
position: relative;
background: none;
border: none;
width: 100px;
height: 30px;
margin-left: 2px;
margin-top: -6px;
text-align: inherit;
display: flex;
align-items: center; /* 垂直居中对齐 */
justify-content: flex-start; /* 水平左对齐,也可以根据需求调整 */
& svg {
position: absolute;
width: 20px;
height: 20px;
top: calc(50% - 10px);
fill: var(--darkgray);
transition: opacity 0.1s ease;
}
}
:root[saved-theme="dark"] {
color-scheme: dark;
}
:root[saved-theme="light"] {
color-scheme: light;
}
:root[saved-theme="dark"] .changemode {
& > #dayIcon {
display: none;
}
& > #nightIcon {
display: inline;
}
}
:root .changemode {
& > #dayIcon {
display: inline;
}
& > #nightIcon {
display: none;
}
}
// text
.text-container {
margin-bottom: -5px;
margin-left: 22px;
a {
font-size: 14px;
color: #7B97AA;
&:hover {
opacity: 0.7;
}
}
}
c.quartz/components/scripts/darkmode.inline.ts
const userPref = window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark"
const currentTheme = localStorage.getItem("theme") ?? userPref
document.documentElement.setAttribute("saved-theme", currentTheme)
const emitThemeChangeEvent = (theme: "light" | "dark") => {
const event: CustomEventMap["themechange"] = new CustomEvent("themechange", {
detail: { theme },
})
document.dispatchEvent(event)
}
document.addEventListener("nav", () => {
const switchTheme = (e: Event) => {
const newTheme =
document.documentElement.getAttribute("saved-theme") === "dark" ? "light" : "dark"
document.documentElement.setAttribute("saved-theme", newTheme)
localStorage.setItem("theme", newTheme)
emitThemeChangeEvent(newTheme)
}
const themeChange = (e: MediaQueryListEvent) => {
const newTheme = e.matches ? "dark" : "light"
document.documentElement.setAttribute("saved-theme", newTheme)
localStorage.setItem("theme", newTheme)
emitThemeChangeEvent(newTheme)
}
// Darkmode toggle
const themeButton = document.querySelector("#darkmode") as HTMLButtonElement
themeButton.addEventListener("click", switchTheme)
window.addCleanup(() => themeButton.removeEventListener("click", switchTheme))
// Changemode toggle
const themeButton2 = document.querySelector("#changemode") as HTMLButtonElement
themeButton2.addEventListener("click", switchTheme)
window.addCleanup(() => themeButton2.removeEventListener("click", switchTheme))
// Listen for changes in prefers-color-scheme
const colorSchemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)")
colorSchemeMediaQuery.addEventListener("change", themeChange)
window.addCleanup(() => colorSchemeMediaQuery.removeEventListener("change", themeChange))
})
h.备案
a.quartz/components/Footer.tsx
import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types"
import style from "./styles/footer.scss"
import { version } from "../../package.json"
import { i18n } from "../i18n"
interface Options {
links: Record<string, string>
}
export default ((opts?: Options) => {
const Footer: QuartzComponent = ({ displayClass, cfg }: QuartzComponentProps) => {
const year = new Date().getFullYear()
const links = opts?.links ?? []
return (
<footer class={`${displayClass ?? ""}`}>
<p>
{i18n(cfg.locale).components.footer.createdWith}{" "}
<a href="https://github.com/halavah">halavah</a> © {year}
</p>
<p>
苏ICP备19059396号-1
</p>
<ul>
{Object.entries(links).map(([text, link]) => (
<li>
<a href={link}>{text}</a>
</li>
))}
</ul>
</footer>
)
}
Footer.css = style
return Footer
}) satisfies QuartzComponentConstructor
b.quartz/components/styles/footer.scss
footer {
text-align: left;
margin-bottom: 1rem;
opacity: 0.7;
& ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: row;
gap: 1rem;
margin-top: -1rem;
}
}
03.启动锁【v1,代码不小心已丢弃】【最简单版本】【123456出现在html】
a.提问
你思考的方向有问题,目前 http://localhost:8080/verify 访问 还是处于 verify.md文件,而且是 内嵌在博客 布局(左边 explorer、右边大纲)里面,虽然verify.html存在,但并不是 @Verify.tsx 定义的 html。
重新思考你的修改方向,然后把多种思路汇报给我。不要生成任何代码
再对 你目前 对项目 所有改动的地方,对 verify 功能 进行检查
你对之前的全部提问,去真正理解我想干什么
先慢修改任何文件,你确定你写的 verifyPage.ts 最终可以生成我想要的 verify.html 页面,然后 http://localhost:8080/verify 可以路由到这个 验证页面吗
现在功能是可以使用的。针对 启动保护页面 功能,现在对你 项目修改的全部文件 进行检查,将不属于这个功能的 冗余代码、文件 进行删除
现在功能是可以使用的。再对 你目前 对项目 所有改动的地方,进行汇报
现在密码是123456,帮我创建100个随机密码,放到页面中。密码长度为10,允许强密码
-----------------------------------------------------------------------------------------------------
布局替换方向:
问题:当前的布局系统是基于 markdown 内容的,即使修改了 layout,仍然会套用基础布局
思路:需要在更底层处理布局,而不是仅仅修改 layout 配置
路由拦截方向:
问题:现在的路由处理是先找到 markdown 文件,然后应用布局
思路:在路由层面拦截 /verify 请求,直接返回 Verify 组件渲染的内容,绕过 markdown 处理流程
组件渲染方向:
问题:Verify.tsx 组件没有被正确地作为独立页面处理
思路:创建一个专门的页面渲染器,用于处理特殊路由的组件渲染
构建流程方向:
问题:构建过程将所有 markdown 文件视为相同类型的内容
思路:在构建时区分特殊页面,使用不同的构建流程
插件系统方向:
问题:当前的插件系统主要处理 markdown 内容
思路:创建新的插件类型,专门处理特殊页面的渲染
-----------------------------------------------------------------------------------------------------
verifyPage.ts分析:
优点:
完全独立的页面
不依赖博客布局
包含所有必要的样式和脚本
符合路由拦截的思路
b.方案2:路由拦截方向
1.访问任意页面
↓
2.Content.tsx 检查验证状态
↓
3.未验证则重定向到 /verify
↓
4.handlers.js 拦截 /verify 请求
↓
5.返回 verifyPage.ts 生成的页面
↓
6.用户输入密码 (123456)
↓
7.验证成功后重定向回原页面
c.quartz/cli/handlers.js - 路由处理改动
// 添加了验证页面路由处理
if (fp === "/verify") {
try {
const { generateVerifyPage } = await import("../../quartz/.quartz-cache/verify-page.js")
res.writeHead(200, { "Content-Type": "text/html" })
res.end(generateVerifyPage())
return
} catch (err) {
console.error("Error serving verify page:", err)
res.writeHead(500)
res.end("Internal Server Error")
return
}
}
d.quartz/build.ts - 构建配置改动
// 添加了 buildVerifyPage 函数
async function buildVerifyPage() {
try {
await esbuild.build({
entryPoints: ['./quartz/util/verifyPage.ts'],
outfile: './quartz/.quartz-cache/verify-page.js',
bundle: true,
format: 'esm',
platform: 'node',
})
console.log('Verify page built successfully')
} catch (err) {
console.error('Error building verify page:', err)
}
}
// 在 buildQuartz 函数中添加了构建验证页面的调用
await buildVerifyPage()
e.quartz/components/pages/Content.tsx - 添加验证脚本
// 添加了验证检查脚本
const verifyScript = `
if(!sessionStorage.getItem('verified')) {
const currentPath = window.location.pathname
if(currentPath !== '/verify') {
sessionStorage.setItem('intendedPath', currentPath)
window.location.href = '/verify'
}
}
`
Content.beforeDOMLoaded = verifyScript
f.新增文件 quartz/util/verifyPage.ts:
export function generateVerifyPage(): string {
const backgroundImages = [
"/static/screen/01.jpg",
"/static/screen/02.jpg",
"/static/screen/03.jpg",
"/static/screen/04.jpg",
"/static/screen/05.jpg",
"/static/screen/06.jpg",
"/static/screen/07.jpg",
]
const randomBackground = backgroundImages[Math.floor(Math.random() * backgroundImages.length)]
const verifyStyles = `
:root {
--primary: #4a90e2;
--secondary: #f5a623;
--background: rgba(240, 244, 248, 0.8);
--text: #333;
--error: #e74c3c;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: var(--text);
line-height: 1.6;
overflow: hidden;
}
.background-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('${randomBackground}');
background-size: cover;
background-position: center;
transform: scale(1.1);
z-index: -1;
}
.verify-page {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
perspective: 1000px;
}
.verify-container {
background-color: var(--background);
padding: clamp(20px, 5vw, 40px);
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
text-align: center;
max-width: min(90vw, 350px);
width: 100%;
backdrop-filter: blur(1px);
transform-style: preserve-3d;
animation: container-entrance 0.6s ease-out;
margin: 0 auto;
}
@keyframes container-entrance {
from {
opacity: 0;
transform: translateY(-50px) rotateX(10deg);
}
to {
opacity: 1;
transform: translateY(0) rotateX(0);
}
}
.lock-icon {
width: clamp(40px, 8vw, 50px);
height: clamp(40px, 8vw, 50px);
margin: 0 auto 15px;
color: var(--primary);
animation: icon-bounce 0.5s ease-out 0.3s both;
}
@keyframes icon-bounce {
0% {
transform: scale(0);
}
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
h1 {
color: var(--primary);
margin-bottom: 8px;
font-size: clamp(20px, 4vw, 24px);
animation: text-fade-in 0.5s ease-out 0.5s both;
}
p {
color: #666;
margin-bottom: 15px;
font-size: clamp(12px, 3vw, 14px);
animation: text-fade-in 0.5s ease-out 0.7s both;
}
@keyframes text-fade-in {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.input-group {
position: relative;
margin-bottom: 15px;
animation: input-fade-in 0.5s ease-out 0.9s both;
}
@keyframes input-fade-in {
from {
opacity: 0;
transform: translateX(-10px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
input {
width: 100%;
padding: clamp(8px, 2vw, 10px);
border: 2px solid #ddd;
border-radius: 4px;
font-size: clamp(14px, 3vw, 16px);
transition: border-color 0.3s, box-shadow 0.3s;
}
input:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.1);
}
label {
position: absolute;
left: 10px;
top: 50%;
transform: translateY(-50%);
color: #999;
pointer-events: none;
transition: 0.3s ease all;
font-size: clamp(12px, 2.5vw, 14px);
}
input:focus ~ label,
input:not(:placeholder-shown) ~ label {
top: 0;
font-size: 12px;
color: var(--primary);
background-color: white;
padding: 0 5px;
}
button {
background-color: var(--primary);
color: white;
border: none;
padding: clamp(8px, 2vw, 12px) clamp(15px, 4vw, 20px);
border-radius: 4px;
font-size: clamp(14px, 3vw, 16px);
cursor: pointer;
transition: background-color 0.3s, transform 0.3s;
width: 100%;
animation: button-fade-in 0.5s ease-out 1.1s both;
}
@keyframes button-fade-in {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
button:hover {
background-color: #3a7bc8;
transform: translateY(-2px);
}
button:active {
transform: translateY(0);
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
20%, 40%, 60%, 80% { transform: translateX(5px); }
}
.error {
border-color: var(--error) !important;
animation: shake 0.5s;
}
.error-message {
color: var(--error);
font-size: 14px;
margin-top: 5px;
display: none;
animation: error-fade-in 0.3s ease-out;
}
@keyframes error-fade-in {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@media (max-width: 480px) {
.verify-page {
padding: 10px;
}
.verify-container {
padding: 20px;
}
.background-container {
transform: scale(1.05);
}
}
`
const verifyScript = `
window.addEventListener('DOMContentLoaded', () => {
const form = document.getElementById('verify-form');
const passwordInput = document.getElementById('verify-password');
const verifyContainer = document.querySelector('.verify-container');
// 400个随机强密码
const validPasswords = [
"123456",
];
if (!sessionStorage.getItem('verified')) {
if (window.location.pathname !== '/verify') {
window.location.href = '/verify';
}
}
form?.addEventListener('submit', (e) => {
e.preventDefault();
const password = passwordInput.value;
if (validPasswords.includes(password)) {
sessionStorage.setItem('verified', 'true');
const intendedPath = sessionStorage.getItem('intendedPath') || '/';
window.location.href = intendedPath;
} else {
passwordInput.classList.add('error');
const errorMessage = document.createElement('div');
errorMessage.className = 'error-message';
errorMessage.textContent = 'Incorrect password. Please try again.';
form.appendChild(errorMessage);
errorMessage.style.display = 'block';
setTimeout(() => {
passwordInput.classList.remove('error');
errorMessage.style.display = 'none';
}, 3000);
}
});
passwordInput?.addEventListener('input', () => {
passwordInput.classList.remove('error');
const errorMessage = form.querySelector('.error-message');
if (errorMessage) {
errorMessage.style.display = 'none';
}
});
// Mouse movement effect
document.addEventListener('mousemove', (e) => {
const { clientX, clientY } = e;
const centerX = window.innerWidth / 2;
const centerY = window.innerHeight / 2;
const moveX = (clientX - centerX) / centerX;
const moveY = (clientY - centerY) / centerY;
verifyContainer.style.transform = \`
perspective(1000px)
rotateY(\${moveX * 5}deg)
rotateX(\${-moveY * 5}deg)
translateZ(10px)
\`;
});
});
`
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Verify Page</title>
<style>
${verifyStyles}
</style>
</head>
<body>
<div class="background-container">
<div class="verify-page">
<div class="verify-container">
<div class="lock-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
</svg>
</div>
<h1>Welcome</h1>
<p>Life drifts untethered, fleeting as a dream.</p>
<form id="verify-form">
<div class="input-group">
<input type="password" id="verify-password" autofocus required>
<label for="verify-password">Password</label>
</div>
<button type="submit">Verify</button>
</form>
</div>
</div>
</div>
<script>
${verifyScript}
</script>
</body>
</html>
`.trim()
}
04.启动锁【v3_仅适配域名_如vercel_不可逆加密】
a.思路
1.访问任意页面
↓
2.Content.tsx 检查验证状态
↓
3.未验证则重定向到 /verify
↓
4.handlers.js 拦截 /verify 请求
↓
5.返回 verifyPage.ts 生成的页面,verify.html
↓
6.用户输入密码 (123456)
↓
7.验证成功后重定向回原页面
b.方案
Token 基于时间验证
不直接存储 verified: true,而是存储一个基于密码和时间生成的token
验证时同时验证token的有效性和时间戳
缺点:仍然可以被复制token绕过,但增加了难度
-----------------------------------------------------------------------------------------------------
多层验证令牌
将验证状态分成多个部分存储
每个部分都是通过密码+随机盐值生成的hash
需要所有部分都验证通过才能访问
缺点:技术人员仍可以通过分析代码找到生成规则
-----------------------------------------------------------------------------------------------------
动态验证码
基于密码和时间戳动态生成验证码
定期检查验证码是否有效
如果验证码过期需要重新验证
缺点:增加了复杂度,可能影响用户体验
-----------------------------------------------------------------------------------------------------
浏览器指纹 + 验证信息绑定
将验证信息与浏览器指纹绑定
即使复制storage也无法在其他浏览器使用
缺点:指纹可能变化,导致误判
-----------------------------------------------------------------------------------------------------
混淆与加密存储
不直接存储验证状态
将验证信息加密后分散存储在不同位置
使用复杂的验证逻辑
缺点:增加代码复杂度,仍可被破解
-----------------------------------------------------------------------------------------------------
需要注意的是,纯前端的安全方案都存在被破解的可能性,因为所有代码都在客户端。如果需要更高的安全性,建议:
考虑使用后端验证
使用 HTTPS 确保传输安全
实现访问频率限制
-----------------------------------------------------------------------------------------------------
考虑添加其他验证方式(如邮箱验证码)
c.采用
根据您的项目结构和需求,我建议采用"Token 基于时间验证"和"混淆与加密存储"的组合方案,因为:
实现相对简单
不需要额外的后端支持
可以在现有代码基础上扩展
性能影响较小
提供足够的安全性
比单纯的 sessionStorage.setItem('verified', 'true') 更安全
增加破解难度
可以设置token过期时间
-----------------------------------------------------------------------------------------------------
验证成功后:
// 不要直接存储 verified: true
// 而是生成一个包含以下信息的token:
- 时间戳
- 密码的hash值
- 随机盐值
存储方式:
// 将验证信息分散存储
- localStorage 存储一部分
- sessionStorage 存储另一部分
- cookie 存储第三部分
验证逻辑:
// 定期检查:
- token是否完整
- 时间戳是否有效
- hash值是否匹配
-----------------------------------------------------------------------------------------------------
这样即使有人知道需要设置storage,也很难知道:
具体需要设置什么值
值是如何生成的
需要在哪些地方设置
d.实现
验证流程:
Content.tsx 中的 verifyScript 在每个页面加载时检查 sessionStorage.getItem('verified')
未验证时保存当前路径到 intendedPath 并重定向到 /verify
handlers.js 处理 /verify 路由,返回验证页面
-----------------------------------------------------------------------------------------------------
关键问题:
目前的验证状态只依赖 sessionStorage.setItem('verified', 'true')
这个状态很容易被手动设置绕过验证
-----------------------------------------------------------------------------------------------------
改进思路:
// 验证成功时:
const generateToken = (password: string) => {
const timestamp = Date.now()
const salt = crypto.randomBytes(16).toString('hex')
// 1. 生成一个包含密码hash、时间戳和salt的token
const rawToken = `${hash(password)}:${timestamp}:${salt}`
// 2. 对token进行加密
const encryptedToken = encrypt(rawToken)
// 3. 分散存储token的不同部分
const [part1, part2, part3] = splitToken(encryptedToken)
sessionStorage.setItem('v_p1', part1)
localStorage.setItem('v_p2', part2)
document.cookie = `v_p3=${part3}`
return true
}
// 验证检查时:
const checkVerification = () => {
try {
// 1. 收集所有部分
const part1 = sessionStorage.getItem('v_p1')
const part2 = localStorage.getItem('v_p2')
const part3 = getCookie('v_p3')
// 2. 重组并解密token
const token = decrypt(joinToken(part1, part2, part3))
// 3. 验证时间戳是否在有效期内
const [hash, timestamp, salt] = token.split(':')
if (Date.now() - parseInt(timestamp) > TOKEN_EXPIRE_TIME) {
return false
}
// 4. 验证hash是否正确
return verifyHash(hash)
} catch {
return false
}
}
-----------------------------------------------------------------------------------------------------
不能简单通过设置 storage 绕过
token 有时效性
验证信息分散存储
即使找到存储位置也很难伪造正确的token
e.BUG:闪一下
不要生成任何代码,为什么 访问 @http://127.0.0.1:8080 会闪一下,然后才跳转 @http://127.0.0.1:8080/verify
-----------------------------------------------------------------------------------------------------
将验证脚本移到 <head> 标签中
使用 defer 或 async 属性
在 DOMContentLoaded 之前执行验证
f.混淆加密(可逆向)
当前的加密数据和盐值都是明文存储的
可以将数据分散存储并引入干扰数据
实现相对简单,不会增加太多复杂度
-----------------------------------------------------------------------------------------------------
将加密数据分散存储在多个变量或对象中
使用字符串编码转换(如Base64、Unicode转换等)
引入干扰数据,真实数据藏在其中
使用多层加密,每层使用不同的算法
-----------------------------------------------------------------------------------------------------
当前的问题
const AUTH = {
SALT: "x9f#k2p$m5",
DATA: "HFUMVxJWH1MDBAABWBlGA0sSUARNFRISWBlGA0sSUAQ="
}
盐值直接明文存储
加密数据使用单一Base64编码
数据结构过于简单直观
-----------------------------------------------------------------------------------------------------
改进思路
A.数据分散存储:
将SALT拆分成多段,分散在不同变量中
使用动态计算组合真实盐值
加入虚假的盐值干扰项
B.多重编码:
Base64 -> Unicode -> Hex 多层转换
字符串反转或位移
添加动态位移量
C.干扰数据:
在加密数据中插入随机干扰字符
使用特定规则来提取真实数据
构建虚假的验证路径
D.数据存储结构:
使用嵌套对象
引入无关的配置数据
使用动态计算的属性名
g.简单加密(可逆向)
a.思路
1.后端验证方案
这是最推荐的方案,将密码验证逻辑完全移到后端:
前端只发送密码到后端API
后端进行验证并返回token
使用session或JWT来保持登录状态
2.密码加密方案
如果必须在前端做验证,可以:
存储密码的哈希值而不是明文
对用户输入进行相同的哈希处理后比较
使用加盐哈希增加安全性
3.混淆加密方案
通过代码混淆和加密来增加破解难度:
使用JavaScript混淆器处理代码
将密码列表进行加密存储
运行时动态解密
b.采用【混淆加密方案】,加密过程是:
每个密码先填充到32字符长度
使用XOR(异或)运算加密每个字符:
密码字符 XOR 密钥字符
密钥是 salt("x9f#k2p$m5") + 当天日期
将所有加密后的字符串拼接
最后用base64编码整个结果
c.解密方法
function encryptPasswords(passwords: string[], salt: string): string {
const key = salt + new Date().getUTCDate()
const data = passwords
.map((pwd) => {
return pwd
.padEnd(32, " ")
.split("")
.map((char, index) => {
return String.fromCharCode(char.charCodeAt(0) ^ key.charCodeAt(index % key.length))
})
.join("")
})
.join("")
return btoa(data)
}
h.只能正向加密(采用)
生成的密码 只能是正向的,不能是逆向的。
而验证时,只能根据输入的密码来正向,最后比较2个最终的结果(比较方式,经过加密)
05.启动锁【废弃】,自动适配【域名】【域名/仓库】
a.提问
让我重新梳理思路:
当前问题:
访问根路径时出现 302 重定向
验证成功后无法正确跳转回原始路径
路径处理在不同环境下不一致
可能的解决思路:
思路A - 纯前端处理:
在 Content.tsx 中检测未验证状态
保存当前路径到 sessionStorage
重定向到验证页面
验证成功后从 sessionStorage 读取路径并跳转
思路B - 服务端重定向:
在 handlers.js 中拦截所有请求
未验证时重定向到验证页面
通过 URL 参数传递原始路径
验证成功后从 URL 参数获取跳转路径
思路C - 混合处理:
服务端处理根路径访问的重定向
前端处理其他页面的验证检查
统一使用 sessionStorage 存储路径
验证页面同时支持 URL 参数和 sessionStorage
各思路的优缺点:
思路A:
优点:实现简单,完全前端控制
缺点:可能出现闪烁,安全性较低
思路B:
优点:更安全,体验更流畅
缺点:实现复杂,需要处理多种路径情况
思路C:
优点:兼顾安全性和用户体验
缺点:逻辑分散,需要同步前后端状态
你觉得哪个思路更适合?我可以详细展开任何一个思路。
-----------------------------------------------------------------------------------------------------
问题所在:
sessionStorage 是前端存储
服务端(handlers.js)无法访问 sessionStorage
导致每次请求服务端都会认为是未验证状态
结果就是不断302重定向
验证流程:
用户访问 http://127.0.0.1:8080/
handlers.js 检查验证状态(但无法访问 sessionStorage)
重定向到 /verify?from=/
即使验证成功存储在 sessionStorage
下次请求时服务端仍然无法知道验证状态
继续重定向...形成循环
所以思路B不可行,应该回到思路A或C:
思路A(纯前端)更合理:
1. 所有验证逻辑在前端处理
Content.tsx 检查 sessionStorage
未验证则保存路径并重定向
4. 验证成功后直接从 sessionStorage 恢复路径
这样避免了服务端重定向的问题,你觉得呢?
-----------------------------------------------------------------------------------------------------
// 对于 https://halavah.github.io/valut/verify
// pathParts = ['valut', 'verify']
// lastPath = 'verify'
// repoPath = 'valut'
// finalBasePath = '/valut'
// 对于 https://valut.vercel.app/verify
// pathParts = ['verify']
// lastPath = 'verify'
// repoPath = ''
// finalBasePath = ''
const pathParts = window.location.pathname.split('/').filter(Boolean)
const lastPath = pathParts[pathParts.length - 1]
const isVerifyPage = lastPath === 'verify'
const repoPath = isVerifyPage && pathParts.length > 1 ? pathParts[pathParts.length - 2] : ''
const finalBasePath = repoPath ? '/' + repoPath : ''
访问 https://halavah.github.io/valut/ 跳转 https://halavah.github.io/valut/verify ,然后通过verify.html来验证
访问 https://halavah.github.io 跳转 https://halavah.github.io/verify ,然后通过verify.html来验证
访问 https://valut.vercel.app 跳转 https://valut.vercel.app/verify ,然后通过verify.html来验证
访问 http://127.0.0.1:8080 跳转 http://127.0.0.1:8080/verify ,然后通过verify.html来验证
b.实现
放弃
6.5 quartz2
01.使用
a.下载
npx shadcn@latest add "https://v0.dev/chat/b/b_4X2vSJZ3iRk"
b.安装
npm install
c.使用
npm run dev --开发环境:启动
-----------------------------------------------------------------------------------------------------
npm run build --生产环境:构建
npm run start --生产环境:启动
02.启动锁【Next.js后端服务】
a.需求
auth.ts 中需要移至后端的部分:
密码加密函数 _encrypt
密码哈希值 correctHashes
Token 生成逻辑 generateToken
Token 验证逻辑 verifyToken
-----------------------------------------------------------------------------------------------------
verifyPage.ts 中需要移至后端的部分:
验证页面生成函数 generateVerifyPage
页面模板可以转换为 Next.js 的页面组件
-----------------------------------------------------------------------------------------------------
Content.tsx 中需要移至后端的部分:
验证状态检查逻辑
b.认证相关 API
POST /api/auth/verify
- 功能:验证密码
- 输入:password
- 返回:token
GET /api/auth/check
- 功能:验证 token
- 输入:token (从 cookie)
- 返回:验证状态
POST /api/auth/logout
- 功能:登出
- 输入:token
- 返回:成功状态
c.页面路由
/verify
- 登录页面
- 使用 Next.js 页面组件
- 包含表单和样式
/api/protected/*
- 受保护的内容 API
- 需要验证 token
d.中间件
middleware.ts
- 路由保护
- token 验证
- 重定向逻辑
03.启动锁【Next.js后端服务】【思路1】
a.当前思路
用户访问 Quartz 页面
↓
Content.tsx 检查验证状态(调用 Next.js API)
↓
未验证则重定向到 Next.js 验证页面
↓
用户输入密码
↓
Next.js 后端验证
↓
验证成功返回 Quartz
b.创建 Next.js 验证服务
quartz-auth/ # Next.js 项目根目录
├── pages/
│ ├── api/ # API 路由
│ │ └── auth/ # 认证相关 API
│ │ ├── verify # 密码验证
│ │ ├── check # token 检查
│ │ └── logout # 登出
│ └── verify.tsx # 验证页面
└── middleware.ts # 路由中间件
c.修改现有 Quartz 代码
quartz-front/quartz/util/verifyPage.ts # 整个文件移除
quartz-front/public/verify.html # 由 Next.js 的 verify.tsx 替代
quartz-front/quartz/util/auth.ts # 移除,逻辑移至 Next.js
d.需要修改
quartz-front/quartz/components/pages/Content.tsx
# 修改验证逻辑,改为调用 Next.js API
e.数据和资源迁移
quartz-front/public/static/screen/* # 背景图片迁移到 Next.js
quartz-front/public/static/icon.png # 图标迁移到 Next.js
f.配置更新
设置 Next.js 服务的域名和端口
配置 CORS 策略
设置环境变量
g.部署流程
部署 Next.js 服务到 Vercel
更新 Quartz 配置指向新的验证服务
确保域名和 SSL 证书配置正确
04.启动锁【Next.js后端服务】【思路2】
a.当前思路
用户访问 Quartz 页面
↓
Content.tsx 检查验证状态(调用 Next.js API)
↓
未验证则重定向到 Next.js 验证页面
↓
用户输入密码
↓
Next.js 后端验证
↓
验证成功返回 Quartz
b.密码验证接口(同时会生成令牌)
curl --location 'http://localhost:3000/api/auth?action=verify' \
--header 'Content-Type: application/json' \
--data '{
"password": "123456"
}'
-----------------------------------------------------------------------------------------------------
成功响应示例:
{
"success": true,
"tokens": {
"session": "TUI5OEly", // 存储到 sessionStorage
"local": "MzNDU2Nz" // 存储到 localStorage
}
// cookie 部分会自动设置到浏览器(v_p3=g5MDphYm)
}
-----------------------------------------------------------------------------------------------------
前端调用示例:
async function verifyPassword(password: string) {
const response = await fetch('/api/auth?action=verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ password }),
credentials: 'include', // 重要:允许设置cookie
})
const data = await response.json()
if (data.success) {
// 存储令牌的两个部分
sessionStorage.setItem(AUTH_CONSTANTS.TOKEN_KEYS.SESSION, data.tokens.session)
localStorage.setItem(AUTH_CONSTANTS.TOKEN_KEYS.LOCAL, data.tokens.local)
// cookie部分已自动设置
return true
}
return false
}
c.令牌检查接口
curl --location 'http://localhost:3000/api/auth?action=check&session=TUI5OEly&local=MzNDU2Nz' \
--header 'Cookie: v_p3=g5MDphYm'
-----------------------------------------------------------------------------------------------------
响应示例:
{
"isAuthenticated": true
}
-----------------------------------------------------------------------------------------------------
前端调用示例:
async function checkAuth() {
const session = sessionStorage.getItem(AUTH_CONSTANTS.TOKEN_KEYS.SESSION)
const local = localStorage.getItem(AUTH_CONSTANTS.TOKEN_KEYS.LOCAL)
if (!session || !local) return false
const response = await fetch(
`/api/auth?action=check&session=${encodeURIComponent(session)}&local=${encodeURIComponent(local)}`,
{
credentials: 'include', // 重要:允许发送cookie
}
)
const data = await response.json()
return data.isAuthenticated
}
d.防止前端 JS 被篡改的几个思路:
服务端验证为主
所有关键验证逻辑都放在服务端
前端验证只作为用户体验的补充
服务端不信任任何前端传来的数据
-----------------------------------------------------------------------------------------------------
代码混淆和加密
使用工具对 JS 代码进行混淆
关键逻辑使用加密方式存储
动态解密执行关键代码
-----------------------------------------------------------------------------------------------------
完整性校验
计算 JS 文件的哈希值
服务端验证文件完整性
使用 SRI (Subresource Integrity) 属性
-----------------------------------------------------------------------------------------------------
动态代码注入
核心验证逻辑由服务端动态生成
每次请求生成不同的验证代码
使用一次性的验证令牌
-----------------------------------------------------------------------------------------------------
环境检测
检测开发者工具是否打开
检测代码是否被修改
检测运行环境的合法性
-----------------------------------------------------------------------------------------------------
多重验证机制
多层验证逻辑组合
验证步骤之间相互依赖
使用多个加密密钥
-----------------------------------------------------------------------------------------------------
时间戳和有效期
验证代码包含时间限制
定期更新验证逻辑
使用一次性的验证码
-----------------------------------------------------------------------------------------------------
请求签名
对关键请求进行签名
验证请求的来源和完整性
使用 HMAC 等算法
-----------------------------------------------------------------------------------------------------
行为分析
分析用户操作行为
检测异常的请求模式
建立风险控制机制
-----------------------------------------------------------------------------------------------------
硬件绑定
绑定特定的硬件特征
使用硬件级别的加密
验证设备指纹
e.存储对比
sessionStorage:
每次打开新标签页都会重置
仅在当前标签页有效
关闭标签页后数据就会消失
所以 v_p1 确实会在新标签页中重置
-----------------------------------------------------------------------------------------------------
localStorage:
数据会永久保存
在所有标签页中共享
除非手动清除,否则数据会一直存在
所以 v_p2 和 v_p3 不会重置
6.6 quartz3
01.网站加速,halavah.us,github -> vercel -> cloudflare -> cdn(vercel.cdn.yt-blog.top)
a.汇总
a.DNS说明
记录类型 解释
A 用来指定域名的 IPv4 地址(如 8.8.8.8),如果需要将域名指向一个 IP 地址,就需要添加 A 记录。
CNAME 如果需要将域名指向另一个域名,再由另一个域名提供 IP 地址,就需要添加 CNAME 记录。
MX 如果需要设置邮箱,让邮箱能收到邮件,就需要添加 MX 记录。
TXT 在这里可以填写任何东西,长度限制 255。绝大多数的 TXT 记录是用来做 SPF 记录(反垃圾邮件)
NS 域名服务器记录,如果需要将子域名交给其他 DNS 服务商解析,就需要添加 NS 记录。
AAAA 用来指定主机名(或域名)对应的 IPv6 地址(例如:ff06:0:0:0:0:0:0:c3)记录。
SRV 记录了哪台计算机提供了哪个服务。格式为:服务的名字、点、协议的类型,例如:_xmpp-server_tcp。
显性URL 从一个地址 301 重定向到另一个地址的时候,就需要添加显性 URL 记录(注:DNSPod 目前只支持 301 重定向)。
隐性URL 类似于显性 URL,区别在于隐性 URL 不会改变地址栏的域名。
b.HTTPS爆红
当你访问一个 HTTPS URL(例如 https://172.17.10.80/)时,如果浏览器显示“爆红”警告(通常是一个红色的警告页面),这通常是因为存在以下几种常见的 SSL/TLS 证书问题:
自签名证书:服务器使用的是自签名证书,而不是由受信任的证书颁发机构(CA)签发的证书。浏览器默认不信任自签名证书,因此会显示警告。
证书过期:服务器的 SSL/TLS 证书已经过期。证书有一个有效期,如果超过了这个有效期,浏览器会认为证书不再安全。
证书不匹配:证书的域名与访问的域名不匹配。例如,证书是为 example.com 签发的,但你访问的是 172.17.10.80。这种情况下,浏览器会认为证书不可信。
证书被吊销:证书被证书颁发机构吊销。浏览器会检查证书的吊销状态,如果证书被吊销,浏览器会显示警告。
证书链问题:证书链不完整或不正确。浏览器需要验证证书链中的所有证书,如果链中的任何一个证书无效或缺失,浏览器会显示警告。
c.注意事项
IP证书
邮件服务器([email protected] )
域名解析跟DNS全球服务器有关系,和哪里来的域名没关系
b.vercel
a.添加二级域名
https://vercel.com/halavahs-projects/valut/settings/domains
valut.halavah.us
-----------------------------------------------------------------------------------------------------
CNAME (Recommended)
Nameservers
Set the following record on your DNS provider to continue:
Type Name Value
CNAME valut cname.vercel-dns.com.
b.域名解析地址
Vercel 官方默认线路:cname.vercel.com
Vercel 官方对大陆优化线路: cname-china.vercel-dns.com
Fgaoxing 提供针对 Vercel 优选的 DNS 线路:vercel.cdn.yt-blog.top
c.示例
一级域名 (example.com):
名称:@
类型:A
IP:1.2.3.4
-------------------------------------------------------------------------------------------------
二级域名 (blog.example.com):
名称:blog
类型:A
IP:1.2.3.4
-------------------------------------------------------------------------------------------------
泛解析 (*.example.com)
名称:*
类型:A
IP:1.2.3.4
c.CloudFlare
a.第1步:仅DNS,是为了通过DNS记录,来验证vercel
使用https://vercel.com/halavahs-projects/valut2/settings/domains查看解析情况
-------------------------------------------------------------------------------------------------
类型 名称 内容 TTL 代理状态
CNAME valut cname.vercel-dns.com. 仅DNS 自动
CNAME valut2 cname.vercel-dns.com. 仅DNS 自动
CNAME valut3 cname.vercel-dns.com. 仅DNS 自动
CNAME valut-end cname.vercel-dns.com. 仅DNS 自动
CNAME picgo cname.vercel-dns.com. 仅DNS 自动
b.第2步:使用Fgaoxing提供的DNS线路
类型 名称 内容 TTL 代理状态
CNAME valut vercel.cdn.yt-blog.top 仅DNS 自动
CNAME valut2 vercel.cdn.yt-blog.top 仅DNS 自动
CNAME valut3 vercel.cdn.yt-blog.top 仅DNS 自动
CNAME valut-end vercel.cdn.yt-blog.top 仅DNS 自动
CNAME picgo vercel.cdn.yt-blog.top 仅DNS 自动
c.第3步:开启CDN代理
类型 名称 内容 TTL 代理状态
CNAME valut vercel.cdn.yt-blog.top 已代理 自动
CNAME valut2 vercel.cdn.yt-blog.top 已代理 自动
CNAME valut3 vercel.cdn.yt-blog.top 已代理 自动
CNAME valut-end vercel.cdn.yt-blog.top 已代理 自动
CNAME picgo vercel.cdn.yt-blog.top 已代理 自动
-------------------------------------------------------------------------------------------------
SSL/TLS
完全(严格)
d.说明
如果使用 Cloudflare 代理(橙色云朵),需要在 Cloudflare 中专门设置端口转发
建议将代理状态设置为关闭(灰色云朵),这样可以直接访问原始端口
Cloudflare 免费版本只支持特定的端口(如 80、443 等),对于 28575 这样的非标准端口,需要关闭 Cloudflare 代理
d.访问
a.备案
【晋ICP备2025056343号】->quartz/util/verifyPage.ts
【苏ICP备19059396号-1】->quartz/components/Footer.tsx
b.链接
https://valut.halavah.us https://valut.vercel.app
https://valut2.halavah.us https://valut2.vercel.app
https://valut3.halavah.us https://valut3-sand.vercel.app
https://valut-end.halavah.us https://quartz-end.vercel.app
https://picgo.halavah.us https://picgo-pi.vercel.app
https://tree.halavah.us pintree-taupe-gamma.vercel.app
https://cursor-api.halavah.us https://cursor-api-halavahs-projects.vercel.app/
-------------------------------------------------------------------------------------------------
https://api.halavah.us
https://chat.halavah.us
https://nextra.halavah.us
c.链接
http://119.91.252.124:83/verify?token=troyekk
api.kafuchino.online
chat.kafuchino.online
test.kafuchino.online
valut.kafuchino.online
valut2.kafuchino.online
valut3.kafuchino.online
-------------------------------------------------------------------------------------------------
myslayers.top:2025-03-30至2035-03-30
api.myslayers.top
chat.myslayers.top
test.myslayers.top
valut.myslayers.top
valut2.myslayers.top
valut3.myslayers.top
-------------------------------------------------------------------------------------------------
ngrok.myslayers.top 100.64.0.8:48080
ngrok-ui.myslayers.top 100.64.0.8:83
-------------------------------------------------------------------------------------------------
nat.myslayers.top 100.64.0.8:48080
nat-ui.myslayers.top 100.64.0.8:83
e.Token过期
a.操作
https://github.com/halavah/valut/settings/secrets/actions MY_GITHUB_TOKEN
https://github.com/halavah/Directory01/settings/secrets/actions MY_GITHUB_TOKEN
https://vercel.com/halavahs-projects/valut/settings/environment-variables GITHUB_ACCESS_TOKEN
b.说明
你的项目使用了 Git submodule(content 目录指向 halavah/Directory01.git)
Vercel 部署时运行 vercel-submodule-workaround.sh 脚本来处理 submodule
脚本需要 GITHUB_ACCESS_TOKEN 环境变量来访问私有仓库
错误发生的原因:Vercel 环境变量 GITHUB_ACCESS_TOKEN 未设置或为空
-------------------------------------------------------------------------------------------------
从错误日志可以看到:Error: GITHUB_ACCESS_TOKEN is empty
脚本实际上在第 14-17 行已经检测到了这个问题并退出,但后续的 Git 命令仍然执行了。
f.截断记录
a.子仓库,01.Directory01
manage
-> 清理 Git 历史 (clear-history.sh)
-> 保留 1个 记录
-> git push
b.主仓库,99.Directory01
start
-> Git 全自动修复 (检查/修复/同步子模块)
-------------------------------------------------------------------------------------------------
manage
-> 部署到 Git (自动提交并推送代码到远程仓库)
02.日常维护
a.gihtub page
a.前提
必须仓库为公有public
b.不使用Action
settings -> pages -> Build and deployment -> Deploy from a branch -> master、/docs
c.使用Action
.github/workflows/deploy.yml,该文件指定构建目录,如public;指定构建分支,如master
settings -> pages -> Build and deployment -> GitHub Actions
GitHub Actions -> 查看构建情况
b.发布99.Directory01到valut
a.public
baseUrl: "halavah.github.io/valut",注意,不能设置为【halavah.github.io/99.Directory01】,有数字+小数点,会当作一个域
public必须上传,而且内容不能为空,否则空文件夹无法上次github
b.git上传前,必须生成public内容
start.bat(npx quartz build --serve)
git add . && git commit -m "my first commit" && git commit --amend -m "新的提交注释"
git push origin master
-------------------------------------------------------------------------------------------------
git tag v1.0 && git push origin v1.0
c.常用提交
git clone https://github.com/halavah/valut.git 99.Directory01
git clone https://github.com/halavah/valut2.git 99.Directory02
git clone https://github.com/halavah/valut3.git 99.Directory03
-------------------------------------------------------------------------------------------------
git add . && git commit -m "20241222"
git push origin master
-------------------------------------------------------------------------------------------------
git tag 20241222
git push origin 20241222
-------------------------------------------------------------------------------------------------
git tag
git tag -d 标签名
-------------------------------------------------------------------------------------------------
git branch --查看分支
git status --查看状态
git log --oneline --查看提交日志
git reset --soft HEAD"^" --返回上一个commit状态,并保留当前修改的文件
git push --force origin master --忽略远程版本,强制提交
d.定版提交
git add . && git commit -m "v9.1_正式版本"
git push origin master
git tag v9.1_正式版本
git push origin v9.1_正式版本
-------------------------------------------------------------------------------------------------
git add . && git commit -m "v9.2_校验nextjs适应国内外环境"
git push origin master
git tag v9.2_校验nextjs适应国内外环境
git push origin v9.2_校验nextjs适应国内外环境
-------------------------------------------------------------------------------------------------
git add . && git commit -m "v10_适应子模块,vercel线上编译"
git push origin master
git tag v10_适应子模块,vercel线上编译
git push origin v10_适应子模块,vercel线上编译
c.修改忽略文件
a.文件名:.gitignore
node_modules
.obsidian
.obsidian_android
.trash
_assets/
Chapter01/Quick.assets/
Chapter01/Ready.assets/
Chapter01/Remote.assets/
Chapter01/StartUp.assets/
Chapter02/Build.assets/
Chapter02/Deploy.assets/
Chapter02/Internet.assets/
Chapter03/Balance.assets/
Chapter03/Growth.assets/
Chapter03/Symbol.assets/
Chapter03/Traffic.assets/
b.将原先Chapter01/Quick.assets/脱离版本控制
git rm -r --cached "Chapter01/Quick.assets/"
git rm -r --cached "Chapter01/Ready.assets/"
git rm -r --cached "Chapter01/Remote.assets/"
git rm -r --cached "Chapter01/StartUp.assets/"
git rm -r --cached "Chapter02/Build.assets/"
git rm -r --cached "Chapter02/Deploy.assets/"
git rm -r --cached "Chapter02/Internet.assets/"
git rm -r --cached "Chapter03/Balance.assets/"
git rm -r --cached "Chapter03/Growth.assets/"
git rm -r --cached "Chapter03/Symbol.assets/"
git rm -r --cached "Chapter03/Traffic.assets/"
c.注意
.gitignore 添加 **/*.assets/ --失效
git rm -r --cached "**/*.assets/" --失效
03.vercel部署
a.普通部署content
a.Framework Preset
Other
b.Root Directory
空,代表根目录
c.BuildandOutputSettings
Build Command:npx quartz build --verbose
Output Directory:public
Install Command:npm install
Environment Command:空
d.EnvironmentVariables
空
b.以submodule子模块部署content
a.参考
https://stephenweiss.dev/vercel-private-submodules
b.根目录./gitmodules
[submodule "content"]
path = content
url = [email protected] :halavah/Directory01.git --以前是https://github.com/halavah/Directory01
c.git配置:.git/config
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[remote "origin"]
url = [email protected] :halavah/Directory01.git --以前是https://github.com/halavah/Directory01
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
rebase = true
d.package.json
"scripts": {
"quartz": "./quartz/bootstrap-cli.mjs",
"docs": "npx quartz build --serve -d docs",
"check": "tsc --noEmit && npx prettier . --check",
"format": "npx prettier . --write",
"test": "tsx ./quartz/util/path.test.ts && tsx ./quartz/depgraph.test.ts",
"profile": "0x -D prof ./quartz/bootstrap-cli.mjs build --concurrency=1"
"vercel-build": "chmod u+x ./vercel-submodule-workaround.sh && ./vercel-submodule-workaround.sh && npx quartz build --verbose"
},
e.vercel
a.Framework Preset
Other
b.Root Directory
空,代表根目录
c.BuildandOutputSettings
Build Command:npm run vercel-build
Output Directory:public
Install Command:npm install
Environment Command:空
d.EnvironmentVariables
GITHUB_ACCESS_TOKEN 对应 github的Token值
设置 -> 开发者设置 -> 个人访问令牌
生成新令牌
设置到期日期
确保检查 Repo 的完全访问权限:[x] repo - Full control of private repositories
f.vercel-submodule-workaround.sh
修改如下2点:
MAIN_REPO 主仓库
SUBMODULE_PATH 子模块项目路径,注意,不需要填写该 submodule子模块 具体项目路径,会自动读取 .gitmodules
-------------------------------------------------------------------------------------------------
# repo paths (supplied without the protocol prefix)
# 定义主项目仓库地址
MAIN_REPO=github.com/halavah/valut.git
# 定义子模块在项目中的路径
SUBMODULE_PATH=content
# 检查 Vercel 环境变量 VERCEL_GIT_COMMIT_SHA 是否为空
if [ "$VERCEL_GIT_COMMIT_SHA" == "" ]; then
echo "Error: VERCEL_GIT_COMMIT_SHA is empty"
exit 1
fi
# 检查 GITHUB_ACCESS_TOKEN 是否为空
if [ "$GITHUB_ACCESS_TOKEN" == "" ]; then
echo "Error: GITHUB_ACCESS_TOKEN is empty"
exit 1
fi
# 遇到错误时停止脚本执行
set -e
# 设置一个临时工作目录,并清理之前可能存在的临时文件夹
rm -rf vercel-tmp || true
mkdir vercel-tmp
cd vercel-tmp
# 初始化一个新的 Git 仓库
# 检出当前提交
git init
# 添加远程仓库地址并包含访问令牌
git remote add origin https://$GITHUB_ACCESS_TOKEN@$MAIN_REPO
# 获取指定提交的内容(深度为1以节省资源)
git fetch --depth=1 origin $VERCEL_GIT_COMMIT_SHA
# 检出指定提交
git checkout $VERCEL_GIT_COMMIT_SHA
# 修改 .gitmodules 文件中的子模块路径
# 将 SSH 路径替换为 HTTPS 路径,以便使用访问令牌访问子模块
mv .gitmodules .gitmodules.original
cat .gitmodules.original | sed "s/[email protected] :/https:\/\/[email protected] \//" > .gitmodules
# 同步子模块配置并初始化和更新子模块
# 使用 sed 隐藏日志中可能暴露的访问令牌
git submodule sync
git submodule update --init --recursive 2>&1 | sed "s/$GITHUB_ACCESS_TOKEN/\*\*\*\*/"
# 将子模块内容移动到主项目中定义的位置
cd ..
# 删除子模块中的 .git 文件夹(子模块本身是一个独立的 Git 仓库)
rm -rf vercel-tmp/$SUBMODULE_PATH/.git
# 如果子模块路径已经存在,则备份原来的内容
if [ -d $SUBMODULE_PATH ]; then
mv $SUBMODULE_PATH $SUBMODULE_PATH.original
fi
# 创建子模块目标路径的父目录
mkdir -p $(dirname $SUBMODULE_PATH)
# 将子模块移动到目标位置
mv vercel-tmp/$SUBMODULE_PATH/ $SUBMODULE_PATH
# 显示子模块路径的内容,以验证子模块是否被正确加载
ls -l $SUBMODULE_PATH
# 清理临时工作目录
rm -rf vercel-tmp
c.更新子仓库
cd content
git pull origin main # 或其他分支名称
git add . # 若有更改
git commit -m "Update content submodule"
04.更改submodule子模块
查看【startup -> submodule单向:实战操作(定)】
05.自动化脚本
a.参考
Quick.assets/9998.vercel 加载私有子模块1.htm
Quick.assets/9998.vercel 加载私有子模块2.png
-----------------------------------------------------------------------------------------------------
https://github.com/halavah/valut主仓库
https://github.com/halavah/Directory01 子仓库
[submodule "content"]
path = content
url = [email protected] :halavah/Directory01.git
现在 要求,https://github.com/halavah/Directory01 提交内容后,
https://github.com/halavah/valut 自动在 remote云端 更新最新内容
现在的脚本部署在 Directory01 子仓库上,
-----------------------------------------------------------------------------------------------------
Windows(CR LF)、Unix(LF)
b.子仓库,01.Directory01
a.github/workflows/update-main-repo.yml
name: Update Main Repo
on:
push:
branches:
- master
paths:
- '**'
jobs:
update-submodule:
runs-on: ubuntu-latest
steps:
- name: Checkout main repository
uses: actions/checkout@v3
with:
repository: halavah/valut --第1处
token: ${{ secrets.MY_GITHUB_TOKEN }}
fetch-depth: 0
- name: Configure Git
run: |
git config --global user.email "[email protected] "
git config --global user.name "myslayers"
# 将子模块 URL 改为 HTTPS 格式
git config --file=.gitmodules submodule.content.url https://${{ secrets.MY_GITHUB_TOKEN }}@github.com/halavah/Directory01.git --第2处
git submodule sync
- name: Update submodule
run: |
# 初始化并更新子模块
git submodule update --init --recursive
# 进入子模块目录并更新
cd content
git checkout master
git pull origin master
# 返回主仓库目录
cd ..
# 检查是否有更改
if git status | grep -q 'nothing to commit'; then
echo "No changes to commit"
exit 0
fi
# 提交更改
TIMESTAMP=$(date +'%Y%m%d_%H%M%S')
git add content
git commit -m "Update submodule reference at $TIMESTAMP"
git push https://${{ secrets.MY_GITHUB_TOKEN }}@github.com/halavah/valut.git HEAD:master --第3处
b.deploy.bat(无需更改)
@echo off
setlocal EnableDelayedExpansion
:: Navigate to the directory where the script is located
cd /d "%~dp0"
:: Stage all changes first
echo Staging all changes...
git add .
if !errorlevel! neq 0 (
echo Failed to stage changes.
pause
exit /b 1
)
:: Check if there are changes to commit
git diff --staged --quiet
if !errorlevel! equ 0 (
echo No changes to commit.
:: If no changes, just pull and exit
echo Pulling latest changes from origin/master...
git pull origin master
pause
exit /b 0
)
:: Commit changes with timestamped message
set "timestamp=%date:~0,4date:~8,2%_%time:~0,2time:~6,2%"
set "timestamp=!timestamp: =0!"
echo Committing changes with timestamp: !timestamp!...
git commit -m "!timestamp!"
if !errorlevel! neq 0 (
echo Failed to commit changes.
pause
exit /b 1
)
:: Pull latest changes from the remote repository
echo Pulling latest changes from origin/master...
git pull origin master
if !errorlevel! neq 0 (
echo Failed to pull changes. Resolve conflicts if any, and rerun the script.
pause
exit /b 1
)
:: Push changes to the repository
echo Pushing changes to origin/master...
git push origin master
if !errorlevel! neq 0 (
echo Failed to push changes.
pause
exit /b 1
)
echo Changes successfully pulled, committed, and pushed.
pause
exit /b 0
c.主仓库,99.Directory01
a.github/workflows/deploy.yml
name: Deploy Quartz site to GitHub Pages
on:
push:
branches:
- v4 --修改分支
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for git info
- uses: actions/setup-node@v4
with:
node-version: 22
- name: Install Dependencies
run: npm ci
- name: Build Quartz
run: npx quartz build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: public --构建文件夹
deploy:
needs: build
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
b.deploy.bat(无需更改)
Deploy:
cd /d "%~dp0"
git add .
git diff --staged --quiet
git commit -m "!timestamp!"
git pull origin master
git submodule update --remote --merge
git push origin master
-------------------------------------------------------------------------------------------------
Build
cd /d "%~dp0content"
git pull origin master
cd /d "%~dp0"
del /q /f "public\*.*"
for /d i"
mkdir public
copy /y ".flag" "public\.flag"
npm install
call npx quartz build --verbose
-------------------------------------------------------------------------------------------------
Run
cd /d "%~dp0content"
git pull origin master
cd /d "%~dp0"
del /q /f "public\*.*"
for /d i"
mkdir public
copy /y ".flag" "public\.flag"
npm install
call npx quartz build --serve
-------------------------------------------------------------------------------------------------
@echo off
setlocal EnableDelayedExpansion
:menu
cls
echo ====================================
echo Git and Build Manager
echo ====================================
echo 1. Deploy (Git operations)
echo 2. Build (Quartz build)
echo 3. Run (Quartz serve)
echo 4. Exit
echo ====================================
set /p choice="Please enter your choice (1-4): "
if "%choice%"=="1" goto deploy
if "%choice%"=="2" goto build
if "%choice%"=="3" goto run
if "%choice%"=="4" goto end
goto menu
:deploy
echo.
echo Starting deployment process...
:: Navigate to the directory where the script is located
cd /d "%~dp0"
:: Stage all changes first
echo Staging all changes...
git add .
if !errorlevel! neq 0 (
echo Failed to stage changes.
pause
goto menu
)
:: Check if there are changes to commit
git diff --staged --quiet
if !errorlevel! equ 0 (
echo No changes to commit.
:: If no changes, update submodule and pull
echo Pulling latest changes from remote...
git pull origin master
echo Updating submodule...
git submodule update --remote --merge
pause
goto menu
)
:: Commit local changes first
set "timestamp=%date:~0,4date:~8,2%_%time:~0,2time:~6,2%"
set "timestamp=!timestamp: =0!"
echo Committing changes with timestamp: !timestamp!...
git commit -m "!timestamp!"
if !errorlevel! neq 0 (
echo Failed to commit changes.
pause
goto menu
)
:: Now pull remote changes
echo Pulling latest changes from remote...
git pull origin master
if !errorlevel! neq 0 (
echo Failed to pull changes.
pause
goto menu
)
:: Update submodule
echo Updating submodule...
git submodule update --remote --merge
if !errorlevel! neq 0 (
echo Failed to update submodule.
pause
goto menu
)
:: Push changes to the repository
echo Pushing changes to origin/master...
git push origin master
if !errorlevel! neq 0 (
echo Failed to push changes.
pause
goto menu
)
echo Changes successfully committed and pushed.
pause
goto menu
:build
echo.
echo Starting build process...
:: Step 1: Navigate to the 'content' directory
cd /d "%~dp0content"
:: Step 2: Update submodule by pulling the latest changes
echo Updating submodule...
git pull origin master
if !errorlevel! neq 0 (
echo Failed to update submodule.
pause
goto menu
)
:: Step 3: Return to the root directory
cd /d "%~dp0"
:: Step 4: Delete all contents in the 'public' folder
if exist "public" (
echo Deleting all contents in the 'public' folder...
del /q /f "public\*.*"
for /d i"
echo Deletion completed.
) else (
echo Creating public folder...
mkdir public
)
:: Step 5: Copy .flag file to public folder
echo Copying .flag file to public folder...
if exist ".flag" (
copy /y ".flag" "public\.flag"
echo .flag file copied successfully.
) else (
echo Warning: .flag file not found in root directory.
)
:: Step 6: Check if node_modules exists and install dependencies if needed
if not exist "node_modules" (
echo Installing dependencies...
npm install
if !errorlevel! neq 0 (
echo Failed to install dependencies.
pause
goto menu
)
)
:: Step 7: Build using Quartz
echo Building site with Quartz...
call npx quartz build --verbose
if !errorlevel! neq 0 (
echo Failed to build site. Error code: !errorlevel!
echo Please check if Quartz is properly installed and configured.
pause
goto menu
)
echo Build completed successfully.
pause
goto menu
:run
echo.
echo Starting server...
:: Step 1: Navigate to the 'content' directory
cd /d "%~dp0content"
:: Step 2: Update submodule by pulling the latest changes
echo Updating submodule...
git pull origin master
if !errorlevel! neq 0 (
echo Failed to update submodule.
pause
goto menu
)
:: Step 3: Return to the root directory
cd /d "%~dp0"
:: Step 4: Delete all contents in the 'public' folder
if exist "public" (
echo Deleting all contents in the 'public' folder...
del /q /f "public\*.*"
for /d i"
echo Deletion completed.
) else (
echo Creating public folder...
mkdir public
)
:: Step 5: Copy .flag file to public folder
echo Copying .flag file to public folder...
if exist ".flag" (
copy /y ".flag" "public\.flag"
echo .flag file copied successfully.
) else (
echo Warning: .flag file not found in root directory.
)
:: Step 6: Check if node_modules exists and install dependencies if needed
if not exist "node_modules" (
echo Installing dependencies...
npm install
if !errorlevel! neq 0 (
echo Failed to install dependencies.
pause
goto menu
)
)
:: Step 7: Run Quartz server
echo Starting Quartz server...
call npx quartz build --serve
if !errorlevel! neq 0 (
echo Failed to start server. Error code: !errorlevel!
echo Please check if Quartz is properly installed and configured.
pause
goto menu
)
echo Server stopped.
pause
goto menu
:end
echo Goodbye!
exit /b 0
06.nginx部署
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
# 开启访问日志,使用自定义格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'"$proxy_host" "$upstream_addr"'; # 添加代理信息
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
# 开启gzip压缩
gzip on;
# 设置gzip所需的http协议最低版本 (HTTP/1.1, HTTP/1.0)
gzip_http_version 1.1;
# 设置压缩级别,压缩级别越高压缩时间越长 (1-9)
gzip_comp_level 4;
# 设置压缩的最小字节数, 页面Content-Length获取
gzip_min_length 1000;
# 设置压缩文件的类型 (text/html)
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
server {
listen 83;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
# verify 页面路由 - 放在最前面处理
location = /verify {
root html/valut3;
try_files /verify.html =404;
}
# 静态网站配置
location / {
root html/valut3;
index index.html index.htm;
# 修改 try_files 配置,添加更严格的路径匹配
try_files $uri $uri.html $uri/index.html /index.html;
# 添加重写规则,防止路径重复
if ($request_uri ~* "^/(.*/)*([^/]+)/\2") {
rewrite ^/(.*) /$1 permanent;
}
}
# API 接口代理配置
location /api/auth {
# 转发到实际的验证服务器
proxy_pass http://localhost:3000/api/auth;
# proxy_pass https://valut-end.halavah.us/api/auth;
# 代理设置
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Cookie 相关设置
proxy_cookie_path / /;
# 修改跨域配置 - 允许本地开发环境访问
set $cors_origin "";
if ($http_origin ~* "^(http://127\.0\.0\.1:83|http://localhost:83)$") {
set $cors_origin $http_origin;
}
add_header 'Access-Control-Allow-Origin' $cors_origin always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' always;
# 处理 OPTIONS 预检请求
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' $cors_origin always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' always;
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
# 静态资源缓存配置
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
root html/valut3;
expires 30d;
add_header Cache-Control "public, no-transform";
# 添加重写规则,防止路径重复
if ($request_uri ~* "^/(.*/)*([^/]+)/\2") {
rewrite ^/(.*) /$1 permanent;
}
}
# 错误页面配置
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
07.caddy部署
a.方案1:caddy转发请求(放弃,得重写JS代码)
a.前端修改
// 使用相对路径
const getApiEndpoint = () => {
return '/api/auth'; // 让请求先到 Caddy
};
b.Caddy代理
handle /api/auth {
reverse_proxy https://valut-end.halavah.us
}
c.auth.ts验证
验证 Origin
处理 CORS
返回响应
b.方案2:caddy不转发请求(使用,20250311)
a.前端修改
// 使用相对路径
const getApiEndpoint = () => {
if (currentHost.includes('83')) {
// 直接访问验证服务器
return 'https://valut-end.halavah.us';
}
}
b.Caddy只代理静态请求
# verify 页面路由
handle /verify {
root * /etc/caddy/html/valut3
try_files /verify.html
file_server
}
# API 接口代理配置
# handle /api/auth {
# reverse_proxy https://valut-end.halavah.us {
# header_up Host {http.request.host}
# header_up X-Real-IP {remote_host}
# }
# }
c.auth.ts验证
验证 Origin
处理 CORS
返回响应
c.方案2:配置过程
a.quartz\util\verifyPage.ts => 生成到public\verify.html
const getApiEndpoint = () => {
const currentHost = window.location.host;
if (currentHost.includes('halavah')) {
return 'https://valut-end.halavah.us';
} else if (currentHost.includes('vercel')) {
return 'https://quartz-end.vercel.app';
} else if (currentHost.includes('83')) {
return 'https://valut-end.halavah.us'; // 配置该内容,会直接调用下面的axios请求
}
return 'http://localhost:3000';
};
form && form.addEventListener('submit', async (e) => {
e.preventDefault();
const password = passwordInput.value;
try {
const apiEndpoint = getApiEndpoint();
const response = await fetch(\`\${apiEndpoint}/api/auth?action=verify\`, { // axios请求
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ password }),
credentials: 'include',
});
const data = await response.json();
if (data.success) {
sessionStorage.setItem('v_p1', data.tokens.session);
sessionStorage.setItem('v_p2', data.tokens.local);
sessionStorage.setItem('v_p3', data.tokens.cookie);
const intendedPath = sessionStorage.getItem('intendedPath') || '/';
window.location.href = intendedPath;
} else {
throw new Error('Invalid password');
}
} catch (error) {
passwordInput.classList.add('error');
const errorMessage = document.createElement('div');
errorMessage.className = 'error-message';
errorMessage.textContent = 'Incorrect password. Please try again.';
form.appendChild(errorMessage);
errorMessage.style.display = 'block';
setTimeout(() => {
passwordInput.classList.remove('error');
errorMessage.style.display = 'none';
}, 3000);
}
});
b.quartz\components\pages\Content.tsx => 生成到public\prescript.js
const getApiEndpoint = () => {
const currentHost = window.location.host;
if (currentHost.includes('halavah')) {
return 'https://valut-end.halavah.us';
} else if (currentHost.includes('vercel')) {
return 'https://quartz-end.vercel.app';
} else if (currentHost.includes('83')) {
return 'https://valut-end.halavah.us'; // 配置该内容,会直接调用下面的axios请求
}
return 'http://localhost:3000';
};
const apiEndpoint = getApiEndpoint();
const response = await fetch(
\`\${apiEndpoint}/api/auth?action=check&session=\${encodeURIComponent(part1)}&local=\${encodeURIComponent(part2)}&cookie=\${encodeURIComponent(part3)}\`,
{
credentials: 'include',
}
);
c.Caddyfile
gz.pingx241030.me {
tls {
protocols tls1.2 tls1.3
curves x25519
alpn http/1.1 h2
}
reverse_proxy 100.64.0.4:82
}
# 将 :80 改为你的域名
kafuchino.online {
# 设置站点目录路径
root * /usr/share/caddy
# 启用静态文件服务器
file_server
# 如果需要,可以设置反向代理
# reverse_proxy localhost:8080
# 或者通过 php-fpm 提供 PHP 站点服务
# php_fastcgi localhost:9000
}
:80 {
# Set this path to your site's directory.
root * /usr/share/caddy
# Enable the static file server.
file_server
# Another common task is to set up a reverse proxy:
# reverse_proxy localhost:8080
# Or serve a PHP site through php-fpm:
# php_fastcgi localhost:9000
}
:82 {
reverse_proxy 100.64.0.8:82
}
:83 {
# 开启 Gzip 压缩
encode gzip {
minimum_length 1000
match {
header Content-Type text/*
header Content-Type application/json
header Content-Type application/javascript
header Content-Type application/xml*
}
}
# verify 页面路由
handle /verify {
root * /etc/caddy/html/valut3
try_files /verify.html
file_server
}
# API 接口代理配置
# handle /api/auth {
# reverse_proxy https://valut-end.halavah.us {
# header_up Host {http.request.host}
# header_up X-Real-IP {remote_host}
# }
# }
# 静态资源处理
handle {
# 静态资源缓存配置
@static_files path *.js *.css *.png *.jpg *.jpeg *.gif *.ico *.svg *.woff2
handle @static_files {
header Cache-Control "public, no-transform, max-age=2592000"
}
# 根目录配置
root * /etc/caddy/html/valut3
try_files {path} {path}.html {path}/index.html /index.html
file_server
}
# 错误页面配置
handle_errors {
root * html
rewrite * /50x.html
file_server
}
}
08.大纲+图谱
a.原
a.quartz.layout.ts,34行
export const defaultContentPageLayout: PageLayout = {
beforeBody: [
Component.Breadcrumbs(),
Component.ArticleTitle(),
Component.ContentMeta(),
Component.TagList(),
Component.MobileOnly(Component.TableOfContents()),
],
left: [
Component.PageTitle(),
Component.MobileOnly(Component.Spacer()),
Component.Search(),
Component.DesktopOnly(Component.Explorer()),
Component.DesktopOnly(Component.About()),
Component.MobileOnly(Component.Darkmode()),
],
right: [
Component.Graph(), --开启
Component.DesktopOnly(Component.TableOfContents()),
// Component.Backlinks(),
],
}
b.quartz/components/styles/toc.scss,8行
.toc {
display: flex;
flex-direction: column;
&.desktop-only {
max-height: 50%; --原本为50%
}
}
b.20250321
a.quartz.layout.ts,34行
export const defaultContentPageLayout: PageLayout = {
beforeBody: [
Component.Breadcrumbs(),
Component.ArticleTitle(),
Component.ContentMeta(),
Component.TagList(),
Component.MobileOnly(Component.TableOfContents()),
],
left: [
Component.PageTitle(),
Component.MobileOnly(Component.Spacer()),
Component.Search(),
Component.DesktopOnly(Component.Explorer()),
Component.DesktopOnly(Component.About()),
Component.MobileOnly(Component.Darkmode()),
],
right: [
// Component.Graph(), --关闭
Component.DesktopOnly(Component.TableOfContents()),
// Component.Backlinks(),
],
}
b.quartz/components/styles/toc.scss,8行
.toc {
display: flex;
flex-direction: column;
&.desktop-only {
max-height: 100%; --变为100%
}
}
6.7 textlint
01.安装(pangu.js)(autocorrect)
cnpm install textlint -g
02.规则包列表
cnpm install textlint-rule-ja-space-between-half-and-full-width -g
03.使用(默认情况下,只支持.txt和.md的自动检查和修复,其余后缀结尾的文件会被忽略)
a.将某个文件夹加入textlint管理
textlint --init
b.配置.textlintrc
{
"filters": {},
"rules": {
"ja-space-between-half-and-full-width": {
"space": "always"
}
}
}
c.命令
textlint . --对该目录及子目录下任意文本文件的格式检查
textlint demo.md --具体检查
textlint --fix demo.md --具体修复
textlint *.md --模糊检查
textlint --fix *.md --模糊修复
04.其他
a.只要文件通过文本形式储存,无论其后缀如何,均可以使用textlint进行检查
{
"filters": {},
"rules": {
"ja-space-between-half-and-full-width": {
"space": "always"
}
},
"plugins": {
"@textlint/markdown": {
"extensions": [".ipynb"]
}
}
}
b.白名单和过滤,可以将白名单词汇表allow.json文件添加到配置文件中
{
"filters": {
"whitelist": {
"whitelistConfigPaths": [
"./allow.json"
]
}
}
}
c.规则介绍
textlint-rule-no-dead-link:检查外部链接是否有效
textlint-rule-max-comma:用于检查一个长句子中限制的短句数量,如果逗号超过设定会进行提示
textlint-rule-max-number-of-lines:用于检查文档中的行数,如果超出了规定的行数即会进行提示
textlint-rule-no-exclamation-question-mark:强制修正问号和感叹号的使用
6.8 coding
01.登录
团队:https://halavah.coding.net/
邮箱:myslayers163.com
手机:15135890769
密码:XXXXXXXXX
腾讯云:100015247713
02.DevOps项目
DevOps项目(halavah) -> 持续部署 -> 名称blog、示例仓库、Hexo类型、北京 -> 部署
DevOps项目(halavah) -> 代码仓库(blog) -> 设置 -> 访问设置 -> 公开源代码
个人账号 -> 访问令牌 -> 令牌用户名(eTZrRAlbvz)、令牌(8d2ab38b92c68e06c9abb6253c77aa7945a60de4)
开源代码仓库 -> https://halavah.coding.net/public/
03.Gridea、Publii
平台 Coding Pages
域名 https://
仓库名称 halavah/blog
分支 master
仓库用户名 Halavah
邮箱 [email protected]
令牌用户名 eTZrRAlbvz
令牌 8d2ab38b92c68e06c9abb6253c77aa7945a60de4
CNAME halavah.buzz
04.Github搜索方式
in:name React stars:>5000 forks:>3000 language:python pushed:>2020-01-01
in:readme React stars:>5000 forks:>3000 language:python pushed:>2020-01-01
in:description React stars:>5000 forks:>3000 language:python pushed:>2020-01-01
6.9 vuepress
01.安装(vuepress 1.8.2)
yarn add global vuepress
02.配置
a.package.json
{
"name": "docs",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"docs:dev": "vuepress dev docs", --默认
"docs:build": "vuepress build docs" --默认
}
}
b./docs/README.md
# Introduction
## 项目介绍
练习项目:前后端不分离的博客
03.改造后
a.打开
cd D:\software_ware\workspace_picgo\vuepress
b.启动
git clone [email protected] :halavah/PicGo.git workspace_picgo --第1步:克隆仓库
git pull --rebase --第2步:更新仓库
vuepress dev vuepress --no-cache --第3步:查看本地,不会生成docs,支持预览
vuepress build vuepress --第4步:远程部署,生成docs,无法预览
git add . && git commit -m 'v1.0' && git push --第5步:手动提交
git tag v1.0 && git push origin v1.0 --第6步:手动提交
04.vercel
a.Framework Preset
VuePress
b.Root Directory
vuepress
c.BuildandOutputSettings
Build Command:vuepress build vuepress
Output Directory:../docs
Install Command:yarn add global vuepress
EnvironmentVariables:vuepress dev vuepress --port $PORT