善意提醒

如果您打开本站很慢,布局排版混乱,并且看不到图片,那么可能是因为您还没有掌握用科学的方法上网的本领。

2024-09-29

信创踩坑笔记

图片来自网络

1. 银河麒麟(Kylin V10)

银河麒麟算是好的,毕竟高仿CentOS。看它的文档,似乎V4的时候还是Ubuntu/Debian系的,现在的V10已经转到RedHat/CentOS派系下了。

我们的程序基本都是静态链接,所以就还好。唯一动态链接的是OpenSSL,这个在《编译自己的CentOS7 OpenSSL 1.0.2u动态链接库》这篇Blog中已经介绍过了。

1.1. ldconfig

说起来算个坑的,就是它的SP2版本的ldconfig无法正确读取被patchelf改过SONAME的库,说什么「已被截断」。搜了一下,说是属于ldconfig的Bug。patchelf改过soname的so库,里面的段顺序会变。但规范里面并没写顺序是有保障的,ldconfig不应该自行假设顺序一定是那个样子。

有人说这是上游供应链(glibc)的Bug。的确无论SP3的哪个版本都是好的。但我看SP2和SP3的glibc的版本也没看出来有什么变化,这里先存疑一下吧。
我的应对方案就是SP2下就不改SONAME了,难看就难看一些。

1.2. VMware

接下来这一个实际上应该放在最前面,不过只是因为我用了VMware来安装这些而已。不见得所有人都会遇到。

银河麒麟V10安装在VMware上的时候,显示分辨率默认是800×600。在这种情况下,无法调整显示分辨率,因为「保存」按钮被挡在屏幕外面了。
解决方法是用xrandr,例如:

xrandr -s 1440x900_60

最后一个参数是刷新率(60Hz)。有些Blog上说这里只能用xrandr列出来的选项,但其实未必,只要显示器支持就行。
另外,有些Blog上说这种方式只能临时调整,重启后效果就没了。的确如此,可是现在屏幕大了,你就可以用UI来正式调整显示分辨率了,不是吗?

2. 达梦(DM8)

总的来说,在Windows上安装达梦8的过程要顺畅很多,没遇到什么问题。Linux下就开始有坑。

2.1 ulimit

准备阶段的第一个坑是ulimit的问题,之前已经先写了Blog,这里就只给出链接了《Linux下修改ulimit不能完全生效的问题》。这个坑严格来说不算麒麟也不算达梦的问题,而且不见得所有人都会遇上。

2.2. cdrom

第二个坑是挂载光驱。挂上来之后没有x权限,但不知道怎么回事,用-o exec也挂不出来x权限。最后只好用命令行强制运行解决:

bash DMInstall.bin

接下来的安装倒是没出多大问题。我在Linux上安装达梦的目的只是为了抠出里面的bin、include和drivers目录来,用来制作Python和PHP的运行环境而已。所以后续运维的踩坑经验我就无法提供提供了。

2.3. Python

我们的Python运行环境是用Conda搭的,有2.7和3.5两个版本。按照达梦官方文档的说法(那文档写得不好,链接恕我不放了,自己搜吧),需要安装达梦客户端,然后再编译驱动。照着操作就可以,没什么大坑。

2.3.1. ldconfig

我是从一台安装了达梦客户端的Linux机器上把bin、include、drivers这三个目录抠了出来,设了一下LD_LIBRARY_PATH,然后去Conda环境里面编译驱动。这样做是没问题。

但是当我把目录放/etc/ld.conf.d里面之后,一跑ldconfig,sshd直接挂掉了。数个SSH会话同时被踢,吓了我一大跳,还以为被黑客入侵了。

好在tty登录没有问题,看起来是OpenSSL导致了OpenSSH不能用了。一看达梦的bin目录,libcrypto.so和libssl.so就这样裸躺在里面,服了。最后还是只能用回LD_LIBRARY_PATH方案。

2.3.2. 多线程

接下来我们尝试在Python环境中登录达梦数据库。有一个小坑:达梦的dmPython.connect会开子线程来进行登录。我们的Python环境在Python解释器跑起来后把nproc改成了0,结果就CoreDump了。看过CoreDump里面的CallStack才明白原因。看起来C代码里面的异常捕获,dmPython完全没有做嘛。抛个Python异常也好啊。

2.4. PHP

达梦的文档在这一部分有比较大的问题。
首先,有点语无伦次。无论是yum还是源代码编译,都是指的PHP的安装方式,但达梦的部分应该都是一样的。然而文档中却说得好像不一样。
其次,版本混乱。安装代码中同时有7和5的库,显然是更新文档的时候没有更新完整。
最后,其交代的技术细节存在着问题,至少与事实不符。我按照其中列出的DPI库准备的环境,PHP的PDO_DM库完全加载不起来。

我想办法得到了一份正确的so依赖列表,比达梦文档中给出的要多,多了不少。主要是因为libdmcalc.so和libdmdta.so导致的。我觉得我直接给出我的so库列表并不是一个好主意,毕竟DM8的版本肯定也在不时地变化。更有用的是介绍我的方法。

我的方法也很简单:找个编辑器打开达梦的两个PDO的so库,然后就搜「.so」。ldd中看得见的,这样能搜到。看不见的,那种用dl_open打开的,这样也能搜到。然后顺藤摸瓜就行。貌似DPI的那些so库都还不会用dl_open。
当然,将来达梦如果对so的内容进行混淆或加密,那我就不敢说这样能行了。希望它不会犯这个蠢。

后面就还好了。我一度担心OpenSSL又惹事,但大概是我们的PHP环境比较简单,没惹出什么麻烦。我直接把它们塞进了一个docker镜像里面,这部分的工作成果总算是被固化了下来。

2024-09-14

Linux下修改ulimit不能完全生效的问题

前言:本文只打算作为「技术笔记」来写,对关键的要点进行一下点拨就完事,没想写成教程。或许能让熟手解决麻烦,如果是新手的话,最好是先有相关的基础知识和经验。当然,直接喂给AI,让它嚼过再给你慢慢解释,可能也是一个办法。

这些天还是在折腾信创的事情。安装了银河麒麟V10 SP2的一个默认设置的版本,带了可视化界面,准备用于安装「达梦」。
达梦的安装手册写得有一些问题,缺了一些要点,不过对于有一定经验的人而言,还算能解决。手册中有一个要求,就是要把ulimit里面的open files数量调大。原始的1024,看起来不太够用。

图片来自网络

对Linux特别是CentOS7熟悉的人,应该反应过来了。不要直接改ulimit,应该去改/etc/security/limits.conf:

* soft nofile 65535
* hard nofile 65535

改完之后,重新登录的账号就已经是新的open files上限了。简单重启一下就应该万事OK了。

可是,不,没有那么简单!(莫名其妙的英式中文)


在我看来,改完重启以后,对于非root用户似乎完全没有效果。
root账号好像真的是OK了。但达梦的安装手册提到需要创建专用的dmdba账号用于DBMS的安装。我在可视化界面登录dmdba账号后,打开「终端」窗口,ulimit还是1024。

测试下来,发现:

  • ssh上来的session有效果;
  • su切换过去的账号有效果。

这说明对/etc/security/limits.conf的修改还是有效果的,只是不知道为什么在某些场合下不能生效。
百思不得其解。最后找到这篇Blog,是博客园的。标题起得有点不好找:《systemd service 设置limit,不生效问题》。它引用的原文的URL已经失效了,所以我还是得把要点直接再说一下。简单来说就是:

  1. 要修改用systemctl启动的服务的ulimit,需要修改/etc/systemd/system.conf
  2. 要修改从可视化界面登录的用户的ulimit,需要修改/etc/systemd/user.conf

实际上的情况比这个要复杂一些。第二点不是原文中的描述,是我自己试出来的。我目前也无意去成为一个Linux或银河麒麟方面的专家,所以就暂时不作更多的探索了。

另外,修改了/etc/systemd/system.conf以后,需要先重启systemd:

systemctl daemon-reexec

然后用systemctl启动/重新启动的服务,才能用上新的ulimit设置。
毕竟咱们改的是systemd的配置文件,对吧。

2024-09-13

SSD散热铜片导致的故障

我的HTPC,一开始真的只是打算用来当作HTPC用,所以SSD只有256GB。后来儿子要玩游戏,因此很快就不够用了。于是大约两年前,我换了一条aigo的NVMe M.2 SSD,P2000,1TB的容量。不是什么好东西,不过因为我在公司里面用过同品牌同型号的产品,心中有点数(相比之下,aigo P3000 Pro简直就是巨坑),所以也就跟着买了。

用到现在倒也都没有出什么问题,但散热真的是个问题。之前的256GB SSD因为有马甲,还不觉得散热有问题。但这块P2000是个「裸条」,我一开始复制大文件,比如电影,温度就往上窜。温度高到了一定程度以后,速度就掉下来了,后来还开始掉盘。于是我又去买了一个散热铜片,粘上以后好了很多,不再有散热问题了。

图片来自网络,非同款,非广告

这个散热铜片有单面款和双面款。我的HTPC是一个很小的ITX机箱,而且主板的M.2插槽在背面。如果贴双面,会不会接触到主板背面的针脚或元件?我的确有这个担心。看别人的评测,说还有一定高度,不会碰到。我自己试下来,也的确如此,于是就这样用了下去。快两年以来,都没有什么问题。

以上是前言。


最近,我一直在与这台HTPC的「关机」方面的顽疾作斗争。
一开始是开机以后自动关机,偶尔有之。最近则变成关机关不掉,关机变重启。重启有的时候来得很快,有的时候时间都说不清。比如昨天,我关了机器去上班,下午三点多,家里都没有人的时候,它自己开机了。要真是能远程唤醒也就罢了,可当我正经来设置的时候,又没法用。
于是昨晚我把BIOS设置给LOAD DEFAULT了。以前一直没能狠下这个心,终于世界清净了。

然而,今天早上,我再想开机的时候,发现机器开不起来了。

我绞尽脑汁地回想我到底做了什么导致的这个后果?
不是BIOS设置的问题,因为现在甚至不给我进BIOS的机会。CPU风扇转一小会儿就断电停了。
拔掉内存,可以长期通电,可见不是电源问题。
CPU烧了?过热保护?但从加电到断电的时间非常短,CPU再热也不至于这么一小会儿都撑不住。何况风扇并没有停。不过保险起见,我还是把前不久换的散热器拆了,重新打了硅胶。还是没有效果。

把配件全拆了,就剩主板和电源,裸接,还是点不亮。那么,主板、CPU,还有就是背面的SSD了。
我很不报希望地把SSD卸了,再加电。这次亮了,进BIOS了。


带着难以置信的心情,我反复试了几次,能够确认就是SSD导致的问题。
难道是SSD坏了?就算不认盘,也不至于连BIOS也进不去吧?不过NVMe走的路线不同,或许会导致CPU故障类似的样子。
我把SSD拆下来,放在NVMe M.2移动硬盘盒上,用笔记本读。识别起来毫无困难,里面内容也没问题,看起来SSD没坏。我算是松了一口气。

好吧,唯一可以怀疑的,就是这个散热片了。我再次看了看主板背面的空间,感觉有可能接触到。身边没有趁手又够薄的绝缘片,于是我还是费了半天劲把散热片拆了下来。还好P2000没有缓存芯片,背面没有元件。而且上次换散热器的时候,送了一片用来刮硅胶的薄塑料片……

拆了这块粘在SSD背面的铜散热片以后,果然故障就消失了。虽然总算是解决了,但还得装回去,最后这一趟折腾总共花了我两个半小时,还一手的伤口。迷你,不是没有代价的。


复盘一下,多半是因为热胀冷缩的关系,铜散热片不知道怎么就跟主板背面的针脚或元件接触上了,于是主板直接短路保护了。我估计针脚的可能性大一些。之前我HTPC一直没关,基本上都是热机的状态,所以工况跟昨晚不太一样。

这块散热铜片,我是不打算装回去了。SSD上的芯片都在正面,正面的散热铜片还在,背面只有PCB板而已。而且背面的散热铜片以前跟主板的间隙就很近,即使没短路,我觉得也不会有什么散热效果。
只是,早知道如此,当初还不如直接买单面的铜片,还便宜一些。

2024-09-10

把Google Code Prettify应用至Blogger

图片来自网络

记得以前给自己的Blogger部署过Google Code Prettify,不过后来可能是因为主题被重置过,效果没了。今天把它重新找了回来,日后也会逐渐套用至需要的Blog上。本文就作为相关内容的技术笔记吧。

部署

在Blogger后台中,点「主题背景」,然后进行「自定义」,去「修改HTML」。
在head标签中放置:

<script src='https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js'/>

然后用下列标签把代码括起来,就可以实现本文中的代码块效果:

<pre class="prettyprint">……</pre>

pre标签中的代码按原始格式存放即可,不过小于号(<)和大于号(>)仍然要进行转义。


以下是一些常用到的option,更多的内容烦请移驾官方Github页面

主题

在引用run_prettify.js的时候,URL后面加一个参数skin即可。例如:

<script src='https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?skin=desert'/>

目前有五种主题,预览图点这里

不标记为代码

用一组带nocode样式的span标签括起来即可,还可以加上自己的样式。例如

<span class="nocode" style="color: red;">注意</span>

语言指定

在pre标签中指定lang-*样式,例如:

<pre class="prettyprint lang-sh">
if [ ! -d '/myfile' ]
then
    mkdir /myfile
fi
</pre>
<pre class="prettyprint lang-cpp">
class A
{
public:
    int a;
}
</pre>

内置支持的语言有["bsh", "c", "cc", "cpp", "cs", "csh", "cyc", "cv", "htm", "html", "java", "js", "m", "mxml", "perl", "pl", "pm", "py", "rb", "sh", "xhtml", "xml", "xsl"],还有一些可以通过extensions进行支持,参见官网页面。

自动换行

有些代码有可能把屏幕宽度撑得很大。要想自动换行的话,在head标签中添加:

<style>
pre {
  white-space: pre-wrap;
  word-wrap: break-word;
  word-break: break-all;
}
</style>

这里的效果是按字母换行,可能会切断单词。如果要按单词换行,去掉word-break这一行。详细的解释参见我的另一篇Blog《关于表格内文字换行的再研究》。

2024-09-09

编译自己的CentOS7 OpenSSL 1.0.2u动态链接库

因为老板想从「信创」分一杯羹,于是我们现在需要把一个CentOS7上面跑着的系统,移植到「银河麒麟」上去运行。
对于「国产」操作系统了解不多,不敢妄自确定方案。先去下载了银河麒麟的数个版本,主要都是服务器操作系统V10,包括SP2的「CentOS兼容版」,海光版,以及SP3 2303以及2403的海光版本。考虑到海光CPU也是x86架构,理论上应该可以跑在普通的Intel/AMD CPU的机器上,实际测试下来也是如此。

不得不说,我一开始对于情况设想得比现状要严峻一些。实在是没有想到银河麒麟V10对于CentOS抄得如此彻底,怪我太高看了国人的本领。无论是「CentOS兼容版」还是海光版,我们在CentOS7上编译的东西,基本上拿上去就可以直接跑。
当然,从好处想,这样做的确提升了这些「国产」操作系统的兼容性,极大拓展了生态链。一定程度上也算是利国利民的好事情。除了钱以外的事情,我也就不吐槽了。

图片来自网络

之所以说是「基本上」可以直接跑,是因为银河麒麟V10大概是从CentOS8开始「魔改」的,所以上面搭载的OpenSSL是1.1.1版本。有一些是1.1.1c,有一些是1.1.1f,总之不是CentOS7的1.0.2。yum list看了一下,源里面也只有1.1.1的版本可供安装。

我们的程序是在CentOS7上编译出来的,用了so版本的OpenSSL 1.0.2,所以缺了这个东西还没法运行。尽管我们可以把自己的代码改成去链接OpenSSL 1.1.1,或者索性静态链接进去,但还有些第三方厂商提供的库也是基于OpenSSL 1.0.2的,而且不算少。总之这个问题是绕不开的,只能迎头而上去解决它。
另外,我们发现那个「CentOS兼容版」的默认安装会在/lib64下面形成OpenSSL 1.0.2o的库。yum list里面还是没有,说明应该是某个软件包自行装上的。既然那个软件包可以这样做,我们也可以。把自己编译的OpenSSL 1.0.2的库放进系统里面去,然后ldconfig就好。

以上交代了背景,接下来就说说看具体怎么做,以及介绍一下踩过的坑。


编译OpenSSL很简单,从OpenSSL官网上下载1.0.2u的tar.gz包(最后一个版本,1.0.2已经停止维护了),解压以后编译:

wget https://openssl.org/source/old/1.0.2/openssl-1.0.2u.tar.gz
tar -xvzf openssl-1.0.2u.tar.gz
cd openssl-1.0.2u
./config --prefix=/usr/local/openssl-1.0.2u --openssldir=/usr/local/openssl-1.0.2u shared
make
make install

以上的操作,随处都可以搜到,AI也能提供。不过编译出来的openssl动态链接库,有两个问题:

  1. 拿这两个编译出来的so库去用,会报「no version information available」。事实上ldd的时候就会报这个错。
  2. 编译出来的文件名是libcrypto.so.1.0.0和libssl.so.1.0.0,而不是我想要的libcrypto.so.1.0.2u和libssl.so.1.0.2u。

前者问题大一些,后者往小了说只是自己看着顺不顺眼的问题。一个一个解决吧。

问题1

拿着「no version information available」去搜,得到的信息不太具有参考价值。问AI也一样。
大多数的回答是说错用了别的操作系统编译的OpenSSL库,可能很多人遇到的情况也的确是这个,但显然我们遇到的情况并不是。

唯一找到一篇相关文章,跟着评论找到了知乎上的一篇文章。作者是想自己编译1.0.2u的库,替换掉CentOS7上的1.0.2k的版本。
顺带说一句:以前CentOS7还在维护,即使是1.0.2k的库,CentOS也会补上安全漏洞。现在CentOS7不维护了,或许将有必要这样去做。但1.0.2u也已经是2019年发布的版本,换句话说,OpenSSL 1.0.2在更早的时间就停止维护了。所以原文作者这样去做可能也没有什么意义。

该文作者的思路和实际操作都没有什么问题,尊重他人的劳动成果,我就不原样贴一遍了。需要的朋友可以根据上面的链接自己去看。虽然原文不知道为什么贴了Markdown的内容,在知乎上看不出样式,至少PC Web版上看不出,但内容总归能看懂。
我遇到的坑是:按照该文操作的「1.4」步骤得到的函数名称中有「@库名」的内容,例如:

sk_find@libcrypto.so.10;
sk_set@libcrypto.so.10;
asn1_add_error@libcrypto.so.10;
……

对于Version Script,这是不可接受的写法。我的处理方法是把这里面的「@libcrypto.so.10」直接删掉了。原文假设所有的函数都是「@@」形式的默认导出,而不是「@」一个符号,这个假设是不对的。
这里是我从CentOS7中的OpenSSL 1.0.2k提取出来的Version Script,既然CentOS7和OpenSSL 1.0.2u都已经停止维护,那这个文件应该算是Stable了。可以点此下载

把下载得到的version.map放在解压生成的openssl-1.0.2u目录下。随后,./config的时候换成下面这句:

./config --prefix=/usr/local/openssl-1.0.2 --openssldir=/usr/local/openssl-1.0.2 shared -Wl,--version-script=/root/openssl-1.0.2u/version.map -Wl,-Bsymbolic-functions zlib-dynamic

最重要的参数就是-Wl,--version-script=version.map这句。再编译生成的so库就不会被报「no version information available」了。而且这里似乎必须得写绝对路径。

问题2

直接改文件名是不行的。因为文件里面有SONAME。做符号链接以及ldconfig的时候都会原形毕露。我们需要把文件内部的SONAME也一起改掉才行。

据说在编译前手动调整一些文件也可以解决这个问题。不过我是选择在编译之后用patchelf来解决这个问题的。为此当然首先要安装patchelf:

yum -y install patchelf

然后就开始改文件了:

patchelf --set-soname libssl.so.1.0.2u libssl.so.1.0.0
patchelf --set-soname libcrypto.so.1.0.2u libcrypto.so.1.0.0
mv libssl.so.1.0.0 libssl.so.1.0.2u
mv libcrypto.so.1.0.0 libcrypto.so.1.0.2u
patchelf --replace-needed libcrypto.so.1.0.0 libcrypto.so.1.0.2u libssl.so.1.0.2u

最后一句也是必须的,因为libssl.so会引用libcrypto.so。