0%

简介

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内存,非常轻松。

风险提示

家庭宽带对外提供网络服务属于违规行为,就算可以通过iptables等手段屏蔽cloudflare以外的流量,比如这个:

# Source:
# https://www.cloudflare.com/ips
# https://support.cloudflare.com/hc/en-us/articles/200169166-How-do-I-whitelist-CloudFlare-s-IP-addresses-in-iptables-

for i in `curl https://www.cloudflare.com/ips-v4`; do iptables -I INPUT -p tcp -m multiport --dports http,https -s $i -j ACCEPT; done
for i in `curl https://www.cloudflare.com/ips-v6`; do ip6tables -I INPUT -p tcp -m multiport --dports http,https -s $i -j ACCEPT; done

# Avoid racking up billing/attacks
# WARNING: If you get attacked and CloudFlare drops you, your site(s) will be unreachable. 
iptables -A INPUT -p tcp -m multiport --dports http,https -j DROP
ip6tables -A INPUT -p tcp -m multiport --dports http,https -j DROP

也只不过是略微提升了安全性,在ISP面前还是掩耳盗铃。另外目前NewFuture DDNS更新IP后,cloudflare的代理会被关闭,需要手动重新开启,期间原始IP暴露无遗。所以如果长期使用,还是买个正经VPS吧。

参考

排名不分前后:

  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

符合预期。

Manjaro ARM软件仓库里可用内核有三个分支:mainline,aml,vim,都有对应的headers。

mainline

更新最快,理论上被投入的开发维护资源更多。如果用mainline kernel一切正常,就选它好了。

aml

可能对Amlogic SOC有加成?我没发现。

vim

可能对vim板子有加成?

用刷入ATV底包的R3300-M盒子测试,三者都能正常启动运行,但是只有vim内核poweroff与reboot正常,故切换到vim内核。

sudo pacman -Sy linux-vim linux-vim-headers

编译WIFI驱动小小修改一下:

git clone https://github.com/jwrdegoede/rtl8189ES_linux.git
cd ~/rtl8189ES_linux/
make -j4 ARCH=arm64 KSRC=/usr/lib/modules/$(uname -r)/build
sudo cp 8189es.ko /usr/lib/modules/$(uname -r)/kernel/drivers/net/wireless/realtek/
sudo depmod -a
sudo modprobe 8189es

直接指定架构为arm64进行编译即可。

首先推荐两个教程:
*. Rust 程序设计语言(第二版 & 2018 edition) 简体中文版
*. 通过例子学 Rust

以上教程均可在线阅读,不过也可下载到本地阅读。以通过例子学 Rust为例:

$ git clone https://github.com/rust-lang-cn/rust-by-example-cn
$ cd rust-by-example-cn
$ cargo install mdbook
$ mdbook build
$ mdbook serve

在arm设备上远程操作,建议新建screen以免意外连接丢失重新来过。另外我需要从其他设备访问文档页面,默认的mdbook server只允许localhost访问,需要略微修改:

mdbook serve -n 0.0.0.0

这样局域网其他设备就可以在浏览器中通过3000端口阅读文档了。如果需要更换端口号,可以通过-p自行指定。