一本码簿

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

本文实现了一套安全、模块化、生产端的 Nginx 反向代理方案,核心功能包括:

  1. 统一代理支持:通过 Nginx 同时提供 HTTP 和 TCP 反向代理;
  2. 真实客户端信息透传:使用标准代理头(如 X-Real-IP、X-Forwarded-For)确保后端服务获取原始请求信息;
  3. 跨域控制(CORS):允许所有域名跨域请求,但仅限 IP 白名单中的客户端;
  4. 独立 IP 白名单:通过单独的 geo 配置文件实现访问控制,默认拒绝所有非白名单 IP,支持动态更新无需重启;
  5. 全局限制策略:统一设置最大上传文件大小(10MB)和响应空闲超时(60秒);
  6. 按需缓存与维护模式:仅对 /api/ 接口启用缓存,并支持通过文件开关快速切换维护页面。

整套方案采用配置分离、职责清晰、Docker 友好的设计,兼顾安全性、可维护性与高性能,适用于企业级生产环境。

📁 整体目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/etc/nginx/
├── nginx.conf # 全局配置文件
├── conf.d/
│ ├── http.conf # HTTP代理配置
│ ├── db.stream # 数据库代理配置
│ └── maintenance.conf # 维护界面独立配置
├── security/
│ ├── blacklist.conf
│ ├── whitelist.conf
│ ├── rate-limiting.conf
│ ├── security_rules.conf
│ ├── security_checks.conf
│ ├── blacklist.ip
│ └── whitelist.ip
├── proxy_params # 通用代理头配置
├── cache_params # 缓存配置
└── cors_params # 跨域控制独立配置

1. 统一配置

1.1 TCP和HTTP配置(/etc/nginx/nginx.conf

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# 全局配置:TCP 代理和全局参数
stream {
# TCP 代理配置(独立于 HTTP)
include /etc/nginx/conf.d/*.stream;
}

http {
# === 全局控制(所有 HTTP 代理生效) ===
include /etc/nginx/mime.types;
default_type application/octet-stream;

# 性能优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain application/json text/css application/javascript;
keepalive_timeout 65;
keepalive_requests 1000;
types_hash_max_size 2048;
server_tokens off;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;

# 超时控制
proxy_connect_timeout 30s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;

# 缓冲区优化
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
proxy_temp_file_write_size 8k;

# 上传文件控制
client_max_body_size 500M;
client_body_buffer_size 1m;
client_body_temp_path /tmp/nginx_body;
client_body_timeout 300s;
proxy_request_buffering on;

set $block_access 0;
set $block_reason "";

# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';

log_format security 'time=$time_iso8601 client=$realip_remote_addr '
'xff="$http_x_forwarded_for" method=$request_method '
'uri="$request_uri" status=$status '
'user_agent="$http_user_agent" '
'blocked=$block_access block_reason=$block_reason '
'rate_limit=$rate_limit_zone cache_status=$upstream_cache_status';

log_format json_combined escape=json
'{"time":"$time_iso8601",'
'"remote_addr":"$realip_remote_addr",'
'"x_forwarded_for":"$http_x_forwarded_for",'
'"method":"$request_method",'
'"uri":"$request_uri",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"request_time":$request_time,'
'"http_referrer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"is_whitelisted":$whitelist_ip,'
'"is_blacklisted":$blacklist_ip}';

# 访问日志
access_log /var/log/nginx/access.log main buffer=32k flush=5s;
access_log /var/log/nginx/security.log security;
access_log /var/log/nginx/audit/audit-$(date +%Y-%m-%d).log json_combined;
error_log /var/log/nginx/error.log warn;

# 真实IP处理(去掉SLB、CDN等内网IP)
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

# 通用代理头(复用)
include proxy_params;

# === 接口缓存配置(全局定义,独立文件生效) ===
# 缓存配置
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m
max_size=1g inactive=60m use_temp_path=off;
proxy_cache_path /var/cache/nginx/static levels=1:2 keys_zone=static_cache:100m
max_size=10g inactive=365d use_temp_path=off;

# 限制并发连接数
limit_conn_zone $binary_remote_addr zone=per_ip:10m;
limit_conn_zone $server_name zone=per_server:10m;

# 包含安全配置
include /etc/nginx/security/*.conf;

# 包含所有独立配置
include /etc/nginx/conf.d/*.conf;
}

💡 关键配置

  • TCP 代理独立在 stream 块(不能与 HTTP 混合)
  • 全局上传大小/超时设置在 http 块(避免重复配置)
  • 缓存路径全局定义,独立配置文件只指定作用域
  • 缓存路径 /var/cache/nginx 需在 Docker 容器中挂载(-v /host/cache:/var/cache/nginx

1.2 传递客户端的真实信息配置(/etc/nginx/proxy_params

1
2
3
4
5
6
7
8
9
# /etc/nginx/proxy_params
proxy_http_version 1.1;
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;
proxy_set_header X-Forwarded-Server $hostname;

1.3 HTTP接口缓存配置(/etc/nginx/cache_params

1
2
3
4
5
6
7
# /etc/nginx/cache_params
proxy_cache api_cache;
proxy_cache_valid 200 302 1d; # 200/302 缓存 1 天
proxy_cache_valid 404 1m; # 404 缓存 1 分钟
proxy_cache_use_stale error timeout updating;
proxy_cache_background_update on;
proxy_cache_lock on;

💡 缓存机制

  • 200/302 响应缓存 1 天(86400 秒)
  • 404 响应缓存 1 分钟
  • 缓存过期后,若后端返回 200 则更新缓存

1.4 CORS跨域控制配置/etc/nginx/cors_params

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# /etc/nginx/cors_params
# 允许所有域名(CORS 配置)
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-SinceCache-Control,Content-Type,Authorization' always;

# 处理预检请求
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-WithIf-Modified-Since,Cache-Control,Content-Type,Authorization' always;
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}

💡 关键配置

  • always 参数确保响应头始终添加(避免缓存干扰)

2. 独立代理配置文件(/etc/nginx/conf.d/

✅ 2.1 HTTP 代理(http.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 仅处理特定域名的 HTTP 代理
server {
listen 80;
server_name api.example.com;

location / {
# 限流(白名单豁免)
if ($rate_limit_exempt != 1) {
limit_req zone=$rate_limit_zone burst=20 nodelay;
limit_req_status 429;
}
proxy_pass http://backend:8080; # Docker 服务名
include cache_params;
}
}

✅ 2.2 TCP代理(db.conf

1
2
3
4
5
6
7
8
9
10
11
    upstream mysql_backend {
server db:3306; # Docker 服务名
}

server {
listen 3306;
proxy_pass mysql_backend;
proxy_connect_timeout 1s; # TCP 连接超时
proxy_timeout 10s; # TCP 响应超时
}
}

✅ 2.3 维护界面(maintenance.conf

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
# 仅对根路径生效(维护模式时重定向)
server {
# 维护模式开关
set $maintenance_mode off;

# 通过环境变量控制维护模式
if ($maintenance_mode = on) {
return 503;
}

# 维护页面配置
error_page 503 @maintenance;
location @maintenance {
# 静态维护页面
root /usr/share/nginx/html;
try_files /maintenance.html =503;

# 或者重定向到外部维护页面
# return 307 https://maintenance.example.com;
}

# API特殊处理(返回JSON)
location /api/ {
if ($maintenance_mode = on) {
add_header Content-Type application/json;
return 503 '{"status":503,"message":"系统维护中,请稍后再试"}';
}

proxy_pass http://backend-service:8080;
}
}

3. 安全配置文件(/etc/nginx/security/

✅ 3.1 限流控制(rate-limiting.conf

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
# /etc/nginx/security/rate-limiting.conf

# 限流区域定义
limit_req_zone $binary_remote_addr zone=global_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=3r/m;
limit_req_zone $binary_remote_addr zone=search_limit:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=static_limit:10m rate=500r/s;

# 基于请求URI的限流区域映射
map $request_uri $rate_limit_zone {
default global_limit;

# API接口
~*/api/v1/ api_limit;
~*/api/v2/ api_limit;

# 认证接口
~*/auth/login login_limit;
~*/oauth/token login_limit;
~*/user/login login_limit;

# 搜索接口
~*/search search_limit;
~*/query search_limit;
~*/find search_limit;

# 静态资源
~*\.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ static_limit;

# 管理接口
~*/admin/ global_limit;
~*/system/ global_limit;
}

# 白名单不限流
map $whitelist_ip $rate_limit_exempt {
0 0;
1 1;
}

# 连接数限制
limit_conn per_ip 10;
limit_conn per_server 1000;

✅ 3.2 黑白名单控制(blacklist.confwhitelist.conf

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
# /etc/nginx/security/blacklist.conf

# 全局黑名单设置
geo $blacklist_ip {
default 0;

# 动态黑名单(从文件读取)
include /etc/nginx/security/blacklist.ip;

# 静态黑名单
10.0.0.0/8 1;
192.168.1.100 1;
172.16.0.0/12 1;
}

# /etc/nginx/security/whitelist.conf
# 全局白名单设置
geo $whitelist_ip {
default 0;

# 动态白名单(从文件读取)
include /etc/nginx/security/whitelist.ip;

# 静态白名单
10.0.0.0/8 1;
192.168.1.100 1;
172.16.0.0/12 1;
}

# API白名单路径
map $request_uri $whitelist_path {
default 0;

# 健康检查
/health 1;
/status 1;
/ping 1;

# 监控
/metrics 1;
/nginx-status 1;

# 静态资源
~*\.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|mp4|webm|mp3)$ 1;

# 公开API
/api/v1/public/ 1;
/api/v1/docs 1;
/swagger-ui 1;

# 机器人协议
/robots.txt 1;
/sitemap.xml 1;
/favicon.ico 1;
}
1
2
3
4
5
6
7
8
9
10
# /etc/nginx/security/blacklist.ip(whitelist.ip)

# 格式:IP/CIDR 标志值;
# 可以通过脚本动态更新

# 恶意IP示例
203.0.113.1 1;
198.51.100.0/24 1;
10.20.30.40 1;

✅ 3.3 综合安全控制(blacklist.conf

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# security/security-rules.conf


# 恶意User-Agent检测
map $http_user_agent $bad_bot {
default 0;

# 已知恶意爬虫
~*(ahrefs|mj12bot|semrushbot|masscan) 1;
~*(sqlmap|nmap|nikto|dirbuster) 1;
~*(nessus|openvas|acunetix|nessus) 1;

# 垃圾机器人
~*(spammer|scraper|harvest|collector) 1;

# 可疑模式
~*[0-9]{10}bot 1;
~*bot[0-9]{10} 1;
"" 1;

# 允许的友好爬虫
~*(baiduspider|googlebot|bingbot|yandexbot|duckduckbot) 0;
~*(slurp|twitterbot|facebookexternalhit|linkedinbot) 0;

# 正常浏览器和工具
~*(Mozilla|Chrome|Safari|Firefox|Edge|Opera) 0;
~*(curl|wget|python-requests|PostmanRuntime) 0;
}

# 恶意请求检测
map $request_uri $bad_request {
default 0;

# 路径遍历
~*(\.\./|\.\.\\|/%2e%2e|/%252e%252e) 1;

# 敏感文件
~*(/etc/passwd|/etc/shadow|/proc/self|/etc/hosts) 1;
~*(\.git/|\.svn/|\.hg/|\.bzr/|\.DS_Store) 1;
~*(\.env|config\.php|settings\.py|web\.config) 1;

# 管理后台
~*(phpmyadmin|adminer|wp-admin|/admin/login|/manager/html) 1;

# SQL注入模式
~*(union\s+select.*from) 1;
~*(sleep\(|benchmark\(|waitfor\s+delay) 1;
~*(load_file\(|into\s+outfile|into\s+dumpfile) 1;
~*(select\s+.*from.*where.*=.*\() 1;

# XSS攻击
~*(<script|javascript:|onload=|onerror=|alert\(|confirm\(|prompt\() 1;

# 命令注入
~*(\|\s*sh|\|\s*bash|\|\s*cmd|\;\s*rm\s+|\;\s*wget\s+) 1;

# 可疑文件
~*\.(asp|aspx|jsp|php|pl|py|sh|cgi|exe|dll|bat|cmd)$ 1;

# 扫描特征
~*(/w00tw00t|test.cgi|xmlrpc.php|/vendor/phpunit) 1;
}

# 错误页面映射
map $block_reason $block_error_page {
default /errors/403.html;
"blacklist_ip" /errors/403.html;
"bad_bot" /errors/444.html;
"bad_request" /errors/403.html;
"rate_limit" /errors/429.html;
"whitelist_only" /errors/403.html;
}

# 访问控制决策
map "$whitelist_ip:$maintenance_mode" $access_allowed {
# 规则优先级:白名单 > 维护模式

# 1. 白名单IP直接允许(即使维护模式)
"~^1:.+" 1;
# 2. 其他情况拒绝
default 0;
}

# 维护模式检测
map $maintenance_mode $is_maintenance {
default 0;
"on" 1;
"yes" 1;
"true" 1;
"1" 1;
}

✅ 3.4 安全检查(security-checks.conf

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
# security/security-checks.conf

# 初始化阻塞原因
set $block_reason "";
set $block_access 0;

# 1. 白名单路径检查(直接通过)
if ($whitelist_path = 1) {
set $block_access 0;
return 200; # 继续处理请求,但标记为不阻止
}

# 2. 访问控制决策
if ($access_allowed = 0) {
set $block_access 1;

if ($whitelist_ip = 0) {
set $block_reason "whitelist_only";
}

if ($maintenance_mode = "on" && $whitelist_ip = 0) {
set $block_reason "maintenance_mode";
return 503;
}
}

# 3. 黑名单检查(白名单可以覆盖)
if ($whitelist_ip != 1) {
if ($blacklist_ip = 1) {
set $block_access 1;
set $block_reason "blacklist_ip";
access_log /var/log/nginx/blocked.log security;
return 403;
}
}

# 4. 恶意User-Agent检查
if ($bad_bot = 1) {
set $block_access 1;
set $block_reason "bad_bot";
access_log /var/log/nginx/bad_bots.log combined;
return 444;
}

# 5. 恶意请求检查
if ($bad_request = 1) {
set $block_access 1;
set $block_reason "bad_request";
access_log /var/log/nginx/attack.log combined;
return 403;
}

🐳 Docker 部署关键配置

1. 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
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
56
57
58
59
60
61
62
# docker-compose.yml
version: '3.8'

services:
nginx:
build: .
container_name: nginx-proxy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
environment:
- NGINX_ENV=production
- BACKEND_SERVICE=backend:8080
- MAINTENANCE_MODE=${MAINTENANCE_MODE:-off}
- API_KEY_WHITELIST=${API_KEY_WHITELIST:-}
- INTERNAL_NETWORK=172.16.0.0/12
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./conf.d:/etc/nginx/conf.d:ro
- ./security:/etc/nginx/security:ro
- ./templates:/etc/nginx/templates:ro
- ./ssl:/etc/nginx/ssl:ro
- ./html:/usr/share/nginx/html:ro
- ./logs:/var/log/nginx
- ./scripts:/scripts:ro
- dynamic_data:/etc/nginx/dynamic
networks:
- proxy-network
healthcheck:
test: ["CMD", "/scripts/health-check.sh"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

backend:
image: ${BACKEND_IMAGE:-your-backend:latest}
container_name: backend-app
restart: unless-stopped
environment:
- VIRTUAL_HOST=app.example.com
- VIRTUAL_PORT=8080
networks:
- proxy-network
expose:
- "8080"

networks:
proxy-network:
driver: bridge
ipam:
config:
- subnet: 172.16.0.0/12

volumes:
dynamic_data:

2. nginx容器Dockerfile

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
56
57
58
59
60
61
62
63
64
65
# Dockerfile
FROM nginx:1.24-alpine

# 安装必要工具
RUN apk add --no-cache \
curl \
jq \
certbot \
certbot-nginx \
bash \
gettext \
openssl \
geoip \
geoip-dev \
libmaxminddb \
libmaxminddb-dev \
&& rm -rf /var/cache/apk/*

# 安装nginx模块
RUN apk add --no-cache nginx-mod-http-geoip2

# 创建目录结构
RUN mkdir -p \
/etc/nginx/security \
/etc/nginx/dynamic \
/etc/nginx/templates \
/usr/share/nginx/html/errors \
/scripts \
/var/log/nginx/audit

# 复制配置文件
COPY nginx.conf /etc/nginx/
COPY conf.d/ /etc/nginx/conf.d/
COPY security/ /etc/nginx/security/
COPY templates/ /etc/nginx/templates/
COPY ssl/ /etc/nginx/ssl/
COPY html/ /usr/share/nginx/html/
COPY scripts/ /scripts/

# 设置权限
RUN chmod +x /scripts/*.sh \
&& chown -R nginx:nginx /var/log/nginx \
&& chmod 600 /etc/nginx/security/.htpasswd \
&& chmod 644 /etc/nginx/security/*.map \
&& chmod 755 /etc/nginx/dynamic

# 生成SSL证书(如果不存在)
RUN if [ ! -f /etc/nginx/ssl/cert.pem ]; then \
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/key.pem \
-out /etc/nginx/ssl/cert.pem \
-subj "/C=CN/ST=State/L=City/O=Organization/CN=localhost"; \
fi

# 生成强DH参数
RUN if [ ! -f /etc/nginx/ssl/dhparam.pem ]; then \
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048; \
fi

# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD /scripts/health-check.sh

# 启动脚本
ENTRYPOINT ["/scripts/entrypoint.sh"]

🛠️ 生产环境验证建议

  1. 测试跨域

    1
    curl -H "Origin: https://frontend.example.com" -X OPTIONS http://api.example.com/api/test

    应返回 204 No Content 且包含 CORS 头

  2. 测试维护模式

    1
    2
    3
    4
    5
    6
    # 启用维护
    export MAINTENANCE_MODE=on


    # 访问应返回 503
    curl -I http://example.com
  3. 测试缓存

    1
    2
    3
    4
    5
    # 第一次请求(应返回 200)
    curl -I http://api.example.com/api/data

    # 第二次请求(应返回 200 from cache)
    curl -I http://api.example.com/api/data

✅ 总结

功能 位置 作用范围 Docker 适配关键点
TCP 代理 nginx.conf (stream) 全局 独立于 HTTP,端口映射 3306:3306
上传大小/超时 nginx.conf (http) 全局 全局生效,避免重复配置
HTTP 代理 http_proxy.conf 按域名生效 通过 Docker 网络解析服务名
跨域控制 cors.conf /api/ always 参数确保头始终添加
接口缓存 cache.conf /api/ 缓存路径挂载到主机,避免容器重启丢失
维护界面 maintenance.conf 仅根路径 通过文件开关,无需重启 Nginx

💡 为什么这样设计?

  1. 全局配置:TCP 和基础参数(上传/超时)放在全局,避免重复且易于全局调整
  2. 独立文件:每个功能模块独立配置,符合“单一职责原则”
  3. Docker 适配
    • 所有挂载路径(/var/cache/nginx, /var/www/maintenance)在主机定义
    • 服务名通过 Docker 网络自动解析(backend:8080
    • 维护模式通过文件开关,无需修改 Nginx 配置

1. 相对于Docker的核心优势

基于 nerdctl(容器CLI工具)和 containerd(行业标准容器运行时)的容器化部署栈,是现代化、云原生优先的架构选择。相较于传统的Docker引擎,其核心优势体现在架构、性能、安全性和生态集成等多个维度。

特性维度 Nerdctl + Containerd Docker Engine 优势分析与影响
架构与定位 模块化、解耦。Containerd作为底层运行时,Nerdctl为兼容Docker CLI的客户端工具。 单体、一体化。Docker Daemon (dockerd) 集成了运行时、构建、网络、存储等多种功能。 更轻量、更专注。Containerd仅负责核心的容器生命周期管理,减少了攻击面和资源开销,符合Unix哲学。
与Kubernetes集成 原生、深度集成。Kubernetes通过Container Runtime Interface (CRI) 直接调用Containerd 间接、桥接。历史上通过dockershim(已弃用),现需额外组件cri-dockerd桥接。 路径更短、更稳定高效。作为K8s默认运行时,移除中间层,减少了故障点,是生产集群的官方推荐方案
资源占用 极低。仅包含核心运行时,无冗余守护进程。 较高。包含完整的Docker Daemon及其附加功能。 显著节省系统资源,尤其适用于大规模集群、边缘计算和资源受限环境。
安全模型 强大的Rootless容器支持。利用RootlessKit和用户命名空间映射,实现非特权用户运行容器,极大提升安全性 Rootless模式相对成熟但集成度与生态稍逊。 有效遏制容器逃逸风险,将安全漏洞的影响范围限制在非特权用户内,是生产环境关键安全实践
核心特性 1. 命名空间隔离:支持多租户(如隔离k8s.io和默认命名空间)。
2. 延迟拉取(Stargz):加速大镜像启动。
3. 镜像加密等实验性功能。
生态成熟,桌面体验和开发者工具链(如Docker Compose)完善。 更专注于探索容器技术前沿,与K8s原生特性(如多租户)结合更紧密。
CLI兼容性 Nerdctl命令与 docker 命令高度兼容,支持绝大部分常用命令和标志。 拥有最完整、统一的命令行生态。 学习迁移成本极低,熟悉Docker的用户可以几乎无缝切换。

2. 安装与设置步骤(基于nerdctl-full一体包)

nerdctl-full发行版包含了运行完整容器环境所需的所有组件(containerd, nerdctl, CNI插件, BuildKit, RootlessKit等),是推荐的部署方式。

2.1 系统依赖与环境准备

确保系统已安装基础依赖,这些通常是现代Linux发行版的标配。

1
2
3
4
5
# 基于Debian/Ubuntu
sudo apt-get update
sudo apt-get install -y libseccomp2 socat iproute2 iptables
# 基于RHEL/CentOS/Fedora
sudo yum install -y libseccomp socat iproute iptables

2.2 核心安装与初始化

  1. 下载并解压 nerdctl-full
    访问 nerdctl GitHub Releases 获取最新稳定版。

    1
    2
    3
    export NERDCTL_VERSION="1.7.6" # 请替换为最新版本
    wget "https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION}/nerdctl-full-${NERDCTL_VERSION}-linux-amd64.tar.gz"
    sudo tar Cxzvf /usr nerdctl-full-${NERDCTL_VERSION}-linux-amd64.tar.gz
  2. 生成配置并启动Containerd服务

    1
    2
    3
    4
    5
    6
    7
    # 生成默认配置文件
    sudo containerd config default > /etc/containerd/config.toml
    # 编辑配置文件(详见第3部分)
    sudo vi /etc/containerd/config.toml
    # 启动并设置开机自启
    sudo systemctl daemon-reload
    sudo systemctl enable --now containerd
  3. 验证基础安装

    1
    2
    3
    sudo containerd --version
    nerdctl version
    sudo nerdctl run --rm hello-world # 运行测试容器

2.3 服务管理

  • Containerd服务

    1
    2
    3
    sudo systemctl status containerd
    sudo systemctl restart containerd
    sudo journalctl -u containerd -f # 查看日志
  • BuildKit服务(用于镜像构建):
    nerdctl-full包含BuildKit,建议启用其服务以支持nerdctl build

    1
    sudo systemctl enable --now buildkit

2.4 设置Rootless无根模式(关键安全实践)

允许非root用户安全地运行容器,是生产环境的重要安全加固步骤。

  1. 安装用户态依赖

    1
    2
    3
    4
    # Ubuntu/Debian
    sudo apt-get install -y uidmap slirp4netns fuse-overlayfs
    # RHEL/Fedora/CentOS
    sudo yum install -y shadow-utils slirp4netns fuse-overlayfs
  2. 执行Rootless安装脚本
    nerdctl-full包内提供了便捷的设置工具。

    1
    containerd-rootless-setuptool.sh install

    该脚本会自动配置用户命名空间、cgroup委托等。安装后,注销并重新登录使用户组变更生效。

  3. 验证与使用Rootless模式

    1
    2
    3
    4
    # 以普通用户身份操作
    id # 确认用户
    nerdctl run -d -p 8080:80 --name my-nginx nginx:alpine
    nerdctl ps

    重要:Rootless模式下,容器网络、端口映射(通常只支持>1024的端口)、存储驱动(如fuse-overlayfs)与特权模式有所不同,需适应。

3. Containerd常用配置 (/etc/containerd/config.toml)

config.toml是Containerd的核心配置文件。以下为关键配置项,修改后需执行 sudo systemctl restart containerd

配置分类 配置项路径 (TOML) 推荐值/示例 作用说明
镜像仓库代理/加速 plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io" endpoint = ["https://<your-mirror>"] 配置国内镜像加速器(如阿里云、中科大源),解决拉取慢问题。
日志配置 plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options SystemdCgroup = true 可配置容器日志的格式、大小和保留策略。
数据存储目录 root /var/lib/containerd Containerd工作根目录。可更改为更大容量的磁盘路径。
私有仓库认证 plugins."io.containerd.grpc.v1.cri".registry.configs."myreg.com".auth username="<user>", password="<pass>" 配置访问私有镜像仓库的认证信息。支持credsStore使用本地凭证助手。
Sandbox 镜像 plugins."io.containerd.grpc.v1.cri".sandbox_image registry.aliyuncs.com/google_containers/pause:3.9 替换K8s Pod基础镜像,通常用于解决gcr.io访问问题。
Cgroup 驱动 plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options.SystemdCgroup true 必须与Kubelet的cgroup驱动一致。对于使用systemd作为init系统的发行版,设为true
运行时数据目录 state /run/containerd 运行时状态目录。
默认运行时 plugins."io.containerd.grpc.v1.cri".containerd.default_runtime name = "runc" 设置默认的底层OCI运行时(如runc, kata, gVisor)。

配置片段示例(镜像加速与cgroup驱动)

1
2
3
4
5
version = 2
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://registry-1.docker.io", "https://mirror.ccs.tencentyun.com"]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true

4. 容器管理与编排常用命令

4.1 基本容器管理(类比Docker)

nerdctl命令与docker高度相似,以下为常用操作:

功能 Nerdctl命令示例 说明
拉取镜像 nerdctl pull nginx:alpine 从仓库拉取镜像。
运行容器 nerdctl run -d --name web -p 80:80 nginx:alpine 后台运行容器并映射端口。
列出容器 nerdctl ps -a 查看所有容器(含停止的)。
执行命令 nerdctl exec -it web sh 进入运行中的容器。
查看日志 nerdctl logs -f web 跟踪容器日志。
停止/删除 nerdctl stop web && nerdctl rm web 停止并删除容器。
构建镜像 nerdctl build -t myapp:latest . 使用当前目录Dockerfile构建镜像(需BuildKit服务)。
镜像管理 nerdctl images, nerdctl rmi <image> 列出、删除镜像。

4.2 关键概念:命名空间管理

这是与Docker管理上最重要的区别。Containerd使用命名空间隔离容器、镜像等资源。Kubernetes创建的Pod默认都在k8s.io命名空间

  • 为Kubernetes准备镜像

    1
    2
    nerdctl -n k8s.io pull nginx:alpine  # 拉取镜像到k8s.io命名空间
    nerdctl -n k8s.io images # 查看供K8s使用的镜像
  • 调试Kubernetes Pod

    1
    2
    nerdctl -n k8s.io ps -a | grep <pod-name>  # 查找对应容器
    nerdctl -n k8s.io logs <container-id> # 查看容器日志
  • 管理独立容器(非K8s管理):默认在default命名空间,可省略-n default

4.3 容器编排:Nerdctl Compose

nerdctl支持docker-compose.yml格式的编排文件,用于本地多容器应用管理。

1
2
3
4
5
6
7
8
# 启动一个Compose项目(需在docker-compose.yml所在目录)
nerdctl compose up -d
# 查看状态
nerdctl compose ps
# 停止并清理
nerdctl compose down
# 查看日志
nerdctl compose logs -f

4.4 网络与数据卷管理

  • 网络nerdctl默认使用CNI插件管理容器网络。

    1
    2
    nerdctl network ls                 # 列出网络
    nerdctl network create my-net # 创建自定义网络
  • 数据卷

    1
    2
    nerdctl volume create my-vol       # 创建数据卷
    nerdctl volume ls # 列出数据卷

总结与建议

  1. 场景选择:若你的工作流深度依赖Kubernetes,或追求极致的轻量化和安全性nerdctl+containerd是理想选择。若开发环境需要一体化的桌面体验和图形界面,Docker Desktop仍有其价值。
  2. 运维核心
    • 牢记命名空间:区分管理k8s.io和默认命名空间的资源。
    • 拥抱Rootless:生产环境应优先采用Rootless模式运行非特权容器。
    • 善用config.toml:正确配置镜像加速、cgroup驱动和私有仓库是稳定运行的基础。
  3. 迁移路径:从Docker迁移时,建议先在测试环境熟悉nerdctl命令和命名空间概念,并严格按照kubelet配置变更流程操作。

该技术栈代表容器运行时的发展方向,随着Kubernetes的统治地位日益巩固,containerd作为其默认运行时,与配套工具nerdctl的协同将变得更加普遍和重要。

前端

  1. 了解Vue.js
  2. 了解vue-element-admin
  3. 掌握ES2015基本用法及新属性
  4. 了解Mapbox地图库
  5. 了解WebPack及常用

后端

  1. 了解CentOS、Nginx、Postgres基本运维操作。
  2. 掌握Docker、Docker-compose工具基本使用方法。
  3. 掌握Springboot、Mybatis、logback、AOP、消息队列、异步、定时任务等内容。
  4. 掌握 Maven、Http Client等工具使用。
  5. 掌握 IntelliJ Idea操作及常用快捷键。

工具

  1. 掌握 IntelliJ Idea操作及常用快捷键。
  2. 掌握 VS Code操作及常用快捷键。
  3. 掌握git分支管理、代码合并、冲突解决等内容。

网络安全

禁止登录或设置弱口令账户(包括第三方网站),禁止传送包含绝密、机密、秘密等字样的标密文档(包括第三方文档),禁止政务网电脑同时接互联网,禁止使用向日葵、TeamViewer等远程工具,禁止使用翻墙工具,禁止使用内网穿透工具,禁止访问不明来源网站。

弱口令规则:
1.小于8位
2.不足三类,大小字母,数字,符号
3.包含用户名
4.包含4个及以上的连续字符,数字
5.包含3个及以上相同的字符、数字
6.包含4个键盘上连续的字符
7.属于常用密码

注意事项:

系统运维安全注意事项
网络终端安全注意事项

重复文件目录分析及删除

1
wget -qO- https://haies.cn/assets/deduplicate.sh

递归分析指定目录下的重复文件和目录,根据用户选择执行删除或仅记录日志。

1
deduplicate [-d] dir1 [dir2 ...]
  • -d:启用删除模式,不添加时仅记录日志
  • dir1 dir2 ...:待分析的目录路径(绝对或相对路径,至少指定一个)

每个目录独立处理并生成日志文件。


跨平台文件和目录名称有效性检测

1
wget -qO- https://haies.cn/assets/checkname.js

递归分析指定目录下的重复文件和目录,根据用户选择执行删除或仅记录日志。

1
deduplicate [-d] dir1 [dir2 ...]
  • -d:启用删除模式,不添加时仅记录日志
  • dir1 dir2 ...:待分析的目录路径(绝对或相对路径,至少指定一个)

每个目录独立处理并生成日志文件。


单目录智能压缩解压

1
wget -qO- https://haies.cn/assets/tar_single.sh

大容量单目录分卷压缩、解压工具。

1
./tar_single.sh -[操作方式][压缩算法] [操作对象]
  • 操作方式c创建、x解压、t测试
  • 压缩算法z gzip(默认)、s zstd(推荐)、o xz(高压缩比)
1
2
3
4
5
6
7
8
9
10
# 创建压缩包
./tar_single.sh -cz /path/to/data # gzip
./tar_single.sh -cs /path/to/data # zstd
./tar_single.sh -co /path/to/data # xz

# 解压压缩包(自动检测格式)
./tar_single.sh -x /path/to/archive_dir

# 测试完整性(自动检测格式)
./tar_single.sh -t /path/to/archive_dir

存档批量压缩

1
wget -qO- https://haies.cn/assets/tar_batch.sh

智能压缩文件数量较多的目录,自动根据深度和文件数量应用压缩规则,排除文档、图片、视频、音频等类型,适合日志目录、临时文件等大量小文件场景。

1
./tar_batch.sh [目标目录]
  • 不指定目录时默认处理脚本所在目录
  • 处理深度 3-5 级,按从浅到深顺序
1
2
./tar_batch.sh              # 压缩当前目录
./tar_batch.sh /path/to/your/data # 压缩指定目录

执行后生成:单卷包目录名.tar.gz或多卷包目录名_archive/文件夹。终端显示压缩进度,生成带时间戳的日志文件。


SVN服务器端工具

1
wget -qO- https://haies.cn/assets/svn_server_tool.sh

在服务器端直接查看和统计 SVN 代码仓库信息,无需通过客户端连接。

1
./svn_server_tool.sh <功能> <仓库路径> [目录/文件路径]
  • 功能参数ls列出目录、log查看历史、stat统计提交
  • 仓库路径:SVN 仓库物理路径,如/var/svn/repos/myproject
  • 目标路径ls为可选,logstat为必填(仓库内相对路径)
1
2
3
4
./svn_server_tool.sh ls /var/svn/repos/myproject
./svn_server_tool.sh ls /var/svn/repos/myproject /trunk/src
./svn_server_tool.sh log /var/svn/repos/myproject /trunk/src
./svn_server_tool.sh stat /var/svn/repos/myproject /trunk/src/main.java

PPT备注批量提取

1.打印为PDF文件,并选择打印内容为备注页
alt text

2.打开PDF文件,Ctrl+A,Ctrl+C即可复制出全部的备注内容。

3.制作页面合适的带备注的PDF版本PPT
根据第一步打印出来的PDF文件一般为A4,页面有大量空白,选择备注最多的页面,通过WPS裁切页面功能,设定固定裁切范围,可批量把所有页面的留白去掉。
alt text

WPS安装字体

1️⃣ 鸿蒙4.2

  1. 在 文件管理 中打开 显示隐藏文件 和 显示系统隐藏文件 菜单。
    显示隐藏
  2. 把字体文件(.ttf/.otf)放进手机存储的 内部存储/Fonts 文件夹(没有就新建一个),该规则全局生效,对所有支持的APP都生效。
    全局字体
  3. 针对PC应用,把字体文件放到 内部存储/PCEngine/.fonts 文件夹(没有就新建一个),该规则对PC应用引擎下的APP生效,也就是wps office pc版生效。(小米澎湃OS对应位置内部存储/HyperEngine/fonts/
    PC引擎字体
  4. 重启APP生效。

2️⃣ 鸿蒙5+

鸿蒙5+平板和电脑支持可选择第三方字体安装,手机上仅支持在线字体安装。
平板字体安装

统信桌面操作系统V20专业版1070(UOS V20 1070)于 2024年05月06日正式发布,与Debian buster、Ubuntu 20.04 LTS(Focal Fossa )软件包版本和依赖关系相似,其核心组件版本如下:

组件 版本
Linux 4.19.0
glibc 2.28.31-deepin1
glib 2.58.3.16-deepin1
libgcc 8.3.0.13-deepin1
systemctl 241

安装QGIS

通过官方源安装Debian Buster版本的 QGIS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

sudo apt install gnupg software-properties-common;
sudo mkdir -m755 -p /etc/apt/keyrings;
sudo wget -O /etc/apt/keyrings/qgis-archive-keyring.gpg https://download.qgis.org/downloads/qgis-archive-keyring.gpg;

sudo tee /etc/apt/sources.list.d/qgis.list <<'EOF'
Types: deb deb-src
URIs: https://qgis.org/debian-ltr
Suites: buster
Architectures: amd64
Components: main
Signed-By: /etc/apt/keyrings/qgis-archive-keyring.gpg
EOF;

sudo apt update;
sudo apt install qgis qgis-plugin-grass;
sudo apt install qgis-server;

以上一键安装脚本

1
sh -c "$(wget -qO- https://haies.cn/assets/install-qgis-uos.sh)"

安装KVM

UOS 编译安装KVM

本教程实现在 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

0%