关于Ubuntu下ZRAM的配置和使用

当前自己使用的服务器内存比较小,需要扩容,只是服务器比较老了,内存扩展困难,但是服务器的负载并不高。因此可以尝试使用内存压缩的方式来适当扩展内存。

安装

软件包封装好了对应的东西(甚至是systemctl服务),并不需要自己写脚本

$ sudo apt install zram-config

重启之后,一个内存大小一半的 ZRAM 就出现了。

参考链接


Ubuntu 22.04使用Podman部署Tomcat 9的详细教程

安装必要的依赖:

# 安装 podman
$ sudo apt install podman

# 准备本地目录映射
$ mkdir /home/data/.tomcat

$ mkdir /home/data/.tomcat/webapps

$ mkdir /home/data/.tomcat/logs

官方镜像会在报错的时候暴露 Tomcat 9 版本号,错误堆栈,构成安全隐患,我们需要通过构建自定义镜像解决此问题:

$ touch Dockerfile

内容如下:

# 详细启动日志在 /usr/local/tomcat/logs 目录下

From docker.io/library/tomcat:9

# xml 编辑工具,方便我们后续修改 tomcat 的xml配置文件
# RUN apt update && apt install -y xmlstarlet

# 增加 <Valve className="org.apache.catalina.valves.ErrorReportValve" showReport="false" showServerInfo="false" /> 阻止错误日志输出

RUN sed -i "s/<\/Host>/  <Valve className='org.apache.catalina.valves.ErrorReportValve' showReport='false' showServerInfo='false' \/>\n\t<\/Host>/" /usr/local/tomcat/conf/server.xml

# 配置AJP协议
# 如果只希望通过 AJP访问,可以参考如下命令 移除原有的 AJP 协议配置
# RUN xmlstarlet ed -L -P -S -d '/Server/Service/Connector' /usr/local/tomcat/conf/server.xml

# 增加新的协议配置
RUN sed -i "s/<\/Service>/  <Connector port='8009' protocol='AJP\/1.3' address='0.0.0.0' redirectPort='8443' secretRequired=''\/>\n  <\/Service>/" /usr/local/tomcat/conf/server.xml

# 移除 xml 编辑工具
# RUN apt -y autoremove --purge xmlstarlet

构建镜像:

$ sudo podman build -t tomcat-9 .

设置容器开机自启:

$ sudo podman stop tomcat-9

$ sudo podman rm tomcat-9

# 启动一个 tomcat 容器 8080 HTTP 访问端口 8009 AJP访问端口
# sudo podman run -d --name tomcat-9 -p 8080:8080 -p 8009:8009 -v /my/local/path:/usr/local/tomcat/webapps localhost/tomcat-9

$ sudo podman run -d --name tomcat-9 -p 8080:8080 -p 8009:8009 -v /home/data/.tomcat/webapps:/usr/local/tomcat/webapps -v /home/data/.tomcat/logs:/usr/local/tomcat/logs localhost/tomcat-9

# 查看该容器
$ sudo podman ps

# 如果需要进入容器查看执行情况,参考如下命令
# sudo podman exec -it tomcat-9 bash

# 每次都启动新容器方式创建servcie //--new参数,每次启动都删除旧容器,启动一个新容器 
$ sudo podman generate systemd --restart-policy=always -n --new -f tomcat-9

查看启动文件:

$ cat container-tomcat-9.service

内容如下:

# container-tomcat-9.service
# autogenerated by Podman 3.4.4
# Sun Mar 10 12:31:31 CST 2024

[Unit]
Description=Podman container-tomcat-9.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=%t/containers

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=always
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/%n.ctr-id
ExecStart=/usr/bin/podman run --cidfile=%t/%n.ctr-id --cgroups=no-conmon --rm --sdnotify=conmon --replace -d --name tomcat-9 -p 8080:8080 -p 8009:8009 -v /home/data/.tomcat/webapps:/usr/local/tomcat/webapps -v /home/data/.tomcat/logs:/usr/local/tomcat/logs localhost/tomcat-9
ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id
ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id
Type=notify
NotifyAccess=all

[Install]
WantedBy=default.target

Systemd 配置:

# 保存到/etc/systemd/system/
$ sudo mv container-tomcat-9.service /etc/systemd/system/

# 刷新配置文件,让其生效
$ sudo systemctl daemon-reload

# 设置容器开机自启,并且现在启动
$ sudo systemctl enable --now /etc/systemd/system/container-tomcat-9.service

# 如果需要进入容器查看执行情况,参考如下命令
# sudo podman exec -it tomcat-9 bash

# 测试,重启虚拟机
$ sudo reboot

# 启动或重启服务 
# systemctl --user start container-tomcat-9.service 
# systemctl --user restart container-tomcat-9.service

# 如果启动失败,观察服务日志
# sudo journalctl -f

后续 WAR 包存储到 /home/data/.tomcat/webapps 目录下即可进行正常访问。

参考链接


ubuntu 22.04.3使用blivet-gui创建SoftwareRAID

最近家里安装降噪棉的时候使用了钉书钉,结果安装的时候,意外震坏了一块八年历史的老西数硬盘,造成数据丢失。

话说,西部数据的硬盘耐用性真的很成问题,家里至少已经坏了五块硬盘了,四块都是西部数据的。

于是另购了一块希捷的银河系列 16TB 硬盘,打算跟现存的一个刚刚替换的西部数据的 12TB 红盘(质保期之内坏了,走售后,花了一个多月换了一张盘,估计寿命也是堪忧),组一个 Raid 1 软阵列,到时候万一再有硬盘损坏,至少可以保住数据。

当前设备是使用 HP Gen8 上安装的 ubuntu 22.04.3 系统,四个盘位,其中两个从群晖上替换下来的 4TB 硬盘直接挂载到两个盘位上,依旧保持群晖的 Raid 1 软阵列。另外两个盘位,就是我们需要新组的软件 Raid 1 的位置了。

网上搜索了半天,都是需要通过命令行,逐个磁盘分区,分区之后再使用 mdadm 通过命令行组建阵列,虽然难度不大,但是操作比较繁琐,还是希望能在 UI 界面上点击一下鼠标搞定。

可以使用 storaged-project/blivet-gui 这个开源项目完成这个需求。

继续阅读ubuntu 22.04.3使用blivet-gui创建SoftwareRAID

云服务器 ECS Linux SSH 客户端断开后保持进程继续运行配置方法

在云服务器 ECS Linux 系统中,通常我们在执行一些运行时间比较长的任务时,必须等待执行完毕才能断开 SSH 连接或关闭客户端软件,否则可能会导致执行中断。

本文介绍几种保障程序在用户退出登录后持续运行的方法。

使用 nohup 执行


nohup 的作用顾名思义,它使得后面的命令不会响应挂断(SIGHUP)信号。也就是说,通过远程登录执行 nohup 后,即使退出登录后,程序还是会正常执行。通常情况下,nohup 命令最后会跟上 & 字符,表示将这个命令放至后台执行,这样才能真正做到将这个命令放至后台持续的执行。

操作示例:
1. 正常的执行命令为 bash hello.sh,执行结果为每秒输出一行的小程序:

2. 在命令头尾分别加上 nohup 和 &,变为 nohup bash hello.sh &,可以看到 nohup 输出了一行信息,再按一下回车键就跳回了 shell 命令行,此时命令已经在后台执行了,nohup 将命令的输出重定向至当前目录的 nohup.out 文件中。同时注意到 nohup 会将对应程序的 PID 输出,PID 可用于需要中断进程时 kill 进程。

3. 通过 tail -f nohup.out 可以持续的查看 nohup.out 的输出,达到监视程序的效果。

4. 在命令中也可以使用重定向将程序的输出改为自己想要的文件名,如 nohup bash hello.sh >hello.log &,则程序的输出就会写到 hello.log 文件中。

5. 若程序不会自动退出,那么此时需要使用 kill 命令来结束进程。比如,可以使用命令 kill -TRM <PID> 来操作,其中 PID 即为之前 nohup 输出的值,在此例中该值为 1231。

使用限制:

nohup 通常用于执行无干预的自动化程序或脚本,无法完成带有交互的操作。

使用 screen 执行


安装 sceen 工具

Linux 系统默认未自带 screen 工具,需要先进行安装:

  • CentOS 系列系统: yum install screen
  • Ubuntu 系列系统: sudo  apt-get  install screen
使用简介

1. 创建 screen 窗口

$ screen -S  name
# name可以设置为ssh、ftp,用于标注该 screen 窗口用途
# 示例:
screen -S ftp

2. 列出 screen 进程,并进入所需 screen

$ screen -ls 
##列出 screen 进程列表

如下图

然后进行所需操作,比如运行脚本、执行程序等等。

如下图示例:创建ftp连接后台下载传输文件

3. 退出保存

前述 ftp 操作示例开始传输后,在窗口中键入Ctrl+a 键,再按下 d 键,就可以退出 SSH 登录,但不会影响 screen 程序的执行。

4. 保存会话以便继续执行

可以利用 screen 这种功能来管理的远程会话。操作步骤概述:

  • 正常 SSH 登录服务器
  • 创建 screen 窗口
  • 执行所需任务
  • 需要临时中断退出时,Ctrl + a 再按下 Ctrl + d 保存退出
  • 需要继续工作时,再次 SSH 登录服务器,然后直接执行 screen -r -d 恢复会话即可。

参考链接


云服务器 ECS Linux SSH 客户端断开后保持进程继续运行配置方法

家庭搭建OPENCONNECT VPN(ubuntu 22.04)

家里运行了一些服务,希望在外面也可以方便的访问它们。

旧办法是通过路由器端口映射到内网端口,但这种方式已经很难满足我的场景,因为例如hadoop服务会开放很多web页面端口,实在难以逐一映射。

于是我选择了在家里自建VPN服务器,然后只把VPN服务的端口映射到路由器,这样只要在外面连接VPN即可像在家里一样任意访问内部网络了。

搭建Openconnect

openconnect是开源VPN项目,包含了服务端和客户端(PC/MAC/Android),是商业产品思科cisco anyconnect的开源版本。

为什么选择它呢?因为它能够从服务端自定义下发路由规则到客户端,这样就可以控制客户端哪些流量需要送往VPN隧道、哪些流量不需要经过VPN隧道,实现类似于同时兼顾访问家庭内网和公司内网的目的。

搭建方式参考官方手册:https://gitlab.com/openconnect/recipes,我以debian为例进行安装配置,非常方便:

$ sudo apt-get update

$ sudo apt-get install ocserv

这样就安装完成openconnect服务端了。

配置Ocserv

接下来配置VPN服务端,分为2大部分:

  • 自签一下SSL证书,因为这个VPN协议需要SSL加密。(自签没关系,只要客户端登录时选择信任证书即可)
  • 配置ocserv.conf配置文件,主要是定义VPN如何认证用户、VPN网段、还有更高级的路由表下发。
SSL证书

首先搞证书,按官方教程来即可:https://gitlab.com/openconnect/recipes/-/blob/master/ocserv-configuration-basic.md#certificate-management-self-signed

第一步:

$ mkdir ~/certificates

$ cd ~/certificates

第二步(原样敲入即可,信息都不重要):

# vim ca.tmpl

cn = "Your CA name"
organization = "Your organization name"
serial = 1
expiration_days = 3650
ca
signing_key
cert_signing_key
crl_signing_key

第三步(原样敲入即可,信息都不重要):

# vim server.tmpl

cn = "Your hostname or IP" 
organization = "Your organization name" 
serial = 2
expiration_days = 3650
signing_key 
encryption_key
tls_www_server

第四步(生成CA证书):

$ certtool --generate-privkey --outfile ca-key.pem

$ certtool --generate-self-signed --load-privkey ca-key.pem --template /etc/ssl/ca.info --outfile ca-cert.pem

第五步(用CA签VPN证书):

$ certtool --generate-privkey --outfile server-key.pem

$ certtool --generate-certificate --load-privkey server-key.pem --load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem --template server.tmpl --outfile server-cert.pem

把VPN证书拷到ocserv配置目录下:

$ sudo cp server-cert.pem server-key.pem /etc/ocserv/
Ocserv.Conf

先修改登录方式,采用用户密码进行登录:

$ sudo vim /etc/ocserv/ocserv.conf


auth = "plain[passwd=/etc/ocserv/ocpasswd]"    #设置用户密码

创建密码文件

$ sudo touch /etc/ocserv/ocpasswd

创建用户

$ sudo ocpasswd -c /etc/ocserv/ocpasswd user

删除用户(如果需要的话),此处只是留下删除用户的命令,不是要求必须执行,否则刚刚创建的用户就被删除了

$ sudo ocpasswd -c /etc/ocserv/ocpasswd -d user1

然后VPN监听端口有需要可以改一下:

tcp-port = 443

udp-port = 443 

然后就是VPN网段的配置了,我家里是192.168.1.x网段,我们要让VPN使用一个不同的网段,因为VPN server要给每个连接过来的VPN client分配一个VPN网段的IP,如果这个IP和192.168.1.x网段的某个IP冲突就有问题了,所以一定是不同网段的,同样道理也不能和客户端所在的局域网段冲突。

ipv4-network = 192.168.50.0
ipv4-netmask = 255.255.255.0

所以我配置了192.168.50.x的一个冷门网段,足够分配254个VPN client,为什么不是255个呢?因为VPN服务端会先占1个IP。

暂时我们配置这些,现在我们启动ocserv来介绍一下VPN是如何工作的。

分析Ocserv工作原理

大家自行在路由器映射VPN端口到公网,然后下载openconnect gui客户端(https://openconnect.github.io/openconnect-gui/),然后连接这样的地址:

https://公网IP:路由器映射端口

即可连接到家里内网的VPN服务端,输入任意正确的linux账号密码即可登录。

连接成功后,在客户端打开命令行查看路由表(我是windows电脑,使用route print命令),会发现2条本就存在的路由记录:

          0.0.0.0          0.0.0.0      192.168.2.1    192.168.2.103     25
      192.168.2.0    255.255.255.0            在链路上     192.168.2.103    281

这是因为windows电脑也在家里,所以本身就被局域网下发了默认网关路由到192.168.2.1路由器、以及192.168.2.x网段的路由记录,这台电脑的自身IP是192.168.2.103。

但是连接VPN后,则多了2条VPN网段的记录:

          0.0.0.0          0.0.0.0      192.168.50.1    192.168.50.250      2
      192.168.50.0    255.255.255.0            在链路上     192.168.50.250    257

又来了一条优先级更高(2)的默认网关路由,指向了192.168.50.1,也就是VPN server的IP地址,同时也多了一条192.168.50.x 这个VPN网段的路由记录,此时电脑上也出现了一张虚拟的网卡,其IP就是192.168.50.250,这是VPN server给分配的,由VPN client负责虚拟出本地网卡。

此时发往192.168.50.x网段的流量会直接从VPN网卡送出,发往其他IP的流量也会命中192.168.8.1的默认网关(同样是从VPN网卡送出),而不是电脑所在局域网原本下发的192.168.2.1的默认网关。

所以VPN网卡已经劫持了所有外出流量,经过VPN虚拟网卡封包为物理IP送往VPN server,再由VPN server拆包后得到真实IP地址,继续进行转发。

此时VPN server也多了一条该客户端的路由记录:

root@debian:/home/work# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.2.201   0.0.0.0         UG    0      0        0 ens18
192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 ens18
192.168.50.250   0.0.0.0         255.255.255.255 UH    0      0        0 vpns0

# macOS 
# netstat -nr

也就是192.168.50.250这个vpn client的流量全部送给vpns0虚拟网卡,也就是说回给该vpn client的包也需要经过vpn server的虚拟网卡封包送走。

vpn基本就是这个原理。

这点原理还不够

不要以为理解上面就万事大吉了,当VPN client请求baidu.com时,baidu的IP地址会命中默认网关发往192.168.50.1默认网关,经过封包送到VPN server的监听端口。

然后VPN server会把封包拆开,linux协议栈看到真实目标IP是baidu.com,那么显然该IP地址不是本机,需要forward给百度,此时需要linux的netfilters进行流量forward才能再次送给192.168.2.1家庭物理网关到达百度,这一步需要我们在服务端开启ipv4 forward特性:

sudo vim /etc/sysctl.conf

net.ipv4.ip_forward=1
net.ipv6.ip_forward=1

然后执行sysctl -p生效。

配置防火墙的IP Masquerading

请使用以下命令检查服务器的主网卡接口

$ ip addr

例如,可以检查到网卡接口名字是eth0,则执行

$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

这里命令-A表示添加到nat表的POSTROUTING链。这样就可以把VPN网络连接到Internet,并且把你的网络对外隐藏起来。这样Internet只能看到你的VPN服务器IP,但是不能看到你的VPN客户端IP,类似于你家中路由器隐藏起家庭网络。

现在可以检查一下NAT表的POSTROUTING链,可以看到目标是anywhere的源为anywhere的都执行MASQUERADE。

$ sudo iptables -t nat -L POSTROUTING

显示输出:

Chain POSTROUTING (policy ACCEPT)


target prot opt source destination


MASQUERADE all -- anywhere anywhere

为了持久化iptables规则(默认重启后就没了),所以我们需要安装一下工具:

sudo apt install iptables-persistent

然后保存一次:

sudo netfilter-persistent save

最后

更高级的特性就是配置ocserv.conf的路由下发,下发一些路由规则到VPNclient ,这样可以控制哪些网段的流量不要发给VPN隧道,可以兼顾客户端本地局域网和家庭局域网两路一起访问的需求,但是这个要求客户端本地局域网段、VPN网段、家庭局域网段三者不能冲突。

大家可以试一下ocserv.conf中的route和no-route配置项,比如我希望VPN client不要让公司网段走VPN,那么就可以加一条这样的配置(假设公司网段是172.26.201.x):

no-route = 172.26.201.0/255.255.255.0

这样VPN client侧的虚拟网卡就会判断目标IP是这个网段的就不发往VPN server了,而是走本地其他路由规则寻址。

如果你家里的网络是路由器/旁路由FQ或者绿色dns的话,那么可以令vpn server的默认网关指向fq路由器,同时让vpn client使用你家里的绿色dns,这样就可以让vpn客户端透明fq了。

比如我家里旁路由上有绿色DNS,所以我可以令ocserv.conf下发它的IP地址作为客户端使用的DNS服务器地址(家里的192.168.2.201运行着绿色DNS,然后vpn client可以通过隧道访问到它):

在ocserv.conf中指定dns服务器地址,下发给vpn client:

dns = 192.168.2.201

这样vpn client就会请求192.168.2.201进行域名解析,得到无污染IP。

理解上述原理需要对路由表、netfilters有清晰认识,否则可能比较困难,希望对你有点帮助。

智能分流

https://github.com/don-johnny/anyconnect-routes

国内IP不进行代理,参考如下开源项目:

https://github.com/CNMan/ocserv-cn-no-route

遇到的问题

1. 对于 ubuntu 22.04 系统,目前(2023.09.01) 系统自带的 ocserv 1.1.3 会在启动之后崩溃,出现如下日志:

$ sudo tail -f /var/log/kern.log

Sep  1 11:01:39 localhost kernel: [   62.471583] traps: ocserv-worker[9587] general protection fault ip:7fa35c1db898 sp:7ffdf42e29a0 error:0 in libc.so.6[7fa35c1db000+195000]

  
$ ocserv --version
ocserv 1.1.3

Compiled with: seccomp, tcp-wrappers, oath, radius, gssapi, PAM, PKCS#11, AnyConnect
GnuTLS version: 3.7.3 (compiled with 3.7.1)

解决此问题的方法就是安装 ocserv 1.1.6以及以后的版本,可以从源代码编译安装。这里有个简单的解决方法,就是从 ubuntu 23.04 的安装源中下载已经编译好的安装包,直接进行安装,如下:

$ wget http://cz.archive.ubuntu.com/ubuntu/pool/universe/o/ocserv/ocserv_1.1.6-2_amd64.deb

$ sudo dpkg -i ocserv_1.1.6-2_amd64.deb

$ sudo systemctl restart ocserv 

2. 对于腾讯云购买的海外 轻量应用服务器 需要在管理控制台配置防火墙规则,放开端口访问,否则无法进行正常的通讯访问。

参考链接


ubuntu 22.04 Warning: apt-key is deprecated

在尝试安装 nvidia-docker 的时候(ubuntu 22.04系统Docker和Nvidia-docker的安装、测试,及运行GUI应用),执行如下命令增加 nvidia 源:

$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
   && curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - \
   && curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

系统发出如下警告:

Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).

经过分析,是脚本中的如下部分导致:

$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo tee /etc/apt/trusted.gpg.d/nvidia-docker.gpg 

解决方法为修改为使用如下脚本:

$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg 

$ sudo chmod 644 /etc/apt/trusted.gpg.d/nvidia-docker.gpg

完整修改后的脚本如下:

$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
   && curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
   && sudo chmod 644 /etc/apt/trusted.gpg.d/nvidia-docker.gpg \
   && curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

参考链接


Warning: apt-key is deprecated (SOLVED)

Ubuntu 22.04搭建TimeMachine

  • 创建一个目录,作为 TimeMachine 保存数据的目录。
$ sudo mkdir /home/data/.timemachine
  • 安装 netatalk 服务和 avahi-daemon 服务。
$ sudo apt install netatalk avahi-daemon
  • 编辑 netatalk 的配置文件:
$ sudo nano /etc/netatalk/afp.conf
  • 在该文件原来的基础上,或新增以下配置:
[TimeCapsule]

path = /home/data/.timemachine

time machine = yes

; 关闭spotlight索引,这个在Centos6上是不能开的,缺依赖,7上面可以开,但是不建议,吃资源
spotlight = no

; 指定某用户有读写权限
rwlist = senra

; 强制指定用户
force user = senra

; 限制TM存储容量,单位为MB
vol size limit = 100000
  • 重启服务。
$ sudo service netatalk restart

现在,你在 TimeMachine 上应该可以看到这个备份服务了,选择该备份服务就可以开始你的第一次备份了。

注意: Debian 12.5 系统上不能安装 netatalk ,原因是这个项目已经长时间没人维护了,后续建议直接使用 SMB 建立 TimeMachine 的备份服务器。

参考链接


ubuntu 22.04升级到cpp-12后flutter编译报错"找不到 -lstdc++"

在今天晚上 ubuntu 22.04 执行如下升级命令之后

$ sudo apt-get dist-upgrade 
正在读取软件包列表... 完成
正在分析软件包的依赖关系树... 完成
正在读取状态信息... 完成                 
正在计算更新... 完成
下列【新】软件包将被安装:
  cpp-12 gcc-12 libasan8 libgcc-12-dev libtsan2
下列软件包将被升级:
  apport apport-gtk dkms firmware-sof-signed libexpat1 libexpat1:i386
  libexpat1-dev libflac8 libfreerdp-client2-2 libfreerdp-server2-2
  libfreerdp2-2 libwinpr2-2 python3-apport python3-problem-report rsync
  xserver-common xserver-xephyr xserver-xorg-core xserver-xorg-legacy xwayland
升级了 20 个软件包,新安装了 5 个软件包,要卸载 0 个软件包,有 0 个软件包未被升级。

再次执行 flutter 的构建命令,报错。

操作过程如下:

$ flutter run
Launching lib/main.dart on Linux in debug mode...
Building Linux application...
/usr/include/glib-2.0/glib/glib-typeof.h:39:10: fatal error: 'type_traits' file not found
/usr/include/glib-2.0/glib/glib-typeof.h:39:10: fatal error: 'type_traits' file not found
Exception: Build process failed

$ flutter --version
Flutter 3.3.9 • channel stable • https://github.com/flutter/flutter.git
Framework • revision b8f7f1f986 (2 天前) • 2022-11-23 06:43:51 +0900
Engine • revision 8f2221fbef
Tools • Dart 2.18.5 • DevTools 2.15.0

$ flutter clean

$ flutter run
Multiple devices found:
Linux (desktop) • linux  • linux-x64      • Ubuntu 22.04.1 LTS 5.15.0-53-generic
Chrome (web)    • chrome • web-javascript • Chromium 107.0.5304.110
[1]: Linux (linux)
[2]: Chrome (chrome)
Please choose one (To quit, press "q/Q"): 1
Running "flutter pub get" in xxxx...                            6.2s
Launching lib/main.dart on Linux in debug mode...
CMake Error at /usr/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake:62 (message):
  The C++ compiler

    "/usr/bin/clang++"

  is not able to compile a simple test program.

  It fails with the following output:

    Change Dir: /home/xxxx/xxxx/xxxxx/build/linux/x64/debug/CMakeFiles/CMakeTmp

    Run Build Command(s):/usr/bin/ninja cmTC_8cfda && [1/2] Building CXX object CMakeFiles/cmTC_8cfda.dir/testCXXCompiler.cxx.o
    [2/2] Linking CXX executable cmTC_8cfda
    FAILED: cmTC_8cfda 
    : && /usr/bin/clang++   CMakeFiles/cmTC_8cfda.dir/testCXXCompiler.cxx.o -o cmTC_8cfda   && :
    /usr/bin/ld: 找不到 -lstdc++: 没有那个文件或目录
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    ninja: build stopped: subcommand failed.


  CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
  CMakeLists.txt:3 (project)

Building Linux application...                                           
Exception: Unable to generate build files

解决方法是手工安装依赖:

$ sudo apt install lib32stdc++-12-dev

之后再执行构建命令。

参考链接


联想T440在ubuntu 22.04系统上安装配置指纹

家里有一台旧的联想T440笔记本,某天来了兴致安装了ubuntu 22.04,默认情况下指纹识别是无法使用的。

查看硬件属于 Elan 指纹识别设备,Ubuntu 自带的 Libfprint 已经提供了支持。

安装前端工具
$ sudo apt install fprintd libpam-fprintd

执行

$ sudo pam-auth-update

将第一项,用空格勾选上,然后点“确定”。这样就授权指纹识别登录设备。

录入指纹

打开“设置---用户---指纹登录”,此时就可以打开了。点击“+”,录入第一个指纹吧

参考链接


联想小新Air2020锐龙版在Ubuntu下添加指纹识别

Flutter The Linux toolchain CMake build dependency (CMake 3.14 or higher is required. You are running version 3.10.2)

ubuntu 22.04 通过 snap 安装了 Flutter SDK(当前是Flutter 3.3.4),如果第三方的依赖了 CMake 3.10.2 更高的版本,会在编译的时候报错:

CMake 3.14 or higher is required. You are running version 3.10.2

这个报错的原因是由于 snap 安装的 Flutter SDK 构建了一个沙箱环境,在这个环境中的 CMake3.10.2 版本,不管系统安装的是哪个版本的 CMake ,都是无效的。

要解决这个问题,或者等待 snapFlutter SDK 更新版本,或者参照 Linux install Flutter 的说明,手工安装并配置 Flutter SDK

可以参考如下代码:

$ sudo snap remove flutter

$ sudo apt-get install curl

$ sudo apt-get install clang

$ sudo apt-get install git

$ sudo apt-get install ninja-build

$ sudo apt-get install pkg-config

$ sudo apt install gettext

$ sudo apt-get install libgtk-3-dev

$ sudo apt install libstdc++-12-dev

$ git clone https://github.com/flutter/flutter.git -b stable

$ export PATH="$PATH:`pwd`/flutter/bin"

$ cd `pwd`/flutter/bin 

$ ./flutter doctor

参考链接