260210-mongodb(copyDatabase) show database 如何调整数据库名称

在 MongoDB 中,没有直接的 plain复制 rename database 命令

copydatabase()已过期
copydatabase()已过期
copydatabase()已过期

方法1:使用plain复制mongodump和plain复制mongorestore(适合大型数据库)

1
2
3
4
5
6
7
8
9
10
# 1. 导出旧数据库
mongodump --db old_db_name --out /backup/path/

# 2. 导入为新数据库名
mongorestore --db new_db_name /backup/path/old_db_name/

# 3. 删除旧数据库(通过 mongo shell)
mongo
> use old_db_name
> db.dropDatabase()

方法2:使用plain复制mongosh的聚合管道(MongoDB 4.2+)

1
2
3
4
5
6
7
// 遍历所有集合并复制
use
old_db_name

db.getCollectionNames().forEach(function (coll) {
db[coll].aggregate([{$out: {db: "new_db_name", coll: coll}}]);
});

⚠️ 注意事项

项目 说明
索引 复制后需要重新创建索引
用户权限 数据库用户不会自动复制,需手动创建
磁盘空间 确保有足够空间存储两份数据
生产环境 建议在维护窗口操作,或先备份

快速检查命令

1
2
3
4
5
6
7
8
9
10
// 查看所有数据库
show
dbs

// 查看当前数据库
db.getName()

// 切换数据库
use
database_name

**推荐在生产环境使用 plain复制 mongodump/mongorestore**,更加稳定可靠,且可以验证数据完整性。

260210-MongoDBHA-MongoDB集群-重置绑定关系-(Replica Set)副本集集群搭建

这是一个涉及数据库运维的操作,需要谨慎处理。

MongoDB 集群配置删除与重新绑定

1. 理解 MongoDB 集群配置存储位置

MongoDB 集群配置主要存储在 Config Servers 中:

  • Config Database (plain复制 config): 包含分片集群的元数据
  • Local Database: 每个节点存储的副本集配置

2. 删除集群配置的方法

场景 A: 完全重置分片集群

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
# 1. 停止所有 mongos 路由进程
killall mongos # 或使用 systemctl stop mongos

# 2. 停止所有分片 mongod 实例
# 在每个分片节点上执行
killall mongod

# 3. 停止 Config Server 副本集
# 在所有 config server 节点上执行
killall mongod

# 4. 清除 Config Server 数据目录(⚠️ 危险操作)
# 假设数据目录为 /data/configdb
rm -rf /data/configdb/*

# 5. 重新初始化 Config Server 副本集
mongod --configsvr --replSet configRS --dbpath /data/configdb --port 27019

# 连接主节点初始化
rs.initiate({
_id: "configRS",
configsvr: true,
members: [
{ _id: 0, host: "cfg1.example.com:27019" },
{ _id: 1, host: "cfg2.example.com:27019" },
{ _id: 2, host: "cfg3.example.com:27019" }
]
})

场景 B: 仅移除分片(保留集群框架)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 连接到 mongos
mongo--
host
mongos.example.com--
port
27017

// 1. 查看当前分片
sh.status()

// 2. 移除分片(会迁移数据)
use
admin
db.runCommand({removeShard: "shard0000"})

// 3. 检查移除进度,直到状态为 "completed"
db.runCommand({removeShard: "shard0000"})

// 4. 如果需要强制移除(数据已备份)
db.runCommand({removeShard: "shard0000", drop: true})

场景 C: 重置副本集配置(非分片集群)

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
// 连接到副本集成员
mongo--
host
mongod.example.com--
port
27017

// 1. 查看当前配置
rs.conf()

// 2. 强制重新配置(适用于节点变更)
rs.reconfig({
_id: "myReplicaSet",
members: [
{_id: 0, host: "newhost1:27017"},
{_id: 1, host: "newhost2:27017"},
{_id: 2, host: "newhost3:27017"}
]
}, {force: true}) // force: true 用于强制重新配置

// 3. 或者完全重置(先删除 local 数据库的配置)
use
local
db.system.replset.remove({}) // ⚠️ 仅在确定要重置时执行
// 然后重启 mongod,重新执行 rs.initiate()

3. 重新绑定新配置

步骤 1: 重新配置 Config Server

1
2
3
4
5
6
7
8
9
10
// 初始化新的 Config Server 副本集
rs.initiate({
_id: "configRS",
configsvr: true,
members: [
{_id: 0, host: "new-cfg1:27019", priority: 2},
{_id: 1, host: "new-cfg2:27019"},
{_id: 2, host: "new-cfg3:27019", arbiterOnly: true}
]
})

步骤 2: 启动 mongos 并配置分片

1
2
# 启动 mongos,指向新的 config server
mongos --configdb configRS/new-cfg1:27019,new-cfg2:27019,new-cfg3:27019 --port 27017
1
2
3
4
5
6
7
8
9
// 连接到 mongos 添加分片
sh.addShard("shardRS1/shard1-node1:27018,shard1-node2:27018")
sh.addShard("shardRS2/shard2-node1:27018,shard2-node2:27018")

// 启用数据库分片
sh.enableSharding("myDatabase")

// 对集合进行分片
sh.shardCollection("myDatabase.myCollection", {shardKey: 1})

4. 关键注意事项

操作 风险等级 说明
删除 Config Server 数据 🔴 极高 会丢失所有分片元数据
强制 rs.reconfig 🟡 中等 可能导致脑裂
removeShard 🟢 较低 数据会自动迁移
停止 mongos 🟢 低 仅影响路由,不丢数据

5. 安全操作建议

1
2
3
4
# 操作前务必备份
mongodump --host configRS/cfg1:27019 --db config --out /backup/config_$(date +%Y%m%d)

# 或者使用文件系统快照(如果使用 WiredTiger)

6. 常见问题排查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 检查 Config Server 状态
use
admin
db.runCommand({getShardMap: 1})

// 查看分片连接状态
sh.status()

// 检查 balancer 状态
sh.getBalancerState()

// 如果配置不一致,强制刷新
use
admin
db.adminCommand({flushRouterConfig: 1})

⚠️ 重要提醒

  • 在生产环境执行前,务必在测试环境验证
  • 确保有完整的数据备份
  • 操作期间会有服务中断,选择维护窗口执行
  • 如果是云托管 MongoDB (Atlas),请使用提供商的控制台操作,不要手动修改

2602-(perfmon.msc)Windows定位和排查CPU占用高进程问题

perfmon.msc(定位CPU问题)

perfmon.msc(性能监视器)定位 Windows CPU 问题,核心是通过添加关键计数器实时监控 / 日志分析,先判断 CPU
瓶颈类型,再定位到进程 / 线程,最后结合 JDK 工具深挖 Java 问题,以下是精准可落地的完整流程

二、添加 CPU 核心计数器(必选)

这是判断 CPU 瓶颈的核心步骤,优先添加以下计数器,覆盖整体、用户 / 内核、进程、线程与中断维度:

计数器路径 作用 正常阈值 异常判断
\Processor(*)% Processor Time 整体 CPU 使用率(* 含所有核心,_Total 为总和) < 70% 持续 > 80% 为瓶颈,>90% 严重
\Processor(*)% User Time 用户态 CPU(如 Java 应用) < 50% 持续 > 80% 多为应用代码问题
\Processor(*)% Privileged Time 内核态 CPU(如驱动、系统调用) < 30% 持续 > 50% 多为驱动 / 系统服务问题
\Process(*)% Processor Time 单个进程 CPU 占用(筛选 java.exe/javaw.exe) 占比高的进程优先排查
\Thread(*)% Processor Time 单个线程 CPU 占用(需指定进程 PID) 定位进程内高 CPU 线程
\System\Processor Queue Length CPU 等待队列长度 每核心 < 2 持续 > 2 且 CPU 高,说明调度拥堵
\Processor(*)% Interrupt Time 中断占用时间 < 5% 持续 > 10% 多为硬件 / 驱动问题

添加操作步骤

  1. 右键性能监视器图表→「添加计数器」;
  2. 在弹出窗口中,依次展开上述计数器类别,选中目标计数器→「添加」→「确定」;
  3. 若需监控特定 Java 进程,在 \Process 类别中筛选 PID 对应的 java.exe/javaw.exe。

通过arthas thread -n 5 指定进程PID查看

1
2
3
4
5
6
7
8
9
10
11
12
"flow-execute290488" Id=930149 cpuUsage=46.42% deltaTime=93ms time=31828ms RUNNABLE
at com.oracle.truffle.api.library.LibraryFactory.dispatch(LibraryFactory.java:548)
at com.oracle.truffle.api.library.LibraryFactory.getUncached(LibraryFactory.java:396)
at com.oracle.truffle.api.interop.InteropLibraryGen$UncachedDispatch.getArraySize(InteropLibraryGen.java:7348)
at com.oracle.truffle.host.HostProxy.getMembers(HostProxy.java:271)
at com.oracle.truffle.host.HostProxyGen$InteropLibraryExports$Cached.getMembers(HostProxyGen.java:941)
at com.oracle.truffle.api.interop.InteropLibrary.getMembers(InteropLibrary.java:734)
at com.oracle.truffle.polyglot.PolyglotMap$Cache$EntrySet.doCached(PolyglotMap.java:589)
at com.oracle.truffle.polyglot.PolyglotMapFactory$CacheFactory$EntrySetNodeGen.executeImpl(PolyglotMapFactory.java:323)
at com.oracle.truffle.polyglot.HostToGuestRootNode.execute(HostToGuestRootNode.java:124)
at com.oracle.truffle.api.impl.DefaultCallTarget.call(DefaultCallTarget.java:118)
at com.oracle.truffle.polyglot.PolyglotMap.entrySet(PolyglotMap.java:131)

jenkins配置保存-重启无效(XML保存异常)-Plugins(ssh-server)-保存了,重启又还原了,是怎么回事.


异常日志 tail -f /jenkins/apache-tomcat-10.1.50/logs/catalina.out -n500

这个密码 看起来是明文,而其他配置都是加密格式({AQAAABAAAA…})!
根本问题:这个明文密码可能包含不可见字符,或者在保存时被错误解析,导致产生了 0x00 空字符。

1
2
3
4
05-Feb-2026 14:42:19.252 警告 [Handling POST /jenkins/manage/configSubmit from 192.168.0.75 : http-nio-8080-exec-1] hudson.model.Descriptor.save Failed to save /jenkins/jenkins_home/jenkins.plugins.publish_over_ssh.BapSshPublisherPlugin.xml
java.io.IOException: java.lang.RuntimeException: Failed to serialize jenkins.plugins.publish_over_ssh.descriptor.BapSshPublisherPluginDescriptor#hostConfigurations for class jenkins.plugins.publish_over_ssh.BapSshPublisherPlugin$Descriptor
at hudson.XmlFile.write(XmlFile.java:223)
at hudson.model.Descriptor.save(Descriptor.java:964)
1
2
3
4
5
6
java.io.IOException: java.lang.RuntimeException: Failed to serialize jenkins.plugins.publish_over_ssh.descriptor.BapSshPublisherPluginDescriptor#hostConfigurations for class jenkins.plugins.publish_over_ssh.BapSshPublisherPlugin$Descriptor
at hudson.XmlFile.write(XmlFile.java:223)
at hudson.model.Descriptor.save(Descriptor.java:964)
at PluginClassLoader for publish-over-ssh//jenkins.plugins.publish_over_ssh.descriptor.BapSshPublisherPluginDescriptor.configure(BapSshPublisherPluginDescriptor.java:158)
at jenkins.model.Jenkins.configureDescriptor(Jenkins.java:4049)
at jenkins.model.Jenkins.doConfigSubmit(Jenkins.java:4013)

Caused by: com.thoughtworks.xstream.io.StreamException: Invalid character 0x0 in XML stream
Invalid character 0x0 表示 SSH 配置的代理密码字段 (proxyPassword) 包含空字符(NULL character),这是 XML 不允许的字符!
这不是权限问题,而是 数据污染问题!

🔍 问题分析

错误链:
Jenkins 尝试保存 Publish Over SSH 配置
序列化 BapSshHostConfiguration#proxyPassword 字段时失败
密码中包含 0x0(空字符),XML 写入器拒绝写入
导致整个配置文件无法保存
可能原因:
之前配置的代理密码包含特殊字符或空字符
配置文件损坏,密码字段被污染
从其他环境复制配置时编码问题

这个密码 看起来是明文,而其他配置都是加密格式({AQAAABAAAA…})!
根本问题:这个明文密码可能包含不可见字符,或者在保存时被错误解析,导致产生了 0x00 空字符。

看到了关键信息!您是用 Tomcat 启动 Jenkins,而且注意到这个参数:

-Dorg.apache.catalina.security.SecurityListener.UMASK=0027
这就是问题根源!

1
2
3
4
5
6
7
ps -ef | grep jenkins
avahi 677 1 0 13:35 ? 00:00:01 avahi-daemon: running [jenkins171.local]
root 8020 1 62 14:16 ? 00:00:53 /usr/local/jdk//bin/java -Djava.util.logging.config.file=/jenkins/apache-tomcat-10.1.50/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xmx14G -Djava.awt.headless=true -DJENKINS_HOME=/jenkins/jenkins_home -Duser.timezone=GMT+08 -Difile.encoding=utf-8 -Dorg.jenkinsci.plugins.gitclient.Git.timeOut=1200 -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dsun.io.useCanonCaches=false -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED -DJENKINS_HOME=/jenkins/jenkins_home -classpath /jenkins/apache-tomcat-10.1.50/bin/bootstrap.jar:/jenkins/apache-tomcat-10.1.50/bin/tomcat-juli.jar -Dcatalina.base=/jenkins/apache-tomcat-10.1.50 -Dcatalina.home=/jenkins/apache-tomcat-10.1.50 -Djava.io.tmpdir=/jenkins/apache-tomcat-10.1.50/temp org.apache.catalina.startup.Bootstrap start
ubuntu 8159 3314 0 14:17 pts/1 00:00:00 grep --color=auto jenkins

-Dorg.apache.catalina.security.SecurityListener.UMASK=0027
-Dorg.apache.catalina.security.SecurityListener.UMASK=0027

问题分析
UMASK=0027 是 Tomcat 的安全机制,它会:
覆盖 root 用户的默认 umask(通常是 0022)
强制新创建文件的权限为 640(即 -rw-r—–)
移除其他用户的写权限
虽然进程是 root,但 Jenkins 在写入配置文件时,Tomcat 的安全监听器会强制应用这个 umask,导致:
文件权限被限制为 640
Jenkins 无法再次写入(因为实际运行中 Jenkins 会检查并尝试重写)


查看文件是否被锁定

1
2
3
4
5
6
7
8
# 检查文件是否被其他进程占用
lsof /jenkins/jenkins_home/jenkins.plugins.publish_over_ssh.BapSshPublisherPlugin.xml

# 检查文件属性(是否有 immutable 标志)
lsattr /jenkins/jenkins_home/jenkins.plugins.publish_over_ssh.BapSshPublisherPlugin.xml

# 如果有 i 标志,移除它
chattr -i /jenkins/jenkins_home/jenkins.plugins.publish_over_ssh.BapSshPublisherPlugin.xml

查看SSH-Server配置是否生效 Publish Over SSH

1
sudo cat /jenkins/jenkins_home/jenkins.plugins.publish_over_ssh.BapSshPublisherPlugin.xml | grep -A5 "jenkins(prod-online)"

查询配置文件权限

1
2
3
4
5
6
7
ls -lh *sh*
-rwxr-x--- 1 root root 366 8月 18 2022 com.dabsquared.gitlabjenkins.GitLabPushTrigger.xml
-rw-r----- 1 root root 4.3K 2月 5 14:11 hudson.plugins.emailext.ExtendedEmailPublisher.xml
-rw-r----- 1 root root 683 1月 21 19:07 hudson.plugins.powershell.PowerShellInstallation.xml
-rw-r----- 1 root root 1.9K 2月 5 14:11 jenkins.plugins.publish_over_ssh.BapSshPublisherPlugin.xml
-rwxr-xr-x 1 root root 42K 2月 5 13:53 jenkins.plugins.publish_over_ssh.BapSshPublisherPlugin.xml260205
-rwxr-xr-x 1 root root 42K 2月 5 14:05 jenkins.plugins.publish_over_ssh.BapSshPublisherPlugin.xml260205003

Tomcat 部署修复

1
2
3
4
5
6
7
8
9
10
11
12
13
# 找到 Tomcat 的 setenv.sh(如果没有则创建)
sudo vi /jenkins/apache-tomcat-10.1.50/bin/setenv.sh

# 添加以下内容
export JENKINS_HOME=/jenkins/jenkins_home
export CATALINA_OPTS="-DJENKINS_HOME=/jenkins/jenkins_home"

# 确保目录存在且有权限
sudo mkdir -p /jenkins/jenkins_home
sudo chown -R tomcat:tomcat /jenkins/jenkins_home

# 重启 Tomcat
sudo systemctl restart tomcat9

2602-DockerMongoDB重置密码

启动临时容器,不加载任何认证

1
2
3
4
5
6
7
8
9
10
11
12
# 2. 启动临时容器,不加载任何认证
docker run -d \
--name mongo_reset \
-v mongo_data:/data/db \
-p 27017:27017 \
registry.cn-hangzhou.aliyuncs.com/farerboy/mongo:8.0.5-rc1 \
mongod --bind_ip_all

# 3. 尝试无认证连接
docker exec -it mongo_reset mongosh


如果能连进去,执行:

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
// 查看所有数据库
show dbs

// 切换到 admin(如果不存在就创建)
use admin

// 查看是否有用户
db.system.users.find().pretty();

// 删除用户
db.dropUser('usertest')

// 如果没有用户,直接创建
db.createUser({
user: "admin",
pwd: "xxxxxxxx",
mechanisms: ["SCRAM-SHA-1"],
roles: [{ role: "clusterMonitor", db: "admin" },{ role: "clusterManager", db: "admin" },{ role: "clusterMonitor", db: "admin" },{ role: "clusterManager", db: "admin" },'readWriteAnyDatabase', 'dbAdminAnyDatabase', {
role: "dbAdmin",
db: 'dbName'
}, {
role: "readWrite",
db: 'dbName'
}]
});

重新绑定MongoDB

1
2
3
4
5
6
7
8
# 3. 重新启动(相当于全新实例,但数据文件还在,需要修复)
docker run -d \
--name mongo_new \
-v mongo_data:/data/db \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=NewPassword123 \
-p 27017:27017 \
registry.cn-hangzhou.aliyuncs.com/farerboy/mongo:8.0.5-rc1

260123-windows 11 开机后必须在电脑上输入密码后,才能远程,是怎么回事


SUCCESS

计算机配置 → 管理模板 → Windows组件 → 远程桌面服务 → 远程桌面会话主机 → 安全

3. Administrator账户是否被禁用

1
Win+R → lusrmgr.msc → 用户 → Administrator → 取消勾选"账户已禁用"

4. 远程桌面服务的安全层设置

1
2
Win+R → gpedit.msc
计算机配置 → 管理模板 → Windows组件 → 远程桌面服务 → 远程桌面会话主机 → 安全

检查这两项:

  • “要求使用网络级别的身份验证…” → 设为已启用(推荐)或已禁用测试
  • “设置客户端连接加密级别” → 设为已禁用或”客户端兼容”

5. 防火墙是否放行

1
2
控制面板 → Windows Defender 防火墙 → 允许应用通过防火墙
确认"远程桌面"勾选了"专用"和"公用"

6. 最粗暴测试:先关掉NLA

1
2
gpedit.msc → 计算机配置 → 管理模板 → Windows组件 → 远程桌面服务 → 远程桌面会话主机 → 安全
"要求使用网络级别的身份验证..." → 已禁用

重启后再试。如果能连,说明是NLA凭据问题;如果连不上,是网络或防火墙问题。


SUCCESS

想让“重启后远程直接能连”,就得让系统在开机后自动完成一次交互式登录,把会话跑起来。做法有两种:

  1. 注册表手动写 AutoAdminLogon(备用方案)

  2. Win+R → regedit

  3. 定位到
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon

  4. 右侧新建/修改以下键值(都是 REG_SZ):

    1
    2
    3
    4
    AutoAdminLogon = 1
    DefaultUserName = Administrator
    DefaultDomainName = . (或你的计算机名)
    DefaultPassword = 你的密码
  5. 重启即可。

安全提醒

  • 自动登录等于把密码明文存在注册表(或 netplwiz 保管),任何能物理接触机器的人都能看到;只建议在受控的机房/家里使用。
  • 如果机器要放在公网,最好改用“开机后先本地输一次密码”的手动方式,或者给 BIOS/BitLocker 加电口令,再配 VPN 跳板,而不是单纯依赖自动登录。

这是 Windows 11 的默认安全机制:
如果本地还没“真正”用密码登录过一次,系统里就没有缓存可供 NLA(网络级身份验证)使用的凭据,远程桌面就会直接拒绝连接,表现为“必须先在本机输完密码,远程才能连”。

为什么会这样

  1. 很多人第一次激活系统用的是 Microsoft 账号,但随后只设了 PIN 或 Windows Hello 刷脸/指纹。

  2. PIN/Hello 只能解锁“已登录的本地会话”,不能当作 NLA 的凭据;而 Microsoft 账号的密码又从未在本地输入过,所以缓存里找不到有效凭据。

  3. 远程桌面服务启动时,NLA 阶段就要求出示“用户名+密码”,本地没有缓存只能失败,于是出现“必须本地先登录一次”的现象

解决思路(任选其一,推荐前两种)

  1. 本地用“账号密码”重新登录一次 a. 先锁屏 Win+L → 登录选项 → 选“密码”并输入 Microsoft 账号密码。 b.
    成功后该凭据会被缓存,今后无需再本地登录即可远程 。

  2. 干脆新建一个本地管理员,专门做远程

    1
    2
    3
    powershell
    net user rdpuser 你的密码 /add
    net localgroup administrators rdpuser /add

然后在“设置 → 系统 → 远程桌面 → 远程桌面用户”里把 rdpuser 加进去。以后远程就用这个本地账户即可

  1. 关闭“仅允许 Windows Hello 登录” 设置 → 账户 → 登录选项 → 关闭“为提高安全性,仅允许 Windows Hello 登录 Microsoft
    账号”。这样你就能在锁屏界面直接选“密码”,完成一次缓存 。

  2. 组策略放行“空密码”(仅家庭版不可用)

  3. 彻底关掉 NLA(降低安全性)

一句话总结
“先本地输一次密码”只是为了让 Windows 把真正的账号密码缓存下来;只要凭据存在,远程桌面就能在 NLA 阶段完成验证,之后再也不需要本地先登录。按上面
1 或 2 操作即可根治。

可以,直接把“Administrator”设为远程桌面用户即可,不需要再新建一个 rdpuser。
步骤如下(Win11 专业版/企业版):

  1. 先在本机用 Administrator 的「密码」登录一次
    ‑ 锁屏 → 登录选项 → 选「密码」并输入 Administrator 的密码,让系统把凭据缓存下来;这是解决“必须本地先登录”的关键。

  2. 把 Administrator 加入「远程桌面用户」组
    Win+X → 终端(管理员) →

    1
    net localgroup "Remote Desktop Users" administrator /add
  3. 确认远程桌面已开启
    设置 → 系统 → 远程桌面 → 打开「启用远程桌面」。

  4. 客户端连接时
    用户名填 .\Administrator(或计算机名\Administrator),再输入密码即可直接远程,无需再本地先登录。

注意

  • 如果系统用的是 Microsoft 在线账号,密码要输入「Microsoft 账号密码」而不是 PIN/Hello。

  • 出于安全考虑,建议给 Administrator 设一个强密码,并在路由器或防火墙里限制可访问 3389 的 IP 范围


260121-Ubuntu生成docker证书

Docker启用TLS加密解决暴露2375端口引发的安全漏洞,被黑掉三台云主机的教训总结

1. 设置主机名

编辑/etc/hostname,服务器主机名 ubuntu

1
vi /etc/hostname

2. 生成TLS证书

创建证书生成脚本 docker-cert.sh,放置/script目录

1
2
3
sudo mkdir -p /script /data/cert/docker
sudo touch /script/docker-cert.sh
sudo vim /script/docker-cert.sh

docker-cert.sh添加内容

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
#!/bin/bash

set -e
if [ -z $1 ];then
echo "请输入Docker服务器主机名"
exit 0
fi
HOST=$1
mkdir -p /data/cert/docker
cd /data/cert/docker
openssl genrsa -aes256 -out ca-key.pem 4096
openssl req -new -x509 -days 3650 -key ca-key.pem -sha256 -out ca.pem
openssl genrsa -out ca-key.pem 4096
openssl req -subj "/CN=$HOST" -sha256 -new -key ca-key.pem -out server.csr
# 配置白名单,推荐配置0.0.0.0,允许所有IP连接但只有证书才可以连接成功
# 创建证书时,您需要提供 localhost 作为主题备用名称。您可以通过提供以下附加参数来做到这一点:-ext "SAN:c=DNS:localhost,IP:127.0.0.1"
# echo subjectAltName = DNS:$HOST,IP:0.0.0.0 > extfile.cnf
# echo subjectAltName = DNS:localhost,IP:0.0.0.0 > extfile.cnf
echo subjectAltName = IP:$HOST,IP:0.0.0.0 > extfile.cnf

openssl x509 -req -days 3650 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-key.pem -extfile extfile.cnf
openssl genrsa -out key.pem 4096
openssl req -subj '/CN=client' -new -key key.pem -out client.csr
echo extendedKeyUsage = clientAuth > extfile.cnf
openssl x509 -req -days 3650 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnf
rm -v client.csr server.csr
chmod -v 0400 ca-key.pem key.pem ca-key.pem
chmod -v 0444 ca.pem server-key.pem cert.pem

执行 docker-cert.sh 脚本,生成证书放置 /data/cert/docker 目录中

1
2
3
4
5
# ubuntu是服务器的主机名
sh /script/docker-cert.sh ubuntu
sh /script/docker-cert.sh VM-12-11-centos (密码: ubuntu666)
sh /script/docker-cert.sh ubuntu (密码: ubuntu666)
sh /script/docker-cert.sh VM-12-4-ubuntu (密码: ubuntu666)

按照提示输入相关信息,密码一致就行,其他信息可留空,等脚本指定完成之后,可在 /data/cert/docker 目录查看到生成的证书。

Docker 只接受「未加密的私钥」

你给的 .key 文件是 RSA 加密私钥(文件头里能看到 —–BEGIN RSA PRIVATE KEY—– 或 Proc-Type: 4,ENCRYPTED),启动时 dockerd
要求你输入密码,但它跑在 systemd 里没人交互,于是读密钥失败 → TLS 配置无效 → dockerd 直接退出。
一句话结论
私钥被加密了,Docker 不会解密,必须换成“无密码”的私钥。

如果私钥仍带密码,先按前面说的去密码:

1
2
3
sudo openssl rsa -in server-key.pem -out server-key-clear.pem
sudo mv server-key-clear.pem server-key.pem
sudo chmod 600 server-key.pem

证书生成过程问题解决

OpenSSL 报错写得很清楚:

1
bad ip address … value=ubuntu

你在 extfile.cnf 里把 主机名ubuntu)直接写进了 IP: 字段,而 IP: 后面必须是纯 IPv4/IPv6 地址,不能是字符串域名或主机名。
改成 DNS:ubuntu 或者干脆去掉域名,只保留合法 IP 即可。

修正扩展文件

1
2
3
cat > extfile.cnf <<EOF
subjectAltName = DNS:ubuntu,IP:127.0.0.1,IP:10.0.0.0/8
EOF

如果你只想让任何地址都能连,也可以最简写:

1
echo "subjectAltName = IP:0.0.0.0" > extfile.cnf

重新签发

1
2
3
4
openssl x509 -req -in server.csr \
-CA ca.pem -CAkey ca-key.pem -CAcreateserial \
-out server-cert.pem -days 3650 -sha256 \
-extfile extfile.cnf

验证

1
openssl x509 -in server-cert.pem -text -noout | grep -A1 "Subject Alternative Name"

应看到:

1
2
X509v3 Subject Alternative Name:
DNS:ubuntu, IP:127.0.0.1, IP:0.0.0.0/8

不再报错即可。

查看生成后的证书

img

3. 配置Docker启用TLS

1
2
sudo cat /usr/lib/systemd/system/docker.service
sudo vim /usr/lib/systemd/system/docker.service

在ExecStart属性后追加

1
2
3
4
--tlsverify --tlscacert=/data/cert/docker/ca.pem  \
--tlscert=/data/cert/docker/server-cert.pem \
--tlskey=/data/cert/docker/server-key.pem \
-H tcp://0.0.0.0:2376 -H unix://var/run/docker.sock
1
--tlsverify --tlscacert=/data/cert/docker/ca.pem --tlscert=/data/cert/docker/server-cert.pem --tlskey=/data/cert/docker/server-key.pem -H tcp://0.0.0.0:2376 -H unix://var/run/docker.sock 

img

重新加载docker配置后重启

1
2
3
4
5
6
7
8
9
10
11
12
sudo systemctl daemon-reload 
sudo systemctl restart docker

sudo journalctl -u docker.service -n 50

# 检查是否加密 如果提示 Enter pass phrase,就说明被加密了。
sudo openssl rsa -in /data/cert/docker/ca-key.pem -check -noout

调试验证
>> /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --tlsverify --tlscacert=/data/cert/docker/ca.pem --tlscert=/data/cert/docker/server-cert.pem --tlskey=/data/cert/docker/server-key.pem -H tcp://0.0.0.0:2376 -H unix://var/run/docker.sock

sudo systemctl daemon-reload && sudo systemctl restart docker

查看2376端口是否启动

1
netstat -nltp | grep 2376

img

本地连接测试Docker API是否可用

  • 没有指定证书访问测试
1
2
curl https://ubuntu:2376/info 
curl https://127.0.0.1:2376/info
  • 指定证书访问测试
1
2
3
4
5
6
7
curl https://ubuntu:2376/info --cert /data/cert/docker/cert.pem --key /data/cert/docker/key.pem --cacert /data/cert/docker/ca.pem

curl https://127.0.0.1:2376/info --cert /data/cert/docker/cert.pem --key /data/cert/docker/key.pem --cacert /data/cert/docker/ca.pem

curl https://ubuntu:2376/info --cert /data/cert/docker/cert.pem --key /data/cert/docker/key.pem --cacert /data/cert/docker/ca.pem

https://ubuntu:2376

4. IDEA配置

将客户端所需的ca.pem、cert.pem、key.pem3个密钥文件从服务器下载到本地

img

IDEA连接Docker配置修改

img

pom.xml

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

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<!--执行mvn package,即执行 mvn clean package docker:build-->
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>

<configuration>
<!-- 镜像名称 -->
<imageName>${project.artifactId}</imageName>
<!-- 指定标签 -->
<imageTags>
<imageTag>latest</imageTag>
</imageTags>
<!-- 基础镜像-->
<baseImage>openjdk:8-jdk-alpine</baseImage>

<!-- 切换到容器工作目录-->
<workdir>/</workdir>

<entryPoint>["java","-jar","${project.build.finalName}.jar"]</entryPoint>

<!-- 指定远程 Docker API地址 -->
<dockerHost>https://ubuntu:2376</dockerHost>
<!-- 指定tls证书的目录 -->
<dockerCertPath>C:\certs\docker\ubuntu</dockerCertPath>

<!-- 复制 jar包到docker容器指定目录-->
<resources>
<resource>
<targetPath>/</targetPath>
<!-- 用于指定需要复制的根目录,${project.build.directory}表示target目录 -->
<directory>${project.build.directory}</directory>
<!-- 用于指定需要复制的文件,${project.build.finalName}.jar就是打包后的target目录下的jar包名称 -->
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>

260121-ubuntu 域名ping 提示Temporary failure in name resolution-ping-baidu.com

ubuntu 域名ping 提示Temporary failure in name resolution

只要 任何域名 都报 Temporary failure in name resolution,就是 本机 DNS 解析链彻底断了,与具体域名无关。
Ubuntu 20.04+ 默认走 systemd-resolved,90 % 是它没跑 / 配置丢失 / 上游 DNS 无响应。
按下面「4 句命令 → 1 次验证」一次性修好即可:


  1. 确认 systemd-resolved 活着

1
systemctl is-active systemd-resolved || sudo systemctl enable --now systemd-resolved

  1. 把 /etc/resolv.conf 指向本地 stub

1
sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

确保文件第一行是

1
nameserver 127.0.0.53

  1. 给 resolver 换可靠的公共 DNS

1
2
3
sudo mkdir -p /etc/systemd/resolved.conf.d
echo -e "[Resolve]\nDNS=8.8.8.8 1.1.1.1" | sudo tee /etc/systemd/resolved.conf.d/99-public.conf
sudo systemctl restart systemd-resolved

  1. 一键验证

1
systemd-resolve google.com && ping -c3 google.com

能解析、能 ping 通就表示修复完成,再去跑你的证书脚本即可。

260119-linux-redis离线安装

一、准备工作

1.下载redis的安装包

下载地址:Index of /releases/

大家可以自行选择redis的版本,笔者选择的是最新的

https://download.redis.io/releases/

img

2.上传到服务器
前提是我先在服务器上创建了一个目录redis7.2.3,我直接上传到这个目录下

二、安装redis
1.解压redis
tar -zxvf redis-7.2.3.tar.gz
AI写代码
2.移动解压完成的目录到/usr/local/下
mv redis-7.2.3 /usr/local/
AI写代码
3.进入到redis-7.2.3的目录
cd /opt/data/iimes/soft/redis-8.4.0
AI写代码
4.编译安装
make install
等待安装

安装完成的目录结构如下:

三、修改配置文件 redis.conf
vim redis.conf

1.设置远程访问
注释掉 bind 127.0.0.1 -::1 这句话意思是 只在本地访问!你不注释掉,到时候你本地RDM 是链接不上的。或者改为 bind 0.0.0.0

2.修改 登陆redis的密码 如图:
作者为了图方便,改为了123456.

3.设置后台启动
将daemonize no 改为 daemonize yes

四、将redis添加到守护进程,并开启开机自启动
1.在/etc/systemd/system/ 目录下创建文件redis.service
/etc/systemd/system目录是Linux系统中用于存放systemd单元配置文件的位置。systemd是一个系统和服务管理器,负责启动、停止和管理系统进程

vim /etc/systemd/system/redis.service
AI写代码
2.添加如下内容
大家注意区分,对于下面/opt/data/iimes/soft/redis-8.4.0/src/redis-server中的 src 是根据redis的安装目录来的,有些是 bin
大家注意观察自己的redis的目录,根据实际情况填写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Unit]
Description=Redis
After=network.target

[Service]
Type=forking
ExecStart=/opt/data/iimes/soft/redis-8.4.0/src/redis-server /opt/data/iimes/soft/redis-8.4.0/redis.conf
ExecStop=/opt/data/iimes/soft/redis-8.4.0/src/redis-server -s stop
PrivateTmp=true
User=root
Group=root

[Install]
WantedBy=multi-user.target

保存并退出

3.设置开机自启
systemctl enable redis
AI写代码
4.添加环境变量
(1)可以直接在/etc/profile文件末尾直接添加

vim /etc/profile

export PATH=$PATH:/opt/data/iimes/soft/redis-8.4.0/src
AI写代码
(2)或在profile.d目录下新建一个,专门放redis的环境变量文件

进入/etc/profile.d/路径下新建redis.sh

vim /etc/profile.d/redis.sh

在redis.sh文件中新增以下内容

export PATH=$PATH:/usr/local/redis/src

5.刷新环境变量
source /etc/profile
AI写代码
6.重启redis
systemctl restart redis
AI写代码
说明:如果后续大家还重新修改了/etc/systemd/system/redis.service文件,启动redis时出现提醒:Warning: The unit file, source
configuration file or drop-ins of redis.service changed on disk. Run ‘systemctl daemon-reload’ to reload units

重新执行命令:systemctl daemon-reload

这个警告提示您的 redis.service 单元文件、源配置文件或附加配置文件在磁盘上发生了变化。为了加载这些变化,您需要运行 systemctl
daemon-reload 命令来重新加载单元。

五、验证
1.查看redis的运行状态

2.查看redis进程

3.使用命令连接客户端
redis-cli

进入之后,需要你输入密码才能获取到redis输出的信息(info)

auth 密码

或者 之前在连接的时候输入密码:

redis-cli -a