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
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
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)
at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:733)
at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:484)
at org.kohsuke.stapler.Function$InstanceFunction.invoke(Function.java:497)
at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:218)
at org.kohsuke.stapler.SelectionInterceptedFunction$Adapter.invoke(SelectionInterceptedFunction.java:37)
at org.kohsuke.stapler.verb.HttpVerbInterceptor.invoke(HttpVerbInterceptor.java:48)
at org.kohsuke.stapler.SelectionInterceptedFunction.bindAndInvoke(SelectionInterceptedFunction.java:26)
at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:140)
at org.kohsuke.stapler.MetaClass$12.doDispatch(MetaClass.java:686)
at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:61)
at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:800)
at org.kohsuke.stapler.Stapler.invoke(Stapler.java:938)
at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:871)
at org.kohsuke.stapler.Stapler.invoke(Stapler.java:938)
at org.kohsuke.stapler.MetaClass$10.dispatch(MetaClass.java:590)
at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:800)
at org.kohsuke.stapler.Stapler.invoke(Stapler.java:938)
at org.kohsuke.stapler.Stapler.invoke(Stapler.java:721)
at org.kohsuke.stapler.Stapler.service(Stapler.java:253)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:204)
at PluginClassLoader for locale//hudson.plugins.locale.LocaleFilter.doFilter(LocaleFilter.java:82)
at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:201)
at PluginClassLoader for metrics//jenkins.metrics.impl.MetricsFilter.doFilter(MetricsFilter.java:125)
at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:201)
at jenkins.util.HttpServletFilter$1.doFilter(HttpServletFilter.java:77)
at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:201)
at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:207)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
at jenkins.ErrorAttributeFilter.doFilter(ErrorAttributeFilter.java:29)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:154)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
at hudson.security.ChainedServletFilter2$1.doFilter(ChainedServletFilter2.java:94)
at jenkins.security.AcegiSecurityExceptionFilter.doFilter(AcegiSecurityExceptionFilter.java:52)
at hudson.security.ChainedServletFilter2$1.doFilter(ChainedServletFilter2.java:99)
at hudson.security.UnwrapSecurityExceptionFilter.doFilter(UnwrapSecurityExceptionFilter.java:54)
at hudson.security.ChainedServletFilter2$1.doFilter(ChainedServletFilter2.java:99)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120)
at hudson.security.ChainedServletFilter2$1.doFilter(ChainedServletFilter2.java:99)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100)
at hudson.security.ChainedServletFilter2$1.doFilter(ChainedServletFilter2.java:99)
at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:114)
at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:105)
at hudson.security.ChainedServletFilter2$1.doFilter(ChainedServletFilter2.java:99)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:227)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:221)
at hudson.security.ChainedServletFilter2$1.doFilter(ChainedServletFilter2.java:99)
at jenkins.security.BasicHeaderProcessor.doFilter(BasicHeaderProcessor.java:98)
at hudson.security.ChainedServletFilter2$1.doFilter(ChainedServletFilter2.java:99)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:117)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at hudson.security.HttpSessionContextIntegrationFilter2.doFilter(HttpSessionContextIntegrationFilter2.java:63)
at hudson.security.ChainedServletFilter2$1.doFilter(ChainedServletFilter2.java:99)
at hudson.security.ChainedServletFilter2.doFilter(ChainedServletFilter2.java:111)
at hudson.security.HudsonFilter.doFilter(HudsonFilter.java:173)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
at org.kohsuke.stapler.UncaughtExceptionFilter.doFilter(UncaughtExceptionFilter.java:26)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
at hudson.util.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:86)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
at org.kohsuke.stapler.DiagnosticThreadNameFilter.doFilter(DiagnosticThreadNameFilter.java:31)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
at jenkins.security.SuspiciousRequestFilter.doFilter(SuspiciousRequestFilter.java:38)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:165)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:88)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:597)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:113)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:83)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:654)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:72)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1774)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:973)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:491)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.base/java.lang.Thread.run(Thread.java:1570)
Caused by: 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.util.RobustReflectionConverter$2.writeField(RobustReflectionConverter.java:276)
at hudson.util.RobustReflectionConverter$2.visit(RobustReflectionConverter.java:243)
at com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider.visitSerializableFields(PureJavaReflectionProvider.java:174)
at hudson.util.RobustReflectionConverter.doMarshal(RobustReflectionConverter.java:228)
at hudson.util.RobustReflectionConverter.marshal(RobustReflectionConverter.java:165)
at com.thoughtworks.xstream.core.AbstractReferenceMarshaller.convert(AbstractReferenceMarshaller.java:68)
at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:59)
at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:44)
at com.thoughtworks.xstream.core.TreeMarshaller.start(TreeMarshaller.java:83)
at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.marshal(AbstractTreeMarshallingStrategy.java:37)
at com.thoughtworks.xstream.XStream.marshal(XStream.java:1307)
at com.thoughtworks.xstream.XStream.marshal(XStream.java:1296)
at com.thoughtworks.xstream.XStream.toXML(XStream.java:1269)
at hudson.XmlFile.write(XmlFile.java:216)
... 100 more
Caused by: java.lang.RuntimeException: Failed to serialize jenkins.plugins.publish_over_ssh.BapSshHostConfiguration#proxyPassword for class jenkins.plugins.publish_over_ssh.BapSshHostConfiguration
at hudson.util.RobustReflectionConverter$2.writeField(RobustReflectionConverter.java:276)
at hudson.util.RobustReflectionConverter$2.visit(RobustReflectionConverter.java:243)
at com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider.visitSerializableFields(PureJavaReflectionProvider.java:174)
at hudson.util.RobustReflectionConverter.doMarshal(RobustReflectionConverter.java:228)
at hudson.util.RobustReflectionConverter.marshal(RobustReflectionConverter.java:165)
at com.thoughtworks.xstream.core.AbstractReferenceMarshaller.convert(AbstractReferenceMarshaller.java:68)
at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:59)
at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:44)
at com.thoughtworks.xstream.core.AbstractReferenceMarshaller$1.convertAnother(AbstractReferenceMarshaller.java:87)
at com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter.writeBareItem(AbstractCollectionConverter.java:94)
at com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter.writeItem(AbstractCollectionConverter.java:66)
at hudson.util.CopyOnWriteList$ConverterImpl.marshal(CopyOnWriteList.java:192)
at hudson.util.XStream2$AssociatedConverterImpl.marshal(XStream2.java:556)
at com.thoughtworks.xstream.core.AbstractReferenceMarshaller.convert(AbstractReferenceMarshaller.java:68)
at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:59)
at com.thoughtworks.xstream.core.AbstractReferenceMarshaller$1.convertAnother(AbstractReferenceMarshaller.java:83)
at hudson.util.RobustReflectionConverter.marshallField(RobustReflectionConverter.java:285)
at hudson.util.RobustReflectionConverter$2.writeField(RobustReflectionConverter.java:272)
... 113 more
Caused by: com.thoughtworks.xstream.io.StreamException: Invalid character 0x0 in XML stream
at hudson.util.PrettyPrintWriter.lambda$writeText$0(PrettyPrintWriter.java:220)
at java.base/java.lang.StringUTF16$CodePointsSpliterator.advance(StringUTF16.java:1503)
at java.base/java.lang.StringUTF16$CodePointsSpliterator.forEachRemaining(StringUTF16.java:1475)
at java.base/java.util.stream.IntPipeline$Head.forEach(IntPipeline.java:617)
at hudson.util.PrettyPrintWriter.writeText(PrettyPrintWriter.java:214)
at hudson.util.PrettyPrintWriter.writeText(PrettyPrintWriter.java:210)
at hudson.util.PrettyPrintWriter.setValue(PrettyPrintWriter.java:192)
at com.thoughtworks.xstream.io.WriterWrapper.setValue(WriterWrapper.java:45)
at com.thoughtworks.xstream.converters.SingleValueConverterWrapper.marshal(SingleValueConverterWrapper.java:45)
at com.thoughtworks.xstream.core.AbstractReferenceMarshaller.convert(AbstractReferenceMarshaller.java:50)
at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:59)
at com.thoughtworks.xstream.core.AbstractReferenceMarshaller$1.convertAnother(AbstractReferenceMarshaller.java:83)
at hudson.util.RobustReflectionConverter.marshallField(RobustReflectionConverter.java:285)
at hudson.util.RobustReflectionConverter$2.writeField(RobustReflectionConverter.java:272)
... 130 more

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

Hello World

README

(ALL-AI)即刻去做&愿有前程可奔赴&亦有岁月可回头

Welcome to Hexo! This is your very first post. Check documentation for more
info. If you get any problems when using Hexo, you can find the answer
in troubleshooting or you can ask me
on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

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

260119-Ubuntu20-04(netplan apply)系统启动后直接加载固定路由-系统启动固定路由

作用:(Ubuntu20.04系统启动后直接加载固定路由)让本机一启动就把 192.168.0.2 / .4 / .102 / .104 / .106 这 5 个地址“当成跟自己同一链路(link)上的邻居”,无需网关即可直达,ARP 解析后直接发包。

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
network:
ethernets:
eno1:
dhcp4: no
addresses: [192.168.0.100/24]
routes:
- to: default
via: 192.168.0.1
scope: link
metric: 10
enp1s0:
dhcp4: no
addresses: [192.168.0.110/24]
dhcp4-overrides:
use-routes: false # 拒绝 DHCP 下发的默认路由
routes: # 你的 5 条主机路由
- to: 192.168.0.2/32
scope: link
- to: 192.168.0.4/32
scope: link
- to: 192.168.0.102/32
scope: link
- to: 192.168.0.104/32
scope: link
- to: 192.168.0.106/32
scope: link
version: 2
wifis: {}

260119-Ubuntu20.04系统启动后直接加载固定路由-/etc/systemd/network/10-enp1s0.network

作用:(Ubuntu20.04系统启动后直接加载固定路由)让本机一启动就把 192.168.0.2 / .4 / .102 / .104 / .106 这 5 个地址“当成跟自己同一链路(link)上的邻居”,无需网关即可直达,ARP 解析后直接发包。

目录位置: /etc/systemd/network/10-enp1s0.network

配置完成,重启(sudo systemctl enable systemd-networkd)

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
[Match]
Name=enp1s0

[Network]
DHCP=yes

# 下面 5 行就是固定路由
[Route]
Destination=192.168.0.2/32
Scope=link

[Route]
Destination=192.168.0.4/32
Scope=link

[Route]
Destination=192.168.0.102/32
Scope=link

[Route]
Destination=192.168.0.104/32
Scope=link

[Route]
Destination=192.168.0.106/32
Scope=link