apt
更新时会触发/usr/lib/cloud-init/ds-identify
的运行。然后这个脚本运行的非常的慢。要 1 分多钟才会运行完。期间 CPU 是满的。而且新的 ssh 连接无法建立。
这个 ds-identify 是个 shell 脚本。ds-identify
开头是#!/bin/sh
,用的是系统默认的dash
。
我自己按照 top 中显示的命令行信息,增加-x
参数,运行/bin/sh -x /usr/lib/cloud-init/ds-identify
,也非常慢,但能看到,卡在check_config
函数的while read line
之后,line=
之前。
for fname in "$@"; do
[ -f "$fname" ] || continue
while read line; do
line=${line%%#*}
case "$line" in
$key:\ *|$key:)
ret=${line#*:};
ret=${ret# };
found=$((found+1))
found_fn="$fname";;
esac
done <"$fname"
done
这“应该”是在读文件内容。
根据打印信息,读取的是/etc/cloud/cloud.cfg.d/aliyun_cloud.cfg
文件,并且是- echo
开头的很长的一行文本上。
多次执行,发现只要是在文件中的行内容过长的地方,就会 read 的很慢。
然后我用bash
执行了一遍。发现同样的ds-identify
,却执行的非常快。
初看像是dash
的某种性能问题。
我新建一个文本文件test.cfg
,将/etc/cloud/cloud.cfg.d/aliyun_cloud.cfg
文件的内容复制进去。
新建一个独立的test.sh
脚本文件,将上面那段函数放进去。
执行这个test.sh
脚本来读取test.cfg
文件。
发现用dash
和bash
都执行的非常快。所以不是dash
的某种性能问题!
aliyun_cloud.cfg
的问题通过ls
,我观察到/etc/cloud/cloud.cfg.d/aliyun_cloud.cfg
文件其实是个链接。
aliyun_cloud.cfg -> /sys/firmware/qemu_fw_cfg/by_name/etc/cloud-init/vendor-data/raw
我直接cat
这个链接文件的内容,显示的很快。不像是某种 IO 问题。
我修改上面的test.sh
脚本,直接读取aliyun_cloud.cfg
这个链接文件。
然后,用bash
这个 shell 读取的非常快,但用dash
这个 shell 读取的却非常慢!
因为/usr/lib/cloud-init/ds-identify
这个脚本是系统在某个时刻调用的。我现在的绕过方式只能是将/bin/sh
的默认指向改为bash
。
我不确定为什么dash
读取阿里云的这个文件很慢,而bash
却很快。
希望有大佬能提供点调试思路。
1
SenLief 288 天前
这机器买过来第一件事就是 dd 了,它自带的还有一个云控,占内存的玩意。
|
2
7lQM1uTy635LOmbu 288 天前
把 cloud-init 干掉
|
3
churchmice 287 天前 via Android
不用啊,你这个脚本头上改成
#!/bin/bash 就好 |
4
weiweiwitch OP @churchmice 这个是 cloud-init 里面的脚本。位置是/usr/lib/cloud-init/下。也就是说,直接改,哪天更新时会被覆盖回去。
不过这些都只是绕过。根本原因还没找到。 |
5
xkwy001 283 天前 1
使用 strace 命令可以明显看出二者区别。
根本原因在于 bash 和 dash 对 read 这个 shell 内建命令的具体实现不一样。 dash 的实现是 read(0, &c, 1)直接使用 read 系统调用,一个字符一个字符地读取; https://git.kernel.org/pub/scm/utils/dash/dash.git/tree/src/miscbltin.c#n151 而 bash 是使用 zreadc(fd, &c)实现的,其内部会有一个 4K 缓冲,每次执行 zreadc 会一次性从文件中读入 4K 内容。 http://git.savannah.gnu.org/cgit/bash.git/tree/builtins/read.def#n683 http://git.savannah.gnu.org/cgit/bash.git/tree/lib/sh/zread.c#n132 对于常规的磁盘文件,使用 read 系统调用也还好,因为内核层面其实也有一层 buffer ,顶多会频繁进/出内核,并不涉及随机读写的磁盘 io 瓶颈。 猜测/sys/firmware/qemu_fw_cfg/by_name/etc/cloud-init/vendor-data/raw 这个文件不是普通的常规硬盘文件,每一次执行 read 系统调用都会触发异常->qemu 处理->balabala 一顿操作才返回,绕了好大一圈,且相对常规文件也没有内核缓冲,等于是每读一个字符都来一遍 |
6
JieS 121 天前
请问这个问题解决了吗?昨晚也发现同样的问题,执行期间 ECS CPU 指标直接被拉满😩
|