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