教程:VENTUNO Q/Linux 系统配置

来自WindwizPi wiki

概述

Arduino® VENTUNO™ Q 在其 Qualcomm® Dragonwing™ QCS8275 片上系统 (SoC) 上运行完整的 Ubuntu Linux 发行版,使该板作为完整的单板计算机而不仅仅是草图和应用程序的开发目标。虽然 Arduino 应用实验室提供了用于构建和部署应用程序的简化工作流程,但许多生产场景需要与底层操作系统直接交互:在启动时启动自定义进程、安排定期任务、在长时间运行的工作负载期间监控资源使用情况,或者将板集成到通过标准 Linux 工具管理的更广泛的系统中。

本教程涵盖了在生产环境中将 VENTUNO Q 作为 Linux 设备进行操作所需的核心系统管理任务。内容围绕标准 Ubuntu 实用程序(“systemd”、“cron”、“journalctl”和常见监控工具)进行组织,这些实用程序适用于与 VENTUNO Q 相关的场景,例如与 Arduino App Lab 一起运行自定义 Python® 服务、观察 AI 推理期间的资源消耗以及管理与板外设交互的服务。

本教程假设开发板已经设置完毕,并且您有一个工作终端会话(通过 SSH 或 ADB)。如果您尚未配置对开发板的访问,请参阅 VENTUNO Q 用户手册 了解初始设置过程。

目标

  • 使用“systemctl”管理 VENTUNO Q 上的系统服务。
  • 创建在启动时运行用户定义脚本的自定义服务。
  • 使用“cron”和“systemd”计时器安排重复任务。
  • 从终端监控 CPU、内存、存储和进程活动。
  • 应用与长时间运行的工作负载相关的一般性能注意事项。

硬件与软件要求

硬件要求

软件要求

  • 通过 SSH 或 ADB 与 VENTUNO Q 的终端会话。请参阅用户手册的通过 SSH 或 ADB 访问部分。
  • 基本熟悉 Linux 命令行。

说明:

本教程中显示的命令是标准 Ubuntu 实用程序,其行为与桌面 Ubuntu 安装相同。这些示例与 VENTUNO Q 相关,其中设备上下文相关。

使用 Systemd 管理系统服务

Ubuntu 使用“systemd”作为其初始化系统和服务管理器。在 VENTUNO Q 上,“systemd”负责启动网络堆栈、SSH 服务器、蓝牙®堆栈以及支持 Arduino 应用实验室的服务等。在将板配置为无人值守操作或对未按预期运行的服务进行故障排除时,从终端管理这些服务至关重要。

“systemd”的主要命令行界面是“systemctl”。大多数修改系统状态的操作都需要“sudo”。

列出服务

要查看板上当前活动的所有服务,请运行以下命令:

systemctl list-units --type=service

该命令的输出列出了每个服务及其负载状态、活动状态和简短描述。要检查系统上安装的每个服务单元(活动或非活动),请运行:

systemctl list-unit-files --type=service

如果您需要快速识别已进入失败状态的服务,请运行:

systemctl --failed

当主板在重新启动或软件更新后未按预期运行时,此命令作为第一个诊断步骤特别有用。

检查服务的状态

要检查特定服务的当前状态,请使用“systemctl status”,后跟服务名称。例如,要检查 SSH 服务器,请运行:

systemctl status ssh

输出报告服务是否已加载、是否处于活动状态、主服务进程的进程 ID、最近的日志条目以及定义服务的单元文件的路径。 这是诊断服务问题时信息最丰富的命令。

启动、停止和重新启动服务

服务的基本生命周期操作通过以下命令执行:

sudo systemctl start <service-name>      # Start the service
sudo systemctl stop <service-name>       # Stop the service
sudo systemctl restart <service-name>    # Stop and start the service
sudo systemctl reload <service-name>     # Reload the service configuration without restarting

并非每个服务都支持“重新加载”。如有疑问,“重新启动”是安全的选择,尽管它会短暂中断服务。

启动时启用和禁用服务

使用“systemctl start”启动服务仅影响当前会话;除非启用该服务,否则该服务不会在下次启动时自动启动。要将服务配置为在引导时启动,请运行:

sudo systemctl enable <service-name>

要防止服务在启动时启动,请使用“disable”:

sudo systemctl disable <service-name>

要检查服务是否配置为在引导时启动,请运行:

systemctl is-enabled <service-name>

配置新服务时的常见快捷方式是一步启用并启动它:

sudo systemctl enable --now <service-name>

使用 Journalctl 查看服务日志

“systemd”命令将每个服务的输出和诊断消息收集到集中式日志中,可以使用“journalctl”进行查询。要查看特定服务的日志,请运行:

journalctl -u <service-name>

对于实时监控,请附加“-f”标志,如下所示,以跟踪新日志条目的写入:

journalctl -u <service-name> -f

该日志支持基于时间的过滤,这在调查已知窗口期间发生的问题时非常有用,例如:

journalctl -u <service-name> --since "1 hour ago"
journalctl -u <service-name> --since "2026-05-12 09:00" --until "2026-05-12 10:00"

要检查自上次启动以来记录的所有内容,请运行:

journalctl -b

说明:

在某些 Ubuntu 配置上,日志默认存储在易失性内存中,这意味着 日志在重新启动时会丢失。要使日志在重新启动后保持不变,请创建目录“/var/log/journal”并重新启动“systemd-journald”服务。 在依赖长期日志日志保留之前验证 VENTUNO Q 上的配置。

创建定制服务

当 Arduino App Lab 中的启动时运行功能不够时(例如,运行未打包为应用程序的脚本时,或者在 Arduino App Lab 可用之前需要启动进程时),定义自定义“systemd”服务可提供对进程运行方式和时间、如何重新启动以及如何记录其输出的细粒度控制。

服务单元剖析

服务由带有“.service”扩展名的单元文件定义,通常放置在“/etc/systemd/system/”中以用于系统范围的服务。该文件分为三个部分,如以下模板所示:

[Unit]
Description=Description of what this service does
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/arduino/my-script.py
WorkingDirectory=/home/arduino
Restart=on-failure
User=arduino

[Install]
WantedBy=multi-user.target

每个部分都有不同的目的:

  • “[Unit]”部分描述了服务及其相对于其他单元的排序。 After=network.target 确保服务仅在网络堆栈可用后启动,这对于任何需要连接的进程都是必要的。其他常见目标在下面的注释中描述。
  • “[Service]”部分定义服务如何运行。 type=simple 表示主进程在前台运行,这是脚本和长时间运行的程序最常见的情况。 ExecStart 指定要执行的命令,并且必须使用绝对路径。 “WorkingDirectory”设置进程运行的目录,这对于引用相对路径的脚本很重要。 Restart=on-failure 指示 systemd 在服务以非零状态退出时自动重新启动服务。 User 定义进程运行的帐户;在 VENTUNO Q 上,默认的非 root 用户是“arduino”。
  • [Install] 部分确定服务何时激活。在系统达到多用户模式后,“WantedBy=multi-user.target”会导致该服务在正常启动期间启动。

说明:

After= 和 WantedBy= 指令的常见目标包括 multi-user.target (系统已达到多用户模式,没有图形界面)、graphical.target (图形会话可用)和 network-online.target (网络已完全配置并在线,而不是仅仅可用)。选择与服务要求相匹配的目标。

示例:在启动时运行 Python® 脚本

为了说明之前解释的工作流程,我们将配置一个小型 Python® 脚本,该脚本每 10 秒将带时间戳的条目写入日志文件,并在启动时自动启动。该过程分为三个阶段:编写脚本、定义服务和启用服务。

首先,在“/home/arduino/heartbeat.py”中创建包含以下内容的脚本:

import time
from datetime import datetime

LOG_FILE = "/home/arduino/heartbeat.log"

while True:
    with open(LOG_FILE, "a") as f:
        f.write(f"{datetime.now().isoformat()} - heartbeat\n")
    time.sleep(10)

在继续之前验证脚本是否从终端正确运行:

python3 /home/arduino/heartbeat.py

按“Ctrl+C”停止脚本并检查条目是否已写入“/home/arduino/heartbeat.log”。

接下来,在“/etc/systemd/system/heartbeat.service”中创建服务单元文件。 需要root权限才能在此目录中写入:

sudo nano /etc/systemd/system/heartbeat.service

将以下内容粘贴到文件中:

[Unit]
Description=Heartbeat logger
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/arduino/heartbeat.py
WorkingDirectory=/home/arduino
Restart=on-failure
User=arduino

[Install]
WantedBy=multi-user.target

保存文件并重新加载“systemd”配置,以便它选择新单元,如下所示:

sudo systemctl daemon-reload

启用该服务,使其在启动时启动,并在当前会话中立即启动它:

sudo systemctl enable --now heartbeat.service

验证服务是否正在运行并使用上一节中介绍的命令检查其输出,如下所示:

systemctl status heartbeat.service
journalctl -u heartbeat.service -f

要停止服务,请运行“sudo systemctl stop heartbeat.service”。要永久删除它、禁用它、停止它并删除单元文件,请运行以下命令:

sudo systemctl disable --now heartbeat.service
sudo rm /etc/systemd/system/heartbeat.service
sudo systemctl daemon-reload

说明:

每当创建或修改单元文件时,必须运行“sudo systemctl daemon-reload”才能使更改生效。 忘记此步骤是编辑后服务未按预期运行的最常见原因之一。

使用 Python® 虚拟环境

如果脚本依赖于虚拟环境中安装的库,则“ExecStart”指令必须指向该环境内的 Python® 解释器,而不是系统解释器。例如,如果虚拟环境位于“/home/arduino/venv”,则指令变为:

ExecStart=/home/arduino/venv/bin/python /home/arduino/my-script.py

这种方法允许服务使用正确的依赖项集,而无需在每次运行之前手动激活环境。

系统服务和用户服务

/etc/systemd/system/ 中定义的服务在系统级别运行,并在任何用户登录之前启动。对于无人值守的工作负载、启动时必须立即可用的服务以及无论用户会话如何都需要运行的任何进程来说,这是适当的选择。

“systemd”还支持用户级服务,这些服务为每个用户独立管理,并且仅在该用户的会话处于活动状态时运行。用户单元文件放置在 ~/.config/systemd/user/ 中,并且 systemctl 命令采用 --user 标志:

systemctl --user enable my-service.service
systemctl --user start my-service.service

对于大多数 VENTUNO Q 部署场景,系统服务是合适的选择。用户服务主要在开发工作流程或板作为具有登录图形会话的单板计算机运行的设置中有用。

安排重复任务

除了连续运行服务之外,VENTUNO Q 还可以按计划执行任务,例如定期数据上传、日志轮转或维护脚本。 Ubuntu 为此提供了两种机制:传统的“cron”守护进程和“systemd”计时器。两者都是有效的,选择取决于任务的要求。

使用计划任务

cron 是经典的 Unix 调度程序,非常适合简单的重复任务。每个用户都有一个个人时间表,称为 crontab,可使用以下命令进行编辑:

crontab -e

第一次运行此命令时,系统可能会提示您选择文本编辑器。 crontab 中的每一行使用五个时间字段定义一个计划任务,后跟要运行的命令:

* * * * * command
| | | | |
| | | | +---- Day of the week (0-7, where both 0 and 7 represent Sunday)
| | | +------ Month (1-12)
| | +-------- Day of the month (1-31)
| +---------- Hour (0-23)
+------------ Minute (0-59)

以下示例说明了常见的时间表:

# Run a script every day at 2:00 AM
0 2 * * * /home/arduino/venv/bin/python /home/arduino/backup.py

# Run a script every 15 minutes
*/15 * * * * /home/arduino/check-status.sh

# Run a script once at every boot
@reboot /home/arduino/startup-task.sh

要列出当前用户的计划任务,请运行“crontab -l”。要编辑 root 用户的 crontab(对于需要提升权限的任务),请使用“sudo crontab -e”。

说明:

由 cron 执行的任务在不加载您的 shell 配置文件的最小环境中运行。始终对解释器和脚本使用绝对路径,并避免依赖仅在交互式会话中定义的环境变量。

使用 Systemd 定时器

“systemd”计时器提供了“cron”的替代方案,可以更紧密地集成到系统的其余部分。因为该任务作为常规服务运行,所以它的输出被捕获在日志中,并且可以使用“journalctl”进行检查,并且它可以声明对其他单元的依赖关系。当计划任务与其他服务紧密相关或集中式日志记录很重要时,计时器是一个不错的选择。

计时器需要两个单元文件:定义任务的服务和定义时间表的计时器。例如,考虑每日备份任务。

首先,在“/etc/systemd/system/backup.service”中创建服务文件。请注意,使用“Type=oneshot”是因为任务运行完成然后退出,而不是连续运行:

[Unit]
Description=Daily backup task

[Service]
Type=oneshot
ExecStart=/home/arduino/venv/bin/python /home/arduino/backup.py
User=arduino

接下来,在“/etc/systemd/system/backup.timer”中创建计时器文件:

[Unit]
Description=Run the backup task daily

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

OnCalendar 指令定义任务运行的时间。 Persistent=true 指令确保如果开发板在预定时间关闭,则任务会在开发板再次启动后运行。 OnCalendar 语法很灵活:

OnCalendar=daily                      # Every day at midnight
OnCalendar=*-*-* 02:00:00             # Every day at 2:00 AM
OnCalendar=Mon *-*-* 09:00:00         # Every Monday at 9:00 AM
OnCalendar=*:0/15                     # Every 15 minutes

创建这两个文件后,重新加载配置并启用计时器(而不是服务):

sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer

要列出所有活动计时器及其下一个计划运行时间,请使用:

systemctl list-timers

此命令提供了由“systemd”管理的每个计划任务的清晰概述,这对于确认计时​​器是否正确配置非常有用。

监控系统资源

在运行人工智能推理、多摄像头捕捉或连续数据处理等要求苛刻的工作负载时,监控 VENTUNO Q 如何使用其资源非常重要。以下工具可以直接从终端查看 CPU、内存、存储和进程活动。

进程和 CPU 使用率

“top”命令提供了正在运行的进程的实时、持续更新的视图,默认情况下按 CPU 使用率排序。它在每个 Ubuntu 安装上都可用:

top

一个更具可读性和交互性的替代方案是“htop”,它显示每个核心的 CPU 使用情况、颜色编码的内存条以及用于排序和过滤进程的更简单的界面。如果尚未安装,可以添加:

sudo apt install htop

要获取所有正在运行的进程的一次性快照,请使用“ps”。以下命令列出消耗最多内存的进程:

ps aux --sort=-%mem | head

内存使用情况

VENTUNO Q 配备 16 GB LPDDR5 RAM。要以人类可读的格式查看当前内存使用情况,请运行:

free -h

输出显示总内存、已用内存、可用内存和可用内存,以及任何配置的交换空间。在运行 AI 模型或处理大型数据集时监控可用内存有助于确定工作负载是否适合可用 RAM。

存储使用情况

VENTUNO Q 包括 64 GB eMMC 存储,可以选择使用 NVMe 驱动器通过 M.2 连接器进行扩展。要查看所有已安装文件系统的使用情况,请运行:

df -h

每个已安装的文件系统都显示为单独的条目,包括 eMMC 和任何附加的 M.2 存储。要查找给定位置中哪些目录占用的空间最多,请使用“du”:

du -sh /home/arduino/*

网络活动

要检查活动网络连接和侦听端口,请使用“ss”:

ss -tulpn

这列出了板正在侦听的 TCP 和 UDP 端口以及关联的进程,这在验证服务是否绑定到预期端口或诊断连接问题时非常有用。

性能考虑因素

除了监控之外,多个系统参数也会影响 VENTUNO Q 在持续负载下的性能。本节中描述的机制是 Ubuntu 系统的标准机制,但可用选项及其效果取决于特定内核和 Dragonwing™ QCS8275 平台。

警告:

本节中描述的设置会影响系统行为、功耗和热输出。可用选项、默认值和最佳配置取决于 VENTUNO Q 的特定内核和硬件。验证板上的每个设置,并在实际工作负载下测试更改,然后再将其应用于生产部署。

首先识别瓶颈

性能调整应始终从测量开始。在更改任何系统参数之前,请使用上一节中的监视工具来识别实际约束。受内存限制的工作负载不会从 CPU 调整中受益,而受存储吞吐量限制的工作负载则需要采用与受 CPU 限制不同的方法。使用“top”、“free”和“df”建立基线可确保任何更改都可以根据可衡量的结果进行评估。

CPU 频率调节

Linux 通过频率调节调节器来管理处理器时钟速度,从而平衡性能与功耗和热量。可以通过“sysfs”接口查询当前的调速器和系统上可用的频率:

cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

典型的调节器包括“性能”(使处理器保持在最高可用频率)和“省电”(有利于降低频率以减少功耗)。 VENTUNO Q 上可用的调速器集取决于 Dragonwing™ QCS8275 的内核配置,应在使用前在电路板上确认。

内存和交换行为

内核参数“vm.swappiness”控制系统将数据从 RAM 移动到交换区的积极程度。较低的值会在 RAM 中保留更多数据,如果有足够的 RAM 可用,这可以使内存密集型工作负载受益。可以通过以下方式检查当前值:

cat /proc/sys/vm/swappiness

可以使用 sysctl 临时调整:

sudo sysctl vm.swappiness=10

要使更改在重新启动后保持不变,请将其添加到“/etc/sysctl.d/”下的文件中。由于该参数仅在配置了swap时才起作用,因此首先使用free -h确认板子的swap配置。

存储注意事项

板载 eMMC 存储的写入周期数量有限,与所有基于闪存的存储一样。安装 M.2 NVMe 驱动器后,执行频繁或大量写入(例如连续记录或缓冲大型数据集)的工作负载将受益于定向到 M.2 NVMe 驱动器,这样既可以提高吞吐量,又可以减少 eMMC 的磨损。对于写入密集型部署,前面讨论的日志持久性和日志记录配置值得回顾。

热和功率意识

持续的高性能工作负载会增加功耗和发热。 VENTUNO Q 定义了取决于电源电压的功率限制,如用户手册的电源概述部分所述。将电路板配置为要求苛刻的连续运行时,请确保电源足以满足预期负载,并且电路板有足够的通风。

故障排除

本节收集在 VENTUNO Q 上配置服务和计划任务时遇到的常见问题以及建议的诊断步骤。

服务启动失败

如果服务未启动,请首先检查其状态和日志:

systemctl status <service-name>
journalctl -u <service-name>

最常见的原因是“ExecStart”中的绝对路径不正确、配置的“User”权限不足或编辑单元文件后缺少“daemon-reload”。确认从终端手动执行时,“ExecStart”中的命令运行正确。

服务启动但立即退出

启动然后停止的服务通常表明程序本身已退出。手动运行程序以检查其输出并确认其行为符合预期。对于依赖于虚拟环境的脚本,请验证“ExecStart”是否指向环境内的解释器而不是系统解释器。

计划任务不运行

对于“cron”,请确认该条目使用绝对路径并且该命令在最小环境中正确运行。对于“systemd”计时器,确认计时器(而不是服务)已启用,并检查时间表:

systemctl list-timers

日记消耗过多存储空间

如果日志已填满存储,则可以修剪日志。以下命令按大小或年龄限制日志:

sudo journalctl --vacuum-size=200M
sudo journalctl --vacuum-time=7d

这些命令将存储的日志减少到指定的大小或保留期限,对于回收长时间运行的主板上的空间非常有用。

总结

在本教程中,您学习了如何将 VENTUNO Q 作为通过标准 Ubuntu 工具管理的 Linux 系统进行操作。您现在知道如何使用“systemd”管理服务、创建在启动时运行脚本的自定义服务、使用“cron”和“systemd”计时器安排重复任务、监控主板资源以及有条不紊地进行性能调整。

这些技能将 VENTUNO Q 的功能扩展到 Arduino App Lab 工作流程之外,从而实现无人值守部署以及与更广泛的 Linux 生态系统更紧密的集成。要继续探索 VENTUNO Q,请参阅 VENTUNO Q 用户手册 了解硬件详细信息和初始设置,并参阅 Linux 类别中的其他教程了解相关主题。


原文:https://docs.arduino.cc/tutorials/ventuno-q/linux-on-ventuno/ 本页为 Arduino 官方教程的中文翻译,供内部查阅。命令与代码保持原文。