杰瑞科技汇

Synology如何用Python?环境配置与实用技巧

使用 Synology DSM API (最常用)

这是最主流和灵活的方式,它通过 HTTP 请求与 NAS 的 Web 服务进行交互,几乎可以控制 DSM 的所有功能,如文件管理、下载任务、系统信息、用户管理等。

准备工作:在 DSM 中启用 API

在编写 Python 脚本之前,你必须在 NAS 上进行一些设置:

  1. 开启 SSH 功能

    • 进入 控制面板 > 终端机和 SNMP
    • 勾选 启用 SSH 功能,这方便你后续调试和直接运行脚本。
  2. 创建专用 API 用户

    • 进入 控制面板 > 用户和用户组
    • 创建一个新用户(api_user),并为其分配一个强密码。
    • 编辑该用户的权限,确保它有足够的权限来执行你需要的操作(如果需要管理文件,就需要赋予相应的文件夹读写权限)。
  3. 获取你的 NAS 信息

    • DSM 版本:进入 控制面板 > 关于
    • NAS 的 IP 地址或域名168.1.100my.synology.me
    • HTTPS 端口:默认 5001,可以在 控制面板 > 外部访问 > DSM 设置 中找到。

核心概念:API 认证

Synology API 使用一种叫做 Session 的机制来保持认证状态,流程如下:

  1. 获取 sid (Session ID):首先向 auth.cgi 发送一个 POST 请求,包含你的用户名和密码,如果成功,服务器会返回一个 sid
  2. 使用 sid 访问其他 API:后续所有的 API 请求都需要在 URL 或 Header 中带上这个 sid,服务器以此来识别你的身份。
  3. 注销 sid:当操作完成时,最好向 auth.cgi 发送一个请求来注销你的会话,释放资源。

Python 实现:安装 requests

我们使用非常流行的 requests 库来处理 HTTP 请求。

pip install requests

完整代码示例:列出共享文件夹中的文件

这个例子将演示如何获取 sid,然后使用 FileStation API 来列出指定共享文件夹下的内容。

import requests
import json
from urllib.parse import urljoin
# --- 配置信息 ---
# 替换为你的 NAS 实际信息
SYNOLOGY_HOST = "192.168.1.100"  # 你的 NAS IP 或域名
SYNOLOGY_PORT = 5001            # DSM HTTPS 端口
USERNAME = "api_user"           # 你创建的 API 用户名
PASSWORD = "your_password"      # API 用户的密码
API_NAME = "FileStation"        # 要调用的 API 名称
API_INFO = "list"               # 要调用的 API 方法
FOLDER_PATH = "/home"           # 你想列出内容的文件夹路径
# --- 1. 获取 Session ID (sid) ---
def get_sid():
    """获取 Synology DSM 的 Session ID"""
    auth_url = f"https://{SYNOLOGY_HOST}:{SYNOLOGY_PORT}/webapi/auth.cgi"
    params = {
        'api': 'SYNO.API.Auth',
        'version': '3',
        'method': 'login',
        'account': USERNAME,
        'passwd': PASSWORD,
        'session': 'FileStation', # 指定会话名称,方便管理
        'format': 'sid'           # 只返回 sid
    }
    try:
        response = requests.post(auth_url, params=params, verify=False) # verify=False 用于忽略自签名证书警告
        response.raise_for_status()  # 如果请求失败则抛出异常
        sid = response.json()['data']['sid']
        print("成功获取 Session ID (sid)!")
        return sid
    except requests.exceptions.RequestException as e:
        print(f"获取 sid 失败: {e}")
        return None
    except KeyError:
        print("获取 sid 失败: 响应数据格式不正确,请检查用户名和密码。")
        return None
# --- 2. 使用 sid 调用 FileStation API 列出文件 ---
def list_files(sid):
    """使用 sid 调用 FileStation API 列出指定文件夹的内容"""
    api_url = f"https://{SYNOLOGY_HOST}:{SYNOLOGY_PORT}/webapi/entry.cgi"
    params = {
        'api': API_NAME,
        'version': '2', # FileStation API 的版本
        'method': API_INFO,
        'path': FOLDER_PATH,
        'additional': 'real_path,owner,size,modification_time', # 获取更多信息
        '_sid': sid     # 关键:在请求中带上 sid
    }
    try:
        response = requests.get(api_url, params=params, verify=False)
        response.raise_for_status()
        data = response.json()
        if data['success']:
            print(f"\n--- 文件夹 '{FOLDER_PATH}' 的内容 ---")
            files = data['data']['files']
            for item in files:
                # 判断是文件还是文件夹
                item_type = "📁" if item['isdir'] else "📄"
                print(f"{item_type} {item['name']} (大小: {item['size']}, 修改时间: {item['mtime']})")
        else:
            print(f"API 调用失败: {data['error']}")
    except requests.exceptions.RequestException as e:
        print(f"调用 API 失败: {e}")
    except KeyError:
        print("解析 API 响应失败,请检查 API 名称和方法是否正确。")
# --- 3. 注销 sid ---
def logout(sid):
    """注销会话,释放资源"""
    logout_url = f"https://{SYNOLOGY_HOST}:{SYNOLOGY_PORT}/webapi/auth.cgi"
    params = {
        'api': 'SYNO.API.Auth',
        'version': '3',
        'method': 'logout',
        '_sid': sid
    }
    try:
        requests.post(logout_url, params=params, verify=False)
        print("\n成功注销 Session ID (sid)。")
    except requests.exceptions.RequestException as e:
        print(f"注销 sid 失败: {e}")
# --- 主程序 ---
if __name__ == "__main__":
    # 注意: verify=False 会产生 InsecureRequestWarning,可以忽略或在生产环境中配置正确的证书
    import urllib3
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    session_id = get_sid()
    if session_id:
        list_files(session_id)
        logout(session_id)

其他常用 API

你可以通过修改 API_NAMEAPI_INFO 来调用不同的功能。

  • Download Station (下载管理):
    • API_NAME: DownloadStation
    • API_INFO: list (列出任务), info (获取任务详情), create (创建下载任务)
  • System Info (系统信息):
    • API_NAME: SYNO.API.Info
    • API_INFO: get (获取 API 列表和版本信息)
  • Virtual Machine Manager (虚拟机管理):
    • API_NAME: VMManager
    • API_INFO: list (列出虚拟机)

使用 Synology Package Center SDK (高级)

如果你要开发的是官方的套件应用,而不是外部脚本,那么你应该使用 Synology Package Center SDK,这个 SDK 提供了更底层、更强大的接口,可以直接与 DSM 的核心系统集成,创建有完整 UI 界面的应用。

特点:

  • 用于开发官方套件:创建可以在套件中心安装和管理的应用。
  • 语言: 主要是 C/C++,但也提供 Python 的绑定。
  • 复杂度高:需要理解 DSM 的应用开发框架,包括 UI 定义、权限管理、后台服务等。
  • 文档: 需要申请 Synology 开发者账号来获取 SDK 和相关文档。

适用场景:

  • 你想开发一个功能复杂的、可以发布给所有群晖用户使用的官方应用。
  • 你的应用需要深度集成系统功能,并且需要有图形用户界面。

对于绝大多数只想用 Python 自动化 NAS 任务的普通用户来说,方式一 (DSM API) 是首选


总结与最佳实践

特性 方式一 (DSM API) 方式二 (Package SDK)
用途 自动化脚本、第三方工具、集成开发 官方套件应用开发
技术栈 Python + requests C/C++, Python (绑定), Web 技术
认证 Session ID (sid) 套件专用 API Key 和权限
部署 在任何有 Python 的机器上运行 作为套件安装到 DSM
学习曲线 较低 较高
推荐度 ⭐⭐⭐⭐⭐ (对于脚本开发者) ⭐⭐⭐ (对于官方应用开发者)

最佳实践建议

  1. 安全第一

    • 不要在代码中硬编码你的用户名和密码,使用环境变量或配置文件来存储它们。
    • 为脚本创建一个权限最低的专用用户。
    • 强烈建议使用 HTTPS 并考虑配置 NAS 的自签名证书。
  2. 错误处理

    • 网络请求可能会失败,API 调用也可能因为权限不足或参数错误而失败,务必使用 try...except 块来处理这些异常,让你的脚本更健壮。
  3. 会话管理

    • 确保在脚本结束时调用 logout 函数来注销 sid,这是一个好习惯,可以避免会话资源被长时间占用。
  4. 探索 API

    • 你可以直接在浏览器中访问 https://<your_nas_ip>:<port>/webapi/entry.cgi?api=SYNO.API.Info&method=get&version=1 来获取所有可用的 API 列表和它们的版本号,这是发现新功能的好方法。

希望这份详细的指南能帮助你顺利地在 Python 中使用 Synology NAS!

分享:
扫描分享到社交APP
上一篇
下一篇