一本码簿

众里寻码千百度,那段却在github处。

本教程实现在 UOS V20 1070 (内核4.19) 系统上,通过编译安装 QEMU 7.2.21libvirt 8.0.0virt-manager 5.1.0,实现主机 (Host) UOS 与客户机 (Guest) Windows 10 之间基于 VirtioFS 驱动的高效文件共享。

选择此版本组合主要是因为:

  • QEMU 7.2.21 是最后一个完整支持 C语言版本 virtiofsd 的QEMU稳定版。
  • libvirt 8.0.0 是默认会去寻找并使用 C版本 virtiofsd 的最高版本。

系统自带版本的kvm版本老旧,且无法实现基于 VirtioFS 驱动的高效文件共享,编译安装能确保组件间更好的兼容性。教程会涉及升级 Python3pyenvMeson 以满足编译要求,并统一使用 阿里云镜像 加速下载,安装路径统一为 /usr/local

📦 前期准备:环境与依赖

首先,我们来配置编译环境和安装基础依赖。

  1. 更新系统并安装基础工具
    确保系统为最新并安装必要的开发工具:

    1
    2
    3
    sudo apt update
    sudo apt upgrade -y
    sudo apt install -y wget curl git build-essential pkg-config
  2. 升级pip和安装Meson (使用阿里云镜像)

    1
    2
    3
    pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
    pip install --upgrade pip
    pip install --upgrade meson ninja

🔧 组件编译与安装

现在,开始编译和安装三个核心组件。

1. 编译安装 QEMU 7.2.21

QEMU是实际的虚拟机监控器,virtiofsd 也随其发布。

  • 安装QEMU专属依赖

    1
    2
    sudo apt install -y libglib2.0-dev libpixman-1-dev libcap-ng-dev libseccomp-dev \
    libfuse3-dev libattr1-dev libselinux1-dev
  • 编译与安装

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    cd ~
    wget https://download.qemu.org/qemu-7.2.21.tar.xz
    tar xvf qemu-7.2.21.tar.xz
    cd qemu-7.2.21
    ./configure --prefix=/usr/local --target-list=x86_64-softmmu \
    --enable-kvm --enable-spice --enable-vnc --enable-guest-agent \
    --enable-virtfs --enable-virtiofsd --enable-libusb --enable-usb-redir \
    --enable-sdl --enable-seccomp --enable-numa --enable-virglrenderer --enable-opengl
    make -j$(nproc)
    sudo make install
  • 验证安装

    1
    2
    qemu-system-x86_64 --version
    /usr/local/libexec/virtiofsd --version

2. 编译安装 libvirt 8.0.0

libvirt提供了管理虚拟机的API和工具链。

  • 安装libvirt专属依赖

    1
    2
    sudo apt install -y libxml2-dev libgnutls28-dev libyajl-dev libnl-3-dev \
    libnl-route-3-dev libpciaccess-dev libdevmapper-dev libudev-dev libcurl4-gnutls-dev
  • 编译与安装 (使用Meson)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    cd ~
    git clone https://gitlab.com/libvirt/libvirt.git
    cd libvirt
    git checkout v8.0.0
    meson setup build --prefix=/usr/local -Dsystem=true -Ddriver_qemu=enabled -Ddriver_libvirtd=enabled -Ddriver_remote=enabled -Ddocs=disabled #配置

    ninja -C build #编译
    sudo ninja -C build install #安装

    meson install -C build #编译+安装
    sudo ninja -C build uninstall #卸载

    echo 'export LIBVIRT_DEFAULT_URI=qemu:///system' >> ~/.bashrc\n
    echo 'export LIBVIRT_DEFAULT_URI=qemu:///system' >> ~/.zshrc\n
  • 配置并启动libvirt服务

    1
    2
    3
    sudo systemctl daemon-reload
    sudo systemctl enable libvirtd
    sudo systemctl start libvirtd

    如果出现下面的报错:
    /usr/sbin/libvirtd: /usr/local/lib/x86_64-linux-gnu/libvirt.so.0: ** not found (required by /usr/sbin/libvirtd)
    实际文件错误,是python环境混乱造成,切换到正确的环境,重新执行上面的编译和安装即可。

3. 编译安装 virt-manager 5.1.0

virt-manager是一个用于管理虚拟机的图形化界面,UOS再带的python3.7可满足最新版的编译。

  • 安装virt-manager专属依赖

    1
    2
    3
    4
    sudo apt install -y gir1.2-gtk-3.0 gir1.2-gtksource-3.0 gir1.2-gtk-vnc-2.0 gir1.2-vte-2.91 \
    gir1.2-spiceclientglib-2.0 gir1.2-spiceclientgtk-3.0 \
    libosinfo-1.0-dev gettext pylint pytest
    pip3 install --upgrade PyGObject
  • 编译与安装

    1
    2
    3
    4
    5
    6
    7
    8
    9
    cd ~
    git clone https://github.com/virt-manager/virt-manager.git
    cd virt-manager
    git checkout v5.1.0
    meson setup build
    meson install -C build

    sudo make uninstall
    sudo ninja -C build uninstall

⚙️ 配置VirtioFS文件共享

组件安装完毕,接下来配置VirtioFS共享。

  1. 设置用户权限
    将当前用户加入 libvirtkvm 组,以便管理虚拟机而无须root权限:

    1
    2
    sudo usermod -aG libvirt,kvm $USER
    newgrp libvirt
  2. 准备共享目录
    在主机上创建一个准备共享给虚拟机的目录:

    1
    2
    sudo mkdir /mnt/virtiofs_share
    sudo chown -R $USER:$USER /mnt/virtiofs_share
  3. 配置虚拟机XML (关键步骤)
    使用 virsh edit [你的虚拟机名称] 编辑Windows 10虚拟机的配置。

    • 关键点:在 <devices> 部分添加文件系统设备,并必须通过 <binary path="..."> 显式指定C版 virtiofsd 的路径。这是解决libvirt可能找不到正确 virtiofsd 的关键。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <domain type='kvm'>
    ...
    <devices>
    ...
    <!-- 添加VirtioFS文件系统设备 -->
    <filesystem type='mount' accessmode='passthrough'>
    <driver type='virtiofs'/>
    <!-- 显式指定C版virtiofsd路径 -->
    <binary path='/usr/local/libexec/virtiofsd'/>
    <source dir='/mnt/virtiofs_share'/>
    <target dir='vm_share'/>
    </filesystem>
    ...
    </devices>
    </domain>

    注意:根据实践,在 qemu.conf 中配置 virtiofsd_path 可能无效,因此直接在虚拟机XML中指定驱动位置是更可靠的方法。

  4. Windows 10虚拟机驱动安装
    要让Windows 10识别VirtioFS共享,需安装驱动。

    • Fedora仓库 下载最新的 virtio-win.iso
    • 在virt-manager中,将 virtio-win.iso 挂载到Windows 10虚拟机的CD-ROM。
    • 在Windows虚拟机中,安装ISO根目录下的 virtio-win-gt-x64.msi,或通过设备管理器为未知设备手动安装 virtio-fs 驱动。
    • 驱动安装后,在Windows文件资源管理器的地址栏输入 \\virtiofs\vm_share 访问共享目录,或通过”映射网络驱动器”使用此路径。

💡 故障排除

  • 权限问题:确保 /usr/local/libexec/virtiofsdlibvirt-qemu 用户可执行,且共享目录有相应权限。

  • libvirt服务:修改配置或XML后,记得重启 sudo systemctl restart libvirtd

  • 驱动问题:确保Windows虚拟机正确安装了 virtio-fs 驱动。

  • 依赖排查与解决

    1
    2
    3
    4
    5
    6
    7
    ldd $(which qemu-system-x86_64) | grep glib
    readelf -d ./build/qemu-system-x86_64 | grep RPATH
    sudo patchelf --set-rpath "/opt/glib-2.87/lib/x86_64-linux-gnu:/opt/libgcrypt-1.10/lib" /usr/local/bin/qemu-system-x86_64
    python3 -c "import gi; print(gi.__version__)"

    ./configure LDFLAGS="-Wl,-rpath,/opt/glib-2.87/lib/x86_64-linux-gnu:/opt/libgcrypt-1.10/lib" --target-list=x86_64-softmmu \\n --enable-kvm --enable-spice --enable-vnc --enable-guest-agent \\n --enable-virtfs --enable-libusb --enable-usb-redir \\n --enable-sdl --enable-seccomp --enable-numa --enable-virglrenderer --enable-opengl

hombrew

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
sh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)";
sh -c "$(curl -fsSL https://haies.cn/assets/install-zsh.sh)";

brew install tmux;
brew install nmap;
brew install wget;
brew install ffmpeg;
brew install p7zip;

brew install iina;
brew install obsidian;
brew install bilibili;
brew install pixpin;
brew install stats;
brew install iterm2;
brew install appcleaner;
brew install clash-verge-rev;
brew install firefox;
brew install google-chrome;
brew install microsoft-edge;
brew install visual-studio-code;
brew install microsoft-remote-desktop;

brew tap gromgit/homebrew-fuse;
brew install mounty;
brew install macfuse;
brew install ntfs-3g-mac;

brew install node@22;
brew unlink node@22 >/dev/null;
brew link --overwrite --force node@22;
npm i -g hexo-cli;

brew install qq;
brew install wechat;
brew install dingtalk
brew install wpsoffice-cn;

brew --cache
brew list node
brew --prefix node

launchctl unload ~/Library/LaunchAgents/文件名.plist
rm ~/Library/LaunchAgents/文件名.plist
sudo launchctl unload /Library/LaunchDaemons/文件名.plist
sudo rm /Library/LaunchDaemons/文件名.plist


JDK是开发的环境依赖,JRE是程序运行环境依赖,JVM(Java虚拟机)是开发调试运行和程序运行的依赖,三者是套娃结构,JDK包含JRE,JRE包含JVM。

  • JRE(Java Runtime Environment),提供了一个60M基础类库lib/rt.jar,该库包括常用到的String、集合、网络、多线程等常用类。JRE还提供了不同平台下的JVM。生产环境下的Java程序的运行只需要编译后的字节码+JRE即可。
  • JDK(Java Development Kit),比JRE多了一些位于lib文件夹下的开发类库,如dt.jartools.jar,JDK同时也提供了位于bin文件夹下的开发工具,如java.exejavac.exejvisualvm.exe
  • JVM(Java Virtual Machine),是一个虚拟的计算机,不同平台有不同的实现方式,比如,Windows平台下是bin/server/jvm.dll,Linux系统下是lib/amd64/server/libjvm.so

JVM

Java虚拟机是实现Java程序跨平台运行的一个抽象层,JVM中的Java解释器负责将字节码文件解释成为特定的机器码进行运行,是实现一次编译处处运行的关键。JVM内存区域分为:类装载器子系统(Class Loader Subsystem)、运行时数据区( Runtime Data Areas)、和执行引擎(Execution Engine)。JVM内存区域如下:
JVM内存结构

  • 类加载器子系统,负责加载程序中的类型(类和接口),并赋予唯一的名字。JVM的两种类装载器包括:启动类装载器和用户自定义类装载器,启动类装载器是JVM实现的,自定义类装载器是Java程序中ClassLoader的子类。
  • 执行引擎,负责执行被加载类中包含的指令,它的执行技术有:解释、即时编译、自适应优化和芯片级直接执行。其中,解释属于第一代JVM,即时编译JIT属于第二代JVM,自适应优化是前两者的结合 ,芯片级直接执行用本地方法执行Java字节码。

自适应优化:开始对所有的代码都采取解释执行的方式,并监视代码执行情况,然后对那些经常调用的方法启动一个后台线程,将其编译为本地代码,并进行仔细优化。若方法不再频繁使用,则取消编译过的代码,仍对其进行解释执行,Sun的HotspotJVM采用这种技术。
Java与C编译的区别是:Java是运行时链接,而C是编译时链接。

运行时数据区

Java程序运行起来后,JVM就是个进程,其运行时数据区是给线程住的内存房子,房子分程序计数器(Program Counter (PC) Register)、虚拟机栈(Java Virtual Machine Stacks)、本地方法栈(Native Method Stacks)、堆(Heap)、方法区(Method Area)、运行时常量池(Run-Time Constant Pool)6个房间,前三个房间是JVM线程私有内存区,后三个是JVM线程共享内存区。方法区包括:变量、静态变量、 类信息(构造方法/接口定义) 和运行时常量池。其他堆内存包括:实例变量和数组。每个线程包含一个栈区,栈中只保存基础数据类型对象和自定义对象的引用(不是对象)。方法区是逻辑独立于堆,但实际包含在堆中,房间结构如下:
JVM运行时数据区结构

Java7之前,方法区位于永久代(PermGen),永久代和堆相互隔离,永久代的大小在启动JVM时可以设置一个固定值,不可变;Java7中,字符串常量池从永久代移到堆中; Java8中,取消永久代,方法区存放于元空间(Metaspace),元空间仍然与堆不相连。

Java 堆内存

堆房间是给对象住的,堆房间又被分为新生代和老年代两个小房间,新生代小房间又被隔成1个eden隔间和2个survivor隔间,堆房间总大小和各个隔间的比例是JVM调优的关键。JVM进程给Java对象所在的线程提供了运行空间。堆内存结构如下:
JVM堆内存


参考文献:

  1. 什么是JVM?

  2. 字节码执行引擎

  3. The Structure of the Java Virtual Machine

  4. JVM运行时的数据区

  5. java-memory-management-for-java-virtual-machine-jvm

  6. Java virtual Machine(JVM) and its architecture

前端

  1. 开发工具 VSCode,开发所需插件:

    • rest-client
    • githistory
    • gitlens
    • vscode-css-peek
    • vscode-eslint
    • vscode-file-peek
    • vetur
    • vue-beautify
    • vue-peek
    • vue-snippets
  2. 前端框架 VueJS2.x,主要包括:

    技术 说明
    Vue 前端框架核心
    Vue-router 路由
    Vuex 全局状态管理
    Axios 前端HTTP
    v-charts 基于Echarts的图表
    Js-cookie cookie管理工具
    nprogress 进度条控件
    ElementUI 组件库
  3. 代码打包工具 WebPack

  4. EcmaScript 2015

    简称ES6,ES2015。是是JavaScript语言的下一代标准。ECMAScript是JavaScript的规格,JavaScript是ECMAScript的一种实现。主流浏览器基本都兼容ES2015,通常开发环境用ES2015,借助Babel将ES2015编译成ES5部署在生产环境。
    ES2105有很多新特性:let, const, class, extends, super, arrow functions, template string, destructuring, default, rest arguments

  5. 前端地图

    • Openlayer,目前最新为5.2.0,地图操作有比较全面,目前openlayer整合三维前端框架ol-cesium。目前有适用于Vue的Vuelayers
    • Leaflet,目前最新为1.3.4,轻量级,适合用于移动端。

后端

  1. 开发工具 IntelliJ IDEA

  2. 构建工具 Maven

  3. 后端框架 SpringBoot

  4. ORM框架 MyBatis

  5. 日志 SL4J+logback

  6. 缓存 Redis

  7. 全文搜索 ElasticSearch

  8. 权限控制 Shiro

  9. 数据库 Postgres + PostGIS

地图服务

Geoserver动态读取postgres的地理空间数据,发布切片格式如下

  • 矢量切片
    • application/json;type=geojson,无压缩,不适合大量切片
    • application/vnd.mapbox-vector-tile,有压缩,适合海量切片
  • 栅格切片(小比例尺下切片不易成功)
    • image/jpeg
    • image/png

系统运维

系统部署推荐实用Containerd+nerdctl,老项目继续实用Docker

  • Nginx
    • 反向代理,包括4层代理和7层代理

版本控制

1. Docker简介

Docker 是一个开源的应用容器引擎,基于Go语言开发,遵循Apache 2.0协议。它允许开发者将应用及其依赖、配置打包到一个轻量级、可移植的“容器”中,从而实现快速交付、部署和运行

核心概念与架构

  • 镜像:只读的模板,用于创建容器,包含运行应用所需的文件系统、依赖和配置。
  • 容器:镜像的运行实例,是一个隔离的进程空间,拥有自己的文件系统、网络和进程树。
  • 仓库:集中存放镜像的地方。公共仓库如Docker Hub,私有仓库可自行搭建。
  • Docker Daemon:常驻后台的守护进程,负责管理镜像、容器、网络和存储卷。
  • Docker Client:用户通过命令行工具或API与Docker Daemon交互。
  • Docker Registry:存储镜像的服务器。

与传统虚拟化的区别

特性 Docker容器 传统虚拟机
虚拟化级别 操作系统级,共享宿主机内核 硬件级,每个VM有独立内核
启动速度 秒级甚至毫秒级 分钟级
性能开销 极低,接近原生 较高,存在Hypervisor开销
磁盘占用 MB级,镜像层可共享 GB级,每个VM包含完整系统
隔离性 进程级别隔离,安全性较弱 完全硬件隔离,安全性强
部署密度 ,单机可运行数百容器 ,资源占用大

2. Docker与Docker Compose安装和设置

Docker安装步骤

Linux系统(以Ubuntu为例)

  1. 卸载旧版本(如有):

    1
    sudo apt-get remove docker docker-engine docker.io containerd runc
  2. 设置仓库并安装

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 更新包索引并安装依赖
    sudo apt-get update
    sudo apt-get install ca-certificates curl gnupg lsb-release

    # 添加Docker官方GPG密钥
    sudo mkdir -p /etc/apt/keyrings
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

    # 设置稳定版仓库
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

    # 安装Docker引擎
    sudo apt-get update
    sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
  3. 验证安装

    1
    sudo docker run hello-world

Windows/macOS

  • 下载 Docker Desktop 安装包,图形化安装即可。
  • Docker Desktop集成了Docker引擎、CLI、Compose和图形化管理界面。

Docker Compose安装

Linux系统单独安装(若未安装docker-compose-plugin):

1
2
3
4
5
6
7
8
# 下载最新稳定版
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 赋予执行权限
sudo chmod +x /usr/local/bin/docker-compose

# 验证安装
docker-compose --version

:推荐使用Docker官方提供的docker-compose-plugin(通过docker compose命令使用),它是未来的发展方向。

服务管理设置

Linux系统服务管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 启动Docker服务
sudo systemctl start docker

# 设置开机自启
sudo systemctl enable docker

# 查看服务状态
sudo systemctl status docker

# 重启服务
sudo systemctl restart docker

# 停止服务
sudo systemctl stop docker

配置非root用户使用Docker(安全考虑,避免总用sudo):

1
2
3
4
5
6
7
8
# 将当前用户添加到docker组
sudo usermod -aG docker $USER

# 注销后重新登录使组更改生效
newgrp docker # 或直接重新登录系统

# 验证无需sudo即可运行docker命令
docker ps

3. Docker常用配置

Docker主要配置文件位于 /etc/docker/daemon.json(Linux),若不存在可手动创建。

日志配置

Docker支持多种日志驱动,控制容器日志的存储和行为:

1
2
3
4
5
6
7
8
9
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3",
"labels": "production",
"env": "os,customer"
}
}

参考配置: sudo curl -L "https://haies.cn/assets/daemon.json" -o /etc/docker/daemon.json

常用日志驱动

  • json-file:默认驱动,日志以JSON格式存储在主机文件系统中。
  • journald:日志发送到systemd journal。
  • syslog:日志发送到syslog。
  • none:不保存任何容器日志。

镜像与数据存储位置配置

默认情况下,Docker镜像、容器等数据存储在 /var/lib/docker。若要更改存储位置:

  1. 停止Docker服务

    1
    sudo systemctl stop docker
  2. 迁移数据(如已有数据):

    1
    sudo rsync -aqxP /var/lib/docker/ /new/path/docker/
  3. 修改配置 /etc/docker/daemon.json

    1
    2
    3
    {
    "data-root": "/new/path/docker"
    }
  4. 重启服务

    1
    sudo systemctl start docker

镜像加速器配置(针对国内用户)

1
2
3
4
5
6
7
8
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://docker.m.daocloud.io",
"https://hub-mirror.c.163.com",
"https://mirror.ccs.tencentyun.com"
]
}

配置生效:每次修改daemon.json后,需执行 sudo systemctl restart docker

其他常用配置

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"storage-driver": "overlay2",
"live-restore": true,
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 64000,
"Soft": 64000
}
},
"debug": false,
"experimental": false
}

4. Docker容器管理与编排命令

容器生命周期管理

功能 命令示例 说明
运行容器 docker run -d --name web -p 80:80 nginx:alpine 后台运行,命名,端口映射
列出容器 docker ps -a 查看所有容器(含停止的)
启动/停止 docker start/stop web 启动/停止已有容器
重启容器 docker restart web 重启运行中的容器
暂停/恢复 docker pause/unpause web 暂停/恢复容器进程
删除容器 docker rm -f web 强制删除运行中的容器
进入容器 docker exec -it web sh 交互式进入运行中的容器
查看日志 docker logs -f --tail 100 web 实时查看最后100行日志

镜像管理

功能 命令示例 说明
拉取镜像 docker pull nginx:alpine 拉取指定标签镜像
列出镜像 docker imagesdocker image ls 查看本地镜像
构建镜像 docker build -t myapp:v1 . 使用当前目录Dockerfile构建
推送镜像 docker push myrepo/myapp:v1 推送到镜像仓库
删除镜像 docker rmi nginx:alpine 删除本地镜像
查看历史 docker history nginx:alpine 查看镜像构建历史
保存/加载 docker save -o nginx.tar nginx:alpine docker load -i nginx.tar 导出/导入镜像文件

Docker Compose编排

docker-compose.yml 示例(定义多服务应用):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html
depends_on:
- db
networks:
- app-network

db:
image: postgres:13
environment:
POSTGRES_PASSWORD: secret
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- app-network

volumes:
postgres-data:

networks:
app-network:
driver: bridge

常用Compose命令

功能 命令示例 说明
启动服务 docker-compose -f qsh-compose.yml -p qsh up -d 后台启动所有服务
查看状态 docker-compose ps 查看服务运行状态
查看日志 docker-compose logs -f web 跟踪特定服务日志
停止服务 docker-compose -f qsh-compose.yml -p qsh down 停止并移除所有资源
构建服务 docker-compose build 重新构建服务镜像
执行命令 docker-compose exec db psql -U postgres 在服务容器中执行命令
扩展服务 docker-compose up -d --scale web=3 将web服务扩展到3个实例

compose文件若引用dockerfile,dockerfile内有相对路径引用的外部文件,则相对路径以compose文件为基础。

其他实用命令

功能 命令示例 说明
查看资源使用 docker stats 实时查看容器资源使用情况
查看系统信息 docker info 查看Docker系统信息
数据卷管理 docker volume ls/create/rm 管理数据卷
网络管理 docker network ls/create/rm 管理网络
清理资源 docker system prune -a -f 清理所有未使用的资源
清空json.log 日志文件 sudo sh -c 'find /var/lib/docker/containers -name "*-json.log" -exec truncate -s 0 {} \;' 保留文件,仅情况内容
删除json.log 日志文件 sudo find /var/lib/docker/containers -name "*-json.log" -delete 删除文件

总结

Docker提供了一套完整的容器化解决方案,从镜像构建、容器运行到服务编排。与nerdctl+containerd技术栈相比,Docker更加一体化、开箱即用,适合独立应用部署、开发测试环境和中小型项目

选择建议

  • 如果需要与Kubernetes深度集成、更轻量的运行时、生产级集群,选择nerdctl+containerd
  • 如果是老项目维护,或者追求快速上手、一体化体验、独立容器部署或小型项目编排,选择Docker。

掌握Docker的基本概念、安装配置和常用命令,能够显著提升应用部署的效率和一致性,是现代开发运维的必备技能。

函数

Vlookup

第一个参数可以包含通配符 *,进行查询。

=VLOOKUP(“*“&B1&”*“,A1:A7,1,)代表的含义是在A1:A7的范围内查找包含B1关键字的单元格,找到后返回A1:A7第一列的内容。函数中的“*”代表任意字符,也就是说在A1:A7内查找B1文本前后任意字符的内容,也就是包含B1文本的意思。其中的1代表返回A1:A7数据区域第一列结果,最后一个逗号后省略参数代表的是精确匹配,也可以输入0或FALSE。

用法

函数计算方式

  • 向量:B2:B6 表示向量。
  • 数组计算:在公式最外有 {},快捷键为 ctrl+shift+enter

数组作为公式参数

=FIND({“杭州”;”湖州”;”嘉兴 “},B1),返回结果也是数组,因此显示为#VALUE!

快捷键

  • 绝对引用切换:选中范围按 F4
  • 显示公式内容:在单元格上按 F2
  • 单元格转数组:选中多个单元格按 F9
  • 公式求值:选中公式按 F9
  • 多个单元格填充:选中多个单元格按 ctrl+enter
  • 单元格定位:F5
  • 快速填充:Ctrl+E

简称ES6,ES2015。是是JavaScript语言的下一代标准。ECMAScript是JavaScript的规格,JavaScript是ECMAScript的一种实现。主流浏览器基本都兼容ES2015,通常开发环境用ES2015,借助Babel将ES2015编译成ES5部署在生产环境。
ES2105有很多新特性:let, const, class, extends, super, arrow functions, template string, destructuring, default, rest arguments

解构赋值

The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.

1
2
3
4
5
6
7
8
9
10
//数组解构赋值
let [a, ...b] = [1, 2, 3];
console.log(a); // 1
console.log(b); // [2, 3]

//对象解构赋值
let o={a:1,b:'b1',c:{ci:'cii'}}
let {a1,c}=o
console.log(a1);//undefined
console.log(c);//{ ci: 'cii' }

import()函数

import函数的参数specifier,指定所要加载的模块的位置。import命令能够接受什么参数,import()函数就能接受什么参数,两者区别主要是后者为动态加载。
import()类似于 Node 的require方法,区别主要是前者是异步加载,后者是同步加载。
ES6 import()返回一个 Promise 对象。

简洁对象定义

1
2
3
4
5
6
7
8
9
10
11
//简洁对象定义
let a = 'foo', b = 42, c = {};
let o = {a, b, c};
console.log(o);//{ a: 'foo', b: 42, c: {} }

//简洁函数定义
let f={
fun1(){
}
}
console.log(f);//{ fun1: [Function: fun1] }

对象属性动态定义

1
2
3
4
5
let lable='lable1'
let od={
[lable]:6378
}
console.log(od);//{ lable1: 6378 }

扩展运算符

Spread syntax allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected. rest 参数的逆运算。

1
2
3
4
let to={'a':'av','b':'bv'}
let ta=['1','2','3']
console.log([...ta,'4']);//[ '1', '2', '3', '4' ]
console.log({...to,'c':'cv');//es2018 下{'a':'av','b':'bv','c':'cv'}

地图前端现状

Openlayers

Openlayer目前最新为5.2.0,地图操作有比较全面,目前openlayer整合三维前端框架ol-cesium。目前有适用于Vue的Vuelayers

Leaflet

Leaflet目前最新为1.3.4,轻量级,适合用于移动端。

Vue

vue-router

静态路由若无redirect选项,刷新后,路由末尾后会自动加斜线,导致后退前进失败,例如

/resource/show会变为/resource/show/

通过addRoutes的动态路由无此问题

vue-x

  • state:保存数据
  • getters:进行类似map操作,store的computed属性。
  • mutations:commit,改变state数据,同步。
  • actions:dispatch,业务代码,调用多个mutations,异步。

axios

linqjs

font-awesome

echarts

rx

lodash

moment

IDEA 配置

语法高亮

  1. 支持Vue语法高亮:安装vuejs插件
  2. HTML标签高亮与自动补全:File | Settings | Editor | FileTypes | HTML 添加 *.vue

添加模板

File | Settings | Editor | File and Code Templates 添加下面为Vue创建模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template lang="html">
</template>

<script>
export default {
data() {
return {}
},
methods: {},
mounted() {

},
computed: {}
}
</script>

<style lang="css">
</style>

SCSS语法提示错误

  1. 在IDEA中,style标签中添加 type="text/scss" 属性
  2. 在VS Code其他等,style标签中添加 rel="stylesheet/scss" 属性
    为支持两者,标签如下:
1
<style rel="stylesheet/scss" lang="scss" type="text/scss">

Webpack alias支持

一般前端开发为适应多种场景,工程根目录不存在webpack.config.json,因此要在
File | Settings | Languages & Frameworks | JavaScript | Webpack
指定实际的webpack配置文件。

一般不设置webpack.dev.conf.js,设置webpack.base.conf.js ,如果仍然显示Module is not installed,重启IDEA即可。

前端问题

空子div的高度完全填充父div剩余部分

html结构为

1
2
3
4
<div id="main">
<div id="nav">nav</div>
<div id="content">content</div>
</div>

css为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/*方法1*/
html, body {
height: 100%;
margin: 0px;
padding: 0px;
}
#main {
background-color: #999;
height: 100%;
}
#nav {
background-color: #85d989;
width: 100%;
height: 50px;
}
#content {
background-color: #cc85d9;
width: 100%;
position: absolute;
top: 50px;
bottom: 0px;
}
/*方法2(省略与上相同部分)*/
#content {
background-color: #cc85d9;
width: 100%;
height: calc(100vh - 50px);/*该方法的减号前后必须要有空格*/
}
/*方法3(省略与上相同部分)*/
#nav {
background-color: #85d989;
width: 100%;
height: 50px;
float: left;
}
#content {
background-color: #cc85d9;
height:100%;
}

数据库设计通常包括:概念设计、逻辑设计和物理设计。

概念设计

概念设计是最顶层设计,包括实体、关系和约束。通常用E-R图表示,分局部E-R图和总E-R图,局部E-R图通常表示管理的一个或几个实体之间的关系及属性,总E-R图通常表示全部实体之间的关系,若实体较多忽略实体属性。若存在几个不相关的实体集,可分开表示,通常该处不表示数据字典。

概念设计图

逻辑设计

逻辑设计是概念设计的实施,表示与数据库类型无关的数据结构、数据类型、约束等相关描述。通常选择关系型数据模型,形式为二维表。

逻辑设计图

物理设计

物理设计是与选择数据库类型相关的具体实施,包括创建表结构、索引和约束等,形式为DDL描述的sql脚本。

1
2
3
4
5
6
7
8
9
CREATE TABLE Customer (
CustNo NUMBER NOT NULL,
CustName VARCHAR2(200) NOT NULL,
Street VARCHAR2(200) NOT NULL,
City VARCHAR2(200) NOT NULL,
State CHAR(2) NOT NULL,
Zip VARCHAR2(20) NOT NULL,
PRIMARY KEY (CustNo)
) ;

在封装地图前端API时,一开始在多层次深对象中无法获取类的实例变量,一开始用prototype上的一个属性代替,但是无法满足多个地图实例启动的要求,因为prototype属性是共享的。以下有三种解决方法。

在运行时绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function SubRun(input){
this._input=input;
}
SubRun.prototype.funs=function(){
const self=this;
return{
show:function(){
// console.log(this._input);
console.log(self._input);
}
}
}
let subRun=new SubRun("sub_run_example");
subRun.funs().show();

通过闭包返回一个函数可获取运行时指向实例的this,但是方法调用时多了一个括号,稍显麻烦。

使用Apply

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function SubApply(input){
this._input=input;
SuperApply.apply(this,arguments);
}
function SuperApply(input){
const self=this;
this._input=input;
this.base= {
show:function(){
console.log("from param: "+input);
console.log("from self: "+self._input);
}
};
this.funs={
show:function(){
console.log("from funs:");
self.base.show();
}
};
}
let subApply=new SubApply("sub_apply_example");
subApply.base.show();
subApply.funs.show();

改方法可解决this对象获取的问题,但是定义多个proto属性需重复写,不优雅。

使用Classs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
class SuperClass{
constructor(input){
this._input=input;
const self=this;
this.base= {
//使用lambda的方式获取this
show:()=>{
console.log("from param: "+input);
console.log("from self: "+this._input);
}
};
this.funs={
show:function(){
console.log("from funs lambda:");
self.base.show();
}
};
}
get self(){
return this;
}
get protoPropterty(){
// const self=this;
return {
property:()=>{
this.protoMethod();
console.log(this._input);
}
}
}
protoMethod(){
console.log("from proto :"+this._input);
}
}
class SubClass extends SuperClass{
constructor(input){
super(input);
this._input=input;
this.ori={
display:()=>{
console.log("from sub call");
this.funs.show();
}
}
}
}

let subClass=new SubClass("sub_class_example");
let subClass2=new SubClass("sub_class_example2");
// subClass.base.show();
// subClass.funs.show();
subClass.protoPropterty.property();
// subClass2.protoPropterty.property();
// subClass.protoMethod();
// subClass.ori.display();

若有多个原型属性,用const self=this的方法稍显繁琐,利用lambda的特性可在多层次深对象中直接获取指向实例的this。

idea

  • Ctrl+F12Alt+7 文件结构
  • Ctrl+Shift+E 最近更改的文件
  • Ctrl+Alt+B 跳转到方法实现处
  • Ctrl+”=/-” 当前方法展开、折叠
  • Ctrl+Shift+”=/-” 全部展开、折叠
  • Shift+F8 步出
  • Alt+F9 运行至光标处
  • Alt+2 收藏

linux

  • 查看一级目录大小:du -hd 1

tumx

  • ta 打开一个窗口
  • ts 创建一个窗口
  • tl 列出窗口
  • tkss 杀死一个窗口
  • tks 杀死全部

vim

  • /search_string\c 向下查找
  • ? 向上查找
  • :%s/foo/bar/gic 全局范围%查找foo并替换为bar,全局替换g,大小写敏感i,确认 c

nginx

  • nginx -V 查看详细信息(模块)

psql

  • sudo -u psql 进入psql
  • \l 列出数据库
  • \dt 列出表
  • \d [tablename] 列出表字段

regex

  • 部分替换

原始字符串:我是程序员
正则:(.*)(([^不是]|[^是]|)程序员)(.*)
替换为:$1工程师$4

  • 非捕捉组

Windows(?=95|98|NT|2000)
匹配 “Windows2000” 中的 “Windows”
不匹配 “Windows3.1” 中的 “Windows”

模式必须放后面(?=Windows)95无法匹配Windows95。
有回查类型的,例如:

2000(?<=Office|Word|Excel)
匹配 “ Office2000” 中的 “2000”
不匹配 “Windows2000” 中的 “2000”

但是回查类型的在Atom和Sublime Text3均无效。

记不住的

  • 开启SVN svnserve -d -r /mnt/d/svncode/project

其他

  • 批量重命名 for i infind -name ‘yale_*’;do mv $i ${i/yale/qsh};done
  • 批量替换文本内容 sed -i "s/yale/qsh/g" `grep yale -lr .`
  • 批量替换带空格的文件内容 grep "dc.zjchey.com" -lrZ hldc | xargs -0 sed -i "s/dc.zjchey.com/qsh.haies.cn/g"
  • docker输入宿主文件docker exec -i gogs-mysql mysql -uroot -pxxfY5019 gogs < win/gogs.sql
0%