说明:阅读该文章需要了解Jenkins的Item以及Docker的容器部署
Jenkins版本为:jenkins:2.479-jdk21
业务说明
我有个maven项目的代码存放在git上,打算通过Jenkins来进行代码的拉取和打包,仓库情况截图如下
错误的产生
jenkins的关于Git拉取项目和maven打包配置如下
前往Item执行失败的控制台输出,发现了以下报错
我们去往Git仓库看看
com/ayo/getipinfo/cors/??????.txt这个路径是什么情况
嗯~是由于
文件名为中文导致的,这个文件我其实没啥用,就是在里面做了些基本的记号记下当时我写这个文件夹代码发生了啥,方便我以后的复盘,而且这也是个学习项目,正常来说我把这个文件删除就好了,问题到这也就结束了,毕竟是学习用的,所以我这里就深究了一下
解决问题
前置: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上来到这个目录
嗯~
说明.txt乱码成了璇存..txt,在一整个工程项目下,同一个文件的类型应该是一致的,所以这块就先不进去src/com/ayo/getipinfo/cors下了,先解决这个看看啥情况
执行下述命令检查文件类型
file -i /home/docker_volume/jenkins/home/workspace/test_d_2/*
嗯!!!这块的输出文件名是正常的,好好好,应该
Xftp的编码导致的,修改Xftp的编码试试
修改为UTF-8
点击确定,然后发现显示正常了
/home/docker_volume/jenkins/home/workspace/test_d_2/src/com/ayo/getipinfo/cors下的文件按照上述再走一遍即可,确认显示正常我们开始下一步
2.检查Jenkins服务编码
来到jenkins的网页端的首页,进入System Information
来到
系统属性这
这里我们主要看两个东西
file.encoding和sun.jnu.encoding
file.encoding:UTF-8sun.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
注意啊,这块的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的字符编码,且正常支持中文,一共有两个值可以设置,分别是
zh_CN.UTF-8C.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
输出的结果也正常,但是啊,但是
其他值除了
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的前端页面的系统属性
确认两个值都是正常的,ok,我们开始重新跑一遍Item
5. 验证最终结果
执行Item
检查服务器jar包
完美结束!!!
知识点: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 值
-
C 或 POSIX:
- 这是最基本的区域设置,通常用于英文环境。
- 字符编码为 ASCII。
- 日期和时间格式为美式英语。
- 数字格式为美式英语。
- 排序规则基于字典顺序。
-
C.UTF-8:
- 类似于
C区域设置,但使用 UTF-8 编码。 - 适用于需要支持多语言字符但保持简单行为的环境。
- 类似于
-
en_US.UTF-8:
- 美国英语,使用 UTF-8 编码。
- 常见的默认区域设置之一,适用于大多数英文环境。
-
en_GB.UTF-8:
- 英国英语,使用 UTF-8 编码。
- 适用于英国和其他英联邦国家。
-
zh_CN.UTF-8:
- 简体中文,使用 UTF-8 编码。
- 适用于中国大陆地区。
-
zh_TW.UTF-8:
- 繁体中文,使用 UTF-8 编码。
- 适用于台湾地区。
-
ja_JP.UTF-8:
- 日语,使用 UTF-8 编码。
- 适用于日本。
-
ko_KR.UTF-8:
- 韩语,使用 UTF-8 编码。
- 适用于韩国。
-
fr_FR.UTF-8:
- 法语,使用 UTF-8 编码。
- 适用于法国。
-
de_DE.UTF-8:
- 德语,使用 UTF-8 编码。
- 适用于德国。
-
es_ES.UTF-8:
- 西班牙语,使用 UTF-8 编码。
- 适用于西班牙。
-
ru_RU.UTF-8:
- 俄语,使用 UTF-8 编码。
- 适用于俄罗斯。
LC_ALL 的优先级
- 最高优先级:
LC_ALL - 次高优先级:
LC_*变量(如LC_CTYPE,LC_TIME等) - 最低优先级:
LANG
示例
假设你有以下环境变量设置:
LANG=en_US.UTF-8
LC_TIME=fr_FR.UTF-8
LC_ALL=de_DE.UTF-8
在这种情况下,尽管 LANG 和 LC_TIME 被设置为不同的值,但 LC_ALL 的值 de_DE.UTF-8 会覆盖所有其他设置。因此,所有与区域设置相关的配置都会使用 de_DE.UTF-8。
使用 LC_ALL 的场景
-
临时覆盖:在命令行中临时覆盖所有区域设置。例如:
LC_ALL=zh_CN.UTF-8 date这条命令会使用
zh_CN.UTF-8区域设置来显示日期和时间,而不会影响其他命令的区域设置。 -
调试:在调试区域设置相关问题时,设置
LC_ALL可以帮助你快速确定问题的根源。 -
脚本:在脚本中设置
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 是一个非常强大的环境变量,它可以覆盖所有其他区域设置变量。在使用时要特别小心,因为它会影响所有与区域设置相关的配置。如果你只需要临时或部分覆盖某些设置,可以考虑使用 LANG 或 LC_* 变量。
知识点:C.UTF-8和zh_CN.UTF-8取舍
C.UTF-8 和 zh_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是更合适的选择。
- 如果您只需要 UTF-8 支持而不需要任何语言特性,可以选择
选择合适的 locale 可以帮助确保程序在处理文本时的准确性和可读性