分类 技术 下的文章 - HelloJXL

技术

Linux下桌面快捷方式启动路径问题

前言

之前提到过当前公司正在进行国产化方面的东西,目前有个桌面软件需要迁移到Linux下,于是通过Avalonia UI实现了一下,具体实现过程还算顺利,跟WPF相比虽说有些差异但感觉可以接受,也可能跟本身项目不复杂有关,毕竟就三个窗口。在添加完桌面快捷方式之后遇到了点问题,于是就有了这篇日志。

创建桌面快捷方式

新建一个utf-8格式的文本,名称改为应用名称,后缀改为.desktop就可以了,为避免误人子弟,常用内容可参考这里,下面是例子:

[Desktop Entry]
Name=XXXX
Type=Application
Exec=/home/test/xxx
Path=/home/test/xxx
Icon=/home/text/xxx.png
StartupNotify=true

完了之后只要将该文件复制到桌面上就变成启动快捷方式了,如果想在开始菜单中或启动器中看到,就把该文件复制到/usr/share/applications目录中就可以了。也可以增加Categories指名应用分类,这样就可以出现在开始菜单或启动器中的不同分类下面了,具体分类可以参考这里

路径问题

正常项目启动时会生成日志文件,但是在桌面启动时却没有生成,研究了一下,找到两种解决办法,

  1. 增加Path这个关键字,该参数可以指名工作路径,处理非常简单,这也是项目里使用的办法。
  2. 可以定义一个脚本,和应用放到一起,通过启动脚本来解决路径问题,对比增加关键字,这种方式更加灵活一点,下面是脚本内容:

     #! /bin/bash
     # shellcheck disable=SC2046
     cd $(dirname $0) || exit
     ./xxx

    然后需要将.desktop文件里替换掉Exec=后面的内容,改为:sh /home/test/xxx.sh就可以了。

结束

对比windows,linux下的处理相对灵活很多,不亏是一切皆文件。

解决p/invoke在Linux下的段错误问题

前言

最近公司打算将操作系统迁移到Linux环境下,于是调研了一下现有引用类库的情况,项目中有个最主要的引用是国产的TLQ,多个项目引用了,看了一下TLQ的介绍,本身就是跨平台的,不过公司在用的是官方给的.net framework版本,本身不是跨平台的,经过协商,对方把源码发了过来,改为.net standard2.0也编译通过了,在Linux下却出问题了。

Lib引用

对于源码中所有P/invoke相关的将dll去掉,在Linux系统下,会自动查找lib开头的类库,如果仍然查找不到,就要设置类库的加载位置了,很简单,一共两种方式,一种是增加LD_LIBRARY_PATH的环境变量,一种是编辑/etc/ld.so.conf文件,增加类库目录,由于网上讲解很多,不再赘述。

内存对齐

遇到的最大问题是在Windows下一切正常,但是在Linux下会报段错误,第一次遇到的时候还很懵逼,后来查了一下原来是指针越界或重复释放内存之类的操作,刚开始的时候由于改动了代码,一直以为是自己改出来的问题,尝试了很多方式都一无所获,后来又经过协商才发现跟自己的改动完全没有关系,问题是出在了一个结构体上,这个结构体一直没有动过,所以没有往这个方向去想,并且项目是在收消息的时候才出现的错误,且只有在第二次收消息的时候才会出段错误,经过了半天调试依然没有头绪,就在快要放弃时突然发现原来类库方为了做跨平台在引用线程时增加了区分,windows下用的int32来代替线程id,Linux下则直接用的Thread_t,那么Thread_t在Linux下是什么类型呢?网上查了一下,果然跟Windows不一样,类型为uint64_t,对应的c#格式为:ulong。查到这个答案的时候心里并没有在意,因为前面已经尝试过n种方法了,但是在改动完之后在Linux上测试,奇迹却出现了,完全正常了。

结束

原本一直以为运行时在进行底层调用时对Intptr进行了改动,造成的指针错误,后来才发现原来是自己错了,如果项目中再出现段错误了,那么就要仔细对比每个数据类型了,通常是类型封送错了。

GDB调试笔记

前言

最近部署到linux的程序遇到段错误,网上查了一些原因,基本上看不出有用的东西出来,于是只能根据gdb进行排查。

寻找core文件

就是内存转储文件,程序崩溃时会自动提示:段错误(内核已转储),gdb调试的时候必须依赖转储文件才能调试。要进行调试还需要知道两个问题:core文件在哪以及为什么没有生成

  1. 文件位置

要查看文件在哪,可以直接执行

 cat /proc/sys/kernel/core_pattern

根据输出内容进行判断,如果为core则代表在执行文件同目录生成,如果为/usr/lib/systemd/systemd-coredump %P %u %g %s %t %e 则代表着被coredumpctl接管了,下面说一下如何从coredumpctl提取core文件,其实很简单

#查看所有的内存转储文件
coredumpctl list

#默认会显示出所有的内存转储文件,我们大部分关心的应该是最后一项,拿到pid后

coredumpctl -o core dump pid

执行完之后就会在当前目录中生成core文件了,文件名可以自定义。

  1. 文件没有生成

默认系统是关闭core文件生成的,可以通过命令查看

ulimit -c

#或
ulimit -a

real-time non-blocking time  (microseconds, -R) unlimited
core file size              (blocks, -c) 0
data seg size               (kbytes, -d) unlimited
scheduling priority                 (-e) 0
file size                   (blocks, -f) unlimited
pending signals                     (-i) 62283
max locked memory           (kbytes, -l) 64
max memory size             (kbytes, -m) unlimited
open files                          (-n) 1024
pipe size                (512 bytes, -p) 8
POSIX message queues         (bytes, -q) 819200
real-time priority                  (-r) 0
stack size                  (kbytes, -s) 8192
cpu time                   (seconds, -t) unlimited
max user processes                  (-u) 62283
virtual memory              (kbytes, -v) unlimited
file locks                          (-x) unlimited

如果输出为0或core file size为0则代表的允许的最大core文件大小为0,即禁止输出core文件,修改大小可以通过

#修改为1个G,文件单位为kbyte
ulimit -c 1024000

#或不限制

ulimit -c unlimited

当前限制仅针对当前shell,如果要持久化可以配置到/etc/sysctl.conf。另外core文件感觉通常都很大,如果core的实际大小超过了限制大小,则会覆盖,gdb也会提示错误,如果只是临时生成一下,可以设置成不限制。

GDB调试

由于是初次接触gdb调试,使用的方式是:gdb [执行文件] core文件,比如,执行文件为a.out,core文件为b.core

gdb a.out b.core

然后gdb会给出一段提示,直接按回车后,输入bt回车后,会打印出异常的地方。

结尾

通过这一次找问题,感觉还是需要掌握gdb调试的,哪怕是最基础的操作,至少在出现问题不会抓瞎。

Linux下的中文乱码问题

起因

最近在论坛里看到有人部署的小说网站,感觉界面还挺好看,联想到之前DP家的100G硬盘的VPS,本来部署的图床,可惜不怎么用,就想折腾弄成小说站,话说也不能浪费了之前下载的15G的小说是吧。

乱码问题

本身用的是Java写的,就一个jar包很简单,直接放到VPS上启动,但是访问的时候总是提示:malformed input or input contains unmappable characters,后面跟着一个路径,一眼看上去路径最后的图片名都是????.jpg,很明显是编码问题,怎么解决呢?因为大部分的VPS用的都是debian的系统,于是查了一下,说是要配置中文,于是通过dpkg-reconfigure locales命令重新配置,并且默认选用zh_CN.UTF-8,但是依然不起作用,看了一下bashrc的配置,发现原来为了登录的时候不提示错误,配置的export LAN=C,改为zh_CN.UTF-8依然不起作用,为此还重启了一次。后来看到可以通过配置java的启动环境变量来配置

java -Dfile.encoding="UTF-8" -Dsun.jnu.encoding="UTF-8" -jar xx.jar

启动的时候果然显示正确了,但是依然提示上面的错误,后来又在一个git的issue界面看到说直接配置为C.UTF-8就可以了,于是改为下面这样

export LAN=C.UTF-8
export LC_ALL=C.UTF-8
export LC_LANG=zh_CN.UTF-8

#重新加载bashrc
source ~/.bashrc

再启动就可以了,完全不用配置java的启动环境变量,Centos下可能需要配置/etc/sysconfig/i18n,流程基本上都差不多。

结束

最近在捣鼓统信的系统,基本上都是基于centos的,可是自己偏偏喜欢用debian,没办法,看来还要学习一下centos的部分配置了。

迁移docker为containerd

2023-02-18更新

最近在升级nerdctl时发现有些地方变更了,最新的文档可以参考containerd官方的文档了


起因

一直在用nezha探针,服务端的部署方式很简单,直接用docker部署就可以了,但是自从上次迁移到racknerd之后出现了严重的内存泄露问题,如果一直看着dashboard,初始状态下从还不足50%会一直占用到70-80%,尝试各种限制但是效果并不明显。后来发现轻量级的containerd,进一步发现docker本身也是间接的管理containerd,既然都是containerd,那为什么还要装docker呢?于是尝试从docker迁移到containerd。

安装containerd

官方的安装说明也很简单,直接下载官方包,解压就可以了,具体安装如下:

#目前最新版为1.6.8,具体可以参考官方说明
wget https://github.com/containerd/containerd/releases/download/v1.6.8/cri-containerd-1.6.8-linux-amd64.tar.gz
#解压进行安装
tar -C / -xzf cri-containerd-1.6.8-linux-amd64.tar.gz

默认可以systemctl进行管理,比如开机自启等,操作如下:

#开机自启
systemctl enable containerd
#启动containerd
systemctl start containerd

安装nerdctl

containerd本身的管理太过简单,可以通过nerdctl进行管理,使用方式跟docker非常类似,具体安装如下:

#目前安装的是0.22.2,最新版参考官方
wget https://github.com/containerd/nerdctl/releases/download/v0.22.2/nerdctl-0.22.2-linux-amd64.tar.gz
#解压并安装到/usr/local/bin,仅限debian系,如果是centos则要么改路径,要么加环境变量
tar Cxzvvf /usr/local/bin nerdctl-0.22.2-linux-amd64.tar.gz

本身还需要cni-plugins,因此也需要安装

#当前最新版为1.1.1
wget https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz

#先创建所需的目录并解压安装
mkdir /opt/cni
mkdir /opt/cni/bin
tar Cxzvvf /opt/cni/bin cni-plugins-linux-amd64-v1.1.1.tgz

安装完之后如果没有其它问题就可以使用了。

遇到的问题

(1)runc无法启动,表现为启动镜像时报错:ctr: failed to create shim: OCI runtime create failed: unable to retrieve OCI runtime error (open /run/containerd/io.containerd.runtime.v2.task/xxxx/xxxxx/log.json: no such file or directory,刚开始时完全不知道怎么处理,后来通过爬文发现是runc的问题,最简单的可以直接执行runc命令,得到的错误是:runc: undefined symbol: seccomp_notify_respond,网上说是libseccomp版本问题,如果是centos则可以尝试更新依赖解决,由于我大部分都是debian,最简单的方式是替换runc,可以直接从这里下载,提供两种修复方式,一种是libseccomp-2.5.4.tar.gz源码,可以下载下来自己编译安装,另外一种是runc的可执行文件,我用的第二种,具体操作如下:

#下载runc
wget https://github.com/opencontainers/runc/releases/download/v1.1.4/runc.amd64
#重命名文件
mv runc.amd64 runc
#增加可执行权限
chmod +x runc
#查找当前runc所在目录
which runc
#替换当前runc,这是debian下的,centos下为/usr/bin/runc
mv runc /usr/local/sbin/runc

(2)缺少iptables组件,会提示:failed to locate iptables: exec: \"iptables\": executable file not found in $PATH",解决方法就是直接安装iptables就可以了

结束

最开始迁移的时候没有太在意,本身不太爱用docker的方式,感觉吃内存跟硬盘,但是最近看到可以用traffmonetizer挂机挣钱,手里小鸡也不算少,就打算部署一下,可官方并没有提供二进制的方式部署只有docker,没办法就用containerd进行部署了,也可以走我的aff,注册之后就可以得到5$,具体部署方式也很简单:

#拉取镜像
nerdctl pull traffmonetizer/cli:latest
# 启动
nerdctl run -d --name tm traffmonetizer/cli start accept --token  你的token

也不知道收益咋样,之前挂过peer2profit,但是感觉收益好少后面就放弃了,试试这个看看咋样😎。