Browse Source

feat(log+doc): 增加log配置,完善文档 (#480)

* update log config

* add cli 文档

* update cli config

* add docker 文档
New Future 5 months ago
parent
commit
bdc9979c10
8 changed files with 1011 additions and 19 deletions
  1. 27 9
      README.md
  2. 279 0
      doc/cli.md
  3. 356 0
      doc/docker.md
  4. 112 3
      doc/env.md
  5. 199 0
      doc/json.md
  6. 10 4
      run.py
  7. 13 1
      schema/v4.0.json
  8. 15 2
      util/config.py

+ 27 - 9
README.md

@@ -19,9 +19,9 @@
   - [二进制文件](https://github.com/NewFuture/DDNS/releases/latest) ![cross platform](https://img.shields.io/badge/system-windows_%7C%20linux_%7C%20mac-success.svg?style=social)
   
 - 配置方式:
-  - [命令行参数](#详细配置)
-  - [JSON 配置文件](#详细配置)
-  - [环境变量配置](doc/env.md) 📖
+  - [命令行参数](doc/cli.md)
+  - [JSON 配置文件](doc/json.md)
+  - [环境变量配置](doc/env.md)
 
 - 域名支持:
   - 多个域名支持
@@ -114,12 +114,27 @@
 
 ## 详细配置
 
-所有字段可通过三种方式进行配置
+所有字段可通过三种方式进行配置,优先级为:**命令行参数 > JSON配置文件 > 环境变量**
 
-1. 命令行参数 `ddns --key=value`(`ddns -h` 查看详情),优先级最高
-2. JSON 配置文件(值为 null 认为是有效值,会覆盖环境变量的设置,如果没有对应的 key 则会尝试使用环境变量)
+1. [命令行参数](doc/cli.md) `ddns --key=value`(`ddns -h` 查看详情),优先级最高
+2. [JSON 配置文件](doc/json.md)(值为 null 认为是有效值,会覆盖环境变量的设置,如果没有对应的 key 则会尝试使用环境变量)
 3. 环境变量 DDNS_ 前缀加上 key 全大写或者全小写,点转下划线(`${ddns_id}` 或 `${DDNS_ID}`,`${DDNS_LOG_LEVEL}`)
 
+### 配置优先级和字段覆盖关系
+
+如果同一个配置项在多个地方设置,将按照以下优先级规则生效:
+
+- **命令行参数**:优先级最高,会覆盖其他所有设置
+- **JSON配置文件**:介于命令行和环境变量之间,会覆盖环境变量中的设置
+- **环境变量**:优先级最低,当其他方式未设置时使用
+
+**特殊情况**:
+- JSON配置中明确设为`null`的值会覆盖环境变量设置
+- `debug`参数只在命令行中有效,JSON配置文件中的同名设置无效
+- 多值参数(如`ipv4`、`ipv6`等)在命令行中使用方式为重复使用参数,如`--ipv4 domain1 --ipv4 domain2`
+
+各配置方式的详细说明请查看对应文档:[命令行](doc/cli.md)、[JSON配置](doc/json.md)、[环境变量](doc/env.md)
+
 > 📖 **环境变量详细配置**: 查看 [环境变量配置文档](doc/env.md) 了解所有环境变量的详细用法和示例
 
 <details open>
@@ -128,6 +143,7 @@
 - 首次运行会自动生成一个模板配置文件
 - 可以使用 `-c` 使用指定的配置文件(默认读取当前目录的 config.json)
 - 推荐使用 vscode 等支持 JsonSchema 的编辑器编辑配置文件
+- 查看 [JSON配置文件详细文档](doc/json.md) 了解完整的配置选项和示例
 
 ```bash
 ddns -c path/to/config.json
@@ -148,9 +164,9 @@ python run.py -c /path/to/config.json
 | index6   | string\|int\|array |    No    | `"default"` |   ipv6 获取方式   | 可设置 `网卡`、`内网`、`公网`、`正则` 等方式                                                                |
 |  ttl     |       number       |    No    |   `null`    | DNS 解析 TTL 时间 | 不设置采用 DNS 默认策略                                                                                     |
 |  proxy   |       string\|array       |    No    |     无      | http 代理 `;` 分割 | 多代理逐个尝试直到成功,`DIRECT` 为直连                                                                     |
-| ~~debug~~|        bool        |    No    |   `false`   |   是否开启调试    | v4 中弃用,请改用 log.level=DEBUG                                                                           |
+|  debug  |        bool        |    No    |   `false`   |   是否开启调试    | 等同于设置 log.level=DEBUG,仅命令行参数`--debug`有效                                                  |
 |  cache   |    string\|bool    |    No    |   `true`    |   是否缓存记录    | 正常情况打开避免频繁更新,默认位置为临时目录下 `ddns.cache`,也可以指定一个具体路径                          |
-|  log     | {"level":string,"file":string} | No | `null` | 日志配置(可选) | 日志配置,日志级别和路径(默认命令行),例如:`{ "level": "DEBUG", "file": "dns.log" }`                    |
+|  log     | object | No | `null` | 日志配置(可选) | 日志配置对象,支持`level`、`file`、`format`、`datefmt`参数                   |
 
 #### index4 和 index6 参数说明
 
@@ -196,7 +212,9 @@ python run.py -c /path/to/config.json
   "proxy": "127.0.0.1:1080;DIRECT",
   "log": {
     "level": "DEBUG",
-    "file": "dns.log"
+    "file": "dns.log",
+    "format": "%(asctime)s %(levelname)s [%(module)s]: %(message)s",
+    "datefmt": "%Y-%m-%dT%H:%M:%S"
   }
 }
 ```

+ 279 - 0
doc/cli.md

@@ -0,0 +1,279 @@
+# DDNS 命令行参数参考
+
+本文档详细说明DDNS工具的命令行参数用法。命令行参数可用于覆盖配置文件和环境变量中的设置,具有**最高优先级**。
+
+## 基本用法
+
+可通过`-h` 查看参数列表
+
+```bash
+# ddns [选项]
+ddns -h
+```
+
+或者使用Python源码:
+
+```bash
+# python run.py [选项]
+python run.py -h
+```
+
+## 参数列表
+
+| 长参数          | 短参数 | 类型            | 描述                                         |
+| --------------- | ------ | --------------- | -------------------------------------------- |
+| `--help`        | `-h`   | 标志            | 显示帮助信息并退出                           |
+| `--version`     | `-v`   | 标志            | 显示版本信息并退出                           |
+| `--config`      | `-c`   | 字符串          | 指定配置文件路径                             |
+| `--dns`         |        | 选择项          | DNS服务提供商                                |
+| `--id`          |        | 字符串          | API 访问 ID 或授权账户                       |
+| `--token`       |        | 字符串          | API 授权令牌或密钥                           |
+| `--ipv4`        |        | 字符串列表      | IPv4 域名列表,多个域名重复使用参数          |
+| `--ipv6`        |        | 字符串列表      | IPv6 域名列表,多个域名重复使用参数          |
+| `--index4`      |        | 字符串/数字列表 | IPv4 地址获取方式,支持多种获取方式          |
+| `--index6`      |        | 字符串/数字列表 | IPv6 地址获取方式,支持多种获取方式          |
+| `--ttl`         |        | 整数            | DNS 解析记录的 TTL 时间(秒)                |
+| `--proxy`       |        | 字符串列表      | HTTP 代理设置,支持多代理重复使用参数        |
+| `--cache`       |        | 布尔/字符串     | 是否启用缓存或自定义缓存路径                 |
+| `--debug`       |        | 标志            | 开启调试模式(等同于 --log.level=DEBUG)     |
+| `--log.file`    |        | 字符串          | 日志文件路径,不指定则输出到控制台           |
+| `--log.level`   |        | 字符串          | 日志级别                                     |
+| `--log.format`  |        | 字符串          | 日志格式字符串                               |
+| `--log.datefmt` |        | 字符串          | 日期时间格式字符串                           |
+
+其中`--debug`和`--help`,`--version`为命令行独有参数。
+
+### 参数值示例
+
+| 参数         | 可能的值                                     | 示例                                    |
+|--------------|----------------------------------------------|----------------------------------------|
+| `--dns`      | dnspod, alidns, cloudflare, 等               | `--dns cloudflare`                     |
+| `--id`       | API ID, 邮箱, Access Key                     | `--id [email protected]`                |
+| `--token`    | API Token, Secret Key                        | `--token abcdef123456`                 |
+| `--ipv4`     | 域名                                         | `--ipv4 example.com --ipv4 sub.example.com` |
+| `--ipv6`     | 域名                                         | `--ipv6 example.com`                   |
+| `--index4`   | 数字, default, public, url:, regex:, cmd:, shell: | `--index4 public`, `--index4 "regex:192\\.168\\..*"` |
+| `--index6`   | 数字, default, public, url:, regex:, cmd:, shell: | `--index6 0`, `--index6 public`         |
+| `--ttl`      | 秒数                                         | `--ttl 600`                            |
+| `--proxy`    | IP:端口, DIRECT                              | `--proxy 127.0.0.1:1080 --proxy DIRECT` |
+| `--cache`    | true, 文件路径                         | `--cache=true`, `--cache=/path/to/cache.json` |
+| `--debug`    | (无值)                                       | `--debug`                              |
+| `--log.file` | 文件路径                                     | `--log.file=/var/log/ddns.log`         |
+| `--log.level`| DEBUG, INFO, WARNING, ERROR, CRITICAL        | `--log.level=DEBUG`                    |
+| `--log.format` | 格式字符串                                 | `--log.format="%(asctime)s: %(message)s"` |
+| `--log.datefmt` | 日期格式字符串                            | `--log.datefmt="%Y-%m-%d %H:%M:%S"`    |
+
+## DNS服务配置参数
+
+### `--dns {alidns,cloudflare,dnscom,dnspod,dnspod_com,he,huaweidns,callback}`
+
+DNS服务提供商。
+
+- **默认值**: `dnspod`
+- **可选值**:
+  - `alidns`: 阿里云DNS
+  - `cloudflare`: Cloudflare
+  - `dnscom`: DNS.COM
+  - `dnspod`: DNSPOD国内版
+  - `dnspod_com`: DNSPOD国际版
+  - `he`: HE.net
+  - `huaweidns`: 华为云DNS
+  - `callback`: 自定义回调
+
+### `--id ID`
+
+API访问ID或用户标识。
+
+- **必需**: 是(部分DNS服务商可选)
+- **说明**:
+  - Cloudflare: 填写邮箱地址(使用Token时可留空)
+  - HE.net: 可留空
+  - 华为云: 填写Access Key ID (AK)
+  - 其他服务商: 根据各自要求填写ID
+
+### `--token TOKEN`
+
+API授权令牌或密钥。
+
+- **必需**: 是
+- **说明**: 部分平台称为Secret Key,请妥善保管
+
+## 域名配置参数
+
+### `--ipv4 [DOMAIN...]`
+
+需要更新IPv4记录的域名列表。
+
+- **默认值**: `[]`(不更新IPv4地址)
+- **示例**:
+  - `--ipv4 example.com` (单个域名)
+  - `--ipv4 example.com --ipv4 subdomain.example.com` (多个域名)
+
+### `--ipv6 [DOMAIN...]`
+
+需要更新IPv6记录的域名列表。
+
+- **默认值**: `[]`(不更新IPv6地址)
+- **示例**:
+  - `--ipv6 example.com` (单个域名)
+  - `--ipv6 example.com --ipv6 ipv6.example.com` (多个域名)
+
+## IP获取方式参数
+
+### `--index4 [METHOD...]`
+
+IPv4地址获取方式。
+
+- **默认值**: `default`
+- **可选值**:
+  - 数字(`0`,`1`,`2`...): 第N个网卡IP
+  - `default`: 系统访问外网默认IP
+  - `public`: 使用公网IP(通过API查询)
+  - `url:{URL}`: 从指定URL获取IP
+  - `regex:{PATTERN}`: 使用正则表达式匹配本地网络配置中的IP
+  - `cmd:{COMMAND}`: 执行指定命令并使用其输出作为IP
+  - `shell:{COMMAND}`: 使用系统shell运行命令并使用其输出作为IP
+- **示例**:
+  - `--index4 0` (第一个网卡)
+  - `--index4 public` (公网IP)
+  - `--index4 "url:http://ip.sb"` (从URL获取)
+  - `--index4 "regex:192\\.168\\.*"` (匹配192.168开头的IP)
+  - `--index4 public --index4 0` (先尝试获取公网IP,失败则使用第一个网卡)
+
+### `--index6 [METHOD...]`
+
+IPv6地址获取方式,用法同`--index4`。
+
+## 网络配置参数
+
+### `--ttl TTL`
+
+DNS解析TTL时间(秒)。
+
+- **默认值**: `null`(使用DNS服务商默认设置)
+- **示例**:
+  - `--ttl 600` (10分钟)
+  - `--ttl 3600` (1小时)
+
+### `--proxy [PROXY...]`
+
+HTTP代理设置,支持多代理轮换。
+
+- **默认值**: 无(DIRECT 直连)
+- **示例**:
+  - `--proxy 127.0.0.1:1080` (单个代理)
+  - `--proxy 127.0.0.1:1080 --proxy DIRECT` (多个代理,逐个尝试)
+
+## 系统配置参数
+
+### `--cache [BOOL|PATH]`
+
+启用缓存以减少API请求。
+
+- **默认值**: `true`
+- **可选值**:
+  - `true`: 启用缓存,使用默认路径
+  - `false`: 禁用缓存
+  - 文件路径: 自定义缓存文件位置
+- **示例**:
+  - `--cache` (启用默认缓存)
+  - `--cache=false` (禁用缓存)
+  - `--cache=/path/to/ddns.cache` (自定义缓存路径)
+
+### `--debug`
+
+启用调试模式(等同于设置`--log.level=DEBUG`)。
+
+- **说明**: 此参数仅作为命令行参数有效,配置文件中的同名设置无效
+- **示例**: `--debug`
+
+## 日志配置参数
+
+### `--log.level {CRITICAL|FATAL|ERROR|WARN|WARNING|INFO|DEBUG|NOTSET}`
+
+设置日志级别。
+
+- **默认值**: `INFO`
+- **示例**:
+  - `--log.level=DEBUG` (调试模式)
+  - `--log.level=ERROR` (仅显示错误)
+
+### `--log.file LOGFILE`
+
+设置日志文件路径。
+
+- **默认值**: 无(输出到控制台)
+- **示例**:
+  - `--log.file=/var/log/ddns.log`
+  - `--log.file=./ddns.log`
+
+### `--log.format FORMAT`
+
+设置日志格式字符串(参考Python logging模块格式)。
+
+- **默认值**: `%(asctime)s %(levelname)s [%(module)s]: %(message)s`
+- **示例**:
+  - `--log.format="%(asctime)s %(levelname)s: %(message)s"`
+  - `--log.format="%(levelname)s [%(filename)s:%(lineno)d]: %(message)s"`
+
+### `--log.datefmt FORMAT`
+
+设置日期时间格式字符串(参考Python time.strftime()格式)。
+
+- **默认值**: `%Y-%m-%dT%H:%M:%S`
+- **示例**:
+  - `--log.datefmt="%Y-%m-%d %H:%M:%S"`
+  - `--log.datefmt="%m-%d %H:%M:%S"`
+
+## 常用命令示例
+
+### 使用配置文件
+
+```bash
+# 使用默认配置文件
+ddns
+
+# 使用指定配置文件
+ddns -c /path/to/config.json
+```
+
+### 命令行临时修改配置
+
+```bash
+# 启用调试模式
+ddns --debug
+
+# 使用指定配置文件并启用调试模式
+ddns -c /path/to/config.json --debug
+
+# 更新特定域名的IPv4地址(多个域名)
+ddns --ipv4 example.com --ipv4 www.example.com
+
+# 设置为阿里云DNS并提供认证信息
+ddns --dns alidns --id YOUR_ACCESS_KEY_ID --token YOUR_ACCESS_KEY_SECRET
+```
+
+### 高级用法示例
+
+```bash
+# 使用公网IP和特定的网络配置
+ddns --ipv4 example.com --index4 public --ttl 600 --proxy 127.0.0.1:1080
+
+# 自定义日志配置
+ddns --log.level=DEBUG --log.file=./ddns.log --log.format="%(asctime)s - %(levelname)s: %(message)s"
+
+# 完整配置示例
+ddns --dns cloudflare --id [email protected] --token API_TOKEN \
+     --ipv4 example.com --ipv4 www.example.com --ipv6 example.com \
+     --index4 public --index6 "regex:2001:.*" \
+     --ttl 300 --proxy 127.0.0.1:1080 --proxy DIRECT \
+     --cache=/var/cache/ddns.cache \
+     --log.level=INFO --log.file=/var/log/ddns.log
+```
+
+## 注意事项
+
+1. 命令行参数具有最高优先级,会覆盖配置文件和环境变量中的设置。
+2. 对于需要空格的参数值,请使用引号包围,例如:`--log.format="%(asctime)s: %(message)s"`。
+3. 对于多值参数(如`--ipv4`、`--index4`、`--proxy`等),请重复使用参数标识,例如:`--ipv4 example.com --ipv4 sub.example.com`。
+4. `--debug`参数仅在命令行中有效,配置文件中的debug设置将被忽略。

+ 356 - 0
doc/docker.md

@@ -0,0 +1,356 @@
+# DDNS Docker 使用文档
+
+本文档详细说明如何使用 Docker 方式运行 DDNS 工具,包括基本用法、高级配置、多种网络模式以及常见问题解决方案。
+可移植性最佳。
+
+## 基本介绍
+
+DDNS 官方提供了优化过的 Docker 镜像,具有以下特点:
+
+- 基于 Alpine Linux,最终编译后的镜像体积小(< 7MB)
+- 支持多种硬件架构(amd64、arm64、arm/v7、arm/v6、ppc64le、s390x、386、mips64le)
+- 内置定时任务,默认每 5 分钟自动更新一次
+- 无需外部依赖,开箱即用
+- 性能优化,资源占用低
+
+## 快速开始
+
+### 镜像版本
+
+DDNS Docker 镜像特殊版本:
+
+- `latest` 最新稳定版(默认)
+- `next` 下一个版本(最新beta版)
+- `edge` 最新开发版(不稳定), 同步master分支
+
+```bash
+docker pull newfuture/ddns:latest
+```
+
+您也可以指定特定版本,例如:
+
+```bash
+docker pull newfuture/ddns:v2.8.0
+```
+
+### 基本运行方式
+
+DDNS Docker 镜像支持三种配置方式:命令行,环境变量和配置文件。
+
+当设置了命令行参数时,容器将直接运行 DDNS 程序,而不会启用定时任务。
+如果您需要定时任务,请使用环境变量或配置文件方式。
+
+#### 使用命令行参数
+
+可以参考[命令行参数说明](cli.md)获取详细的参数列表。
+此时 `docker run --name=ddns --network=host newfuture/ddns` 就相当于 `ddns` 命令行,不会执行定时任务。
+
+此方式适合需要一次性运行或调试的场景。
+
+```bash
+docker run --name=ddns --network=host newfuture/ddns -h
+```
+
+#### 使用环境变量
+
+```bash
+docker run -d \
+  -e DDNS_DNS=dnspod \
+  -e DDNS_ID=12345 \
+  -e DDNS_TOKEN=mytokenkey \
+  -e DDNS_IPV4=example.com,www.example.com \
+  -e DDNS_INDEX4=['public',0] \
+  -e DDNS_IPV6=example.com,ipv6.example.com \
+  --network host \
+  --name ddns \
+  newfuture/ddns
+```
+
+想要了解所有支持的环境变量,请参考[环境变量配置说明](env.md)。
+
+#### 使用配置文件
+
+```bash
+docker run -d \
+  -v /host/config/:/ddns/ \
+  --network host \
+  --name ddns \
+  newfuture/ddns
+```
+
+其中 `/host/config/` 是您本地包含 `config.json` 的目录。Docker 容器内的工作目录是 `/ddns/`,配置文件会被映射到容器内的 `/ddns/config.json`。
+
+详见 `config.json` 的内容可以参考 [JSON 配置文件说明](json.md)。
+
+## 网络模式
+
+### host 网络模式(推荐)
+
+使用 `--network host` 可让容器直接使用宿主机的网络,这样 DDNS 可以正确获取宿主机的 IP 地址。
+
+对于Public 或者 url 通常不需要设置 host
+
+```bash
+docker run -d \
+  -e DDNS_DNS=dnspod \
+  -e DDNS_ID=12345 \
+  -e DDNS_TOKEN=mytokenkey \
+  -e DDNS_IPV4=example.com \
+  --network host \
+  newfuture/ddns
+```
+
+### bridge 网络模式(默认)
+
+如果您不想使用 host 网络模式,也可以使用默认的 bridge 模式,但需要注意此时容器获取的是内部 IP,您需要使用 `public` 模式获取公网 IP:
+
+```bash
+docker run -d \
+  -e DDNS_DNS=dnspod \
+  -e DDNS_ID=12345 \
+  -e DDNS_TOKEN=mytokenkey \
+  -e DDNS_IPV4=example.com \
+  -e DDNS_INDEX4=public \
+  newfuture/ddns
+```
+
+## 高级配置
+
+### 自定义定时更新频率
+
+默认情况下,容器每 5 分钟执行一次 DDNS 更新。您可以通过挂载自定义的 crontab 文件来修改定时策略:
+
+```bash
+# 创建自定义 crontab 文件
+echo "*/10 * * * * cd /ddns && /bin/ddns" > mycron
+# 挂载自定义 crontab 文件
+docker run -d \
+  -v /path/to/config/:/ddns/ \
+  -v $(pwd)/mycron:/etc/crontabs/root \
+  --network host \
+  newfuture/ddns
+```
+
+### 一次性运行(不启用定时任务)
+
+如果您只想执行一次更新而不启用定时任务,可以直接传递参数给容器:
+
+```bash
+docker run --rm \
+  -e DDNS_DNS=dnspod \
+  -e DDNS_ID=12345 \
+  -e DDNS_TOKEN=mytokenkey \
+  -e DDNS_IPV4=example.com \
+  --network host \
+  newfuture/ddns --debug
+```
+
+这里 `--debug` 是传递给 DDNS 程序的参数,启用调试模式。任何以 `-` 开头的参数都会被传递给 DDNS 程序。
+
+### 多域名配置
+
+环境变量方式配置多域名:
+
+```bash
+docker run -d \
+  -e DDNS_DNS=dnspod \
+  -e DDNS_ID=12345 \
+  -e DDNS_TOKEN=mytokenkey \
+  -e DDNS_IPV4='["example.com", "www.example.com", "sub.example.com"]' \
+  -e DDNS_IPV6='["example.com", "ipv6.example.com"]' \
+  --network host \
+  newfuture/ddns
+```
+
+### 启用IPv6支持
+
+要在Docker容器中使用IPv6,需要确保Docker守护程序配置了IPv6支持:
+
+1. 编辑 `/etc/docker/daemon.json`:
+
+```json
+{
+  "ipv6": true,
+  "fixed-cidr-v6": "fd00::/80"
+}
+```
+
+2. 重启Docker服务:
+
+```bash
+sudo systemctl restart docker
+```
+
+3. 启动容器时启用IPv6:
+
+```bash
+docker run -d \
+  --network host \
+  -e DDNS_DNS=dnspod \
+  -e DDNS_ID=12345 \
+  -e DDNS_TOKEN=mytokenkey \
+  -e DDNS_IPV6=example.com \
+  newfuture/ddns
+```
+
+## Docker Compose 示例
+
+创建 `docker-compose.yml` 文件:
+
+### 基本环境变量配置
+
+```yaml
+version: '3'
+services:
+  ddns:
+    image: newfuture/ddns:latest
+    restart: always
+    network_mode: host
+    environment:
+      - DDNS_DNS=dnspod
+      - DDNS_ID=12345
+      - DDNS_TOKEN=mytokenkey
+      - DDNS_IPV4=example.com,www.example.com
+      - DDNS_IPV6=example.com,ipv6.example.com
+      - DDNS_TTL=600
+      - DDNS_LOG_LEVEL=INFO
+```
+
+### 使用配置文件
+
+```yaml
+version: '3'
+services:
+  ddns:
+    image: newfuture/ddns:latest
+    restart: always
+    network_mode: host
+    volumes:
+      - ./config:/ddns
+```
+
+运行 Docker Compose:
+
+```bash
+docker-compose up -d
+```
+
+## 使用自定义镜像
+
+如果您需要在容器中添加其他工具或自定义环境,可以基于官方镜像创建自己的 Dockerfile:
+
+```dockerfile
+FROM newfuture/ddns:latest
+
+# 安装额外的工具
+RUN apk add --no-cache curl
+
+# 添加自定义脚本
+COPY custom-script.sh /bin/
+RUN chmod +x /bin/custom-script.sh
+
+# 覆盖默认入口点(可选)
+# ENTRYPOINT ["/bin/custom-script.sh"]
+```
+
+## 容器日志查看
+
+查看容器输出日志:
+
+```bash
+docker logs ddns
+```
+
+实时跟踪日志:
+
+```bash
+docker logs -f ddns
+```
+
+## 排障和常见问题
+
+### 容器无法获取正确的IP地址
+
+**问题**: DDNS无法正确获取主机IP
+
+**解决方案**:
+
+1. 使用 `--network host` 网络模式
+2. 或者设置 `-e DDNS_INDEX4=public` 强制使用公网API获取IP
+
+### 未收到定时任务更新
+
+**问题**: 容器运行但不自动更新DNS
+
+**解决方案**:
+
+1. 检查容器日志 `docker logs ddns`
+2. 确认容器没有被暂停 `docker ps -a`
+3. 尝试手动执行更新 `docker exec ddns /bin/ddns`
+
+### 首次运行后立即退出
+
+**问题**: 容器启动后立即退出
+
+**解决方案**:
+
+1. 添加 `-it` 参数以交互方式运行查看问题 `docker run -it --rm newfuture/ddns`
+2. 检查环境变量或配置文件是否正确设置
+
+### 网络连接问题
+
+**问题**: 容器无法连接到DNS服务商API
+
+**解决方案**:
+
+1. 检查网络连接 `docker exec ddns ping api.dnspod.cn`
+2. 配置HTTP代理 `-e DDNS_PROXY=http://proxy:port`
+
+## 高级主题
+
+### 持久化数据
+
+为了保存DDNS的缓存数据,避免频繁API调用,可以挂载缓存目录:
+
+```bash
+docker run -d \
+  -e DDNS_DNS=dnspod \
+  -e DDNS_ID=12345 \
+  -e DDNS_TOKEN=mytokenkey \
+  -e DDNS_IPV4=example.com \
+  -e DDNS_CACHE=/ddns/cache.json \
+  -v /path/to/cache:/ddns \
+  --network host \
+  newfuture/ddns
+```
+
+### 容器健康检查
+
+Docker Compose配置添加健康检查:
+
+```yaml
+version: '3'
+services:
+  ddns:
+    image: newfuture/ddns:latest
+    restart: always
+    network_mode: host
+    environment:
+      - DDNS_DNS=dnspod
+      - DDNS_ID=12345
+      - DDNS_TOKEN=mytokenkey
+      - DDNS_IPV4=example.com
+    healthcheck:
+      test: ["CMD", "pgrep", "crond"]
+      interval: 5m
+      timeout: 10s
+      retries: 3
+```
+
+## 更多资源
+
+- [DDNS GitHub 主页](https://github.com/NewFuture/DDNS)
+- [Docker Hub - newfuture/ddns](https://hub.docker.com/r/newfuture/ddns)
+- [环境变量配置详情](env.md)
+- [JSON 配置文件详情](json.md)
+- [命令行参数详情](cli.md)

+ 112 - 3
doc/env.md

@@ -2,11 +2,14 @@
 
 ## 概述
 
-DDNS 支持通过环境变量进行配置,环境变量的优先级为:**命令行参数 > 配置文件 > 环境变量**
+DDNS 支持通过环境变量进行配置,环境变量的优先级为:**[命令行参数](cli.md) > [配置文件](json.md) > 环境变量**
 
 所有环境变量都以 `DDNS_` 为前缀,后跟参数名(推荐全大写),点号(`.`)替换为下划线(`_`)。
 
-## 环境变量命名规则
+> export DDNS_xxx="xxx"  命令作用于当前主机
+> docker run -e DDNS_xxx="xxx" 命令作用于容器内
+
+### 环境变量命名规则
 
 | 配置参数 | 环境变量名称 | 示例 |
 |---------|-------------|------|
@@ -15,6 +18,42 @@ DDNS 支持通过环境变量进行配置,环境变量的优先级为:**命
 | `log.level` | `DDNS_LOG_LEVEL` 或 `ddns_log_level` | `DDNS_LOG_LEVEL=DEBUG` |
 | `log.file` | `DDNS_LOG_FILE` 或 `ddns_log_file` | `DDNS_LOG_FILE=/var/log/ddns.log` |
 
+## 环境变量完整参数列表
+
+以下是DDNS支持的所有环境变量参数列表:
+
+| 环境变量 | 类型 | 默认值 | 描述 |
+|---------|------|--------|------|
+| `DDNS_ID` | 字符串 | 无 | API访问ID或用户标识 |
+| `DDNS_TOKEN` | 字符串 | 无 | API授权令牌或密钥 |
+| `DDNS_DNS` | 字符串 | `dnspod` | DNS服务提供商 |
+| `DDNS_IPV4` | 数组/字符串 | 无 | IPv4域名列表 |
+| `DDNS_IPV6` | 数组/字符串 | 无 | IPv6域名列表 |
+| `DDNS_INDEX4` | 数组/字符串/数字 | `default` | IPv4地址获取方式 |
+| `DDNS_INDEX6` | 数组/字符串/数字 | `default` | IPv6地址获取方式 |
+| `DDNS_TTL` | 整数 | 无 | DNS解析TTL时间(秒) |
+| `DDNS_PROXY` | 数组/字符串 | 无 | HTTP代理设置 |
+| `DDNS_CACHE` | 布尔值/字符串 | `true` | 缓存设置 |
+| `DDNS_LOG_LEVEL` | 字符串 | `INFO` | 日志级别 |
+| `DDNS_LOG_FILE` | 字符串 | 无 | 日志文件路径 |
+| `DDNS_LOG_FORMAT` | 字符串 | `%(asctime)s %(levelname)s [%(module)s]: %(message)s` | 日志格式字符串 |
+| `DDNS_LOG_DATEFMT` | 字符串 | `%Y-%m-%dT%H:%M:%S` | 日期时间格式字符串 |
+
+### 参数值示例
+
+| 环境变量 | 可能的值 | 示例 |
+|---------|---------|------|
+| `DDNS_DNS` | dnspod, alidns, cloudflare, dnscom, dnspod_com, he, huaweidns, callback | `export DDNS_DNS="cloudflare"` |
+| `DDNS_IPV4` | JSON数组, 逗号分隔的字符串 | `export DDNS_IPV4='["example.com", "www.example.com"]'` |
+| `DDNS_IPV6` | JSON数组, 逗号分隔的字符串 | `export DDNS_IPV6="example.com,ipv6.example.com"` |
+| `DDNS_INDEX4` | 数字、default、public、url:、regex:、cmd:、shell: | `export DDNS_INDEX4='["public", "regex:192\\.168\\..*"]'` |
+| `DDNS_INDEX6` | 数字、default、public、url:、regex:、cmd:、shell: | `export DDNS_INDEX6="public"` |
+| `DDNS_PROXY` | IP:端口, DIRECT, 分号分隔的列表 | `export DDNS_PROXY="127.0.0.1:1080;DIRECT"` |
+| `DDNS_CACHE` | true/false, 文件路径 | `export DDNS_CACHE="/path/to/cache.json"` |
+| `DDNS_LOG_LEVEL` | DEBUG, INFO, WARNING, ERROR, CRITICAL | `export DDNS_LOG_LEVEL="DEBUG"` |
+| `DDNS_LOG_FORMAT` | 格式字符串 | `export DDNS_LOG_FORMAT="%(asctime)s: %(message)s"` |
+| `DDNS_LOG_DATEFMT` | 日期格式字符串 | `export DDNS_LOG_DATEFMT="%Y-%m-%d %H:%M:%S"` |
+
 ## 基础配置参数
 
 ### 认证信息
@@ -276,6 +315,44 @@ DDNS 支持通过环境变量进行配置,环境变量的优先级为:**命
   export DDNS_LOG_FILE="./ddns.log"
   ```
 
+#### DDNS_LOG_FORMAT
+
+- **类型**: 字符串
+- **必需**: 否
+- **默认值**: `%(asctime)s %(levelname)s [%(module)s]: %(message)s`
+- **说明**: 日志格式字符串,参考Python logging模块的格式化语法
+- **示例**:
+
+  ```bash
+  # 默认格式(含模块名)
+  export DDNS_LOG_FORMAT="%(asctime)s %(levelname)s [%(module)s]: %(message)s"
+  
+  # 包含文件名和行号(debug模式下默认格式)
+  export DDNS_LOG_FORMAT="%(asctime)s %(levelname)s [%(filename)s:%(lineno)d]: %(message)s"
+  
+  # 简单格式
+  export DDNS_LOG_FORMAT="%(levelname)s: %(message)s"
+  ```
+
+#### DDNS_LOG_DATEFMT
+
+- **类型**: 字符串
+- **必需**: 否
+- **默认值**: `%Y-%m-%dT%H:%M:%S`
+- **说明**: 日期时间格式字符串,参考Python time.strftime()的格式化语法
+- **示例**:
+
+  ```bash
+  # ISO 格式(默认)
+  export DDNS_LOG_DATEFMT="%Y-%m-%dT%H:%M:%S"
+  
+  # 简短格式
+  export DDNS_LOG_DATEFMT="%m-%d %H:%M:%S"
+  
+  # 标准格式
+  export DDNS_LOG_DATEFMT="%Y-%m-%d %H:%M:%S"
+  ```
+
 ## 使用示例
 
 ### 基础配置示例
@@ -307,6 +384,8 @@ docker run -d \
   -e DDNS_INDEX6=public \
   -e DDNS_TTL=600 \
   -e DDNS_LOG_LEVEL=INFO \
+  -e DDNS_LOG_FORMAT="%(asctime)s %(levelname)s [%(module)s]: %(message)s" \
+  -e DDNS_LOG_DATEFMT="%Y-%m-%dT%H:%M:%S" \
   --network host \
   newfuture/ddns
 ```
@@ -335,6 +414,8 @@ export DDNS_CACHE="/home/user/.ddns_cache"
 # 日志配置
 export DDNS_LOG_LEVEL="DEBUG"
 export DDNS_LOG_FILE="/var/log/ddns.log"
+export DDNS_LOG_FORMAT="%(asctime)s %(levelname)s [%(filename)s:%(lineno)d]: %(message)s"
+export DDNS_LOG_DATEFMT="%Y-%m-%d %H:%M:%S"
 
 # TTL 设置
 export DDNS_TTL="300"
@@ -349,7 +430,35 @@ ddns
    - JSON 数组格式:`'["item1", "item2"]'`(推荐)
    - 逗号分隔格式:`"item1,item2"`
 
-2. **环境变量优先级**: 环境变量会被配置文件中的非 null 值覆盖
+2. **配置优先级和字段覆盖关系**: 
+   
+   DDNS工具中的配置优先级顺序为:**命令行参数 > JSON配置文件 > 环境变量**
+   
+   - **命令行参数**: 优先级最高,会覆盖JSON配置文件和环境变量中的相同设置
+   - **JSON配置文件**: 优先级中等,会覆盖环境变量中的设置,但会被命令行参数覆盖
+   - **环境变量**: 优先级最低,当命令行参数和JSON配置文件中都没有相应设置时使用
+   
+   举例说明:
+   
+   ```
+   # 环境变量设置
+   export DDNS_TTL="600"
+   
+   # JSON配置文件内容
+   {
+     "ttl": 300
+   }
+   
+   # 命令行参数
+   ddns --ttl 900
+   ```
+   
+   在上述例子中:
+   - 最终生效的是命令行参数值:`ttl=900`
+   - 如果不提供命令行参数,则使用JSON配置文件值:`ttl=300`
+   - 如果JSON配置和命令行参数都不提供,则使用环境变量值:`ttl=600`
+   
+   另外,JSON配置文件中明确设置为`null`的值会覆盖环境变量设置,相当于未设置该值。
 
 3. **大小写兼容**: 环境变量名支持大写、小写或混合大小写
 

+ 199 - 0
doc/json.md

@@ -0,0 +1,199 @@
+# DDNS JSON配置文件参考
+
+本文档详细说明DDNS工具的JSON配置文件格式和参数。JSON配置文件优先级介于命令行参数和环境变量之间。
+
+## 基本用法
+
+默认情况下,DDNS会在当前目录查找`config.json`文件。您也可以使用`-c`参数指定配置文件路径:
+
+* 当前目录 `config.json` (注意Docker运行目录是 `/ddns/`)
+* 当前用户目录 `~/.ddns/config.json`
+* Linux当前系统 `/etc/ddns/config.json`
+
+> 注意:在Docker中使用配置文件时,需要通过卷映射将配置文件挂载到容器的`/ddns/`目录。详情请参考[Docker使用文档](docker.md)。
+
+```bash
+# 使用默认配置文件
+# 无配置时会自动生成配置文件
+ddns
+
+# 使用指定配置文件
+ddns -c /path/to/config.json
+
+# 或者使用Python源码
+python run.py -c /path/to/config.json
+```
+
+## JSON模式
+
+DDNS配置文件遵循JSON模式(Schema),推荐在配置文件中添加`$schema`字段以获得编辑器的自动补全和验证功能:
+
+```json
+{
+  "$schema": "https://ddns.newfuture.cc/schema/v4.0.json"
+}
+```
+
+## 配置参数表
+
+|  键名    |        类型        | 必需 |   默认值    |    说明          | 备注                                                                                                         |
+| :------: | :----------------: | :--: | :---------: | :---------------: | ------------------------------------------------------------------------------------------------------------ |
+|   id     |       string       |  是  |     无      |    API 访问 ID    | Cloudflare为邮箱(使用Token时留空)<br>HE.net可留空<br>华为云为Access Key ID (AK)                         |
+|  token   |       string       |  是  |     无      |  API 授权令牌     | 部分平台叫secret key                                                                                    |
+|  dns     |       string       |  否  | `"dnspod"`  |    DNS服务商      | 可选值: dnspod, alidns, cloudflare, dnscom, dnspod_com, he, huaweidns, callback                              |
+|  ipv4    |       array        |  否  |    `[]`     |   IPv4域名列表    | 为`[]`时,不会获取和更新IPv4地址                                                                            |
+|  ipv6    |       array        |  否  |    `[]`     |   IPv6域名列表    | 为`[]`时,不会获取和更新IPv6地址                                                                            |
+| index4   | string\|int\|array |  否  | `"default"` |   IPv4获取方式    | 详见下方说明                                                                                               |
+| index6   | string\|int\|array |  否  | `"default"` |   IPv6获取方式    | 详见下方说明                                                                                               |
+|  ttl     |       number       |  否  |   `null`    | DNS解析TTL时间     | 单位为秒,不设置则采用DNS默认策略                                                                          |
+|  proxy   | string\|array      |  否  |     无      | HTTP代理          | 多代理逐个尝试直到成功,`DIRECT`为直连                                                                      |
+|  debug   |       boolean      |  否  |   `false`   | 是否开启调试       | 等同于设置log.level=DEBUG,配置文件中设置此字段无效,仅命令行参数`--debug`有效                             |
+|  cache   |    string\|bool    |  否  |   `true`    | 是否缓存记录       | 正常情况打开避免频繁更新,默认位置为临时目录下`ddns.cache`,也可以指定具体路径                              |
+|  log     |       object       |  否  |   `null`    | 日志配置(可选)   | 日志配置对象,支持`level`、`file`、`format`、`datefmt`参数                                                |
+
+### log对象参数说明
+
+|  键名   |   类型   | 必需 |               默认值                |    说明    |
+| :-----: | :------: | :--: | :---------------------------------: | :--------: |
+|  level  |  string  |  否  |               `INFO`                | 日志级别   |
+|  file   |  string  |  否  |                 无                  | 日志文件路径 |
+| format  |  string  |  否  | `%(asctime)s %(levelname)s [%(module)s]: %(message)s` | 日志格式字符串 |
+| datefmt |  string  |  否  |         `%Y-%m-%dT%H:%M:%S`         | 日期时间格式 |
+
+### index4和index6参数说明
+
+`index4`和`index6`参数用于指定获取IP地址的方式,可以使用以下值:
+
+- **数字**(如`0`、`1`、`2`...):表示使用第N个网卡的IP地址
+- **字符串**:
+  - `"default"`:系统访问外网的默认IP
+  - `"public"`:使用公网IP(通过API查询)
+  - `"url:xxx"`:通过指定URL获取IP,例如`"url:http://ip.sb"`
+  - `"regex:xxx"`:使用正则表达式匹配本地网络配置中的IP,例如`"regex:192\\.168\\..*"`
+    - 注意:JSON中反斜杠需要转义,如`"regex:10\\.00\\..*"`表示匹配`10.00.`开头的IP
+  - `"cmd:xxx"`:执行指定命令并使用其输出作为IP
+  - `"shell:xxx"`:使用系统shell运行命令并使用其输出作为IP
+- **布尔值**:`false`表示禁止更新相应IP类型的DNS记录
+- **数组**:按顺序尝试不同的获取方式,使用第一个成功获取的结果
+
+## 自定义回调配置
+
+当`dns`设置为`callback`时,可通过以下方式配置自定义回调:
+
+- `id`字段:填写回调地址,以HTTP或HTTPS开头
+- `token`字段:POST参数,为空则使用GET方式发起回调
+
+支持的常量替换:
+
+| 常量名称 | 常量内容 | 说明 |
+|---------|---------|------|
+| `__DOMAIN__` | DDNS域名 | - |
+| `__RECORDTYPE__` | DDNS记录类型 | A或AAAA |
+| `__TTL__` | DDNS TTL | - |
+| `__TIMESTAMP__` | 请求发起时间戳 | 包含小数 |
+| `__IP__` | 获取的IP地址 | - |
+
+## 配置示例
+
+### 基本配置示例
+
+```json
+{
+  "$schema": "https://ddns.newfuture.cc/schema/v4.0.json",
+  "id": "12345",
+  "token": "mytokenkey",
+  "dns": "dnspod",
+  "ipv4": ["example.com", "www.example.com"],
+  "ipv6": ["example.com", "ipv6.example.com"],
+  "ttl": 600
+}
+```
+
+### 高级配置示例
+
+```json
+{
+  "$schema": "https://ddns.newfuture.cc/schema/v4.0.json",
+  "id": "12345",
+  "token": "mytokenkey",
+  "dns": "cloudflare",
+  "ipv4": ["example.com", "www.example.com"],
+  "ipv6": ["example.com", "ipv6.example.com"],
+  "index4": ["public", "regex:192\\.168\\.1\\..*"],
+  "index6": "public",
+  "ttl": 300,
+  "proxy": "127.0.0.1:1080;DIRECT",
+  "cache": "/var/cache/ddns.cache",
+  "log": {
+    "level": "DEBUG",
+    "file": "/var/log/ddns.log",
+    "format": "%(asctime)s %(levelname)s [%(filename)s:%(lineno)d]: %(message)s",
+    "datefmt": "%Y-%m-%d %H:%M:%S"
+  }
+}
+```
+
+### 使用多种IP获取方式的配置
+
+```json
+{
+  "$schema": "https://ddns.newfuture.cc/schema/v4.0.json",
+  "id": "12345",
+  "token": "mytokenkey",
+  "dns": "dnspod",
+  "ipv4": ["example.com"],
+  "ipv6": ["example.com"],
+  "index4": ["public", 0, "regex:192\\.168\\..*"],
+  "index6": ["public", "url:http://ipv6.icanhazip.com"],
+  "ttl": 600
+}
+```
+
+### 自定义回调配置示例
+
+```json
+{
+  "$schema": "https://ddns.newfuture.cc/schema/v4.0.json",
+  "id": "https://api.example.com/ddns/update?domain=__DOMAIN__&type=__RECORDTYPE__&ip=__IP__",
+  "token": "{\"domain\": \"__DOMAIN__\", \"ip\": \"__IP__\", \"timestamp\": \"__TIMESTAMP__\"}",
+  "dns": "callback",
+  "ipv4": ["example.com"],
+  "ipv6": ["example.com"],
+  "ttl": 600
+}
+```
+
+## 配置优先级和字段覆盖关系
+
+DDNS工具中的配置优先级顺序为:**命令行参数 > JSON配置文件 > 环境变量**。
+
+- **命令行参数**:优先级最高,会覆盖JSON配置文件和环境变量中的相同设置
+- **JSON配置文件**:介于命令行参数和环境变量之间,会覆盖环境变量中的设置
+- **环境变量**:优先级最低,当命令行参数和JSON配置文件中都没有相应设置时使用
+
+### 配置覆盖示例
+
+假设有以下配置:
+
+1. **环境变量**:`DDNS_TTL=600`
+2. **JSON配置文件**:`"ttl": 300`
+3. **命令行参数**:`--ttl 900`
+
+最终生效的是命令行参数的值:`ttl=900`
+
+如果没有提供命令行参数,则使用JSON配置值:`ttl=300`
+
+### 特殊情况
+
+- 当JSON配置文件中某个值明确设为`null`时,将覆盖环境变量设置,相当于未设置该值
+- 当JSON配置文件中缺少某个键时,会尝试使用对应的环境变量
+- 某些参数(如`debug`)仅在特定配置方式下有效:`debug`参数只在命令行中有效,JSON配置中的设置会被忽略
+
+## 注意事项
+
+1. 配置文件使用UTF-8编码,不包含BOM标记
+2. JSON中所有键名区分大小写
+3. 在配置文件中,对于需要使用反斜杠的字符串(如正则表达式),需要进行双重转义
+4. `debug`参数在配置文件中设置无效,仅支持命令行参数`--debug`
+5. 首次运行时会在当前目录自动生成一个模板配置文件
+6. 推荐使用支持JSONSchema的编辑器(如VSCode)编辑配置文件,可获得自动补全和验证功能

+ 10 - 4
run.py

@@ -10,7 +10,7 @@ from os import path, environ, name as os_name
 from io import TextIOWrapper
 from subprocess import check_output
 from tempfile import gettempdir
-from logging import basicConfig, info, warning, error, debug
+from logging import basicConfig, info, warning, error, debug, DEBUG, NOTSET
 
 import sys
 
@@ -126,12 +126,18 @@ def main():
     """
     init_config(__description__, __doc__, __version__)
 
+    log_level = get_config('log.level')
+    log_format = get_config('log.format', '%(asctime)s %(levelname)s [%(module)s]: %(message)s')
+    # Override log format in debug mode to include filename and line number for detailed debugging
+    if (log_level == DEBUG or log_level == NOTSET) and not log_format:
+        log_format = '%(asctime)s %(levelname)s [%(filename)s:%(lineno)d]: %(message)s'
     basicConfig(
-        level=get_config('log.level'),
-        format='%(asctime)s [%(levelname)s] %(message)s',
-        datefmt='%m-%d %H:%M:%S',
+        level=log_level,
+        format=log_format,
+        datefmt=get_config('log.datefmt', '%Y-%m-%dT%H:%M:%S'),
         filename=get_config('log.file'),
     )
+
     info("DDNS[ %s ] run: %s %s", __version__, os_name, sys.platform)
 
     # Dynamically import the dns module as configuration

+ 13 - 1
schema/v4.0.json

@@ -192,7 +192,7 @@
       "$id": "/properties/log",
       "type": "object",
       "title": "Log Config",
-      "description": "日志配置,支持自定义日志级别和输出位置。可通过命令行 --log.level, --log.file 或环境变量 DDNS_LOG_LEVEL, DDNS_LOG_FILE 设置。",
+      "description": "日志配置,支持自定义日志级别、输出位置、格式和日期格式。可通过命令行 --log.level, --log.file, --log.format, --log.datefmt 或环境变量 DDNS_LOG_LEVEL, DDNS_LOG_FILE, DDNS_LOG_FORMAT, DDNS_LOG_DATEFMT 设置。",
       "properties": {
         "level": {
           "type": "string",
@@ -205,6 +205,18 @@
           "type": ["string", "null"],
           "title": "Log Output File",
           "description": "日志输出文件路径,留空或为null时输出到控制台"
+        },
+        "format": {
+          "type": ["string", "null"],
+          "title": "Log Format",
+          "description": "日志格式,参考Python logging模块的格式字符串",
+          "default": "%(asctime)s %(levelname)s [%(module)s]: %(message)s"
+        },
+        "datefmt": {
+          "type": ["string", "null"],
+          "title": "Date Format",
+          "description": "日期时间格式,参考Python time.strftime()的格式字符串",
+          "default": "%Y-%m-%dT%H:%M:%S"
         }
       },
       "required": [],

+ 15 - 2
util/config.py

@@ -96,12 +96,22 @@ def init_config(description, doc, version):
                         help='https proxy [设置http 代理,多代理逐个尝试直到成功]')
     parser.add_argument('--cache',  type=str2bool, nargs='?',
                         const=True, help='cache flag [启用缓存,可配配置路径或开关]')
+    parser.add_argument('--debug', action='store_true',
+                        help='debug mode [调试模式,等同log.level=DEBUG]')
     parser.add_argument('--log.file', metavar='LOG_FILE',
                         help='log file [日志文件,默认标准输出]')
     parser.add_argument('--log.level', type=log_level,
                         metavar='|'.join(log_levels))
+    parser.add_argument('--log.format', metavar='LOG_FORMAT',
+                        help='log format [日志格式字符串]')
+    parser.add_argument('--log.datefmt', metavar='DATE_FORMAT',
+                        help='date format [日期格式字符串]')
 
     __cli_args = parser.parse_args()
+    if __cli_args.debug:
+        # 如果启用调试模式,则设置日志级别为 DEBUG
+        setattr(__cli_args, 'log.level', log_level('DEBUG'))
+
     is_configfile_required = not get_config("token") and not get_config("id")
     config_file = get_config("config")
     if not config_file:
@@ -141,6 +151,10 @@ def __load_config(config_path):
                     __config['log.level'] = log_level(__config['log']['level'])
                 if 'file' in __config['log']:
                     __config['log.file'] = __config['log']['file']
+                if 'format' in __config['log']:
+                    __config['log.format'] = __config['log']['format']
+                if 'datefmt' in __config['log']:
+                    __config['log.datefmt'] = __config['log']['datefmt']
             elif 'log.level' in __config:
                 __config['log.level'] = log_level(__config['log.level'])
     except Exception as e:
@@ -211,8 +225,7 @@ def generate_config(config_path):
         'ttl': None,
         'proxy': None,
         'log': {
-            'level': 'INFO',
-            'file': None
+            'level': 'INFO'
         }
     }
     try: