作者归档:songtianlun

快速感受编程乐趣的编程语言推荐

快速看到效果对于感受编程乐趣非常重要,最近看完《计算机是怎样运行的》,推荐想要快速看到效果可以使用 VB。我认为这非常重要,现在编程语言非常多,但是能够稳定复现可以看到效果的,VB这样的方案是很少见的。如果没有可以运行 VB 的环境,可以尝试 PyQt 来查看效果。下面用 Claude4 生成了一篇文章,给大家做参考。如果想要快速体验到编程的乐趣,可以看一看。

编程的魅力在于能够用代码创造出实用的程序,看到自己的想法变成现实。对于初学者来说,选择一门合适的编程语言至关重要——它应该能让你快速上手,立刻看到成果,从而激发学习的兴趣。本文将介绍几种特别适合快速感受编程乐趣的语言。

什么是”快速感受编程乐趣”?

在深入具体语言之前,我们需要明确什么叫”快速感受编程乐趣”。理想的入门语言应该具备以下特点:

  • 即时反馈:写完代码能立刻看到运行结果
  • 简洁语法:不需要复杂的样板代码就能实现功能
  • 可视化效果:能够创建图形界面或动态效果
  • 学习曲线平缓:语法接近自然语言,容易理解
  • 丰富的库支持:有大量现成的工具可以直接使用

推荐语言列表

1. Python 🐍

推荐指数:⭐⭐⭐⭐⭐

Python 无疑是最适合初学者的语言之一。它的语法简洁优雅,几乎就像写英语一样自然。

优势:

  • 语法简单,可读性强
  • 交互式环境,可以立即测试代码片段
  • 丰富的第三方库(pygame用于游戏开发,matplotlib用于数据可视化)
  • 应用领域广泛:网站开发、数据分析、人工智能等

快速上手示例:

# 5行代码画一个彩色螺旋
import turtle
for i in range(100):
    turtle.circle(i)
    turtle.right(91)

2. Scratch 🎨

推荐指数:⭐⭐⭐⭐⭐

Scratch是MIT开发的可视化编程语言,特别适合完全零基础的初学者。

优势:

  • 拖拽式编程,无需输入代码
  • 即时预览,所见即所得
  • 丰富的多媒体支持(声音、图像、动画)
  • 社区活跃,有大量优秀作品可以学习

适合人群: 儿童、青少年以及对传统编程语法感到困惑的初学者

3. JavaScript 🌐

推荐指数:⭐⭐⭐⭐

JavaScript是唯一能在浏览器中直接运行的编程语言,这意味着你不需要安装任何软件就能开始编程。

优势:

  • 零配置,打开浏览器就能开始编程
  • 能够创建交互式网页
  • 立即看到视觉效果
  • 学会后可以做前端、后端、移动应用开发

快速上手示例:

// 在网页上显示当前时间,每秒更新
setInterval(() => {
    document.body.innerHTML = new Date().toLocaleTimeString();
}, 1000);

4. Visual Basic (VB) 📋

推荐指数:⭐⭐⭐⭐

正如《计算机是怎样跑起来的》一书中所推荐的,VB是一门非常适合初学者的语言。虽然现在不如以前流行,但它仍然是理解编程概念的优秀工具。

优势:

  • 可视化界面设计
  • 拖拽控件即可创建程序界面
  • 语法相对简单
  • 能快速创建实用的Windows应用程序

适合场景: 希望快速创建桌面应用程序的初学者

5. Processing 🎨

推荐指数:⭐⭐⭐⭐

Processing专门为视觉艺术和创意编程设计,特别适合想要创作数字艺术作品的人。

优势:

  • 专注于图形和动画
  • 代码简洁,效果立竿见影
  • 活跃的创意编程社区
  • 作品可以导出为网页或应用程序

快速上手示例:

// 彩色粒子动画
void draw() {
    fill(random(255), random(255), random(255), 50);
    ellipse(random(width), random(height), 20, 20);
}

6. MIT App Inventor 📱

推荐指数:⭐⭐⭐⭐

如果你想快速体验移动应用开发的乐趣,MIT App Inventor是绝佳选择。

优势:

  • 可视化移动应用开发
  • 拖拽式界面设计
  • 作品可以直接安装到Android手机上
  • 支持传感器、相机等手机功能

学习路径建议

对于完全零基础的初学者:

  1. Scratch (1-2周) → 理解编程基本概念
  2. Python (2-4周) → 学习文本编程
  3. JavaScript → 创建网页应用

对于想快速做出实用程序的学习者:

  1. Python → 强大的通用语言
  2. MIT App Inventor → 制作移动应用

对于艺术创作爱好者:

  1. Processing → 数字艺术创作
  2. JavaScript + HTML5 Canvas → 网页交互艺术

学习资源推荐

书籍

  • 《计算机是怎样跑起来的》- 矢泽久雄著,详细解释了计算机工作原理,推荐VB作为入门语言
  • 《Python编程快速上手》- Al Sweigart著,实用的Python入门书籍
  • 《JavaScript高级程序设计》- Nicholas C. Zakas著,深入了解JavaScript
  • 《代码的乐趣》- Roy Osherove著,讲述编程的核心乐趣和最佳实践

在线平台

  • Codecademy – 交互式编程学习平台
  • freeCodeCamp – 免费的全栈开发课程
  • 慕课网 – 中文编程学习社区
  • bilibili – 有大量优质编程教学视频

实践项目建议

  1. 计算器程序 – 学习基本的用户输入和数学运算
  2. 待办事项清单 – 了解数据存储和界面交互
  3. 简单游戏(如贪吃蛇、俄罗斯方块)- 综合运用编程知识
  4. 个人网站 – 展示你的学习成果

总结

编程的乐趣在于创造。选择合适的入门语言能让你更快地体验到这种创造的快感。无论选择哪种语言,最重要的是开始动手实践,在做中学,在学中做。记住,编程不仅是一门技术,更是一种思考问题和解决问题的方式。

当你用几行代码创造出第一个程序,看到屏幕上出现”Hello, World!”的那一刻,你就已经踏上了这个充满无限可能的编程世界的旅程。


希望这篇文章能帮助你找到适合自己的编程语言,开始你的编程之旅!

Debian 11 + PVE LACP Mac 冲突问题调查与解决方案

By TL.S

问题背景

在Debian 11 + Proxmox VE环境中,当配置LACP(Link Aggregation Control Protocol)绑定接口时,有一个环境遇到一个令人困惑的问题:相同硬件配置的多台服务器上,所有服务器的同名bond接口都被分配了相同的MAC地址。这种情况会导致严重的网络连接问题,特别是在集群环境中。

根本原因分析

经过深入调查,这个问题的根本原因可以归纳为以下几个方面:

1. systemd/udev MAC 地址生成策略变更

systemd 242 版本开始,引入了新的MACAddressPolicy=persistent策略。该策略的目标是为虚拟网络设备(如bond、bridge、vlan等)生成持久的MAC地址,避免重启后MAC地址变化。

核心变更:systemd通过哈希算法,基于机器的machine-id和接口名称来生成MAC地址,确保在同一台机器上重启后MAC地址保持不变。

Refs: https://github.com/systemd/systemd/pull/11382

2. machine-id 相同导致的问题

关键问题:当多台服务器具有相同的machine-id时,相同的接口名称会生成完全相同的MAC地址。

machine-id 相同的几种情况:

  • 克隆安装:从同一个镜像克隆安装的系统
  • 模板部署:使用相同模板部署的虚拟机或物理机
  • 其他原因:其他原因导致 /etc/machine-id文件内容重复

3. MAC地址分配类型

通过查看系统文件可以确认MAC地址的分配方式:

root@server:~# cat /sys/class/net/bond0/addr_assign_type
3

根据Linux内核文档,addr_assign_type=3表示”set using dev_set_mac_address”,即通过dev_set_mac_address函数设置的MAC地址。

4. 虚拟设备的特殊性

问题主要影响虚拟网络设备,因为这些设备缺少必要的ID_NET_NAME_*属性,udev 无法为它们分配稳定的MAC地址。systemd 的解决方案是使用 接口名称+machine-id 的组合来生成MAC地址。

技术原理深度解析

MAC地址生成算法

systemd使用以下算法生成MAC地址:

  1. 获取/etc/machine-id的内容
  2. 结合接口名称(如bond0、vmbr0等)
  3. 通过哈希算法计算出唯一的MAC地址
  4. 确保生成的MAC地址符合本地管理地址规范

解决方案

方案一:重置machine-id(推荐)

这是最根本的解决方案,适用于所有情况:

# 停止网络服务
systemctl stop networking

# 备份原machine-id(可选)
cp /etc/machine-id /etc/machine-id.backup

# 清空machine-id
echo -n > /etc/machine-id

# 重新生成machine-id
systemd-machine-id-setup

# 验证新的machine-id
cat /etc/machine-id

# 重启系统使配置生效
reboot

注意事项

  • 重置machine-id可能影响其他依赖machine-id的服务
  • 建议在维护窗口期间执行
  • 重启后所有虚拟网络接口的MAC地址都会更新

方案二:手动指定MAC地址

如果不想更改machine-id,可以在网络配置中手动指定MAC地址:

# 编辑网络配置文件
vim /etc/network/interfaces

# 为bond接口指定唯一的MAC地址
auto bond0
iface bond0 inet manual
    bond-slaves ens1f0 ens1f1
    bond-miimon 100
    bond-mode 802.3ad
    bond-xmit-hash-policy layer3+4
    hwaddress ether 02:01:02:03:04:05  # 手动指定MAC地址

# 为bridge接口指定唯一的MAC地址
auto vmbr0
iface vmbr0 inet static
    address 10.10.4.41/24
    gateway 10.10.4.1
    bridge-ports bond0
    bridge-stp off
    bridge-fd 0
    hwaddress ether 02:01:02:03:04:06  # 手动指定MAC地址

方案三:更改MAC地址策略

修改systemd的MAC地址策略来解决MAC冲突问题。首先了解当前策略和可选项:

当前默认策略查看

# 查看当前systemd网络配置
ls -la /etc/systemd/network/
ls -la /lib/systemd/network/

# 查看当前默认策略文件(如果存在)
cat /lib/systemd/network/99-default.link 2>/dev/null || echo "默认策略文件不存在"

# 查看当前接口的MAC策略
networkctl status bond0

MAC地址策略选项说明

systemd支持以下MACAddressPolicy选项:

策略 说明 适用场景
persistent 当前默认策略,基于machine-id和接口名生成稳定MAC 需要MAC地址在重启后保持不变
random 每次启动时生成随机MAC地址 不需要MAC地址稳定性
none 不设置MAC地址,使用驱动程序默认值 物理接口或需要保持原有MAC

当前问题的根源:默认的persistent策略在相同machine-id的服务器上会生成相同的MAC地址。

实施步骤

# 1. 检查是否已有配置文件
echo "检查现有配置..."
if [ -f /etc/systemd/network/99-default.link ]; then
    echo "发现现有配置文件:"
    cat /etc/systemd/network/99-default.link
    echo ""
    echo "是否要备份现有配置?(y/n)"
    read -r response
    if [ "$response" = "y" ]; then
        cp /etc/systemd/network/99-default.link /etc/systemd/network/99-default.link.backup.$(date +%Y%m%d_%H%M%S)
        echo "已备份到: /etc/systemd/network/99-default.link.backup.$(date +%Y%m%d_%H%M%S)"
    fi
else
    echo "未发现现有配置文件,将创建新配置"
fi

# 2. 创建网络配置目录(如果不存在)
mkdir -p /etc/systemd/network

# 3. 根据需求选择策略创建配置文件

# 选项A:使用random策略(推荐用于解决冲突)
cat > /etc/systemd/network/99-default.link << EOF
# MAC地址策略配置
# 创建时间: $(date)
# 目的: 解决LACP MAC地址冲突问题

[Match]
OriginalName=*

[Link]
MACAddressPolicy=random
NamePolicy=keep kernel database onboard slot path
EOF

# 选项B:仅对虚拟接口使用random策略
cat > /etc/systemd/network/99-virtual.link << EOF
# 虚拟接口MAC地址策略配置
# 创建时间: $(date)

[Match]
Kind=bond bridge vlan macvlan veth

[Link]
MACAddressPolicy=random
EOF

# 选项C:禁用MAC地址自动分配
cat > /etc/systemd/network/99-no-mac.link << EOF
# 禁用MAC地址自动分配
# 创建时间: $(date)

[Match]
OriginalName=*

[Link]
MACAddressPolicy=none
EOF

# 4. 验证配置文件语法
echo "验证配置文件..."
systemd-analyze verify /etc/systemd/network/99-default.link

# 5. 应用新策略
echo "应用新的MAC地址策略..."
# 重新加载systemd配置
systemctl daemon-reload

# 重启网络服务(根据系统使用的网络管理器)
if systemctl is-active --quiet systemd-networkd; then
    systemctl restart systemd-networkd
    echo "已重启systemd-networkd"
elif systemctl is-active --quiet networking; then
    systemctl restart networking
    echo "已重启networking服务"
else
    echo "警告:未检测到活跃的网络服务,可能需要手动重启网络或系统"
fi

# 6. 验证策略是否生效
echo "等待网络接口重新初始化..."
sleep 5

echo "验证新的MAC地址策略:"
networkctl status | grep -E "(bond|vmbr|bridge)"

策略选择建议

推荐策略组合

  1. 对于生产环境

    # 仅对虚拟接口使用random策略,物理接口保持默认
    [Match]
    Kind=bond bridge vlan
    
    [Link]
    MACAddressPolicy=random
  2. 对于测试环境

    # 所有接口使用random策略
    [Match]
    OriginalName=*
    
    [Link]
    MACAddressPolicy=random
  3. 对于特定接口

    # 只对特定名称的接口应用
    [Match]
    OriginalName=bond* vmbr*
    
    [Link]
    MACAddressPolicy=random

回滚方案

如果新策略导致问题,可以快速回滚:

# 删除自定义策略文件
rm -f /etc/systemd/network/99-default.link

# 或者恢复备份
if [ -f /etc/systemd/network/99-default.link.backup.* ]; then
    cp /etc/systemd/network/99-default.link.backup.* /etc/systemd/network/99-default.link
fi

# 重启网络服务
systemctl daemon-reload
systemctl restart systemd-networkd

注意事项

  • 影响范围:此方案会影响系统中所有匹配的网络接口
  • 重启要求:配置更改后,需要重启网络服务或重启系统
  • 兼容性:确保你的系统使用systemd-networkd而不是NetworkManager
  • 监控:更改后应监控网络连接是否正常

方案四:运行时动态修改

如果需要立即解决问题而不重启:

# 生成随机MAC地址(注意要符合本地管理地址规范)
NEW_MAC=$(printf '02:00:00:%02x:%02x:%02x\n' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)))

# 停止接口
ip link set dev bond0 down

# 设置新的MAC地址
ip link set dev bond0 address $NEW_MAC

# 启动接口
ip link set dev bond0 up

# 验证更改
ip link show bond0

预防措施

1. 标准化部署流程

在部署新系统时,确保:

# 在系统部署脚本中加入
if [ -f /etc/machine-id ]; then
    echo "重置machine-id..."
    echo -n > /etc/machine-id
    systemd-machine-id-setup
fi

2. 监控和检查

定期检查集群中的MAC地址冲突:

#!/bin/bash
# mac_check.sh - 检查MAC地址冲突

echo "检查集群MAC地址冲突..."
for host in server1 server2 server3; do
    echo "=== $host ==="
    ssh $host "ip link show | grep -E 'bond|vmbr' | grep 'link/ether'"
done

3. 文档化和记录

建立标准的网络配置文档,记录:

  • 每台服务器的machine-id
  • 手动分配的MAC地址范围
  • 网络拓扑和接口映射

影响范围和版本信息

受影响版本

  • Debian 10/11 + systemd >= 242
  • Proxmox VE 6.x/7.x/8.x
  • 其他基于systemd的Linux发行版

特别注意

  • Intel网卡比Broadcom网卡更容易出现此问题
  • 虚拟化环境中的问题更加常见
  • 集群环境影响更严重

总结

Debian 11 + PVE LACP Mac冲突问题的根本原因是systemd的MAC地址生成策略与machine-id机制的相互作用。当多台服务器具有相同的machine-id时,会为相同名称的虚拟网络接口生成相同的MAC地址,导致网络冲突。

References

Rclone WebUI 选择指南:全面对比各种图形界面方案

Rclone 作为强大的云存储同步工具,虽然命令行功能丰富,但对于普通用户来说学习曲线较陡。为了解决这个问题,社区开发了多种图形界面方案。本文将详细对比各种 Rclone WebUI 选择,帮助您找到最适合的解决方案。

WebUI 方案概述

1. Rclone WebUI React(官方)

这是 Rclone 官方支持的 React 前端界面,已集成到 Rclone 主程序中。通过 rclone rcd --rc-web-gui 命令即可启动,界面现代化,功能相对完善。

特点:

  • 官方维护,集成度高
  • React 技术栈,界面现代
  • 支持在线版本和本地部署
  • 基本的文件管理功能

部署方式:

# 本地部署
rclone rcd --rc-web-gui --rc-user=admin --rc-pass=password

# 在线版本
rclone rcd --rc-user=admin --rc-pass=password --rc-allow-origin="https://rclone.github.io"

2. Rclone WebUI Angular

这是由社区开发者 yuudi 创建的 Angular 前端,提供了另一种现代化的界面选择。相比官方 React 版本,在某些功能上有所增强。

特点:

  • Angular 技术栈
  • 更丰富的功能
  • 社区活跃维护
  • 支持多种部署方式

3. Rclone RC Web GUI(简洁版)

这是一个轻量级的双窗格文件管理器风格界面,灵感来自 Norton Commander 和 Total Commander。专注于文件传输操作,界面简洁实用。

特点:

  • 双窗格设计,操作直观
  • 专注文件传输,功能精简
  • 基于原生 JavaScript,加载快速
  • 适合远程服务器部署

4. RcloneBrowser(桌面应用)

虽然不是 WebUI,但 RcloneBrowser 是一个成熟的跨平台桌面 GUI 应用,支持 Windows、macOS 和 Linux。

特点:

  • 完整的桌面应用体验
  • 支持挂载功能
  • 任务调度和自动化
  • 托盘集成和通知

5. Rclone UI(商业版)

Rclone UI 是一个用 Rust 编写的桌面应用,提供免费版本和付费版本。界面美观,用户体验良好。

特点:

  • Rust 编写,性能优秀
  • 现代化界面设计
  • 免费功能够用,付费解锁高级功能
  • 跨平台支持

6. RcloneView(新兴方案)

RcloneView 是 2024 年新推出的商业 GUI 解决方案,专注于提供现代化的用户体验。

特点:

  • 现代化界面设计
  • 拖拽操作支持
  • 进度监控和日志查看
  • 支持外部 Rclone 守护进程

7. Rclone Manager

Rclone Manager 是一个基于 Tauri 和 Angular 的跨平台应用,结合了 GTK 样式和 Material Design。

特点:

  • 现代化技术栈(Tauri + Angular)
  • 支持几乎所有 Rclone 远程类型
  • OAuth 认证支持
  • 系统托盘集成

详细对比表格

特性 WebUI React WebUI Angular RC Web GUI RcloneBrowser Rclone UI RcloneView Rclone Manager
类型 Web 界面 Web 界面 Web 界面 桌面应用 桌面应用 桌面应用 桌面应用
官方支持 ✅ 官方 ❌ 社区 ❌ 社区 ❌ 社区 ❌ 第三方 ❌ 商业 ❌ 社区
开源程度 ✅ 完全开源 ✅ 完全开源 ✅ 完全开源 ✅ 完全开源 ⚠️ 部分开源 ❌ 商业软件 ✅ 完全开源
技术栈 React Angular 原生 JS Qt (C++) Rust/Tauri 未公开 Angular/Tauri
部署难度 简单 中等 简单 很简单 很简单 很简单 简单
在线使用
远程管理 ⚠️ 有限 ⚠️ 有限 ⚠️ 有限
文件浏览 ✅ 基础 ✅ 增强 ✅ 双窗格 ✅ 完整 ✅ 完整 ✅ 现代化 ✅ 完整
传输监控 ✅ 详细 ✅ 详细 ✅ 详细
任务调度 ⚠️ 基础 ⚠️ 基础
挂载支持 ⚠️ 部分
配置管理 ✅ 基础 ✅ 增强 ⚠️ 有限 ✅ 完整 ✅ 完整 ✅ 完整 ✅ 完整
OAuth 支持 ⚠️ 有限 ✅ 强大
多语言 ⚠️ 有限 ⚠️ 有限 ⚠️ 有限 ⚠️ 有限 ⚠️ 有限
移动端适配 ✅ 响应式 ✅ 响应式 ⚠️ 基础
资源消耗 中等 很低 中等 中等 中等
学习曲线 中等 很低 很低 中等
社区活跃度 中等 中等 低(新项目) 中等
维护状态 ✅ 活跃 ✅ 活跃 ⚠️ 缓慢 ✅ 活跃 ✅ 活跃 ✅ 活跃 ✅ 活跃
适用场景 通用 WebUI 高级 WebUI 轻量远程 桌面重度 桌面轻量 商业环境 现代桌面

选择建议

🌐 Web 界面需求

初学者推荐:Rclone WebUI React

  • 官方支持,稳定可靠
  • 部署简单,一行命令启动
  • 在线版本可直接使用

高级用户推荐:Rclone WebUI Angular

  • 功能更丰富
  • 界面更现代
  • 社区活跃开发

轻量级需求:RC Web GUI

  • 资源消耗最小
  • 双窗格操作直观
  • 适合服务器环境

🖥️ 桌面应用需求

功能全面:RcloneBrowser

  • 功能最完整
  • 社区成熟稳定
  • 完全免费开源

现代体验:Rclone Manager

  • 技术栈最新
  • 界面最现代
  • OAuth 支持最佳

轻量易用:Rclone UI

  • 用户体验最佳
  • Rust 性能优秀
  • 免费版功能够用

🏢 商业环境

推荐:RcloneView

  • 专业商业支持
  • 现代化界面
  • 企业级功能

快速部署示例

官方 WebUI React

# 基础部署
rclone rcd --rc-web-gui --rc-user=admin --rc-pass=your_password

# 公网访问(注意安全)
rclone rcd --rc-web-gui \
  --rc-user=admin \
  --rc-pass=your_password \
  --rc-addr=0.0.0.0:5572 \
  --rc-allow-origin="*"

Docker 部署

version: '3.8'
services:
  rclone-webui:
    image: rclone/rclone:latest
    container_name: rclone-webui
    command: rcd --rc-web-gui --rc-addr=0.0.0.0:5572 --rc-user=admin --rc-pass=password
    ports:
      - "5572:5572"
    volumes:
      - ./config:/config/rclone
      - ./data:/data
    environment:
      - RCLONE_CONFIG=/config/rclone/rclone.conf

Angular WebUI 部署

# 使用 Angular 版本
rclone rcd \
  --rc-user=admin \
  --rc-pass=password \
  --rc-web-gui \
  --rc-web-gui-update \
  --rc-web-fetch-url="https://s3.yuudi.dev/rwa/embed/version.json"

安全注意事项

  1. 密码保护:始终设置强密码,避免使用默认凭证
  2. 网络安全:公网部署时务必使用 HTTPS 和防火墙
  3. 访问控制:限制访问 IP 范围,避免 --rc-allow-origin="*"
  4. 定期更新:保持 Rclone 和 WebUI 版本最新

总结

选择合适的 Rclone WebUI 方案需要根据具体需求:

  • 追求稳定:选择官方 WebUI React
  • 需要功能:选择 Angular 版本或 RcloneBrowser
  • 要求轻量:选择 RC Web GUI
  • 重视体验:选择 Rclone UI 或 RcloneView
  • 喜欢新技术:选择 Rclone Manager

无论选择哪种方案,都建议先在测试环境中试用,确认满足需求后再部署到生产环境。大多数方案都提供了良好的文档和社区支持,可以帮助您快速上手。

开源自托管数据备份解决方案全面对比

在数据日益重要的今天,选择一个合适的备份解决方案至关重要。本文将对比介绍六个优秀的开源自托管数据备份方案,帮助您根据实际需求做出最佳选择。

方案概述

1. Duplicati – 全能型备份工具

Duplicati 是一个功能完善的备份解决方案,以其友好的用户界面和广泛的存储支持而闻名。它采用客户端-服务器架构,提供了直观的 Web 管理界面,特别适合需要定期备份到多种云存储的用户。

核心优势:

  • 开箱即用的 Web 界面,配置简单直观
  • 原生支持加密和压缩
  • 强大的调度系统,支持复杂的备份策略
  • 详细的备份报告和邮件通知

适用场景: 家庭用户、小型企业,需要将数据备份到多种云存储服务

2. Kopia – 现代化高性能备份

Kopia 是一个相对较新但技术先进的备份工具,采用现代化的存储架构和算法,在性能方面表现出色。它支持多种用户界面,包括命令行、桌面应用和 Web 界面。

核心优势:

  • 出色的性能和内存效率
  • 先进的重复数据删除算法
  • 强大的快照管理功能
  • 支持策略继承和模板

适用场景: 技术用户、大数据量备份、对性能有较高要求的场景

3. Restic – 简洁高效的备份工具

Restic 专注于简洁性和可靠性,是一个纯命令行工具,但可以通过第三方 Web 界面进行管理。它设计精良,代码质量高,在安全性方面表现突出。

核心优势:

  • 设计简洁,代码质量高
  • 强大的加密和验证机制
  • 跨平台兼容性好
  • 备份数据格式稳定,长期可维护

适用场景: 技术用户、脚本自动化、对安全性要求极高的场景

4. UrBackup – 企业级备份解决方案

UrBackup 是一个专业的客户端-服务器备份系统,特别适合企业环境。它不仅支持文件备份,还支持整个系统的镜像备份,功能非常全面。

核心优势:

  • 专业的企业级功能
  • 支持文件和镜像两种备份模式
  • 强大的客户端管理能力
  • 详细的权限管理和用户控制

适用场景: 企业环境、多客户端管理、需要系统镜像备份

5. Rclone + WebUI – 云存储同步专家

Rclone 本身是一个强大的命令行工具,专门用于与云存储服务交互。通过第三方 Web UI,可以获得图形化的管理界面,特别适合云存储的同步和备份。

核心优势:

  • 支持 70+ 种云存储服务
  • 功能丰富,支持同步、复制、挂载等多种操作
  • 资源消耗低,性能优秀
  • 社区活跃,更新频繁

适用场景: 云存储重度用户、跨平台同步、资源受限的环境

6. Syncthing – P2P 实时同步

Syncthing 是一个独特的点对点同步工具,它不依赖中央服务器,而是在设备之间直接同步数据。虽然严格来说它是同步工具而非传统意义的备份工具,但在某些场景下可以很好地满足备份需求。

核心优势:

  • 去中心化,无需服务器
  • 实时同步,延迟极低
  • 端到端加密,隐私保护好
  • 跨平台支持完善

适用场景: 设备间同步、实时备份、注重隐私的用户

功能特性对比表

特性 Duplicati Kopia Restic UrBackup Rclone+WebUI Syncthing
部署难度 简单 中等 中等 简单 中等 简单
Web 管理界面 ✅ 原生 ✅ 原生 ⚠️ 第三方 ✅ 原生 ⚠️ 第三方 ✅ 原生
容器支持 ✅ 完善 ✅ 完善 ✅ 完善 ✅ 完善 ✅ 完善 ✅ 完善
本地存储
OneDrive
Google Drive
WebDAV
S3 兼容
定时备份 ✅ 强大 ✅ 强大 ⚠️ 需脚本 ✅ 强大 ⚠️ 需脚本 ❌ 实时同步
增量备份 ✅ 差异同步
重复数据删除 ✅ 先进
数据加密 ⚠️ 传输加密 ⚠️ 部分支持 ✅ 端到端
版本控制 ✅ 强大 ⚠️ 有限 ✅ 文件历史
多客户端管理 ⚠️ 有限 ✅ 强大 ✅ 设备管理
备份验证 ✅ 强大 ⚠️ 基础 ✅ 自动
性能 中等 优秀 良好 良好 优秀 优秀
资源消耗 中等 低-中等 中等
学习曲线 中等 中-高 中等
社区活跃度 中等 极高 极高
企业级功能 ⚠️ 有限 ⚠️ 有限 ✅ 强大 ⚠️ 有限
邮件通知 ⚠️ 需配置 ⚠️ 需配置

选择建议

🏠 家庭用户推荐

  • 首选:Duplicati – 界面友好,配置简单,支持主流云存储
  • 备选:Syncthing – 设备间实时同步,操作简单

💼 小型企业推荐

  • 首选:UrBackup – 企业级功能,支持多客户端管理
  • 备选:Duplicati – 成本低,功能够用

🔧 技术用户推荐

  • 首选:Kopia – 性能优秀,功能先进
  • 备选:Restic – 代码质量高,安全性强

☁️ 云存储重度用户推荐

  • 首选:Rclone + WebUI – 支持最多云存储服务
  • 备选:Duplicati – 云存储支持好,界面友好

⚡ 实时同步需求推荐

  • 首选:Syncthing – P2P实时同步,无延迟
  • 备选:Rclone – 支持实时同步模式

部署示例

Duplicati 快速部署

# Docker Compose 部署
version: '3'
services:
  duplicati:
    image: linuxserver/duplicati
    container_name: duplicati
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Shanghai
    volumes:
      - ./config:/config
      - ./data:/data
      - /source:/source:ro
    ports:
      - "8200:8200"
    restart: unless-stopped

Syncthing 快速部署

# Docker 部署
docker run -d \
  --name syncthing \
  -p 8384:8384 \
  -p 22000:22000/tcp \
  -p 22000:22000/udp \
  -p 21027:21027/udp \
  -v /path/to/config:/var/syncthing \
  -v /path/to/data:/data \
  syncthing/syncthing:latest

总结

选择备份方案时,需要根据具体需求平衡以下因素:

  1. 易用性 vs 功能性 – Duplicati 和 Syncthing 易用,Kopia 和 Restic 功能更强
  2. 性能 vs 资源消耗 – Kopia 和 Rclone 性能好,Restic 和 Syncthing 资源消耗低
  3. 备份 vs 同步 – 前五者专注备份,Syncthing 专注同步
  4. 企业 vs 个人 – UrBackup 适合企业,Duplicati 和 Syncthing 适合个人

建议根据实际场景选择,也可以组合使用多种方案来满足不同的备份需求。例如,使用 Syncthing 进行实时同步,同时用 Duplicati 进行定期云备份,这样可以获得最佳的数据保护效果。

Claude Code 实用技巧

  1. CLAUDE.md(规则文件)= 冰箱家规 先把“进门换鞋、10点关灯、刀具归位”写清楚,Claude 做任何事之前都要看一遍并遵守。

  2. Task(多任务并行)= 多台家电同时干活 扫地机器人+洗碗机+空调一起开工,Claude 同时跑多个任务,效率翻倍。

  3. /自定义指令(常用操作快捷)= 场景模式 设好“回家模式”:开门回家就自动 开灯→开空调→放音乐。

  4. Hook (事件触发器)= 自动提醒/联动开关 洗衣机结束→手机提醒你晾衣服;门磁感应到你进门→灯自己亮。

  5. Sub Agent(子智能体)= 家里的专业小队 管家、厨师、保洁、物业、维修师傅……每个都有专长,随叫随到

还有个mcp,这个是标配了~ ————

可以按照如下流程来打造“满血版 Claude Code”

先定家规(CLAUDE.md)→ 招专业团队(Sub Agent)→ 设自动触发器(Hook)→ 添加mcp → 做几个一键场景口令(/自定义指令)→ 一点全自动多任务Task同时执行

References

CentOS 7 重置 root 密码

引言

很多遗留系统都采用 CentOS 系统,经常出现忘记密码,故在此记录方法。

以下内容转自 CentOS 7 重置 root 密码

CentOS 7 重置 root 密码

与之前的 CentOS 5、 CentOS 6 不同的是,当忘记 CentOS 7 root 密码,并采用 GRUB2 为启动器时,
将无法通过单用户模式重置 root 密码,下面介绍 CentOS 7 如何重置 root 密码。

  1. 启动系统,并在 GRUB2 启动屏显时,按下 e 键进入编辑模式。
  2. linux16/linux/linuxefi 所在参数行尾添加以下内容: init=/bin/sh
  3. 按 Ctrl + X 启动到 Shell。
  4. 挂载文件系统为可写模式:mount -o remount,rw /
  5. 运行 passwd, 并按提示修改 root 密码。
  6. 运行命令 exec /sbin/init 来正常启动,或者用命令 exec /sbin/reboot 重启

遇到的问题,不确认是 VMware Workstation 有 Bug 还是键盘问题,进行密码重置时,
输入 2 次密码很多次,总是提示密码不匹配,用很简单的密码也提示。
然后采用直接清空 root 密码的方式(/etc/passwd root 用户密码列 x 删除)先登录系统,然后再修改。

Ref

telnet 如何退出

telnet 的退出 分成两种,一中是在telnet命令中,直接输入 quit 或者 q 即可退出。 二种情况是 已经进入了端口中,需要先从端口中退出,然后再退出telnet。

telnet 直接退出

输入 q 或者 quit 即可退出。

telnet 退出端口后退出telnet

  1. 输出 ctrl + ]
  2. q 或者 quit

Ref

kubernetes 的挂载传播(mount propagation)机制

以下内容转载自:kubernetes 的挂载传播(mount propagation)机制

概述

今天在看 kubectl-debug 这个项目的时候,看到其部署文件的 volumeMounuts 中使用了一个 mountPropagation 字段,因为不清楚这个字段的作用,就做了一下了解。mount propagation 背后的东西还是很多的,因此整理了这篇文章,顺便梳理一下知识点。

kubernetes 的 mount propagation 翻译成中文就是挂载传播。挂载传播提供了共享卷挂载的能力,它允许在同一个 Pod,甚至同一个节点内,在多个容器之间共享卷的挂载。

kubernetes 的挂载传播

卷的挂载传播由 Container.volumeMounts 的 mountPropagation 字段控制。它的值有:

  • None: 这种卷挂载将不会收到任何后续由 host 创建的在这个卷上或其子目录上的挂载。同样的,由容器创建的挂载在 host 上也是不可见的。这是默认的模式。这个其实很好理解,就是容器内和 host 的后续挂载完全隔离。
  • HostToContainer: 这种卷挂载将会收到之后所有的由 host 创建在该卷上或其子目录上的挂载。换句话说,如果 host 在卷挂载内挂载的任何内容,在容器中都是可见的。同样,如果任何具有 Bidirectional 的 Pod 挂载传播到该卷挂载上,具有 HostToContainer 的挂载传播都可以看见。整个挂载传播的流程如下:

  • Bidirectional: 这种挂载机制和 HostToContainer 类似。此外,任何在容器中创建的挂载都会传播到 host,然后传播到使用相同卷的所有 Pod 的所有容器。注意:Bidirectional 挂载传播是很危险的。可能会危害到 host 的操作系统。因此只有特权容器在允许使用它。

在了解了这几种挂载传播之后,我们可以做一些实验来验证一下,首先验证的是 None 的挂载传播类型,我们创建一个 nginx 的Pod:

apiVersion: v1
kind: Pod
metadata:
    name: mount-a
    namespace: default
    label:
      app: mount
spec:
    containers:
    - name: main
      image: nginx:latest
      volumeMounts:
      - name: testmount
        mountPath: /home
        mountPropagation: None
    volumes:
    - name: testmount
      hostPath:
        path: /mnt/

YAML

然后我们分别向 host 的 /mnt 和容器的 /home 下挂载目录并查看容器和 host 的情况:

容器中:

$ kubectl exec -it mount-a sh
$ cd /home
$ ls 
sda1

Bash

host 上:

$ cd /mnt
$ ls 
sda1

Bash

然后在 host 上创建挂载:

$ mkdir /mnt/none
$ sudo mount --bind /var /mnt/none
$ ls none
cache  empty  lib  lock  log  run  spool  tmp

Bash

这个时候,我们再看容器中的文件:

$ ls none
# 无输出

Bash

这说明 host 上在该卷下的挂载并不会改变容器中的文件。接下来我们可以在容器中按照上面的方案来验证容器中的挂载也不会影响 host 中的目录视图。这里就不展示了。接下来看一下 HostToContainer 的挂载传播,我们将上面的 Pod 的 mountPropagation 字段改成 HostToContainer,然后先取消 host 上的挂载:

sudo umoint /mnt/none

然后重新创建 Pod,和上面一样,在 host 上创建挂载,查看容器中的挂载情况:

$ ls none
cache  empty  lib  lock  log  run  spool  tmp

Bash

host 上的挂载因为 HostToContainer 机制传播到了容器中。我们继续看最后一种 Bidirectional 机制。这次我们要创建两个 Pod: mount-a, mount-b,并把 mountPropagation 字段改成 Bidirectional。注意,因为 Bidirectional 是危险的,所以只有特权容器才可以使用。因此这里还需要把容器改成特权模式,最后在 mount-a 中的容器执行挂载,验证挂载是否传播到 host 和 mount-b 的容器中。

apiVersion: v1
kind: Pod
metadata:
    name: mount-a
    namespace: default
    labels:
      app: mount
spec:
    containers:
    - name: main
      image: nginx:latest
      securityContext:
        privileged: true
      volumeMounts:
      - name: testmount
        mountPath: /home
        mountPropagation: Bidirectional
    volumes:
    - name: testmount
      hostPath:
        path: /mnt/
---
apiVersion: v1
kind: Pod
metadata:
    name: mount-b
    namespace: default
    labels:
      app: mount
spec:
    containers:
    - name: main
      image: nginx:latest
      securityContext:
        privileged: true
      volumeMounts:
      - name: testmount
        mountPath: /home
        mountPropagation: Bidirectional
    volumes:
    - name: testmount
      hostPath:
        path: /mnt/

YAML

然后进入 mount-a,创建挂载:

$ kubectl exec -it mount-a sh
$ su
$ mount --bind /var /home/none
$ ls /home/none
backups  lib    lock  mail  run    tmp
cache    local  log   opt   spool

Bash

这时候查看 host 下的 /mnt/none:

$ ls /mnt/none
backups  lib    lock  mail  run    tmp
cache    local  log   opt   spool

Bash

可以发现,容器中的挂载传播到了 host 上。这时候再查看 mount-b 中的容器。

$ ls /home/none
backups  lib    lock  mail  run    tmp
cache    local  log   opt   spool

Bash

挂载也传播到了 mount-b 的容器中。

linux mount 的几种类型

上面分析了 kubernetes 的挂载传播机制,在 linux mount 中,也有类似的概念。mount 分为下面几种:

  • shared mount: 相当于上面所说的 Bidirectional 的挂载传播
  • slave mount: 每个 slave mount 都有一个 shared master mount,挂载传播只能从 master -> slave,等同于上面的 HostToContainer, host 是 master,container 是 slave。
  • private mount: 很明显,private 就是相当于 None,挂载不会向任何一方传播。
  • unbindable mount:unbindable mount 其实就是 unbindable private mount,也就是不允许使用 --bind 的挂载。

mount namespace 的机制

kubernetes 的挂载传播不是其本身实现的,也不是 docker 之类的容器运行时提供的。这是由容器化技术的基础:linux namespace 提供的,linux namespace 当前共有 6 种:

  • cgroup namespace: 隔离 cgroup 根目录
  • pid namespace: 隔离进程 id
  • ipc namespace: 隔离 System V IPC, POSIX message queues
  • uts namespace: 隔离 Hostname 和 NIS domain name
  • user namespace: 隔离用户和用户组 ID
  • mount namespace: 隔离挂载点
  • network namespace: 隔离网络设备,网络栈,端口等

其中,mount namespace 是这篇文章的重点。我们可以通过 clone 调用来看看 mount namespace 的使用:

#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>

#define STACK_SIZE (1024*1024)
static char container_stack[STACK_SIZE];

char* const container_args[] = {
    "/bin/bash",
    NULL
};

int container_main(void* arg)
{
    printf("Container [%5d] - inside the container!\n", getpid());
    mount("none", "/", NULL, MS_REC|MS_PRIVATE, NULL);
    execv(container_args[0], container_args);
    printf("Something's wrong!\n");
    return 1;
}
int main()
{
    printf("Parent [%5d] - start a container!\n", getpid());
    /* 启用Mount Namespace - 增加CLONE_NEWNS参数 */
    int container_pid = clone(container_main, container_stack+STACK_SIZE, CLONE_NEWNS | SIGCHLD, NULL);
    waitpid(container_pid, NULL, 0);
    printf("Parent - container stopped!\n");
    return 0;
}

C

编译运行:

$ gcc main.c -o mount
$ sudo ./mount

Bash

然后尝试挂载,来验证挂载 MS_PRIVATE 的挂载传播问题。MS_PRIVATE 下 namespace 内和 host 应该是隔离的。MS_PRIVATE 还可以替换成 MS_UNBINDABLEMS_SLAVEMS_SHARED

关于更多的 namespace 的资料,建议看这两篇文章:

参考资料