关于Malformed input or input contains unmappable characters问题

572 阅读7分钟

说明:阅读该文章需要了解Jenkins的Item以及Docker的容器部署

Jenkins版本为:jenkins:2.479-jdk21

业务说明

我有个maven项目的代码存放在git上,打算通过Jenkins来进行代码的拉取和打包,仓库情况截图如下

image.png

错误的产生

jenkins的关于Git拉取项目和maven打包配置如下 image.png 前往Item执行失败的控制台输出,发现了以下报错

image.png 我们去往Git仓库看看 com/ayo/getipinfo/cors/??????.txt这个路径是什么情况

image.png 嗯~是由于文件名为中文导致的,这个文件我其实没啥用,就是在里面做了些基本的记号记下当时我写这个文件夹代码发生了啥,方便我以后的复盘,而且这也是个学习项目,正常来说我把这个文件删除就好了,问题到这也就结束了,毕竟是学习用的,所以我这里就深究了一下

解决问题

前置:docker运行容器

其中Docker的容器创建运行命令如下

docker run -d \
--name jenkins \
--restart=always \
-u root \
-p 9095:8080 \
-v /home/docker_volume/jenkins/home:/var/jenkins_home \
-v /home/docker_volume/jenkins/opt:/opt \
-v /etc/localtime:/etc/localtime \
-v /etc/timezone:/etc/timezone \
-v /etc/default/locale:/etc/default/locale \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $(which docker):/usr/bin/docker \
-v /home/docker_volume/jenkins/env/.bashrc:/root/.bashrc \
-v /home/docker_volume/jenkins/ssh:/root/.ssh \
-e LANG="zh_CN.UTF-8" \
-e JAVA_OPTS="-Dsun.jnu.encoding=UTF-8 -Dfile.encoding=UTF-8" \
-e LC_ALL="zh_CN.UTF-8" \
jenkins:2.479-jdk21

1.检查服务器文件是否正常

通过 -v /home/docker_volume/jenkins/home:/var/jenkins_home \ 已经将Jenkins_home文件夹进行了Docker挂载,所以我就直接通过Xftp进行查看挂载目录即可

每当Jenkins的进行Git拉取项目的时候,都会将仓库的代码拉到jenkins_home\workSpace\item名目录下,所以我们在Xftp上来到这个目录

image.png 嗯~说明.txt乱码成了璇存..txt,在一整个工程项目下,同一个文件的类型应该是一致的,所以这块就先不进去src/com/ayo/getipinfo/cors下了,先解决这个看看啥情况

执行下述命令检查文件类型

file -i /home/docker_volume/jenkins/home/workspace/test_d_2/*

image.png 嗯!!!这块的输出文件名是正常的,好好好,应该Xftp的编码导致的,修改Xftp的编码试试

image.png

修改为UTF-8

image.png 点击确定,然后发现显示正常了

image.png

/home/docker_volume/jenkins/home/workspace/test_d_2/src/com/ayo/getipinfo/cors下的文件按照上述再走一遍即可,确认显示正常我们开始下一步

image.png

2.检查Jenkins服务编码

来到jenkins的网页端的首页,进入System Information

image.png 来到系统属性

image.png 这里我们主要看两个东西file.encodingsun.jnu.encoding

image.png

image.png

  • file.encoding:UTF-8
  • sun.jnu.encoding:ANSI_X3.4-1968

发现sun.jnu.encoding的值不为UTF-8,这里就可以发现问题了,我们只要让sun.jnu.encoding值为UTF-8即可

3.检查容器编码

进入jenkins容器

docker exec -it jenkins bash

嗯~一进入报错了

root@hcss-ecs-f738:/etc# docker exec -it jenkins bash                                                                                       
bash: warning: setlocale: LC_ALL: cannot change locale (zh_CN.UTF-8)

执行下述命令查看容器的系统编码

locale

image.png

注意啊,这块的LC_ALL是成功设置了值zh_CN.UTF-8,但是系统警告说不能将LC_ALL的值设为zh_CN.UTF-8

不知道你们有没有注意docker创建容器并运行的命令里有两条环境变量设置的语句

-e LANG="zh_CN.UTF-8" \
-e LC_ALL="zh_CN.UTF-8" \

从我百度的结果其实发现有这玩意如果要支持UFT-8的字符编码,且正常支持中文,一共有两个值可以设置,分别是

  1. zh_CN.UTF-8
  2. C.UTF-8

这是个知识点,记录在后面

由于zh_CN.UTF-8值已经报错了,就直接采用C.UTF-8

查看Java的sun.jnu.encoding

java -XshowSettings:properties -version

输出如下

Property settings:                                                                                                                              
    file.encoding = UTF-8                                                                                                                       
    file.separator = /                                                                                                                          
    java.class.path =                                                                                                                           
    java.class.version = 65.0                                                                                                                   
    java.home = /opt/java/openjdk                                                                                                               
    java.io.tmpdir = /tmp                                                                                                                       
    java.library.path = /usr/java/packages/lib                                                                                                  
        /usr/lib64                                                                                                                              
        /lib64                                                                                                                                  
        /lib                                                                                                                                    
        /usr/lib                                                                                                                                
    java.runtime.name = OpenJDK Runtime Environment                                                                                             
    java.runtime.version = 21.0.4+7-LTS                                                                                                         
    java.specification.name = Java Platform API Specification                                                                                   
    java.specification.vendor = Oracle Corporation                                                                                              
    java.specification.version = 21                                                                                                             
    java.vendor = Eclipse Adoptium                                                                                                              
    java.vendor.url = https://adoptium.net/                                                                                                     
    java.vendor.url.bug = https://github.com/adoptium/adoptium-support/issues                                                                   
    java.vendor.version = Temurin-21.0.4+7                                                                                                      
    java.version = 21.0.4                                                                                                                       
    java.version.date = 2024-07-16                                                                                                              
    java.vm.compressedOopsMode = 32-bit                                                                                                         
    java.vm.info = mixed mode                                                                                                                   
    java.vm.name = OpenJDK 64-Bit Server VM                                                                                                     
    java.vm.specification.name = Java Virtual Machine Specification                                                                             
    java.vm.specification.vendor = Oracle Corporation                                                                                           
    java.vm.specification.version = 21                                                                                                          
    java.vm.vendor = Eclipse Adoptium                                                                                                           
    java.vm.version = 21.0.4+7-LTS                                                                                                              
    jdk.debug = release                                                                                                                         
    line.separator = \n                                                                                                                         
    native.encoding = ANSI_X3.4-1968                                                                                                            
    os.arch = amd64                                                                                                                             
    os.name = Linux                                                                                                                             
    os.version = 5.15.0-76-generic                                                                                                              
    path.separator = :                                                                                                                          
    stderr.encoding = ANSI_X3.4-1968                                                                                                            
    stdout.encoding = ANSI_X3.4-1968                                                                                                            
    sun.arch.data.model = 64                                                                                                                    
    sun.boot.library.path = /opt/java/openjdk/lib                                                                                               
    sun.cpu.endian = little                                                                                                                     
    sun.io.unicode.encoding = UnicodeLittle                                                                                                     
    sun.java.launcher = SUN_STANDARD                                                                                                            
    sun.jnu.encoding = ANSI_X3.4-1968                                                                                                           
    sun.management.compiler = HotSpot 64-Bit Tiered Compilers                                                                                   
    user.country = US                                                                                                                           
    user.dir = /                                                                                                                                
    user.home = /root                                                                                                                           
    user.language = en                                                                                                                          
    user.name = root                                                                                                                            
                                                                                                                                                
openjdk version "21.0.4" 2024-07-16 LTS                                                                                                         
OpenJDK Runtime Environment Temurin-21.0.4+7 (build 21.0.4+7-LTS)                                                                               
OpenJDK 64-Bit Server VM Temurin-21.0.4+7 (build 21.0.4+7-LTS, mixed mode)                                                                      
root@dd6a82bfca98:/#                   

其实这块和Jenkins那块的页面显示是一致的,sun.jnu.encoding = ANSI_X3.4-1968 ,嗯~肯定是一致的,毕竟页面的值就是从这查出来的

退出容器

exit

4.更新容器环境编码

停止容器

docker stop jenkins

删除容器

docker rm jenkins

重新创建运行

docker run -d \
--name jenkins \
--restart=always \
-u root \
-p 9095:8080 \
-v /home/docker_volume/jenkins/home:/var/jenkins_home \
-v /home/docker_volume/jenkins/opt:/opt \
-v /etc/localtime:/etc/localtime \
-v /etc/timezone:/etc/timezone \
-v /etc/default/locale:/etc/default/locale \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $(which docker):/usr/bin/docker \
-v /home/docker_volume/jenkins/env/.bashrc:/root/.bashrc \
-v /home/docker_volume/jenkins/ssh:/root/.ssh \
-e LANG="zh_CN.UTF-8" \
-e JAVA_OPTS="-Dsun.jnu.encoding=UTF-8 -Dfile.encoding=UTF-8" \
-e LC_ALL="C.UTF-8" \
-e LANGUAGE="C.UTF-8" \
jenkins:2.479-jdk21

重新进入容器

docker exec -it jenkins bash

正常且没有报错警告

locale

输出的结果也正常,但是啊,但是

image.png 其他值除了LANG是主动设置的以外,都和LC_ALL的值保持了统一,如果我没设置LC_ALL的值其实你会发现都和LANG保持了统一,你试试就知道了

这也是个知识点,后面讲

其实到这里已经正常了,最后确认一遍

查看Java的sun.jnu.encoding

java -XshowSettings:properties -version

输出如下

root@a12072e157f6:/# java -XshowSettings:properties -version                                                                                    
Property settings:                                                                                                                              
    file.encoding = UTF-8                                                                                                                       
    file.separator = /                                                                                                                          
    java.class.path =                                                                                                                           
    java.class.version = 65.0                                                                                                                   
    java.home = /opt/java/openjdk                                                                                                               
    java.io.tmpdir = /tmp                                                                                                                       
    java.library.path = /usr/java/packages/lib                                                                                                  
        /usr/lib64                                                                                                                              
        /lib64                                                                                                                                  
        /lib                                                                                                                                    
        /usr/lib                                                                                                                                
    java.runtime.name = OpenJDK Runtime Environment                                                                                             
    java.runtime.version = 21.0.4+7-LTS                                                                                                         
    java.specification.name = Java Platform API Specification                                                                                   
    java.specification.vendor = Oracle Corporation                                                                                              
    java.specification.version = 21                                                                                                             
    java.vendor = Eclipse Adoptium                                                                                                              
    java.vendor.url = https://adoptium.net/                                                                                                     
    java.vendor.url.bug = https://github.com/adoptium/adoptium-support/issues                                                                   
    java.vendor.version = Temurin-21.0.4+7                                                                                                      
    java.version = 21.0.4                                                                                                                       
    java.version.date = 2024-07-16                                                                                                              
    java.vm.compressedOopsMode = 32-bit                                                                                                         
    java.vm.info = mixed mode                                                                                                                   
    java.vm.name = OpenJDK 64-Bit Server VM                                                                                                     
    java.vm.specification.name = Java Virtual Machine Specification                                                                             
    java.vm.specification.vendor = Oracle Corporation                                                                                           
    java.vm.specification.version = 21                                                                                                          
    java.vm.vendor = Eclipse Adoptium                                                                                                           
    java.vm.version = 21.0.4+7-LTS                                                                                                              
    jdk.debug = release                                                                                                                         
    line.separator = \n                                                                                                                         
    native.encoding = UTF-8                                                                                                                     
    os.arch = amd64                                                                                                                             
    os.name = Linux                                                                                                                             
    os.version = 5.15.0-76-generic                                                                                                              
    path.separator = :                                                                                                                          
    stderr.encoding = UTF-8                                                                                                                     
    stdout.encoding = UTF-8                                                                                                                     
    sun.arch.data.model = 64                                                                                                                    
    sun.boot.library.path = /opt/java/openjdk/lib                                                                                               
    sun.cpu.endian = little                                                                                                                     
    sun.io.unicode.encoding = UnicodeLittle                                                                                                     
    sun.java.launcher = SUN_STANDARD                                                                                                            
    sun.jnu.encoding = UTF-8                                                                                                                    
    sun.management.compiler = HotSpot 64-Bit Tiered Compilers                                                                                   
    user.dir = /                                                                                                                                
    user.home = /root                                                                                                                           
    user.language = en                                                                                                                          
    user.name = root                                                                                                                            
                                                                                                                                                
openjdk version "21.0.4" 2024-07-16 LTS                                                                                                         
OpenJDK Runtime Environment Temurin-21.0.4+7 (build 21.0.4+7-LTS)                                                                               
OpenJDK 64-Bit Server VM Temurin-21.0.4+7 (build 21.0.4+7-LTS, mixed mode) 

可以看到sun.jnu.encoding = UTF-8 值已经改成了UTF-8

退出容器

exit

回到Jenkins的前端页面的系统属性

image.png

image.png 确认两个值都是正常的,ok,我们开始重新跑一遍Item

5. 验证最终结果

执行Item

image.png

image.png 检查服务器jar包

image.png 完美结束!!!

知识点:LC_ALL

LC_ALL 是一个环境变量,用于覆盖所有其他的区域设置(locale)环境变量。它是一个“超级”变量,其值会覆盖 LC_*LANG 等其他区域设置变量。这意味着,如果你设置了 LC_ALL,那么它将影响所有与区域设置相关的配置,包括但不限于以下方面:

  • LC_CTYPE:字符分类和转换规则
  • LC_NUMERIC:数字格式
  • LC_TIME:日期和时间格式
  • LC_COLLATE:字符串排序和比较规则
  • LC_MONETARY:货币格式
  • LC_MESSAGES:消息和警告的本地化
  • LC_PAPER:纸张大小
  • LC_NAME:姓名格式
  • LC_ADDRESS:地址格式
  • LC_TELEPHONE:电话号码格式
  • LC_MEASUREMENT:度量单位
  • LC_IDENTIFICATION:区域设置的元数据

常见的 LC_ALL 值

  1. CPOSIX

    • 这是最基本的区域设置,通常用于英文环境。
    • 字符编码为 ASCII。
    • 日期和时间格式为美式英语。
    • 数字格式为美式英语。
    • 排序规则基于字典顺序。
  2. C.UTF-8

    • 类似于 C 区域设置,但使用 UTF-8 编码。
    • 适用于需要支持多语言字符但保持简单行为的环境。
  3. en_US.UTF-8

    • 美国英语,使用 UTF-8 编码。
    • 常见的默认区域设置之一,适用于大多数英文环境。
  4. en_GB.UTF-8

    • 英国英语,使用 UTF-8 编码。
    • 适用于英国和其他英联邦国家。
  5. zh_CN.UTF-8

    • 简体中文,使用 UTF-8 编码。
    • 适用于中国大陆地区。
  6. zh_TW.UTF-8

    • 繁体中文,使用 UTF-8 编码。
    • 适用于台湾地区。
  7. ja_JP.UTF-8

    • 日语,使用 UTF-8 编码。
    • 适用于日本。
  8. ko_KR.UTF-8

    • 韩语,使用 UTF-8 编码。
    • 适用于韩国。
  9. fr_FR.UTF-8

    • 法语,使用 UTF-8 编码。
    • 适用于法国。
  10. de_DE.UTF-8

    • 德语,使用 UTF-8 编码。
    • 适用于德国。
  11. es_ES.UTF-8

    • 西班牙语,使用 UTF-8 编码。
    • 适用于西班牙。
  12. ru_RU.UTF-8

    • 俄语,使用 UTF-8 编码。
    • 适用于俄罗斯。

LC_ALL 的优先级

  • 最高优先级LC_ALL
  • 次高优先级LC_* 变量(如 LC_CTYPELC_TIME 等)
  • 最低优先级LANG

示例

假设你有以下环境变量设置:

LANG=en_US.UTF-8
LC_TIME=fr_FR.UTF-8
LC_ALL=de_DE.UTF-8

在这种情况下,尽管 LANGLC_TIME 被设置为不同的值,但 LC_ALL 的值 de_DE.UTF-8 会覆盖所有其他设置。因此,所有与区域设置相关的配置都会使用 de_DE.UTF-8

使用 LC_ALL 的场景

  1. 临时覆盖:在命令行中临时覆盖所有区域设置。例如:

    LC_ALL=zh_CN.UTF-8 date
    

    这条命令会使用 zh_CN.UTF-8 区域设置来显示日期和时间,而不会影响其他命令的区域设置。

  2. 调试:在调试区域设置相关问题时,设置 LC_ALL 可以帮助你快速确定问题的根源。

  3. 脚本:在脚本中设置 LC_ALL 可以确保脚本在特定的区域设置下运行,避免因环境变量不同而导致的行为差异。

查看当前区域设置

你可以使用 locale 命令来查看当前的区域设置:

locale

输出示例:

LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=C.UTF-8

在这个示例中,LC_ALL 被设置为 C.UTF-8,这意味着所有区域设置相关的配置都会使用 C.UTF-8

总结

LC_ALL 是一个非常强大的环境变量,它可以覆盖所有其他区域设置变量。在使用时要特别小心,因为它会影响所有与区域设置相关的配置。如果你只需要临时或部分覆盖某些设置,可以考虑使用 LANGLC_* 变量。

知识点:C.UTF-8和zh_CN.UTF-8取舍

C.UTF-8zh_CN.UTF-8 是两种不同的语言环境(locale),它们的主要区别在于所代表的语言和区域设置。以下是对这两者的详细解释:

1. C.UTF-8

  • 定义C.UTF-8 是一种通用的字符集,通常被称为 "C locale" 或 "POSIX locale"。

  • 用途: 它用于确保程序在没有特定区域设置时仍能以 UTF-8 编码正确处理字符。适合用于编程、调试或不需要特定语言支持的场景。

  • 特性:

    • 不会进行语言或地区的本地化处理,所有文本均按字母顺序排列。
    • 它提供了 UTF-8 支持,但不会影响排序或其他地区特性。

2. zh_CN.UTF-8

  • 定义zh_CN.UTF-8 是专为简体中文(China)设置的语言环境。

  • 用途: 用于需要显示和处理中文文本的应用程序,提供中文字符的本地化支持。

  • 特性:

    • 会根据中国的语言习惯进行本地化处理,包括日期格式、货币符号、时间显示等。
    • 适用于需要在用户界面或输出中显示中文的应用。

总结

  • 适用场景:

    • 如果您只需要 UTF-8 支持而不需要任何语言特性,可以选择 C.UTF-8
    • 如果您的应用程序需要处理中文文本,并且需要遵循中文的本地化规则,那么 zh_CN.UTF-8 是更合适的选择。

选择合适的 locale 可以帮助确保程序在处理文本时的准确性和可读性