用Linux也有几个年头了,最长碰见的问题就是,不同的程序对于同一套基础软件有着不同的版本需求,比如Python2/Python3,Java8/Java11,以及各个版本的gcc等等。然而,由于太懒一直没有找到一个好的软件版本管理工具。
可是这次在玩Rock64的时候,被mawk
活生生地坑了一把,还顺便学会了update-alternatives
这个基本命令= =
起因是Rock64的swap
虚拟内存。秉持着内存多大,swap就应该有多大的传统思想,看到我4G内存的Rock64只有1G的swap,心里甚是不爽,于是决定修改配置文件来把swap修改到至少2G以上。
由于编写系统的人不同,初始化系统swap的脚本位置也不同。在Armbian的系统下,使用的swap也是压缩的zram
,初始化的脚本位置在/usr/lib/armbian/armbian-zram-config
,
可以看到其中激活zram作为swap分区的函数activate_zram_swap
,截取其中的关键部分如下:
# Load zram module with n instances for swap: one per CPU core, $ZRAM_MAX_DEVICES
# defines the maximum, on modern kernels we overwrite this with 1 and rely on
# max_comp_streams being set to count of CPU cores or $ZRAM_MAX_DEVICES
uname -r | grep -q '^3.' && zram_max_devs=${ZRAM_MAX_DEVICES:=4} || zram_max_devs=1
cpu_cores=$(grep -c '^processor' /proc/cpuinfo | sed 's/^0$/1/')
[[ ${cpu_cores} -gt ${zram_max_devs} ]] && zram_devices=${zram_max_devs} || zram_devices=${cpu_cores}
module_args="$(modinfo zram | awk -F" " '/num_devices/ {print $2}' | cut -f1 -d:)"
[[ -n ${module_args} ]] && modprobe zram ${module_args}=$(( ${zram_devices} + 2 )) || return
# Expose 50% of real memory as swap space by default
zram_percent=${ZRAM_PERCENTAGE:=50}
mem_info=$(LC_ALL=C free -w 2>/dev/null | grep "^Mem" || LC_ALL=C free | grep "^Mem")
memory_total=$(awk '{printf("%d",$2*1024)}' <<<${mem_info})
mem_per_zram_device=$(( ${memory_total} / ${zram_devices} * ${zram_percent} / 100 ))
可以看到,脚本获得系统的内存容量,然后按照预先设置好的比例建立好zram的分区大小。奇怪的是,按照脚本设计,zram大小应该是系统内存的一半实际上只有四分之一。
这是为啥呢?好问题。
在我多次修改swap分区比例,并重启测试之后发现,似乎脚本所识别到的内存容量只占总内存容量的一半。在我手动执行了上面的相关代码后,露出了端倪:awk
的数据大小有限制。系统所自带的awk
,允许的最大整数为2147483647
,使用再大的数输入awk
,输出的整数结果都不会超过这个数,而这恰好是一个32位有符号整形的最大值。
在网上冲浪后发现,实际上Debian最小化安装版(听名字应该能发现Armbian是Debian家的吧)中,默认自带的awk
是mawk
,查看版本可以发现这玩意还是1996年11月的,怎么想支持64位数据的可能性都不大= =(ps. 查了一下,amd64
指令集的提出是2000年,产品最早出现在2003年)
然后就要感谢大公无私的GNU了。作为awk
的后继,GNU组织开发了gawk
,在实现awk
原有功能的基础上添加了大量插件库(虽然我还没用到过),不必多想,64位数据的问题自然早已解决。
安装完gawk
后,实际上系统是把/usr/bin/awk
最终重定向到了gawk
的可执行文件。根据上文表述可以推测,Debian的非最小化安装版本的默认awk不是mawk
,而是gawk
。这也是为啥只有在嵌入式设备上才容易发生这类问题的原因了吧= =
为什么说是最终呢?观察/usr/bin/awk
的指向可以发现,它并非直接指向/usr/bin/gawk
,而是指向了/etc/alternatives/awk
。这就引出了本文的后半篇内容,update-alternatives
命令。(名字又臭又长的,一度以为是ubuntu用户专属命令)
update-alternatives
是Linux下的一个标准命令。简单解释来说,就是允许在系统中安装同一个软件包的多个版本,并且根据需求修改默认调用软件包版本的版本。比如在本文前半篇中的场景,一个系统中可能同时安装了mawk
和gawk
,两者的基本功能完全一致,到底使用哪一个awk
作为默认的这个工作,就可以通过update-alternatives
配置软链接轻松完成。
常用命令:
update-alternatives --get-selections # 查看当前所有存在配置的文件(似乎还可以配置程序库)
update-alternatives --config <name> # 使用交互方式设置该条目的默认配置;如果留空,对当前系统中存在的所有条目依次进行配置