跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

博客

按日期的更新与感想。

按日期写的更新与感想。需要长期查阅的主题笔记放在学习

1 - Linux 服务器 SSH 登录与安全加固笔记

从连不上服务器、私钥权限报错,到改端口、UFW 放行与密钥登录——CentOS/Ubuntu VPS 实操整理。

最近在 VPS 上折腾 SSH:外网连超时、私钥权限报错、改端口后 systemd 不生效……把 Obsidian 里的几篇笔记合并成一篇,按「先能连上 → 再加固 → 防火墙配合」的顺序记录。

SSH 登录与安全加固示意
从客户端到服务器:云安全组、UFW 与 sshd 一层层放行
虚构示例

文中 IP 用 ip1ip2 等占位(如 ip1 = 服务器、ip2 = 允许连入的来源);域名 xxx.xxx.com、端口(如 22222)、用户名 username 亦为演示占位,非真实环境。请替换为你自己的值。

SSH 登录四要素

远程登录可以记成四个量:

要素说明常见默认值
IP / 主机名公网可达的地址扫描脚本会随机扫网段,无法真正「隐藏」
端口TCP 端口22
用户名登录账户常为 root
凭证密码或密钥密码无默认值;密钥需本地私钥 + 服务器公钥

加固思路:端口、用户名、认证方式都可以改;密码换密钥、禁 root、改非 22 端口 是常见组合。

连不上:超时与排查

典型报错:

ssh username@xxx.xxx.com
ssh: connect to host xxx.xxx.com port 22: Connection timed out

可能原因:

  1. SSH 不在 22 端口 — 需指定 -p <PORT>
  2. 云厂商安全组未放行 — 控制台里要允许你的 IP 或来源段
  3. 必须先 VPN / 跳板 — 机房内网节点往往不能从宿舍/家宽直接 SSH,要先连 VPN 或跳板机,再 ssh 到目标主机

需要确认端口以及用户名

外网路径大致是:云安全组 → 本机防火墙(UFW)→ sshd。任一层未放行都会表现为超时或拒绝。

踩坑:私钥权限过大

连上之前还遇到过 OpenSSH 直接拒绝加载私钥:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0664 for '/home/username/.ssh/id_ed25519' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/home/username/.ssh/id_ed25519": bad permissions

原因:私钥文件权限是 0664,组用户和其他用户可读。OpenSSH 认为密钥可能已泄露,宁可不用这把钥匙,也不带着风险去连——于是这次登录等于没带上有效私钥。

处理:私钥仅本人可读(必要时目录也要收紧):

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
路径建议权限
~/.ssh/700
私钥600
公钥 *.pub644 通常可接受
服务器端 ~/.ssh/authorized_keys600
公钥文件名

上传到 VPS 的公钥不要.txt 等后缀;若有需重命名。服务器端公钥文件也建议 chmod 600

改 SSH 端口(含 systemd + UFW)

稳妥顺序(先加新端口,验证后再删旧端口):

  1. sshd_config 追加Port(暂时保留旧端口)
  2. daemon-reload + 重启 ssh.socket / ssh.service
  3. sshd -Tss 确认新端口在监听
  4. UFW(及云安全组)放行新端口
  5. 新开一个终端用新端口试连
  6. 确认无误后再删旧端口规则、关 22

改 sshd 配置

sudo nano /etc/ssh/sshd_config

增加一行(示例:在原有 22222 之外再加 9753):

Port 9753

sshd_config 管的是 sshd 服务端:听哪些端口、是否允许 root、是否允许密码登录等。nano:Ctrl+O 保存,Ctrl+X 退出。

Ubuntu 上为何要动 ssh.socket

在 Ubuntu 上 SSH 常由 systemd socket 激活:先由 ssh.socket 占端口,再交给 ssh.service 里的 sshd。只改 sshd_config 不够,还要让生成器把新端口写进 socket 配置:

sudo systemctl daemon-reload
sudo systemctl restart ssh.socket ssh.service
操作磁盘配置内存中的 unit内核 LISTEN
只改 Port 9753
daemon-reload新(生成器已更新)仍可能是旧的
restart ssh.socket新(重建 bind)

验证「配置认为该听什么」:

sudo sshd -T | grep -i '^port '
# 例:port 22222 \n port 9753

验证「系统正在听什么」:

sudo ss -tlnp | grep ssh

ss -tlnp:TCP、LISTEN、数字端口、显示进程。注意:本机在听 ≠ 外网能连,还要 UFW 和安全组。

UFW 放行新端口

UFW 是 Ubuntu 自带的防火墙前端。流量顺序:

云厂商安全组 → UFW(本机) → sshd

查看状态:

sudo ufw status verbose
  • inactive:UFW 未启用,仅安全组 + sshd 生效
  • active:按规则过滤入站

示例输出解读:

含义
To本机开放的端口
ActionALLOW 放行;DENY / REJECT 拒绝
FromAnywhere 任意 IP;也可写成仅允许你家 IP

放行新端口:

sudo ufw allow 9753/tcp
sudo ufw status verbose

看到 9753/tcp ALLOW IN 即规则已写入。常用维护:

sudo ufw status numbered
sudo ufw delete 3
sudo ufw allow from <ip2> to any port 22222 proto tcp   # 仅允许 ip2 连入(替换为你的来源 IP)
sudo ufw limit 22222/tcp    # 对同一 IP 短时多次连接节流,减轻扫端口

用户、禁 root、密钥登录

  1. 新建非 root 用户sudo adduser username;Debian/Ubuntu 需 apt install sudo,用 visudo 加入 sudo 组(按最小权限配置,不必一律 NOPASSWD)。
  2. 禁用 root SSHsshd_configPermitRootLogin no
  3. 密钥登录、关密码 — 本地生成密钥对(推荐 Ed25519,避免 DSA;ECDSA/Ed25519 选型见下节),公钥写入服务器 ~/.ssh/authorized_keys;服务器端:
    • PubkeyAuthentication yes
    • PasswordAuthentication no

改配置后同样要 reload/restart,并保留一个已登录的会话,防止把自己锁在外面。

密钥算法简记

类型说明
RSA常见,密钥较长;可用但非唯一选择
DSA已不安全,不要用
ECDSA短、快;算法争议较多
Ed25519现代默认推荐之一,文档公开、性能好

systemd 与 SSH:两单元

systemd 是多数现代发行版的 init/服务管家(pid 1)。与 SSH 相关的概念:

  • ssh.service — 跑 /usr/sbin/sshd 进程
  • ssh.socket — 由 systemd 先监听端口,再激活 service(socket 激活)

关系可以简化为:

systemd (pid 1)
  ├── ssh.socket   → 监听 0.0.0.0:22222 / 9753 …
  ├── ssh.service  → sshd 接手已有 fd
  └── generator    → 读 sshd_config,生成 socket 该听的端口列表

unit 文件位置:/usr/lib/systemd/system/(软件包)与 /etc/systemd/system/(本机覆盖);systemctl cat ssh.service 可看合并结果。改端口时记住:Ubuntu 上要 reload + restart socket,不是只 systemctl restart ssh 就万事大吉。

小结

阶段要点
连不上查端口、安全组、VPN/跳板;三层防火墙都要通
私钥报错chmod 600 私钥、700 .ssh;OpenSSH 拒绝「过于开放」的密钥
改端口先加后删;sshd -T + ss 验证;UFW + 安全组同步放行
加固非 root、禁 root 登录、密钥认证、非默认端口

这是学习笔记,不是生产 checklist。动手前建议在测试机上练一遍,并始终保留一条不会把自己锁死的登录路径。

2 - 用 Oink 搭个人站:从零到发布的笔记整理

不太懂前端时,如何用 Hugo + Oink 搭文档站——内容结构、博客写法、hugo.yml 与本地预览命令。

Oink 官方教程 写得很完整,但对不太了解前端的人来说,第一次把「文件夹、配置、命令」串起来仍会有点晕。这篇把我最近搭 YHY Study Website 时的笔记整理成一条线:先搞清 Oink 是什么,再理解 content/ 怎么组织,最后走一遍写博客和发布的流程。

Oink 建站示意
Markdown → Hugo → Oink 主题 → 可发布的静态站点

Oink 和 Hugo 各管什么

Hugo 是静态站点生成器:读 Markdown + 配置,输出 HTML。
Oink 是 Hugo 主题:决定侧栏、卡片、提示块、代码块等「长什么样」。

内容和外观分开维护:

  • 站点仓库my-project-docs):Markdown 文章、hugo.yml 配置
  • 主题仓库 github.com/pgsty/oink:模板与样式

站点在 hugo.yml 里声明「用 Oink 主题」,go.mod 固定版本(当前 v0.6.0)。运行 hugo server 时:

  1. 从站点仓库读文章和配置
  2. 从主题模块(按 go.mod 下载)读模板和样式
  3. 把内容套进主题,生成网页
日常够用的一条命令

只写文档、不改主题时,记住 hugo server 即可;不必一开始就碰 make dev

本地预览:先让站跑起来

进入项目目录后启动:

cd D:\MyData\yhy\6data\repository\my-project-docs
hugo server

浏览器打开 http://localhost:1313/。改 content/ 下的 .md 保存后会自动刷新。

若希望每次改动都做更完整的重渲染(排查样式问题时有用):

hugo server -DFE --disableFastRender
  • -DFE:草稿、未来日期页面也显示,方便写作
  • --disableFastRender:关掉快速渲染,避免增量更新带来的偏差

content/ 怎么分层

Oink 不单独维护导航库:磁盘上的文件夹结构 = 侧栏结构 = URL 路径。

三个常用概念:

概念含义
Section(分区)_index.md 的文件夹,这一层本身也有入口页
Page(页面)文件夹里的 .md,或子文件夹里的 index.md
Sibling(同级)同一目录下多篇 .md,用 weight: 10/20/30… 排序

本站根目录示意:

content/
├── _index.md           → 首页
├── search.md           → 搜索页(特殊,一般不改)
├── links.md            → 友链
├── experience/         → 经历(文档型,type: docs)
├── learn/              → 学习
└── blog/               → 博客(按 date 排序)

一篇文章两种放法:

方式路径示例适合
单文件content/blog/my-post.md纯文字、图放 static/
页面包content/blog/my-post/index.md + 同目录图片一篇多图,图与文放一起

hugo.yml 里先认这几个键

不用一次读完整个配置文件,先知道这几项即可:

作用
title站名,出现在浏览器标签、顶栏等
params.productionURL + baseURL正式上线后的完整网址;影响 sitemap、RSS、绝对链接
params.github_repo「编辑此页」等按钮指向的内容仓库
params.copyright页脚版权信息
languages.zh.menus.main顶栏菜单(经历 / 学习 / 博客 / 友链)

baseURL 常和 productionURL 用 YAML 锚点绑在一起:

productionURL: &productionURL https://ryanyhy.github.io/YHY-Website/
baseURL: *productionURL

&productionURL 定义名字,*productionURL 引用,改一处全站生效。

写一篇博客:五步

  1. 起文件名 — 在 content/blog/ 新建 .md,文件名会变成 URL 的一部分,建议用英文 slug(如 oink-site-setup-notes.md/blog/oink-site-setup-notes/)。
  2. 写 front matter — 文件最上方元数据,至少含 titledatedescriptionlinkTitle 是列表/卡片上的短标题。
  3. 写正文 — 从 Obsidian 复制后改语法(见下节);可加提示块、步骤列表、锚点、图片。
  4. 本地预览hugo server,打开 /blog/ 看卡片和文章页。
  5. 发布git addgit commitgit push,GitHub Actions 构建并更新 GitHub Pages。

front matter 模板:

---
title: 文章完整标题
linkTitle: 列表短标题
description: 一句话摘要,搜索和卡片会用。
date: 2026-08-29
tags: [Oink, Hugo]
---

Obsidian 迁到 Oink:语法对照

ObsidianOink / Markdown处理
==高亮==**加粗**全部替换
[[双链]][文字](/path/) 或外链改成真实链接
图片 ![[x.png]]![说明](路径)见下文

Oink 常用组件(详见 组件文档):

提示块

> [!NOTE] 阅读提示
> 正文写在这里。

步骤列表 — 每行用 1.,末尾加 {.steps}(见上文「五步」)。

标题锚点## 小节 {#id}{#id} 不显示,用于 [文字](#id) 文内跳转。

图片与图注{caption="..."} 必须写在图片下一行(不能和 ![...](...) 挤同一行):

![示意](/images/blog/example.png)
{caption="图注显示在图片正下方"}
  • 全局图:放 static/images/...,文中用 /images/...
  • 页面包:与 index.md 同目录,用相对路径

make 四条命令:改主题才需要

Makefile 里的四条是别名。Windows 上往往没有 make,且 make dev / make check 需要上级目录有 ../oink 主题源码

命令主题来源适合
make dev本地 ../oink改主题时快速预览
make check本地 ../oink改主题后跑 npm test
make buildgo.mod 固定版正式构建,与线上一致
make servego.mod 固定版生产配置本地预览

只写内容、不改主题时,用 PowerShell 等价即可:

目的PowerShell
日常预览hugo server
正式构建hugo --cleanDestinationDir --minify
接近线上效果hugo server --environment production --minify
dev 与 check 的分工

dev 偏快、给人看效果;check 偏慢、跑自动化测试。改主题时:先 dev 满意,再 check 过关。

发布:git 三步

确认本地预览无误后:

git add content/blog/oink-site-setup-notes.md
git commit -m "blog: add Oink site setup notes"
git push origin main
  • git add:选中本次要提交的文件(只提交博客就写具体路径;全部提交可用 git add -A
  • git commit:在本地打快照
  • git push:推到 GitHub,触发 Actions 部署

顺序:add → commit → push

小结

搭 Oink 站可以记一条主线:Hugo 生成页面,Oink 管样式,content/ 文件夹就是导航树。写博客 = front matter + Markdown 正文 + 本地 hugo server + push。图注记得换行写 {caption=...};Obsidian 的 ==[[链接]] 发布前要改成标准 Markdown。

更系统的阅读顺序仍推荐 Oink 教程书 第 1–3 章;本站 RAICOM 文档 可作为写法范例对照。

3 - ROS 工作空间移植整理

把多台 ROS 小车、多个 catkin 工作空间收敛成一条干净 source 链的实操记录——同名包、编译快照与 udev 都要查。

给 ROS 小车换机、换盘或「多车共用一套代码」时,最容易踩的坑不是 copy 文件,而是 shell 里还留着旧工作空间的 source 链。同一台机器上若叠了多个 catkin ws,甚至出现同名包,运行时到底用的是哪一份,往往要到报错时才暴露。

这篇是我整理、移植工作空间时的笔记:先搞清 catkin 怎么找包,再按顺序收敛 source,最后补上 udev 等硬件绑定。

ROS 工作空间移植示意
多条混乱的 source 链收敛成一条干净的主工作空间

背景:为什么要整理

典型场景:

  • 一台小车上叠了 主 ws + cartographer_ws + cv_bridge_ws 等多个空间
  • 不同目录里存在 同名包(例如多个 mw_multi
  • .bashrc、启动脚本、甚至某次 export ROS_PACKAGE_PATH=... 各写各的

如果不主动整理,会出现「编译过、launch 也能起,但跑的是旧包路径」的隐性问题。我的目标很简单:只保留一条主 source 链,辅助 ws 按需 extend,并能用一条命令验证当前生效的包

先搞清:catkin 按什么顺序找包

ROS Melodic + catkin 的 overlay 规则可以记成一句话:

越晚 source 的工作空间,优先级越高。

从低到高大致是:

/opt/ros/melodic  →  先 source 的 ws  →  后 source 的 ws

因此移植前不必背所有路径,只要回答两个问题:

  1. 当前任务依赖哪些包?
  2. 这些包 实际 来自哪个 ws?

用下面命令查「此刻生效」的那份:

rospack find mw_multi

其中 mw_multi 换成你要确认的包名;输出路径就是 ROS 当前会用的那一份。

建议

.bashrc 或脚本 之前、之后各跑一次 rospack find,对比路径是否切到新 ws。

整理步骤

下面是我实际操作的顺序。前几步解决「显式 source」问题,第 4 步处理 catkin 编译时写进 setup 的「隐式 underlay」。

  1. 收敛成一条主 source 链,辅助 ws 单独保留 — 主工作空间(例如整理后的 1raicom_ws)放整车代码;cartographer_wscv_bridge_ws 等若仍需要,作为 extend 链上的辅助 ws,不要和主 ws 混在同一层反复 source。做法:新建/指定一个主 ws,把要用的包归进去;在 .bashrc注释掉 其它旧 ws 的 source,只保留新主 ws(及必要的 extend)。改完后 rospack find 验证关键包是否指向新路径。
  2. 清掉 ROS_PACKAGE_PATH 的手工 prepend — 仅注释 source 往往不够。若 shell 或脚本里有类似写法:
    export ROS_PACKAGE_PATH=/home/username/old_ws/src:$ROS_PACKAGE_PATH
    它会把 old_ws/src 插到最前面,优先级甚至高于 catkin overlay,只影响执行过这条 export 的会话或从该会话启动的进程。这类行也要注释或删除。(路径中的 username 为占位,请换成你自己的家目录。)
  3. 检查启动脚本里的 source.bashrc 改完还不够:比赛脚本、自写 launch 前 wrapper、setup_env.sh 等若仍 source 旧 ws,从脚本启动的节点仍会走旧链。把所有入口脚本过一遍,统一指向新 ws。
  4. 排查其它 ws 是否仍链着旧 underlay — 若只移植部分 ws、其余 ws 未动,要注意:devel/setup.sh编译时快照。在哪个 shell 环境下 catkin_make,catkin 就把当时的 underlay 写进 setup;之后每次 source .../devel/setup.bash --extend 都可能把旧链带出来。可选做法:重写一个 setup_env.sh,显式定义 source 顺序;或在正确的 underlay 下 重编 cv_bridge_ws 等辅助 ws。
  5. 移植 udev 串口规则 — 换车或换 USB 口后,底盘、IMU、雷达等设备节点可能变。把 config/udev/ 拷到新机器,按新车实际端口改规则并 reload。
我踩过的坑

只改 .bashrcrospack find 是对的,但用旧脚本 rosrun 仍报找不到包——原因是脚本里还有一次对旧 ws 的 source。入口脚本和交互 shell 要一起查。

移植后怎么确认「真的成功了」

检查项怎么做期望
包路径rospack find <包名>指向新 ws 下的路径
环境变量echo $ROS_PACKAGE_PATH无旧 ws 手工 prepend,或为空/符合预期
启动入口.bashrc.sh 里的 source仅新 ws + 必要的 extend
节点能否起roslaunch / 实车 preppackage not found、无错包版本
硬件ls -l /dev/carserialudev 绑定正确

全部通过后,再考虑把旧 ws 目录归档或从机器上移除,避免以后误 source。

小结

工作空间移植的核心不是「文件拷过去」,而是 让运行时只有一条可解释的 overlay 链:主 ws 清晰、辅助 ws 按需 extend、没有残留的 ROS_PACKAGE_PATH 和编译快照里的旧 underlay。rospack find 是最便宜的回归测试;udev 则是换车时不该忘的硬件一步。

若你也在整理多台小车的 ROS 环境,欢迎对照上面的检查表逐项过一遍。