通过在serv00上搭建Alist复现在huggingface保活运行程序

本文主要集中在huggingface保活,在serv00部署的所有服务都可以参考下面方式进行保活

1.开放一个端口并开启应用权限

2.将域名托管到serv00并创建Website

域名托管不在这里叙述,可以看这部分,也可以使用CF进行托管

创建Website

3. 创建mysql数据库

记住你创建的数据库,等会需要用

4.下载Alist

进入 public_html 文件下

cd /usr/home/你的serv名字/domains/域名/public_html

下载alist包

wget https://github.com/uubulb/alist-freebsd/releases/download/v3.36.0/alist

5.进入文件管理器后台创建并编辑 data/config.json文件

在下载alist同级目录创建data文件,并进入data文件在其下创建config.json文本

把代码放入其中

{
  "force": false,
  "site_url": "",
  "cdn": "",
  "jwt_secret": "random_generated",
  "token_expires_in": 48,
  "database": {
    "type": "sqlite3",
    "host": "",
    "port": 0,
    "user": "",
    "password": "",
    "name": "",
    "db_file": "data\\data.db",
    "table_prefix": "x_",
    "ssl_mode": "",
    "dsn": ""
  },
  "meilisearch": {
    "host": "http://localhost:7700",
    "api_key": "",
    "index_prefix": ""
  },
  "scheme": {
    "address": "0.0.0.0",
    "http_port": 5244,
    "https_port": -1,
    "force_https": false,
    "cert_file": "",
    "key_file": "",
    "unix_file": "",
    "unix_file_perm": ""
  },
  "temp_dir": "data\\temp",
  "bleve_dir": "data\\bleve",
  "dist_dir": "",
  "log": {
    "enable": true,
    "name": "data\\log\\log.log",
    "max_size": 50,
    "max_backups": 30,
    "max_age": 28,
    "compress": false
  },
  "delayed_start": 0,
  "max_connections": 0,
  "tls_insecure_skip_verify": true,
  "tasks": {
    "download": {
      "workers": 5,
      "max_retry": 1
    },
    "transfer": {
      "workers": 5,
      "max_retry": 2
    },
    "upload": {
      "workers": 5,
      "max_retry": 0
    },
    "copy": {
      "workers": 5,
      "max_retry": 2
    }
  },
  "cors": {
    "allow_origins": [
      "*"
    ],
    "allow_methods": [
      "*"
    ],
    "allow_headers": [
      "*"
    ]
  },
  "s3": {
    "enable": false,
    "port": 5246,
    "ssl": false
  }
}

修改

database": {
    "type": "sqlite3",
    "host": "",
    "port": 0,
    "user": "",
    "password": "",
    "name": "",

"site_url": "",为你你自己的:格式:https://xxx.com
type改为mysql,余信息填写你前面创建的mysql数据库
"http_port": 5244,改为你自己放行的端口

5.进行alist调试并获取密码

赋权并执行alist

chmod +x alist && ./alist server

获取你的密码并保存(只出现一次

进入后台并更改你的账号密码
初始账号:admin
密码:前面获取到的

下面是保活的重点

6.创建start.sh文件

在alist同级目录创建start.sh文件,这个是启动文件,执行./alist server命令(因为alist本身不自带,需要自行创建)其余项目类似

#!/bin/bash

cd /usr/home/Serv00账号名/domains/域名/public_html
chmod +x alist
./alist server

路径对应你自己的,并将其中的serv00域名换为你自己的,下面同理

7.创建restart.sh文件

在alist同级目录创建restart.sh文件,这个文件是保活文件,用于检测start.sh是否运行,没运行则重启服务

#!/bin/bash

# 设置脚本路径
SCRIPT_PATH="/usr/home/Serv00账号名/domains/域名/public_html/start.sh"
WORK_DIR="/usr/home/Serv00账号名/domains/域名/public_html"

# 检查脚本是否在运行
if ! pgrep -f "$SCRIPT_PATH" > /dev/null
then
    # 如果脚本没有运行,则重新启动它
    cd "$WORK_DIR"
    nohup ./start.sh > /dev/null 2>&1 &
    echo "Restarted start.sh at $(date)" >> "$WORK_DIR/restart_log.txt"
fi

8.赋权所创建的脚本

chmod +x start.sh restart.sh

9.在CF上保活

9.进入huggingface创建一个空间(不稳定)




放入以下代码:

FROM python:3.8-slim-buster

WORKDIR /app

RUN apt-get update && apt-get install -y openssh-client
RUN pip install paramiko schedule flask

COPY vps_monitor.py .

EXPOSE 8080

CMD ["python", "-u", "vps_monitor.py"]


编辑 README.md,README.md 添加app_port: 8080

创建一个名为vps_monitor.py的文本


放入以下代码并保存

import paramiko
import schedule
import time
import os
import sys
from flask import Flask, jsonify, render_template_string
from threading import Thread
import logging

app = Flask(__name__)

vps_status = {}

# 设置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.StreamHandler(sys.stdout),
        logging.StreamHandler(sys.stderr)
    ]
)
logger = logging.getLogger()

def get_vps_configs():
    configs = []
    index = 1
    while True:
        hostname = os.environ.get(f'HOSTNAME_{index}')
        if not hostname:
            break
        
        config = {
            'index': index,
            'hostname': hostname,
            'username': os.environ.get(f'USERNAME_{index}'),
            'password': os.environ.get(f'PASSWORD_{index}'),
            'script_path': os.environ.get(f'SCRIPT_PATH_{index}')
        }
        configs.append(config)
        
        logger.info(f"Config {index}: {config['hostname']}, {config['username']}, {config['script_path']}")
        
        index += 1
    return configs

def check_and_run_script(config):
    logger.info(f"Checking VPS {config['index']}: {config['hostname']}")
    client = None
    try:
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        
        client.connect(
            hostname=config['hostname'],
            username=config['username'],
            password=config['password'],
            port=22
        )
        
        script_path = config['script_path']
        script_name = os.path.basename(script_path)
        
        check_command = f"ps -eo args | grep {script_name} | grep -v grep"
        
        stdin, stdout, stderr = client.exec_command(check_command)
        output = stdout.read().decode('utf-8').strip()
        
        if output and script_path in output:
            status = "Running"
            logger.info(f"Script is running on {config['hostname']}")
        else:
            logger.info(f"Script not running on {config['hostname']}. Executing restart script.")
            restart_command = f"nohup /bin/sh {script_path} > /dev/null 2>&1 &"
            stdin, stdout, stderr = client.exec_command(restart_command)
            
            status = "Restarted"
            logger.info(f"Script restarted on {config['hostname']}")
        
        vps_status[config['index']] = {
            'index': config['index'],
            'hostname': config['hostname'],
            'status': status,
            'last_check': time.strftime('%Y-%m-%d %H:%M:%S'),
            'username': config['username']
        }
        
    except Exception as e:
        logger.error(f"Error occurred while checking VPS {config['index']} - {config['hostname']}: {str(e)}")
        vps_status[config['index']] = {
            'index': config['index'],
            'hostname': config['hostname'],
            'status': f"Error: {str(e)}",
            'last_check': time.strftime('%Y-%m-%d %H:%M:%S'),
            'username': config['username']
        }
    finally:
        if client:
            client.close()

def check_all_vps():
    logger.info("Starting VPS check")
    vps_configs = get_vps_configs()
    for config in vps_configs:
        check_and_run_script(config)
    
    # 创建表格头
    table = "+---------+-----------------------+----------+-------------------------+----------+\n"
    table += "| Index   | Hostname              | Status   | Last Check              | Username |\n"
    table += "+---------+-----------------------+----------+-------------------------+----------+\n"
    
    # 添加每个VPS的状态
    for index in sorted(vps_status.keys()):
        status = vps_status[index]
        table += "| {:<7} | {:<21} | {:<8} | {:<23} | {:<8} |\n".format(
            status['index'],
            status['hostname'][:21],
            status['status'][:8],
            status['last_check'],
            status['username'][:8]
        )
        table += "+---------+-----------------------+----------+-------------------------+----------+\n"
    
    logger.info("\n" + table)

@app.route('/')
def index():
    html = '''
    <h1>VPS Status Overview</h1>
    <table border="1">
        <tr>
            <th>Index</th>
            <th>Hostname</th>
            <th>Status</th>
            <th>Last Check</th>
            <th>Username</th>
        </tr>
        {% for index in vps_status.keys()|sort %}
        {% set data = vps_status[index] %}
        <tr>
            <td>{{ data['index'] }}</td>
            <td><a href="/status/{{ data['index'] }}">{{ data['hostname'] }}</a></td>
            <td>{{ data['status'] }}</td>
            <td>{{ data['last_check'] }}</td>
            <td>{{ data['username'] }}</td>
        </tr>
        {% endfor %}
    </table>
    '''
    return render_template_string(html, vps_status=vps_status)

@app.route('/status/<int:index>')
def vps_status_detail(index):
    if index in vps_status:
        return jsonify(vps_status[index])
    else:
        return jsonify({"error": "VPS not found"}), 404

@app.route('/health')
def health_check():
    return jsonify({"status": "healthy", "uptime": time.time() - start_time}), 200

def run_flask():
    app.run(host='0.0.0.0', port=8080)

def main():
    global start_time
    start_time = time.time()
    
    logger.info("===== VPS monitoring script is starting =====")
    
    flask_thread = Thread(target=run_flask)
    flask_thread.start()
    logger.info("Flask server started in background")

    vps_configs = get_vps_configs()
    logger.info(f"Found {len(vps_configs)} VPS configurations")

    logger.info("Running initial VPS check")
    check_all_vps()

    schedule.every(15).minutes.do(check_all_vps)
    logger.info("Scheduled VPS check every 15 minutes")
    
    logger.info("===== VPS monitoring script is running =====")
    
    heartbeat_count = 0
    while True:
        schedule.run_pending()
        time.sleep(60)
        heartbeat_count += 1
        if heartbeat_count % 5 == 0:  # 每5分钟输出一次心跳信息
            logger.info(f"Heartbeat: Script is still running. Uptime: {heartbeat_count} minutes")

if __name__ == "__main__":
    main()

9.在后台填写变量

USERNAME_X   
HOSTNAME_X
PASSWORD_X
SCRIPT_PATH_X

X为数字编号 如(1,2,3),每个主机4项要相同才能对应
如:

USERNAME_1     
HOSTNAME_1
PASSWORD_1
SCRIPT_PATH_1

USERNAME 为serv00用户名,HOSTNAME 为主机名(如:s3.serv00.com ),PASSWORD 为serv00密码,SCRIPT_PATH 为执行脚本的绝对路径(如:/usr/home/serv00用户名/domains/域名/public_html/restart.sh


running后点击logs可以查看进度

点击app可看到服务器正常启动,这时你可以访问你的网址进入你部署的项目

在huggingface部署的重启脚本避免了后台被清除,因为他是远程访问的 :wink:

他可以保活账号并且保活运行的程序,可以多个账号一起保活,前面的4个变量序号一致就行

参考项目

276 Likes

感谢你的分享

4 Likes

感谢分享

5 Likes

太强了吧!

4 Likes

感谢分享

4 Likes

另辟蹊径,不错不错。感谢分享

3 Likes

用上了,

4 Likes

怎么样,还行吧 :wink:

3 Likes

真不错

4 Likes

:cow:

2 Likes

这种配置能搭alist?

3 Likes

alist很小啊

2 Likes

halo都能干,只是运行超了100多m :wink:
看这个 :wink:
https://newapi.rr.nu

3 Likes

我昨天搞了一个S8波兰的,还不知道搭啥服务

3 Likes

论坛里找找,有很多教程
serv00

1 Like

感谢佬

6 Likes

VPS 1 - s8.serv00.com: Status: Error: [Errno 110] Connection timed out, Username: sakamoto

这个怎么解决啊佬

1 Like

huggingface中的吗?

4 Likes

成功,感谢分享

3 Likes

是的

3 Likes