home / kengdb / noteTb

noteTb: 250

This data as json

id user_id content tags created_at updated_at enable pinned folder_id comment position visibility
250 1 1 # 阿里云经验 作者:copilot 版本:1.2.4 # 登录信息 - ip:8.219.6.216 - 登录名称 leedreamer@1638581163749953.onaliyun.com - 登录密码 - AccessKey ID: <已脱敏,见本地 onlinenote.md> - AccessKey Secret: <已脱敏,见本地 onlinenote.md> - SecurityPhoneDevice: 86-17520074504 - SecurityEmailDevice: 24730039@qq.com - ssh 已经上传了公钥,可以直接用密钥登录 >ssh-rsa AAAA...kw== leedreamer44@gmail.com --- # SSH 终端静止自动断开问题 ## 问题描述 阿里云 Ubuntu 服务器,SSH 连接一段时间不操作就自动断开。 ## 原因 `/etc/ssh/sshd_config` 中 `ClientAliveInterval` 默认值为 0(禁用),导致服务端不发送保活信号,连接超时断开。 ## 解决方法 修改 `/etc/ssh/sshd_config`,启用保活机制: ```bash sudo sed -i 's/^#ClientAliveInterval 0/ClientAliveInterval 300/' /etc/ssh/sshd_config sudo sed -i 's/^#ClientAliveCountMax 3/ClientAliveCountMax 5/' /etc/ssh/sshd_config sudo systemctl restart ssh ``` - `ClientAliveInterval 300`:每 5 分钟向客户端发一次保活信号 - `ClientAliveCountMax 5`:最多 5 次无响应后才断开 ## ⚠️ 坑 - 该 Ubuntu 系统 SSH 服务名是 `ssh` 而不是 `sshd`,重启要用 `sudo systemctl restart ssh`,用 `sshd` 会报 "Unit sshd.service not found" - 可用 `sudo systemctl list-units --type=service | grep ssh` 确认服务名 --- # RAM 子用户 AccessKey 无 ECS 权限问题 ## 问题描述 用 AccessKey 调用 ECS API(查实例、修改安全组等)报 403 Forbidden,提示 RAM User not authorized。 ## 原因 存储的 AccessKey(已脱敏)是 **RAM 子用户**(用户名 `leedreamer`)的 Key,不是主账号 Key。 RAM 子用户默认没有任何权限,必须由主账号显式授权才能调用各产品 API。 该用户当前未绑定 `AliyunECSFullAccess` 等策略,所以 ECS API 全部 403。 ## 诊断方法 用 STS `GetCallerIdentity` 确认 AK 身份: ```python from aliyunsdkcore.client import AcsClient from aliyunsdksts.request.v20150401.GetCallerIdentityRequest import GetCallerIdentityRequest import json client = AcsClient('<AK_ID>', '<AK_SECRET>', 'cn-hangzhou') req = GetCallerIdentityRequest() print(json.loads(client.do_action_with_exception(req))) # IdentityType=RAMUser 说明是子用户;IdentityType=Account 说明是主账号 ``` ## 解决方法(一劳永逸) 去控制台 **一次性** 给该 RAM 用户附加 `AdministratorAccess` 策略,之后所有 API 操作均可通过代码完成,不再需要上控制台: 1. 打开 https://ram.console.aliyun.com/users 2. 找到用户 `leedreamer` → 点「添加权限」 3. 选系统策略 `AdministratorAccess` → 确定 ## ⚠️ 坑 - 要通过 API 授权给 RAM 用户,调用者本身也需要 `AliyunRAMFullAccess`——如果 RAM 权限也没有,只能先去控制台手动授权一次,形成鸡和蛋的问题 - 主账号 AK 天生有全部权限,但泄露影响整个账号,不推荐长期使用;推荐只用子用户 AK + 最小化权限 --- # transNote 服务部署(阿里云 SWAS + systemd) > 原名 updateNote,2026-05 重构为 transNote,增加写后回读验证功能。 ## 服务信息 - 脚本路径:`/home/project/simpleNote/transNote.py` - 监听端口:`8888`(注意:必须 > 1024,普通用户无权绑定 ≤1024 的端口) - systemd 服务名:`transnote` - 健康检查:`GET http://8.219.6.216:8888/health`(无需认证) - 鉴权 Header:`X-Api-Key: simpleNote888` - 日志:`/home/project/simpleNote/transNote.log` - 尸体清单:`/home/project/simpleNote/corpseList.txt` ## 接口说明 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/health` | 健康检查,无需鉴权 | | GET | `/notes` | 列出所有笔记 | | GET | `/notes/dead` | 列出已删除笔记 | | GET | `/crops` | 读取可复活笔记 ID 缓存(文件为 `corpseList.txt`) | | GET | `/note/<id>` | 读取笔记内容 | | POST | `/note` | 写入/复活笔记,写后验证 | | DELETE | `/note/<id>` | 删除笔记,标记 `deleted=true` 后验证 | ## ⚠️ 重要经验:服务器端 POST 可能返回 412/502,但不能只看状态码 从阿里云服务器端调用 Simperium POST API(写笔记/删除笔记)时,可能返回 412 或 502,但内容有时已经实际写入。 因此 transNote 不能只看 Simperium 的 HTTP 状态码,而是采用“写入后再验证”的策略: - 普通写入:等待 0.8 秒后 `GET /i/<id>`,对比云端 content 是否等于写入内容。 - 删除笔记:不能依赖 `GET /i/<id>`,已删除笔记可能触发 502;应查询 `/index?limit=100&data=true`,以目标笔记的 `deleted=true` 为准。 当前结论:服务器端 transNote 可以可靠完成读、写、删除;不再是“只能本地 PC 写”。 ## 部署步骤(完整) ```bash # 1. 上传脚本(先传临时文件,再 mv,避免服务正在占用目标路径) scp transNote.py admin@8.219.6.216:~/transNote_new.py ssh admin@8.219.6.216 "mv ~/transNote_new.py /home/project/simpleNote/transNote.py" # 2. 创建本地 transnote.service,scp 上传 scp transnote.service admin@8.219.6.216:~/transnote.service ssh admin@8.219.6.216 "sudo mv ~/transnote.service /etc/systemd/system/transnote.service" # 3. 启用并启动 ssh admin@8.219.6.216 "sudo systemctl daemon-reload && sudo systemctl enable transnote && sudo systemctl start transnote" ``` ## transnote.service 内容 ```ini [Unit] Description=Simplenote Trans Service After=network.target [Service] Type=simple User=admin WorkingDirectory=/home/project/simpleNote ExecStart=/usr/bin/python3 /home/project/simpleNote/transNote.py Restart=always RestartSec=5 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target ``` ## ⚠️ 坑 ### 1. Linux 端口 ≤1024 需要 root 权限 普通用户(admin)绑定 `0.0.0.0:888` 会报 `PermissionError: [Errno 13] Permission denied`。 解决:改用 **8888** 端口(> 1024 不需要额外权限)。 ### 2. PowerShell heredoc 会被压成一行 在 PowerShell 里用 `ssh ... "sudo tee file << 'EOF' ... EOF"` 会因换行符丢失而失败。 **解决:** 本地创建好文件,用 `scp` 上传,不要在 SSH 命令行里写多行内容。 ### 3. scp 目标路径里不能有服务正在打开的文件 systemd 服务在 restart 循环时会反复打开同一个 `.py` 文件,直接 `scp` 到该路径会写入一个空文件(文件被进程占用)。 **解决:** scp 到临时路径(如 `~/transNote_new.py`),再 `mv` 到目标路径;或先 `systemctl stop`,上传完再 `start`。 ### 4. scp 目标路径含中文时 No such file or directory Windows 下 `scp` 传中文路径时,路径被编码为 `\346\265\201...` 八进制,服务器收到的路径不对导致报错: ``` C:\Windows\System32\OpenSSH\scp.exe: dest open "...": No such file or directory ``` **解决:** 先 scp 到 `~/xxx_new.py`(ASCII 路径),再 ssh mv 到目标中文路径(用单引号包裹): ```powershell scp localfile.py admin@8.219.6.216:~/tmp_new.py ssh admin@8.219.6.216 "mv ~/tmp_new.py '/home/project/company/流水同步/check.py'" ``` --- # 轻量应用服务器 API —— 与普通 ECS 完全不同 ## 问题描述 调用 `DescribeSecurityGroups`、`DescribeInstances` 等 ECS API,即使 RAM 用户有 `PowerUserAccess`,返回结果仍为空(0 条记录)。 没有 403 报错,但查不到任何资源。 ## 根本原因(已更正) **该服务器是"轻量应用服务器"(Lighthouse/SWAS),不是普通 ECS 实例。** 两者完全独立,使用不同的 API 产品、不同的 endpoint、不同的 RAM 权限策略: | 属性 | 普通 ECS | 轻量应用服务器 | |------|---------|--------------| | 产品名 | ECS | SWAS / Lighthouse | | 防火墙概念 | 安全组 SecurityGroup | 防火墙规则 FirewallRule | | 查询 API | `DescribeSecurityGroups` | `DescribeFirewallRules` | | Endpoint | `ecs.cn-xxx.aliyuncs.com` | `swas.ap-southeast-1.aliyuncs.com` | | RAM 权限策略 | `AliyunECSFullAccess` | `AliyunSWASFullAccess` | 调用 ECS API 查轻量服务器当然返回空——两个产品的资源不互通。 ## ⚠️ 坑 - 控制台里"轻量应用服务器"和"云服务器 ECS"是两个不同的入口,页面长得不一样 - RAM 子用户 `leedreamer`(账号 ID `1638581163749953`)和轻量服务器**属于同一主账号**,账号匹配没有问题 - 之前误以为是"跨账号问题",实际根因是**产品类型不同、API 不同** ## 正确的 API 使用方式 RAM 子用户需要授权 `AliyunSWASFullAccess`,然后调用 SWAS API: ```python from aliyunsdkcore.client import AcsClient from aliyunsdkswas20200601.request.v20200601.DescribeFirewallRulesRequest import DescribeFirewallRulesRequest client = AcsClient('AK_ID', 'AK_SECRET', 'ap-southeast-1') req = DescribeFirewallRulesRequest() req.set_InstanceId('your-instance-id') # 轻量服务器实例 ID resp = client.do_action_with_exception(req) ``` ## 解决方法 - 去 RAM 控制台给 `leedreamer` 子用户添加 `AliyunSWASFullAccess` 权限 - 用 SWAS SDK 调用 `RunFirewallRules` / `DeleteFirewallRules` 管理防火墙规则 --- # VSCode/SSH 远程开发目录权限问题 ## 问题描述 用 VS Code Remote-SSH 连接服务器后,保存 `/home/project/web/index.html` 等文件时报错: ``` 无法写入文件 ... Error: EACCES: permission denied, open '/home/project/web/index.html' ``` ## 原因 `/home/project/web` 目录的所有者是 `root`,而你用 `admin` 用户登录,普通用户没有写权限。 ## 解决方法 用 SSH 登录服务器,执行: ```bash sudo chown -R admin:admin /home/project/web ``` 把整个 web 目录的所有权改为 `admin`,VS Code 就能正常保存文件了。 ## ⚠️ 坑 - 只要不是 `admin` 用户创建的目录/文件,都要检查权限,否则 VS Code/SSH 编辑会失败。 - 用 `ls -la /home/project/` 可以快速查看所有者。 --- # nginx 反代 Python HTTP Server(SSE 流式输出) ## 场景 在服务器上用 Python 标准库 `http.server` 写一个简单 API Server(支持 SSE 流式输出),nginx 反代某个路径到它。 ## nginx location 配置要点 ```nginx location /liushui/ { proxy_pass http://127.0.0.1:8901/; proxy_http_version 1.1; proxy_set_header Connection ''; proxy_set_header Host $host; proxy_buffering off; # 必须关闭缓冲,SSE 才能实时到达浏览器 proxy_cache off; } ``` - `proxy_pass` 末尾的 `/` 会把 `/liushui/` 前缀去掉,后端看到的路径从 `/` 开始 - `proxy_buffering off` 对 SSE 至关重要,否则浏览器收不到流式数据 - 后端还要在响应头加 `X-Accel-Buffering: no`(让 nginx 层面彻底放弃缓冲) ## Python 后端 SSE 关键点 ```python self.send_header("Content-Type", "text/event-stream; charset=utf-8") self.send_header("Cache-Control", "no-cache") self.send_header("X-Accel-Buffering", "no") # 每条消息格式: self.wfile.write(f'data: {json.dumps(line)}\n\n'.encode('utf-8')) self.wfile.flush() # 必须 flush,否则数据会卡在缓冲区 ``` ## 修改 nginx 配置的正确流程 1. 用 Python 脚本(bytes 替换)修改配置,比 `sed` 更可靠 2. `sudo nginx -t` 验证语法 3. `sudo systemctl reload nginx` 热重载(不中断现有连接) ## ⚠️ 坑 ### PowerShell 里 SSH heredoc 中的 `$host` 会被展开 在 PowerShell 里执行: ```powershell ssh server "sudo tee /etc/nginx/xxx.conf << 'EOF' proxy_set_header Host $host; EOF" ``` 即使 bash 侧是单引号 EOF,`$host` 仍会被 **PowerShell** 先展开为 `System.Management.Automation.Internal.Host.InternalHost`,导致 nginx 配置写错。 **解决:** 用 PowerShell here-string `@"..."@` 包裹整个 SSH 命令,加上 bash 侧单引号 heredoc,并把 `$host` 写成 `\$host`;或者把配置文件本地写好再 scp 上传。 ### Python heredoc 里的 `$host` 同理 用 `@"..."@` 传 Python 脚本给 SSH 时,字符串里的 `$host` 也会被 PowerShell 展开。 **解决:** 把 Python 脚本写成本地文件(`create_file`),再 scp 上传执行。 --- # SSH 卡在 banner exchange,且 HTTP 端口只连接不响应 ## 问题描述 本机之前可以 SSH 到阿里云轻量应用服务器 `8.219.6.216`,后来执行: ```powershell ssh admin@8.219.6.216 ``` 连接失败。`ssh -vvv` 显示 TCP 已建立,但超时在 banner 阶段: ```text Connection established. Local version string SSH-2.0-OpenSSH_for_Windows_9.5 Connection timed out during banner exchange ``` 同时,服务器上 transNote 的 `8888` 端口也表现为 TCP 可连接,但 HTTP 请求没有任何响应: ```powershell curl.exe --noproxy '*' -v --connect-timeout 8 --max-time 20 http://8.219.6.216:8888/health ``` 结果是请求已发送,20 秒内收到 0 字节响应。 --- # Nginx 路由配置 — 多服务共用一个域名 ## 场景 单域名 `leedreamer.cn` 下,按路径分流到多个后端服务: - `/` → 自定义提示页(不显示 nginx 默认页) - `/company` → Python HTTP Server(财务后台,端口 8902) - `/transnote/` → Python API Server(笔记中继,端口 8888) - `/tranNote/` → 静态 HTML 前端(笔记前端页面,`alias` 静态目录) - `/liushui/` → Python SSE Server(流水同步,端口 8901) ## 路由配置要点 ### 1. 根路径返回自定义 HTML(不用默认 nginx 页) ```nginx location / { add_header Content-Type 'text/html; charset=utf-8'; return 200 '<!DOCTYPE html>...自定义内容...'; } ``` 注意:`return` 指令可以携带响应体,结合 `add_header Content-Type` 实现内联 HTML,无需额外文件。 ### 2. 静态文件目录用 alias 配合 try_files ```nginx location = /tranNote { return 301 /tranNote/; # 无尾斜杠 → 重定向加斜杠 } location /tranNote/ { alias /home/project/simpleNote/www/; index index.html; try_files $uri $uri/ index.html; # SPA fallback } ``` - `alias` + `try_files` 必须写 `index.html`(相对于 alias 目录),不能写 `/tranNote/index.html` - 用 `location = /path` 处理无尾斜杠跳转,避免 alias 路径错误 ### 3. 前端 API 路径必须与 nginx 代理路径一致 前端 HTML 里的 `fetch('/note', ...)` 是根路径,nginx 无法代理到 `/transnote/note`。 **解决:** 把前端 fetch 路径改为 `/transnote/note`,与 nginx `location /transnote/` 代理路径匹配。 ```javascript // ❌ 错误:根路径,nginx 无法匹配到后端 fetch('/note', { ... }) // ✅ 正确:带 nginx 代理前缀 fetch('/transnote/note', { ... }) ``` ### 4. PowerShell SSH 修改远程文件的坑 用 `sed` 在 PowerShell SSH 命令里做字符串替换会遇到引号转义问题: - 单引号在 PowerShell 中有特殊含义,传到 bash 的引号可能丢失 - `sed "s|'xxx'|'yyy'|g"` 通过 SSH 传输时常失败 **正确方案**:写本地 Python 脚本 → `scp` 上传 → `ssh python3 /tmp/script.py` 执行: ```powershell # 本地写脚本 'content = open(path).read()' | Out-File fix.py # scp 上传 scp -i ~/.ssh/id_rsa fix.py root@server:/tmp/fix.py # 远程执行 ssh -i ~/.ssh/id_rsa root@server "python3 /tmp/fix.py" ``` ## 最终路由表 | 路径 | 行为 | 备注 | |------|------|------| | `/` | 显示"私人后台,不要进来哦" | 内联 HTML,`return 200` | | `/transnote/` | 代理到 127.0.0.1:8888 | API 接口 | | `/liushui/` | 代理到 127.0.0.1:8901 | SSE 流式 | | `/company` | 代理到 127.0.0.1:8902 | 财务后台 | | `/tranNote/` | 静态文件 `/home/project/simpleNote/www/` | 前端页面 | ## 影响范围 - 多服务共用单域名的所有 nginx 路由配置场景 - 前端 fetch 路径必须与 nginx 代理前缀匹配 - 静态文件 `alias` 与 `root` 用法差异:`alias` 替换整个路径,`root` 拼接路径 ## 判断方法 先区分问题发生在哪一层: ```powershell Test-NetConnection 8.219.6.216 Test-NetConnection 8.219.6.216 -Port 22 Test-NetConnection 8.219.6.216 -Port 8888 curl.exe --noproxy '*' -v --connect-timeout 8 --max-time 20 http://8.219.6.216:8888/health ssh -vvv -o BatchMode=yes -o ConnectTimeout=30 admin@8.219.6.216 exit ``` 如果结果同时满足: - ping 成功 - 22 端口 TCP 成功 - 8888 端口 TCP 成功 - SSH 卡在 `banner exchange`,没有进入密钥认证 - HTTP 请求 0 字节响应直到超时 则通常不是本机密钥、用户名、known_hosts 或阿里云防火墙简单关闭端口的问题,而是服务器端系统或进程异常。 ## 原因 SSH banner 是服务端 `sshd` 在认证前就应返回的协议版本行。卡在 banner 之前,说明还没到密钥认证阶段。 多个端口同时“能建立 TCP,但应用层不返回”,常见原因包括: - 服务器 CPU/内存/IO 卡死或负载极高 - 进程数或文件句柄耗尽 - sshd/transNote 进程被阻塞 - 系统网络栈或安全组件异常 - 磁盘满导致服务异常 ## 解决办法 本机无法通过 SSH 修复时,需要走云厂商外部管理通道: 1. 登录阿里云控制台,进入“轻量应用服务器”。 2. 查看实例状态、CPU、内存、磁盘 IO、带宽监控。 3. 如果实例运行但服务无响应,优先在控制台执行实例重启。 4. 重启后验证: ```powershell ssh admin@8.219.6.216 curl.exe --noproxy '*' http://8.219.6.216:8888/health ``` 5. SSH 恢复后立刻检查服务器内部状态: ```bash uptime free -h df -h sudo journalctl -u ssh --since "1 hour ago" sudo journalctl -u transnote --since "1 hour ago" sudo systemctl status ssh transnote ``` 6. 如果控制台重启后仍然不恢复,使用阿里云 VNC/救援连接检查系统日志、磁盘空间、防火墙和 sshd 状态。 ## 影响范围 - VS Code Remote-SSH 无法连接 - scp/ssh 上传部署命令无法执行 - 依赖服务器上 transNote 的 Simplenote 中继服务不可用 - 但公网 IP 和端口未必是关闭状态,普通端口探测可能误判为“网络正常” --- # Nginx duplicate default_server 错误 ## 问题描述 Nginx UI 页面报错: ``` a duplicate default server for 0.0.0.0:80 in /etc/nginx/sites-enabled/transNote:6 nginx: configuration file /etc/nginx/nginx.conf test failed exit status 1 ``` nginx 无法重新加载配置,进入错误状态。 ## 原因 `/etc/nginx/sites-enabled/` 下有两个站点配置文件,同一端口(80 或 443)上都有 `listen 80 default_server;`,nginx 只允许每个端口/地址有一个 default server。 典型触发场景:用 Nginx UI 新建了一个涵盖所有路由的综合站点(default),但旧的站点配置文件(transNote)仍保留着 `default_server` 标记。 ## 解决办法 从旧站点配置中去掉所有 `default_server` 标记: ```bash # 去掉 transNote 配置里所有 default_server sed -i 's/listen 80 default_server;/listen 80;/g; \ s/listen \[::\]:80 default_server;/listen [::]:80;/g; \ s/listen 443 ssl default_server;/listen 443 ssl;/g; \ s/listen \[::\]:443 ssl default_server;/listen [::]:443 ssl;/g' \ /etc/nginx/sites-enabled/transNote # 验证 nginx -t && nginx -s reload ``` ## ⚠️ 注意 - 去掉 `default_server` 后,两个站点 `server_name` 相同(都是 `leedreamer.cn`)时 nginx 会产生 warn:`conflicting server name "leedreamer.cn", ignored` - 这是警告不是错误,nginx 会用先加载的那个站点配置处理请求,另一个被忽略 - 理想的做法是直接删除或禁用已被完全替代的旧站点,但 Nginx UI 管理的站点不要通过 SSH 手动删除 ## 影响范围 - 所有通过 Nginx UI 管理并新增站点的场景 - 旧配置文件保留 `default_server` 是最常见的触发原因 [] 2026-05-12 13:59:56 2026-05-12 13:59:56 T F   source=simplenote; source_id=41c85de8-8279-4204-a3f0-217c073e832f 19 public

Links from other tables

  • 0 rows from note_id in noteShareTb
  • 0 rows from note_id in shareLinkTb
Powered by Datasette · Queries took 17.458ms