使用cbuild编译Keil工程

Keil 的工程可以通过 uv2csolution 转成 CMSIS 工程, 再用 cbuild 在 Windows 或 Linux 的命令行下编译, 不需要打开 µVision.

这里记录 Arm Compiler 6.24.19, CMSIS-Toolbox 2.14.1 和 MDK-Toolbox 1.1.0 的安装及工程转换过程. 下面以 Linux x86_64 为例, 工具安装到 /opt, 测试工程文件为 project.uvprojx. Windows 下操作流程相同, 换成对应的 Windows 工具包, 并调整安装路径和环境变量的设置方式即可.

安装 Arm Compiler

这里使用 MDK Community(社区版) 的 Arm Compiler 下载链接, 其他下载入口可以查看 Arm 官方下载页面.

……

Continue reading

在Proxmox中固定网卡名字

给 nas 加了块 sn640, 结果重启后上不了网了.
检查了下发现网卡名字变了, 从 enp6s0 变成 enp7s0.
根据新的名字修改/etc/network/interfaces后重启就正常了.
为了防止以后加盘再次失联(毕竟AIO, 断网还是很烦的), 查了下给网卡固定名字的办法.

默认命名规则

systemd自v197引入的一种网卡命名方式, 详见PredictableNetworkInterfaceNames
网卡名字改变,是由于添加新PCIe设备导致网卡的总线号发生了变化.

……

Continue reading

使用nginx访问apcupsd

一直用apcupsd管理ups, 因为本来就要使用nginx, 所以想把默认用的apache换成nginx.
查了下, 用fcgiwrap 就行了, 记录下修改过程.

  • 安装软件包

    apt install -y apcupsd apcupsd-cgi fcgiwrap nginx
    
  • 修改配置文件
    修改/etc/apcupsd/apccontrol 使用自定义关机脚本

    SHUTDOWN=/root/bin/poweroff
    

    修改/etc/apcupsd/apccontrol 使用USB连接, 设定SHUTDOWN时间

    UPSTYPE usb
    DEVICE
    MINUTES 5
    

    修改/etc/nginx/sites-enabled/default 加入apcupsd相关配置.

    location ~ cgi-bin/apcupsd/.*\.cgi$ {
        fastcgi_param       SCRIPT_FILENAME     /usr/lib$fastcgi_script_name;
        fastcgi_pass        unix:/var/run/fcgiwrap.socket;
        include             fastcgi_params;
    }
    
  • 重启服务

    service apcupsd restart
    service fcgiwrap restart
    service nginx restart
    
  • 现在可以通过127.0.0.1/cgi-bin/apcupsd/multimon.cgi 查看ups 状态了.

……

Continue reading

Proxmox 配置外部SMTP发送邮件

proxmox 自带的邮件服务虽然也能发, 不过经常进QQ的垃圾箱.
想想还是配置成QQ的SMTP好了, 稳定点, 别警告邮件都收不到.

安装依赖

apt install -y libsasl2-modules

删除以前配置的aliases

sed '/root:.*/d' /etc/aliases -i

mailname

echo "pve.local" > /etc/mailname
echo "[email protected] [email protected]" > /etc/postfix/generic

配置SMTP服务器, 账号:密码

echo "smtp.qq.com [email protected]:password" > /etc/postfix/sasl_passwd

创建数据库, 设置权限

postmap /etc/postfix/sasl_passwd
postmap /etc/postfix/generic
chmod 0600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db

修改配置文件

$ vim /etc/postfix/main.cf, 在结尾加上配置

relayhost = smtp.qq.com:465
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sender_dependent_authentication = yes
smtp_generic_maps = hash:/etc/postfix/generic
smtp_use_tls = yes
smtp_tls_wrappermode = yes
smtp_tls_security_level = encrypt
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt

重启服务

service postfix restart

测试

echo "test mail" | mail -s "proxmox" [email protected]
……

Continue reading

通过debootstrap在btrfs raid1上安装debian

最近想试试将 debian 安装在 btrfs raid1 上.
用安装盘安装, 直接安装在 btrfs raid1上, 会在安装 grub 的时候出错.
使用单盘 btrfs 安装完后, 再加另一个盘组 raid1 倒是可以.
就是以后如果重装, 又要的拆成单盘再重装, 很麻烦.
试了下 debootstrap 安装debian, 直接就能安装在 btrfs raid1 上, 记录下安装过程.

初始化live cd 环境

启动 debian live cd
sudo su -
sed 's/deb.debian.org/mirrors.huaweicloud.com/' /etc/apt/sources.list -i
apt update
# 装openssh-server 后可以通过别的电脑连接这台跑安装, 方便复制粘贴.
# 用户名: user 密码: live
apt install -y debootstrap openssh-server

硬盘分区 建立 btrfs raid1

#新建分区表
sgdisk /dev/sda -o
#第一个分区留给bios引导用, 使用bios+gpt方式, 设置legacy_boot flag
#如果使用uefi+gpt方式, 第一个分区留512M, 分区type code用ef00
#第二个分区swap
#第三个分区btrfs

#bios
sgdisk /dev/sda -n 0:2048:+1M -t 0:ef02 -A 1:set:2
#uefi
sgdisk /dev/sda -n 0:2048:+512M -t 0:ef00
mkfs.fat -F 32 /dev/sda1

sgdisk /dev/sda -n 0:0:+8G -t 0:8200
sgdisk /dev/sda -n 0:0:0 -t 0:8300

#swap
mkswap /dev/sda2

#复制分区表
sgdisk -R /dev/sdb /dev/sda

#让分区UUID一样
dd if=/dev/sda1 of=/dev/sdb1
dd if=/dev/sda2 of=/dev/sdb2

btrfs raid1, subvolume

#建立 raid 1, 挂载到 /mnt
mkfs.btrfs -f -m raid1 -d raid1 /dev/sda3 /dev/sdb3
mount -t btrfs /dev/sda3 /mnt

#新建subvolume, 2个 subvolume 给 / 和 /home 用
btrfs sub create /mnt/@
btrfs sub create /mnt/@home

#挂载 @ 用于安装系统
umount /mnt
mount -t btrfs -o subvol=@ /dev/sda3 /mnt

debootstrap 安装基本系统

debootstrap --arch amd64 buster /mnt https://mirrors.huaweicloud.com/debian

chroot

mount -t proc /proc /mnt/proc/
mount -t sysfs /sys /mnt/sys/
mount -t devpts /dev/pts /mnt/dev/pts
mount -o bind /dev /mnt/dev/
chroot /mnt /bin/bash

fstab

UUID 可以通过 blkid 查看.

vi /etc/fstab

UUID=xxxx /      btrfs defaults,subvol=@       0 0
UUID=xxxx /home  btrfs defaults,subvol=@home   0 0
UUID=xxxx /rpool btrfs defaults,subvol=/       0 0
UUID=xxxx none   swap  rw                      0 0

配置 apt sources

vi /etc/apt/sources.list

deb https://mirrors.huaweicloud.com/debian/ buster main contrib non-free
deb https://mirrors.huaweicloud.com/debian/ buster-updates main contrib non-free
deb https://mirrors.huaweicloud.com/debian-security/ buster/updates main contrib non-free
deb https://mirrors.huaweicloud.com/debian/ buster-backports main contrib non-free

apt update

系统配置

apt install -y locales
dpkg-reconfigure locales tzdata

apt install -y fonts-wqy-microhei btrfs-progs openssh-server sudo

#新建用户
useradd -m -G sudo user
#修改密码
passwd user

#安装kernel, 驱动
apt install -y linux-image-amd64 firmware-linux

#网卡驱动
#firmware-realtek

#network
vi /etc/network/interfaces
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp

vi /etc/resolv.conf
nameserver 114.114.114.114

#安装标准工具
tasksel install standard

GRUB

#bios
apt install -y grub2
update-grub
grub-install /dev/sda
grub-install /dev/sdb

#uefi
apt install -y grub-efi
update-grub
mkdir /boot/efi
mount -t vfat /dev/sda1 /boot/efi
grub-install --efi-dir=/boot/efi
dd if=/dev/sda1 of=/dev/sdb1

#rootflags 加上 degraded, 在丢盘的时候也能正常开机
vi /etc/grub.d/10_linux
rootflags=degraded,subvol=...

#grub 安装失败问题:
# grub-install: warning: Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet..
# grub-install: error: filesystem `btrfs' does not support blocklists.
用 wipefs -o 0x10040 /dev/sdx 命令来擦掉 BTRFS superblock
……

Continue reading

Proxmox VE 6 常用设置

安装

使用rufus dd模式烧到U盘做引导盘

关闭 lvm-thin (用起来还是不习惯)

mkdir -p /mnt/data
umount -l /mnt/data
lvremove -y /dev/pve/data
lvcreate -l $(vgdisplay pve | grep Free | awk '{ print $5 }') -n data pve
mkfs.xfs -f /dev/pve/data
sed '/\/dev\/pve\/data/d' /etc/fstab -i
echo "/dev/pve/data /mnt/data xfs defaults 0 0" >> /etc/fstab
mount -a

还原 lvm-thin

umount -l /mnt/data
lvremove /dev/pve/data
lvcreate -l 1 -n data pve
lvconvert --type thin-pool pve/data
lvextend -l +99%FREE pve/data     #pve默认分区最后没有使用全部空间, 这里也留了1%

关闭订阅提醒

vim /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
搜索 if (data.status !== 'Active')
修改为 if (false)

配置源

rm -f /etc/apt/sources.list.d/pve-enterprise.list

echo "deb http://download.proxmox.com/debian/pve buster pve-no-subscription" >> /etc/apt/sources.list

开启硬件直通

sed -E 's/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on"/' /etc/default/grub -i
{
    echo "vfio"
    echo "vfio_iommu_type1"
    echo "vfio_pci"
    echo "vfio_virqfd"
} | tee /etc/modules
update-grub

硬盘直通

ls -l /dev/disk/by-id
qm set 101 -scsi3 /dev/disk/by-id/harddisk-id

查看 mce 错误

ras-mc-ctl --errors

按电源键不关机(防止误触)

sed -E 's/.*HandlePowerKey.*/HandlePowerKey=ignore/' /etc/systemd/logind.conf -i

爱快

安装要使用vmware兼容显卡
爱快不支持pve的关机指令, 关机重启会卡很久, 可以先在pve里面运行reboot, 然后在爱快web里面选关机.

Proxmox Web界面显示CPU温度

  1. 读取CPU温度

    apt install lm-sensors
    sensors-detect
    sensors
    
  2. 显示CPU温度

    vim /usr/share/perl5/PVE/API2/Nodes.pm
    在 PVE::pvecfg::version_text(); 后面加入
    $res->{thermalstate} = `sensors`;
    
  3. 定期读取sensors

    vim /usr/share/pve-manager/js/pvemanagerlib.js
    在 PVE Manager Version 后面加一个item:
    {
        itemId: 'thermal',
        colspan: 2,
        printBar: false,
        title: gettext('CPU Thermal State'),
        textField: 'thermalstate',
        renderer:function(value){
            const c0 = value.match(/Core 0.*?\+([\d\.]+)?/)[1];
            const c1 = value.match(/Core 1.*?\+([\d\.]+)?/)[1];
            return `Core 0: ${c0} ℃ | Core 1: ${c1} ℃ `;
        }
    }
    
  4. 重启Web管理服务

    systemctl restart pveproxy
    
……

Continue reading

[转]Windows命令行下用netsh实现端口转发(端口映射)

微软Windows的netsh是一个命令行脚本实用工具。使用netsh工具 ,可以查看或更改本地计算机或远程计算机的网络配置。不仅可以在本地计算机上运行这些命令,而且可以在网络上的远程计算机上运行。

可以手动运行Netsh命令,或创建批处理文件或脚本实现过程的自动化。netsh提供了脚本功能,让您在批处理模式下针对指定的计算机,运行一组命令。利用netsh ,可以将配置脚本保存为文本文件,便于存档或用于配置其他的计算机。

……

Continue reading

解决 Docker 持久化数据的权限问题

Docker的数据持久化即数据不随着 container 的结束而结束, 数据存在于 host 机器上: 存在于 host 的某个指定目录中(使用-v 或者--mount), 或者 docker 自己管理的 volume (Dockerfile 里面设置VOLUME, 目录在/var/lib/docker/volumes).

实际使用的时候, 会碰到文件权限的问题:

容器向挂载的目录写入数据后, host 没有权限访问这些数据, 因为容器默认是使用 root 用户运行的(对应 host 的 root 用户).

……

Continue reading

Go交叉编译CGO提示undefined

在linux下面交叉编译windows版本的sciter的代码, 提示一堆未定义变量
编译linux版本的就没问题

$go build .
$CC=x86_64-w64-mingw32-gcc GOOS=windows go build .
# github.com/sciter-sdk/go-sciter
../../github.com/sciter-sdk/go-sciter/types_string.go:27:9: undefined: BehaviorEvent
../../github.com/sciter-sdk/go-sciter/types_string.go:62:9: undefined: MouseEvent
../../github.com/sciter-sdk/go-sciter/types_string.go:78:9: undefined: CursorType
../../github.com/sciter-sdk/go-sciter/types_string.go:89:9: undefined: KeyEvent
../../github.com/sciter-sdk/go-sciter/types_string.go:100:9: undefined: FocusEvent
../../github.com/sciter-sdk/go-sciter/types_string.go:111:9: undefined: ScrollEvent
../../github.com/sciter-sdk/go-sciter/types_string.go:122:9: undefined: GestureCmd
../../github.com/sciter-sdk/go-sciter/types_string.go:139:9: undefined: GestureState
../../github.com/sciter-sdk/go-sciter/types_string.go:171:9: undefined: GestureTypeFlag
../../github.com/sciter-sdk/go-sciter/types_string.go:197:9: undefined: DrawEvent
../../github.com/sciter-sdk/go-sciter/types_string.go:197:9: too many errors

查了半天, 发现是CGO_ENABLED的锅, 交叉编译的时候, 这个选项默认为0了, 手动设了后编译通过.

CC=x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows go build .
……

Continue reading

用scoop代替chocolatey做Windows包管理器

原来一直用chocolatey做包管理器, 最近发现了一个scoop, 试了几天, 可以换掉chocolatey了.

chocolatey VS scoop

  • chocolatey权限要求高, scoop 使用-g安装才需要管理员权限, 默认普通用户权限.
  • scoop可以建软件包仓库, 如果官方仓库里没有想用的软件, 可以自己建一个仓库, 存放自己的软件.
  • chocolatey很多软件安装位置不固定, 会污染Path

scoop 安装

  • 设置powershell

    set-executionpolicy remotesigned -s currentuser
    
  • 默认安装(安装到C:\Users\<user>\scoop), 在powershell里面运行:

    Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
    
  • 安装到指定目录(D:\tool\scoop)

    $env:SCOOP='D:\tool\scoop'
    [Environment]::SetEnvironmentVariable('SCOOP', $env:SCOOP, 'User')
    Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
    
  • 指定-g安装目录(D:\tool\scoop_global)

    $env:SCOOP_GLOBAL='D:\tool\scoop\scoop_global'
    [environment]::setEnvironmentVariable('SCOOP_GLOBAL',$env:SCOOP_GLOBAL,'Machine')
    
……

Continue reading