0%

从零开始

手里有台八重州FT-8900R,是当年对业余无线电近乎一无所知时购买的第一步电台。官方手册上说其背部的Data Port可以搭配TNC实现Packet Radio功能。由此,很自然产生了几个疑问:

  1. 何为封包无线电
    可以参考业余无线分包通信DIYPacket-Radio-ModulationIntroduction to Packet RadioPacket Radio以及Packet Radio几篇文章。封包无线电的概念无需赘述,这里只需要明确一点:普通的FM收发机即可使用NFM模式,在UHF/VHF频段以1200或2400bps速率进行封包无线电操作。

  2. FM收发机支持哪些玩法
    身边的ham圈里大家不是在玩短波就是数字+MMDVM,FM少有人涉足。刚刚通读了《业余无线电通信(第四版)》的小白可能会对语音以外的诸多通信模式跃跃欲试,不过在购买设备前最好先弄明白模式与频段对于一台收发机的意义。频段很直观,一部仅支持U/V两端的手台,当然不支持收发5MHz的短波。另一方面,电台即便支持某一频段,也未必支持特定模式。FM收发机价格便宜,不过只支持频率调制,即Frequency Modulation的字面含义,没有办法进行CW、PSK31等操作。具体可以参考2m or 70cm FM mobile radio for digital mode operationPSK and FSK over NBFM。举个例子,FM收发机连接电脑可以用类似cw player软件在439.500MHz“发电报”,在其他电台里守听可以听到滴滴哒哒的摩斯码声音,不过这和真正的全模式电台在439.500MHz进行CW操作存在本质区别,其核心就是电台调制解调方式。CW最大带宽不超过150Hz,NFM则要占用3KHz,是CW的20倍,遑论能效比的差距。

所以总结下来,FM收发机除了语音通联/中继,貌似只有封包无线电一路可走。

  1. TNC是什么
    TNC,Terminal Node Controller,中文翻译终端节点控制器。淘宝搜索零条匹配 …… 请教了群里大佬,大佬在指出封包无线电与TNC是上世纪遗产之余,推荐了名为专用电台连接器的东西。到手后主体就是个小盒子,盒子反面具备CATDATACW接口(对于FT-8900R只能用上DATA),正面具备SPMICUSB口,显然这3个都需要连接电脑。简单测试下来,可以实现用电脑控制收发信息,自动录音等操作。

至于这个所谓的专用电台连接器,卖家没有提供原理图,不过国外ham显然也折腾过类似东西:UD04YA USB Data Mode Cable - PDF4PRO。结合八重州电台DATA针脚定义来看,电台输入输出音频信号直连电脑,PTT通过虚拟COM口和电脑连接实现控制。所以专用电台连接器并不是TNC,是字面意义上的连接器。过去硬件TNC的大部分功能,如今已经在电脑上软件实现了。

软件包选择

概述

参考Packet Radio,作者介绍了MixWFlexnet32AWGPE。对于前两者作者给予了积极评价。至于AWGPE,作者评价其“不稳定”“不值得花钱”,不过AWGPE在国内较前两者知名度更高一些,可以自行评估判断。

除了上面3个Windows专有软件,跨平台的soundmodem值得一提。在Debian衍生系统中,可以用apt命令直接安装,最新版为0.2,更新于2000年8月1日……如果发行版软件仓库里没有,那就只能自行编译。经过一番考古找到了0.2版本的源码:

https://github.com/yu4zed/soundmodem-backup

备用下载地址:

  1. https://archive.org/details/soundmodem-0.20
  2. https://archive.org/download/soundmodem-0.20/soundmodem-0.20.tar.gz
  3. http://archive.ubuntu.com/ubuntu/pool/universe/s/soundmodem/soundmodem_0.20.orig.tar.gz

源码包下载下来解压缩,进入目录执行./configure,根据提示查缺补漏。我的Deepin编译环境比较全,所以只额外安装了libgtk2.0-0libaudiofile-dev。configure没问题执行make CXXFLAGS+=" -fpermissive",然后sudo make install即可。

除了man页面,对soundmodem的介绍还可以参考Multiplatform Soundcard Packet Radio Modem,页面上同时给出了Windows安装包。不过都是老古董,即便不能正常运行也不要过于失望。

AGWPE

本部分主要参考自Download and Install AGWPE

下载

下载页面: https://www.sv2agw.com/downloads/default.htm

作者的许可比较宽松,Pro版于2020年1月6日更新,以Shareware许可分发,试用期30天。按页面上对Shareware的定义,应该是试用期后也可继续使用,售价约合人民币320元。不想掏钱又不愿意试用的可以下载2013年4月15日发布的旧版,这个作者宣布ham可以永久免费使用。而且旧版支持从Win95到Win10的Windows系统,捡一台瘦主机或者上网本搭建平台也很合适。

安装

下载下来的压缩包绿色免安装直接运行。注意不要把程序文件夹放到C:\Program Files即可,否则权限问题会导致配置文件写入失败。

程序入口为AGW Packet Engine.exe,建议在桌面新建快捷方式。

配置

以一个声卡,一部电台为例配置。

注意声卡的选择。一般而言,连接主板音频插口,然后软件里选择主板声卡即可。类似无线耳机、显示器等都不要选。

(未完待续)

MixW

(未完待续)

提要

终于,折腾电视盒子告一段落了。想要的功能已经实现,于是回头继续学习无线电。前些年考取了业余无线电A证,买了八重州车台和ICOM手台,不过一直没深入,呼号也是拖到今年才办下来。考虑到当前形势,又入手了2部宝峰UV-5R。我买的是一代,2800mah电池版才90多块,上手感觉还不错,以ICOM手台5%的价格实现了80%以上功能,通过验机也没问题,深受海内外hammer欢迎,配件便宜资料齐全,是入门hammer的好伙伴。以UV-5R为工具,我们来探究下亚音。

亚音

CTCSS

CTCSS (Continuous Tone Controlled Squelch System) ,模拟亚音。
UV-5R可以使用如下模拟亚音:

DCS

DCS(DigitalCoded Squelch),数字亚音。
UV-5R可以使用如下数字亚音:

实际上在设置中你会发现,每个亚音有N和I两种,以023为例,有D023N和D023I两种,这是怎么回事呢?

字面含义,N是正码(normal),I是反码(inverted),两者选用的原则又是什么呢?

经过一番搜索,在D023N/D0231找到了答案。信号经过单相放大电路时(原文single stage amplifier circuit,不知这样翻译是否妥当),信号相位会翻转180°,在这种情况下,需要用反码。中文以放大器 相位反转为关键词搜索,可以找到许多解释及解决办法。

另外需要澄清,反码一般上不作为DCS的拓展,简单的例子,D413N与D054I是一模一样的,并不是说用了反码DCS范围就拓展到原来的2倍。

应用场景

亚音的运用可以屏蔽干扰。比如在繁忙的信道,通过约定接收亚音与发射亚音,不符合条件的信号得以过滤。需要特别指出,亚音本身并非加密手段,对于未设置接收亚音的收听者,无论信号有无亚音,被如何设置,他都可以接受到。

简介

LAMPLNMP许多人不会陌生。L代表Linux,P代表PHP,M以前指代MySQL,如今换成了MariaDB,用法大体相同。至于server本身也有很多选择。Apache和Nginx之外,Caddy现在也很流行,具备反代和自动获取证书等许多实用功能。本文介绍搭建LCMP以及安装WordPress过程,希望对潜在的读者有所帮助。

硬件平台

还是 R3300-M 盒子哈哈,4核2GHz加上1G内存配置足够了,TF卡选择三星128G,IO性能不是瓶颈。

网络环境

我有公网IPv6地址,使用 cloudflare 做AAAA记录,本地运行NewFuture DDNS自动更新IP地址。为了隐藏真实IP + 提供IPv4接入,cloudflare那边请打开Proxy。

Linux

系统

使用 Manjaro ARM 21.10 minimal vim2 镜像。为了关机重启正常请使用vim内核。emmc安卓底包为ATV,可提升CPU频率至2016MHz,约提升19%性能。刷机、换国内软件源、换内核等可参考本人之前的文章。

清理无用软件包

sudo pacman -Rsu ap6398s-firmware kvim1-firmware kvim2-firmware

R3300-M不具备相应硬件,故其驱动可以卸载。

禁用SWAP

sudo systemctl stop zswap-arm.service
sudo systemctl disable zswap-arm.service

1G内存专门用来搭建环境运行WordPress足够了。Manjaro ARM中SWAP服务由 zswap-arm 这个包提供,如有洁癖也可以直接卸载。

安装配置networkmanager

sudo pacman -S networkmanager
sudo systemctl enable --now NetworkManager
sudo systemctl stop dhcpcd.service
sudo systemctl disable dhcpcd.service
sudo systemctl restart NetworkManager

注意一定要禁用掉 dhcpcd 服务,否则 NetworkManager 无法获取到IP地址。

为什么要安装networkmanager呢?因为盒子的有线网卡mac地址每次开机都变化,所以DHCP获取到的IP地址也变来变去。我知悉的唯一有效解决办法是使用nmtui提供的mac-address-clone功能固定mac地址,而 nmtuinetworkmanager 提供。

mariadb

安装

sudo pacman -S mariadb
sudo mariadb-install-db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
sudo systemctl enable --now mysql.service

然后执行设置密码等步骤。网上的许多教程在执行这一步前没有打开 mysql.service ,所以此步骤会失败。

sudo mysql_secure_installation

至此mariadb安装完成,稍后将进行新建数据库、新建用户操作。

配置

首先登录到数据库:

mysql -u root -p

然后新建一个名为 wordpress 的数据库,字符集为 utf8mb4 ;新建一个名为 wp 的用户,密码为”password”(你需要自行替换密码),赋予这个用户全部权限:

CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL ON wordpress.* TO 'wp'@'localhost' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
EXIT;

至此数据库配置完成。

PHP

安装

sudo pacman -S php php-fpm php-gd
sudo systemctl enable --now php-fpm

配置

编辑 /etc/php/php.ini ,启用以下扩展(删掉行首的注释即可):

extension=bz2
extension=curl
extension=gd
extension=mysqli
extension=pdo_mysql
extension=zip

为了方便使用,对部分参数进行修改:

memory_limit=256M
post_max_size=100M
upload_max_file_size=100M

编辑 /etc/php/php-fpm.d/www.conf 文件,使其以caddy身份运行:

user = http
group = http

修改为

user = caddy
group = caddy

如果不改成caddy,过一会儿试图安装WordPress时caddy会报502错误。

重新加载

sudo systemctl restart php-fpm

WordPress

下载

将WordPress下载到当前用户家目录:

cd ~/
curl -O https://wordpress.org/latest.tar.gz

移动到 /srv/http 目录下并解压缩:

sudo mv ~/latest.tar.gz /srv/http
cd /srv/http
sudo tar -zxvf latest.tar.gz

然后在 /srv/http 会出现 wordpress 文件夹。

早年用过 centos 等Linux发行版的人可能对 /srv/http 不是很熟悉,在Manjaro(或者称其为Archlinux更贴切)中网站目录一般放在这里。当然放在哪里都行,只要在Caddy配置文件中定义明白即可,放在这里只是遵循了Archlinux关于文件目录的设计理念。

完成后,开始调配Caddy。

Caddy

安装

sudo pacman -S caddy

配置

domain.com {
    # 指向wordpress位置
    root * /srv/http/wordpress
    encode zstd gzip
    file_server

    @cache {
        not header_regexp Cookie "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in"
        not path_regexp "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(index)?.xml|[a-z0-9-]+-sitemap([0-9]+)?.xml)"
        not method POST
        not expression {query} != ''
    }

    route @cache {
        try_files /wp-content/cache/cache-enabler/{host}{uri}/https-index.html /wp-content/cache/cache-enabler/{host}{uri}/index.html {path} {path}/index.php?{query}
    }
       
    # Change the path here according to your server
    php_fastcgi unix//run/php-fpm/php-fpm.sock
}

这个配置是从Example: configure WordPress with a static cache略微修改来的,你如果同样使用Manjaro ARM,那么只需要用自己的域名替换就行了。

/etc/caddy 目录中,将默认的Caddyfile复制一份并改名为Caddyfile.ori,然后清空Caddyfile,把自己的配置粘贴进去保存即可。

修改wp-content权限

sudo chown -R caddy:caddy /srv/http/wordpress/wp-content/

这步的操作目的是将 wp-content 目录用户和组修改为caddy。刚才解压后得到的wordpress目录中,所有文件用户和组均为 nobody ,权限大部分为644,故caddy只有可读权限,无法写入,在后续安装使用(比如安装插件)中会产生许多麻烦。网上流传的所谓sudo chmod -R 755甚至sudo chmod -R 777方法不要用,因其对linux权限系统的破坏是不可逆的。用户与组至少随时可以改回来。严格来说 wp-content 用户与组修改为 caddy 也不安全,不过在只运行一个网站的情况下,安全性应该还行?

启动

sudo systemctl enable --now caddy
sudo systemctl restart caddy

不出意外,此时访问自己的域名会看到wordpress初始化向导。

性能表现

全套搭建完毕网站上线运行的情况下,系统负载约0.03,约使用277MB内存,非常轻松。

参考

排名不分前后:

  1. Example: configure WordPress with a static cache
  2. 在 Arch Linux 中安装 WordPress
  3. PicUploader使用系列(一)——在Archlinux上使用Caddy部署PicUploader
  4. 在 ArchLinux 下利用Caddy PHP-FPM MariaDB 迅速搭建 WordPress 博客
  5. NewFuture DDNS
  6. Can’t change language (only “English (United States)”)

推荐阅读

  1. 最简明扼要的 Systemd 教程,只需十分钟
  2. Systemd 入门教程:命令篇

几例应用

关闭swap

swap的使用一直存在争议,为了延长TF卡使用寿命,将其关掉。内存如果不够用,关掉一些服务就行了。毕竟不能指望一台1G内存的电视盒子面面俱到。
临时关闭:

$ sudo swapoff -a

永久关闭:

$ sudo systemctl stop zswap-arm.service
$ sudo systemctl disable zswap-arm.service

修改hostname

$ sudo hostnamectl set-hostname manjaro-arm

也可以使用nmtui修改,不过hostnamectlsystemd提供的工具,更底层、更直接。大部分现代Linux发行版都使用systemd。

定时任务

systemd可以编写timer,作为cronat的上位替代。类似Manjaro ARM等发行版已经取消了cron的预装。

以DDNS为例:

[Unit]
Description=NewFuture ddns
Requires=network-online.target

[Service]
Type=simple
WorkingDirectory=/usr/share/DDNS
ExecStart=/usr/bin/env python /usr/share/DDNS/run.py -c /etc/DDNS/config.json

[Install]
WantedBy=multi-user.target
[Unit]
Description=NewFuture ddns timer
Requires=network-online.target

[Timer]
OnBootSec=1m
OnUnitActiveSec=5m
Unit=ddns.service

[Install]
WantedBy=multi-user.target

运行环境

某S905机顶盒 + TF卡 + Manjaro ARM 21.10

示例说明

假设我们有一个marly.com的域名,且已经使用cloudflare进行解析。在家里的电视盒子上运行了一个http服务:http://localhost:3000,登录linux系统的用户为marly,我们想在外网通过https://world.marly.com访问这个服务,还要有正规证书。通过Cloudflare Tunnel可以方便实现。

如果有公网IP,上通过端口转发 + 调用API自动更新A记录 + Let's Encrypt也可以实现。

  1. 端口转发。本地路由器配置。
  2. 调用API自动更新A记录。GitHub上找到一个看起来不错的项目:NewFuture DDNS。支持DNSPOD,阿里 DNS,DNS.COM,DNSPOD 国际版,CloudFlare,HE.net(不支持自动创建记录),华为云。
  3. 签发Let's Encrypt证书 + 续期。使用ACME即可。

此外还发现ehang-io/nps,不过没完整折腾过。

安装cloudflared

可以直接下载官方预编译的二进制执行文件或者安装包,地址 https://github.com/cloudflare/cloudflared/releases/ ,或者使用yay根据当前最新源码编译安装:

$ yay -s 

如果半天没进度,请检查网络状况。

使用yay安装的cloudflared包含三部分:

/usr/bin/cloudflared /etc/cloudflared /usr/share/man/man1/cloudflared.1.gz

日志文件为/var/log/cloudflared.log,默认文件权限640。cloudflared以普通用户权限运行所以没法读写这个日志文件,可以手动把它改成666:

$ sudo chmod 666 /var/log/cloudflared.log

登录授权

$ cloudflared tunnel login

复制终端上的网址,在浏览器中打开,选择marly.com。认证完成后,cloudflared会生成~/.cloudflared/cert.pem

tunnel创建

$ cloudflared tunnel create hello

上述命令产生如下后果:

  • 根据提供的name,cloudflared会生成一个UUID,与name唯一对应;
  • ~/.cloudflared/中,cloudflared会生成.json文件;

最后使用$ cloudflared tunnel list查看tunnel是否创建成功。

DNS记录生成

连接到应用

$ cloudflared tunnel route dns hello world.marly.com

此步骤在cloudflare后台创建了world.marly.com的CNAME。

连接到网络

$ cloudflared tunnel route ip add <IP/CIDR> <UUID or NAME>

可以使用

$ cloudflared tunnel route ip show

查看是否路由成功。

配置文件创建

cloudflared的配置文件为config.yml,遵循Linux传统,全局文件路径/etc/cloudflared/config.yml,用户文件路径~/.cloudflared/config.yml

全局文件默认内容:

---
logfile: /var/log/cloudflared.log
proxy-dns: true
proxy-dns-address: 127.0.0.1
proxy-dns-port: 5300
proxy-dns-upstream:
        - https://1.1.1.1/dns-query
        - https://1.0.0.1/dns-query

~/.cloudflared/中,创建config.yml文件:

连接到应用

url: http://localhost:8000
tunnel:
credentials-file: /root/.cloudflared/.json

根据自身情况修改,比如应用端口,UUID,以及credentials-file位置。

连接到网络

tunnel:
credentials-file: /root/.cloudflared/.json

tunnel运行

$ cloudflared tunnel run <UUID or NAME>

如果存在多个配置文件(比如同时运行了多条tunnel),建议通过--config指定路径:

$ cloudflared tunnel --config path/config.yaml run

最好使用绝对路径。

检查tunnel状况

列出所有

$ cloudflared tunnel list

检查单个

$ cloudflared tunnel info <UUID or NAME>

运行

调试

cloudflared tunnel run --url http://localhost:3000 hello

作为服务运行

首先准备好config.yml文件:

tunnel: hello
credentials-file: /home/marly/.cloudflared/fe63bc80-7123-65a4-e516-e125b06f0a12.json

ingress:
  - hostname: world.marly.com
    service: http://localhost:3000
  - service: http_status:404

然后将该文件移动到/etc/cloudflare目录下,原有的文件提前改名或删除。

安装服务:sudo cloudflared service install 。cloudflare文档说明此步骤会自动将~/.cloudflared/config.yml复制到/etc/cloudflared中,但实际测试找不到配置文件,故手动复制。

启动服务:

sudo systemctl enable cloudflared
sudo systemctl start cloudflared

前言

Rocket.Chat是一个开源,可定制的交流平台,支持docker和snap。本文介绍在Manjaro ARM的安装方式。

安装

首先安装snap:

sudo pacman -Sy snapd
sudo snap install rocketchat-server

然后在浏览器中,访问服务器的3000端口就行了。注意3000端口常用(比如mdbook就会默认占用),注意不要冲突。

完成安装后,系统会自动配置好相应服务,默认开机启动,不需要额外配置:

systemctl status snap.rocketchat-server.rocketchat-server.service
● snap.rocketchat-server.rocketchat-server.service - Service for snap application rocketchat-server.rocketchat-server
     Loaded: loaded (/etc/systemd/system/snap.rocketchat-server.rocketchat-server.service; enabled; vendor preset: disabled)
     Active: active (running) since Thu 2021-10-28 15:41:03 CST; 2min 58s ago
   Main PID: 443 (startRocketChat)
      Tasks: 25 (limit: 664)
     Memory: 544.6M
        CPU: 2min 10.298s
     CGroup: /system.slice/snap.rocketchat-server.rocketchat-server.service
             ├─ 443 /bin/bash /snap/rocketchat-server/1460/bin/startRocketChat
             └─1140 node /snap/rocketchat-server/1460/main.js

Oct 28 15:43:41 marly-aml rocketchat-server.rocketchat-server[1140]: ➔ |      MongoDB Version: 3.6.21            |
Oct 28 15:43:41 marly-aml rocketchat-server.rocketchat-server[1140]: ➔ |       MongoDB Engine: wiredTiger        |
Oct 28 15:43:41 marly-aml rocketchat-server.rocketchat-server[1140]: ➔ |             Platform: linux             |
Oct 28 15:43:41 marly-aml rocketchat-server.rocketchat-server[1140]: ➔ |         Process Port: 3000              |
Oct 28 15:43:41 marly-aml rocketchat-server.rocketchat-server[1140]: ➔ |             Site URL: http://localhost  |
Oct 28 15:43:41 marly-aml rocketchat-server.rocketchat-server[1140]: ➔ |     ReplicaSet OpLog: Enabled           |
Oct 28 15:43:41 marly-aml rocketchat-server.rocketchat-server[1140]: ➔ |          Commit Hash: 5e9f4bc424        |
Oct 28 15:43:41 marly-aml rocketchat-server.rocketchat-server[1140]: ➔ |        Commit Branch: HEAD              |
Oct 28 15:43:41 marly-aml rocketchat-server.rocketchat-server[1140]: ➔ |                                         |
Oct 28 15:43:41 marly-aml rocketchat-server.rocketchat-server[1140]: ➔ +-----------------------------------------+

服务启动比较慢,如果systemctl status snap.rocketchat-server.rocketchat-server.service提示ERROR: ld.so: object '/usr/lib/libgtk3-nocsd.so.0' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.,等待3分钟即可。

性能

参考官方文档,4核1G内存的树莓派2或者3配合32G存储卡,能够满足大约50个用户同时使用。对于S905盒子而言毫无压力。

前言

2021年9月15日,人民银行、网信办、最高人民法院、最高人民检察院、工业和信息化部、公安部、市场监管总局、银保监会、证监会、外汇局联合印发《关于进一步防范和处置虚拟货币交易炒作风险的通知》(银发〔2021〕237号),明确虚拟货币相关业务活动属于非法金融活动。不过掌握虚拟货币的基本概念,以及对其工具具备认知仍具备正面意义。本文介绍了在Manjaro ARM平台运行hummingbot过程,仅供学习用途。

在Docker中运行

下载一键脚本

wget https://raw.githubusercontent.com/CoinAlpha/hummingbot/development/installation/docker-commands/create.sh
wget https://raw.githubusercontent.com/CoinAlpha/hummingbot/development/installation/docker-commands/start.sh
wget https://raw.githubusercontent.com/CoinAlpha/hummingbot/development/installation/docker-commands/update.sh

给脚本添加可执行权限

chmod a+x *.sh

创建hummingbot实例

./create.sh

第一步提示hummingbot镜像版本,对于ARM平台当然需要使用ARM标签。hummingbot更新比较频繁,可以到 https://hub.docker.com/r/coinalpha/hummingbot/tags 查看。

常用docker命令

列出container:docker container ps

查看container实时状态:dockerc container stats

启动container:docker start hummingbot-instance

连接到container:docker attatch hummingbot-instance

断开container:Ctrl + P 然后 Ctrl + Q (container在后台继续运行)

至成稿时,最新版本为version-0.43.1-arm_beta

小结

刚创建的hummingbot-instance约占用374MB内存以及不低于20%的CPU,CPU有时还会满载,1G内存的S905盒子跑起来略吃力。如果用Manjaro ARM Minimal搭建最小化运行环境可能会略微改善。笔者没有交易所账号,没有进行更深入测试。

源码安装

源码安装比较麻烦,不过可以实现:

源码拉取

https://github.com/coinalpha/hummingbot

python包安装

官方在树莓派上的教程有些过时了。杂糅下教程中引用的和setup/requirements-arm.txt包,共需要这些依赖:

0x-contract-wrappers 0x-order-utils aioconsole aiohttp aiokafka aioresponses attrdict binance cachetools coverage cython diff-cover eth_account eth_bloom ethsnarks-loopring flake8 idna-ssl jwt mypy_extensions nose numpy objgraph pandas pre-commit prompt_toolkit psutil pyinstall pyjwt pyperclip python-binance python-telegram-bot rsa ruamel.yaml signalr-client-aio simplejson sqlalchemy telegram tzlocal ujson web3 websockets

解决粘贴问题,再加上QtPy

另外值得指出,hummingbot依赖sqlalchemy提供的RowProxy。但是在sqlalchemy1.4中,RowProxy被移除了,所以这个包需要用旧版本。

pip官方源在国内下载很慢,故使用-i选项指定清华镜像。

pip install 0x-contract-wrappers 0x-order-utils aioconsole aiohttp aiokafka aioresponses attrdict binance cachetools coverage cython diff-cover eth_account eth_bloom ethsnarks-loopring flake8 idna-ssl jwt mypy_extensions nose numpy objgraph pandas pre-commit prompt_toolkit psutil pyinstall pyjwt pyperclip python-binance python-telegram-bot rsa ruamel.yaml signalr-client-aio simplejson sqlalchemy telegram tzlocal ujson web3 websockets QtPy -i https://pypi.tuna.tsinghua.edu.cn/simple

pip install --user SQLAlchemy==1.3.6  -i https://pypi.tuna.tsinghua.edu.cn/simple

这样python依赖包就安装好了。

Miniforge3安装

wget https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-aarch64.sh
chmod u+x Miniforge3-Linux-aarch64.sh 
./Miniforge3-Linux-aarch64.sh 

装好后,重新登录系统以使conda命令生效。

hummingbot编译

cd hummingbot
./clean && ./compile

hummingbot运行

hummingbot源码根目录下,执行bin/hummingbot.py。首次运行会进行一些初始化配置,按提示操作即可。

小结

用源码折腾很麻烦,CPU照样满载,docker至少方便一些。

Manjaro ARM官方制作维护了许多开箱即用的镜像,不过同时提供了打包工具,可以用来自行制作镜像包或启动TF卡/U盘。

Manjaro提供了2个工具,manjaro-arm-tools和manjaro-arm-installer。manjaro-arm-tools可生成镜像包,目前仅支持Manjaro。manjaro-arm-installer用于直接制作启动盘,可运行在任意发行版。也可以通过创建loop设备方式,将镜像写入磁盘,方便分发使用。

本例中,在deepin上配置使用manjaro-arm-installer。

下载manjaro-arm-installer

manjaro-arm-installer就是一个bash脚本,下载地址: https://gitlab.manjaro.org/manjaro-arm/applications/manjaro-arm-installer/-/tags 选择最新的即可。

安装依赖

该脚本依赖:

"git" "parted" "systemd-nspawn" "wget" "dialog" "bsdtar" "openssl" "awk" "btrfs" "mkfs.vfat" "mkfs.btrfs" "cryptsetup"

大部分依赖系统已预装,或者直接按包名安装即可,注意在deepin中,systemd-nspawnsystemd-container提供。

另外qemu-user-static也要安装。装好后,进入/usr/lib/binfmt.d。这个目录下针对不同架构有许多文件,我们的盒子是aarch64架构,所以将qemu-aarch64-static.conf复制一份,改名为qemu-static.conf

执行脚本

按提示进行选择机型、版本、设置用户名密码、时区等操作即可。建议全程出国上网,直连下载rootfs很慢(约170.11M)。完成后,对应TF卡/U盘存在fat与ext4两分区,用过Armbian的应该很熟悉下步配置了。

硬件

R3300-M一台,TF卡一个(运行Manjaro ARM),拆机硬盘DIY的移动硬盘一个。电源用12V 2A的,1A的带硬盘不够。

安装

sudo pacman -Sy transmission-cli

配置文件

sudo vim /var/lib/transmission/.config/transmission-daemon/settings.json

以下为常用配置,设置下载队列大小,下载路径,缓存等。对于一个headless下载机而言能够远程访问很重要,所以建议把局域网地址添加到rpc-whitelist中。

"cache-size-mb": 50,
"download-dir": "/mnt/transmission",
"download-queue-size": 50,
"download-dir": "/mnt/transmission",
"rpc-whitelist": "192.168.1.*,127.0.0.1,::1",

启动服务

sudo systemctl enable transmission
sudo systemctl start transmission

transmission-cli贴心地提供了系统服务,启用即可。

运行smb服务

下篇讲解。

需要开机自动执行的脚本

#!/bin/bash
# rustdocs.sh
# 别忘记给它可执行权限
/home/marly/.cargo/bin/mdbook serve -n 0.0.0.0 -p 3000 /home/marly/Documents/rust/trpl-zh-cn&
/home/marly/.cargo/bin/mdbook serve -n 0.0.0.0 -p 4000 /home/marly/Documents/rust/rust-by-example-cn&

第一行如果末尾不加”&”,第二句命令就不会执行。

另外脚本启动发生在marly登录bash之前,所以类似.bash_profile中自定义的$PATH无效,需要使用绝对路径。

systemd服务

[Unit]
Description=Start rust doc service on boot
Requires=network-online.target
Documentation=man:rustc

[Service]
User=marly
Type=forking
ExecStart=/home/marly/.local/bin/rustdocs.sh

[Install]
WantedBy=multi-user.target

把它命名为 rustdoc-start.service 即可,必须以.service结尾。

启动服务

将上述service文件放置在/etc/systemd/system/usr/lib/systemd/system/中,然后执行sudo systemctl enable rustdoc-start.service。完毕后重启设备观察效果,如无意外mdbook服务会自动启动。

注意sudo systemctl enable rustdoc-start.service的细节。此步骤在/etc/systemd/system/multi-user.target.wants创建了指向rustdoc-start.service的同名符号链接。

分析

上面的User,Type,ExecStart,WantedBy是重点。User=marly即以用户marly身份执行,ExecStart为所执行命令,本例中即刚才编写的脚本路径。WantedBy决定了服务启动时机,multi-user.target对应的系统状态大致为: (参考自 Why do most systemd examples contain WantedBy=multi-user.target?)

multi-user.target normally defines a system state where all network services are started up and the system will accept logins, but a local GUI is not started. This is the typical default system state for server systems, which might be rack-mounted headless systems in a remote server room.

所有网络服务已启动,系统已经做好接受登录的准备,但是GUI还未启动。对于无头服务器而言,这是默认的系统状态。

本例需要对外提供网络服务,所以WantedBy=multi-user.target是合适的。

最后是Type,有simple, exec, forking, oneshot, dbus, notify, idle几种类型。借用下金步国先生的翻译

如果设为 forking ,那么表示 ExecStart= 进程将会在启动过程中使用 fork() 系统调用。 也就是当所有通信渠道都已建好、启动亦已成功之后,父进程将会退出,而子进程将作为主服务进程继续运行。 这是传统UNIX守护进程的经典做法。 在这种情况下,systemd 会认为在父进程退出之后,该服务就已经启动完成。 如果使用了此种类型,那么建议同时设置 PIDFile= 选项,以帮助 systemd 准确可靠的定位该服务的主进程。 systemd 将会在父进程退出之后 立即开始启动后继单元。

个人理解,执行rustdocs.sh本身创建了一个进程,其中的两条mdbook命令又创建了2个子进程。只有2个子进程存续,我们的rust doc服务才能访问。所以oneshot,simple等都不行。

简单验证一下猜想:

$ ps x | grep rust
    403 ?        Sl     0:05 /home/marly/.cargo/bin/mdbook serve -n 0.0.0.0 -p 3000 /home/marly/Documents/rust/trpl-zh-cn
    404 ?        Sl     0:05 /home/marly/.cargo/bin/mdbook serve -n 0.0.0.0 -p 4000 /home/marly/Documents/rust/rust-by-example-cn
  63046 pts/0    S+     0:00 grep rust

验证成功。再顺便看看进程的owner:

$ stat -c '%U' /proc/403 /proc/404
marly
marly

符合预期。