本文想定时上报orangepi的WLAN网络接口的IP地址,因为orangepi连接的是校园网且通过DHCP服务器分配IP地址,所以IP地址是会变化的,但我又不想每次都打开终端通过以太网连接到orangepi再查看WLAN网络接口的IP地址,因此有了本文的尝试。

linux 系统设置开机自启脚本方式 | Thee
flask 框架视图函数错误 TypeError: The view function did not return a valid response. -CSDN 博客
crontab 可视化分析网站:Crontab 在线生成器 | 菜鸟工具

云服务器配置

香橙派服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from flask import Flask, request

# 创建orangepi上传ip地址的服务器 使用nginx反向代理
# ip日志文件为/var/log/latest_orangepi_ip.txt
# 已创建systemctl开机自启脚本服务orangepi_ip_reporter.service

app = Flask(__name__)
API_KEY = "secret_key" # 与香橙派脚本中的API_KEY一致

@app.route('/update_ip', methods=['POST'])
def update_ip():
data = request.json
if data.get('key') != API_KEY:
return "Unauthorized", 401
with open('/var/log/latest_orangepi_ip.txt', 'w') as f:
f.write(data['ip']+'\n')
return "OK", 200

@app.route('/update_ip', methods=['GET'])
def get_ip():
"""处理 GET 查询IP"""
# 验证密钥(通过请求体)
client_key = request.get_json().get('key') # 从请求体获取

if client_key != API_KEY:
return "Unauthorized", 401

return "OK", 200

使用 Gunicorn 启动 Flask 应用

  • 安装 Gunicorn
1
2
# 在云服务器上安装
$ pip install gunicorn
  • 创建/etc/systemd/system/orangepi_ip_reporter.service 文件
1
2
3
4
5
6
7
8
9
10
11
12
[Unit]
Description=Gunicorn instance for IP Reporter
After=network.target

[Service]
User=root
WorkingDirectory=/home/thee/code_sources
ExecStart=/usr/local/bin/gunicorn -w 2 -b 127.0.0.1:5000 orangepi2_ip_server:app
Restart=always

[Install]
WantedBy=multi-user.target
  • 启动 systemd 服务
1
2
3
$ sudo systemctl start orangepi_ip_reporter
$ sudo systemctl enable orangepi_ip_reporter
$ sudo systemctl daemon-reload

nginx 反向代理

  • 创建/etc/nginx/conf.d/orangepi.conf文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}

server {
listen 443 ssl;
server_name example.com;

ssl_certificate /path/fullchain.pem;
ssl_certificate_key /path/privkey.pem;

location /update_ip {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

  • 重启nginx服务

香橙派配置

上传 IP 地址代码

  • orangepi_report_ip.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#!/usr/bin/env python3
import requests
import json
import logging
from datetime import datetime
import socket
import fcntl
import struct

# 读取wlan0的ip地址并上报给云服务器,相关日志文件路径为/var/log/orangepi_report_ip.log
# 已配置crontab定时任务,每天零点自动上传ip地址

# 配置部分
API_URL = "https://example.com/update_ip" # HTTP API 地址
API_KEY = "secret_key" # 认证密钥
NET_INTERFACE = "wlan0" # 按需改为 eth0/wlan0 等
LOG_FILE = "/var/log/orangepi_report_ip.log" # 日志文件路径

# 设置日志记录
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(LOG_FILE),
logging.StreamHandler()
]
)

def get_ip_address(interface):
"""获取指定网络接口的IP地址"""
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ip = socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', interface[:15].encode('utf-8'))
)[20:24])
return ip
except Exception as e:
logging.error(f"获取 {interface} 接口IP失败: {str(e)}")
return None

def report_ip():
"""上报IP到服务器"""
# 获取本机IP
ip_addr = get_ip_address(NET_INTERFACE)
if not ip_addr:
return False

# 生成时间戳
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

# 准备上报数据
data = {
"ip": ip_addr,
"timestamp": timestamp,
"key": API_KEY
}

# 上报到服务器
try:
response = requests.post(
API_URL,
headers={"Content-Type": "application/json"},
data=json.dumps(data),
timeout=10 # 设置超时时间
)

if response.status_code == 200:
logging.info(f"IP上报成功: {ip_addr}")
return True
else:
logging.error(f"服务器返回错误: {response.status_code} - {response.text}")
return False

except requests.exceptions.RequestException as e:
logging.error(f"请求服务器失败: {str(e)}")
return False
except Exception as e:
logging.error(f"发生未知错误: {str(e)}")
return False

if __name__ == "__main__":
# 执行上报
success = report_ip()

# 记录到日志文件
with open(LOG_FILE, 'a') as f:
status = "成功" if success else "失败"
log_entry = f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - {NET_INTERFACE} IP上报{status}\n"
f.write(log_entry)

cron 定时服务

  • cron 服务配置,执行crontab -e命令后配置定时任务:
1
2
# 每天零点定时上传香橙派ip地址到云服务器
0 0 * * * /path/to/orangepi_report_ip.py