File size: 3,290 Bytes
6107d9f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# app.py
import gradio as gr
import subprocess
import os
import shlex # 用于安全地分割命令

# 检查配置文件路径(主要用于调试)
config_path = "/root/.config/rclone/rclone.conf"
if os.path.exists(config_path):
    print(f"INFO: rclone config file found at {config_path}")
    # 可以在这里添加读取大小或少量内容进行验证,但避免打印敏感信息
    # config_size = os.path.getsize(config_path)
    # print(f"INFO: rclone config file size: {config_size} bytes")
    if os.path.getsize(config_path) == 0:
         print("WARNING: rclone config file exists but is empty. Check RCLONE_CONFIG_CONTENT secret value.")
else:
    print(f"WARNING: rclone config file not found at {config_path}. Ensure RCLONE_CONFIG_CONTENT secret is set correctly.")

def run_rclone_command(command_string):
    """ Executes an rclone command and returns its output """
    if not command_string or not command_string.strip().lower().startswith("rclone"):
        return "Error: Invalid command. Input must start with 'rclone'."

    # 使用 shlex 安全地分割命令和参数
    try:
        # 将命令转换为列表,以便 subprocess.run 安全处理
        args = shlex.split(command_string)
        print(f"Executing command: {' '.join(args)}") # Log the command being run

        # 执行 rclone 命令
        result = subprocess.run(
            args,
            capture_output=True, # 捕获标准输出和标准错误
            text=True,          # 以文本形式捕获输出
            check=False         # 不会在命令失败时抛出异常,而是检查返回码
        )

        # 准备输出字符串
        output = f"Command: {' '.join(args)}\n"
        output += f"--- STDOUT ---\n{result.stdout}\n"
        if result.stderr:
            output += f"--- STDERR ---\n{result.stderr}\n"
        output += f"--- Exit Code: {result.returncode} ---"

        print(f"Command finished with exit code {result.returncode}") # Log exit code
        return output

    except FileNotFoundError:
        print(f"Error: '{args[0]}' not found.")
        return f"Error: '{args[0]}' command not found. Is rclone correctly installed in the Docker container?"
    except Exception as e:
        print(f"Error executing command: {e}")
        return f"An unexpected error occurred: {str(e)}"

# 创建 Gradio 用户界面
iface = gr.Interface(
    fn=run_rclone_command,
    inputs=gr.Textbox(lines=2, placeholder="Enter rclone command here...\ne.g., rclone version", label="Rclone Command"),
    outputs=gr.Textbox(lines=20, label="Output Log"),
    title="Rclone Command Runner",
    description="Enter an rclone command below and click 'Submit'. Ensure your rclone configuration is provided via the `RCLONE_CONFIG_CONTENT` secret in Space settings.",
    examples=[
        ["rclone version"],
        ["rclone listremotes"],
        ["rclone config file"], # 显示 rclone 正在使用的配置文件路径
        # ["rclone lsd YourRemoteName:"] # 取消注释并替换 YourRemoteName
    ],
    allow_flagging='never' # 禁止用户标记输出(通常用于反馈)
)

# 启动 Gradio 应用
if __name__ == "__main__":
    # server_name="0.0.0.0" 使应用在 Docker 容器内监听所有接口
    iface.launch(server_name="0.0.0.0")