绕过了一个 VPS 上恶心问题,但不确定原因。麻烦大佬们提供下排查思路。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
weiweiwitch
V2EX    Linux

绕过了一个 VPS 上恶心问题,但不确定原因。麻烦大佬们提供下排查思路。

  •  
  •   weiweiwitch 2024-01-25 16:05:28 +08:00 2011 次点击
    这是一个创建于 628 天前的主题,其中的信息可能已经有所发展或是发生改变。

    环境

    • 机器:阿里云上的 VPS 。
    • 系统:Ubuntu 22.04

    问题现象

    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的某种性能问题。

    排查 dash 读长文本慢的原因,却发现不是

    我新建一个文本文件test.cfg,将/etc/cloud/cloud.cfg.d/aliyun_cloud.cfg文件的内容复制进去。

    新建一个独立的test.sh脚本文件,将上面那段函数放进去。

    执行这个test.sh脚本来读取test.cfg文件。

    发现用dashbash都执行的非常快。所以不是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却很快。

    希望有大佬能提供点调试思路。

    7 条回复    2024-07-24 08:30:21 +08:00
    SenLief
        1
    SenLief  
       2024-01-25 16:42:20 +08:00
    这机器买过来第一件事就是 dd 了,它自带的还有一个云控,占内存的玩意。
    7lQM1uTy635LOmbu
        2
    7lQM1uTy635LOmbu  
       2024-01-25 17:41:02 +08:00
    把 cloud-init 干掉
    churchmice
        3
    churchmice  
       2024-01-26 00:28:26 +08:00 via Android
    不用啊,你这个脚本头上改成
    #!/bin/bash 就好
    weiweiwitch
        4
    weiweiwitch  
    OP
       2024-01-26 10:21:26 +08:00
    @churchmice 这个是 cloud-init 里面的脚本。位置是/usr/lib/cloud-init/下。也就是说,直接改,哪天更新时会被覆盖回去。
    不过这些都只是绕过。根本原因还没找到。
    xkwy001
        5
    xkwy001  
       2024-01-30 10:58:28 +08:00   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 一顿操作才返回,绕了好大一圈,且相对常规文件也没有内核缓冲,等于是每读一个字符都来一遍
    JieS
        6
    JieS  
       2024-07-10 12:12:14 +08:00
    请问这个问题解决了吗?昨晚也发现同样的问题,执行期间 ECS CPU 指标直接被拉满
    xkwy001
        7
    xkwy001  
       2024-07-24 08:30:21 +08:00   1
    @JieS sudo ln -sf /bin/bash /bin/sh
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5978 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 06:13 PVG 14:13 LAX 23:13 JFK 02:13
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86