国内VPS的青龙面板中利用 WebSSH 保活 serv00 和 ct8 等服务(支持多账号, 也适用于 serv00 的某些区在国内连不上的问题)

WebSSH 使用的佬友搭建的地址:https://webssh.linux-do.rr.nu/
来源:在Serv00上部署WebSSH——妈妈再也不用担心我无法SSH连接Serv00(网站挂了)
脚本参考的:[ 暂停维护 ] Linux.do保活脚本青龙版来喽

1. 创建依赖

选择左侧依赖管理菜单, 点击右上角创建依赖, 依赖类型选择 python3 , 名称输入 selenium , 点击确定

再点击右上角创建依赖, 依赖类型选择 linux , 名称输入下面内容, 自动拆分选择 , 之后点击确定

chromium
chromium-chromedriver

2. 创建脚本

打开左侧菜单脚本管理, 点击右上角加号进行创建脚本, 类型选择空文件 , 文件名为 webSSH_keep_alive.py , 点击确定

之后粘贴以下脚本内容

import logging
import time
import random
import os
import json
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException
import shutil

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s] %(message)s', datefmt='%H:%M:%S')

# 获取环境变量中的账号信息
accounts_json = os.getenv('VPS_ACCOUNTS')
if not accounts_json:
    logging.error("未找到环境变量 VPS_ACCOUNTS,请确保已设置环境变量。")
    exit(1)

# 检查 chromedriver 路径
chromedriver_path = shutil.which("chromedriver")
if not chromedriver_path:
    logging.error("chromedriver 未找到,请确保已安装并配置正确的路径。")
    exit(1)

# 设置 Chrome 选项
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--disable-dev-shm-usage")

def simulate_typing(element, text, typing_speed=0.1, random_delay=True):
    logging.info(f"开始模拟输入: {text}")
    for char in text:
        element.send_keys(char)
        if random_delay:
            time.sleep(typing_speed + random.uniform(0, 0.1))
        else:
            time.sleep(typing_speed)

def find_and_fill(driver, by, value, text, typing_speed=0.1, random_delay=True):
    try:
        logging.info(f"尝试查找元素 {value}")
        element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((by, value)))
        simulate_typing(element, text, typing_speed, random_delay)
        logging.info(f"✔️ 成功找到并填写元素 {value}")
        return True
    except TimeoutException:
        logging.error(f"❌ 未能找到元素 {value}")
        return False

def connect_vps(ip, port, username, password):
    logging.info("💻 启动 WebDriver")
    driver = webdriver.Chrome(service=Service(chromedriver_path), options=chrome_options)
    try:
        logging.info("🔍 访问 https://webssh.linux-do.rr.nu/")
        driver.get('https://webssh.linux-do.rr.nu/')

        # 填写表单信息
        if not find_and_fill(driver, By.ID, 'hostname', ip):
            return False
        if not find_and_fill(driver, By.ID, 'port', str(port)):
            return False
        if not find_and_fill(driver, By.ID, 'username', username):
            return False
        if not find_and_fill(driver, By.ID, 'password', password):
            return False

        # 点击连接按钮
        try:
            logging.info("尝试查找连接按钮")
            connect_button = driver.find_element(By.XPATH, "//button[@type='submit' and text()='Connect']")
            connect_button.click()
            logging.info("✔️ 成功找到并点击连接按钮")
        except NoSuchElementException:
            logging.error("❌ 未能找到连接按钮")
            return False

        # 检查连接结果
        logging.info("等待连接结果")
        try:
            # 等待出现 terminal 或内容不为空的 status 元素
            element = WebDriverWait(driver, 30).until(
                EC.any_of(
                    EC.presence_of_element_located((By.CSS_SELECTOR, '#terminal:not(:empty)')),
                    EC.presence_of_element_located((By.CSS_SELECTOR, '#status:not(:empty)'))
                )
            )

            if element.get_attribute("id") == "terminal":
                logging.info("😁😁😁 连接成功")
                return True
            elif element.get_attribute("id") == "status":
                status_text = element.text.strip()
                logging.info(f"😭😭😭 连接失败,状态信息: {status_text}")
                return False

        except TimeoutException:
            logging.error("❌ 未能确定连接状态")
            return False

    except Exception as e:
        logging.error(f"发生错误: {e}")
        return False

    finally:
        logging.info("关闭 WebDriver")
        driver.quit()

# 解析账号信息
try:
    accounts_list = json.loads(accounts_json)
    logging.info(f"共获取到 {len(accounts_list)} 个账号。")
    logging.info("\n")  # 添加换行
except json.JSONDecodeError as e:
    logging.error(f"解析账号信息时发生错误: {e}")
    exit(1)

for index, account in enumerate(accounts_list):
    try:
        ip = account['host']
        port = account['port']
        username = account['username']
        password = account['password']
        logging.info(f"开始登录第 {index + 1} 个账号: IP={ip}, Username={username}")
        success = connect_vps(ip, port, username, password)
        if success:
            logging.info(f"成功连接到 VPS: IP={ip}, Username={username}")
        else:
            logging.error(f"连接 VPS 失败: IP={ip}, Username={username}")
    except KeyError as e:
        logging.error(f"账号信息格式错误,缺少键: {e}")
    logging.info("\n")  # 添加换行

粘贴好之后点击右上角保存

3. 创建环境变量

点击左侧环境变量菜单, 点击右上角创建变量按钮, 名称输入 VPS_ACCOUNTS , 自动拆分选择 , 值填写示例如下(支持多账号), 备注可填可不填, 之后点击确定

[{"host": "s1.serv00.com", "port": 22, "username": "user1", "password": "pass1"}, {"host": "s2.serv00.com", "port": 22, "username": "user2", "password": "pass2"}]

值说明:
host:连接地址
port:端口
username:用户名称
password:密码

4. 创建定时任务

点击左侧定时任务菜单, 点击右上角创建任务按钮, 名称输入 webssh 登录 serv00 保活 , 可随便填写, 命令/脚本输入 task webSSH_keep_alive.py , 定时规则输入 0 1 * * * , 之后点击确定

5. 测试运行

点击任务右边的运行, 之后打开日志, 运行结果如下所示

可以使用 ssh 工具连接 serv00 查看上次登录时间, 确认下是否登录成功

image

image

时间对不上是因为波兰跟中国时间会相差七个小时, 计算之后可以看到时间只会相差一两秒, 说明刚才登录成功了

2 个赞

镜像源补充:
Python 软件包镜像源
https://mirrors.aliyun.com/pypi/simple/
Linux 软件包镜像源
https://mirrors.aliyun.com

谢谢分享,先保活再说

感谢大佬分享

2 个赞

利用SCP或者sftp上传下载文件到serv00算不算登陆ssh呢?

应该也算吧, 不登录怎么传文件呢

那写个小脚本放到Linux定时上传或者下载一个小文件不就保活了,用得着这么麻烦去操作吗?

你下载文件肯定不算保活啊, 需要 ssh 登录或者登录后台才算, 你用 sftp 传文件的话肯定是需要先 ssh 登录的吧, 而且这个方法可以用于登录国内访问不了的 serv00 服务

肯定是使用sftp或者SCP进行上传下载啊!

嗯, 我使用这种方法主要是为了解决国内 ssh 连接不了的问题