使用Rust 编写脚本实现对社区服检测玩家并重启 服务器管理

wq 赞助用户组 1天前 31

rust脚本实现检测是否存在玩家并重启

该脚本只能够运行在使用lgsm搭建的csgo服务器中,在目录为默认情况下自动识别服务器ip与port。使用高性能语言rust编写并编译为二进制运行不需要在本地服务器上安装rust环境可以直接运行。

执行前请在~/lgsm/config-lgsm/csgoserver/common.cfg中添加ip="(本机ip)",脚本依赖ip和port字段运行。

./csgo_checker     //运行命令

可使用crontab定时执行,执行日志保存在logs中。

附源码:

use std::{
    fs::{self, OpenOptions},
    io::Write,
    path::{Path, PathBuf},
    process::Command,
};
use regex::Regex;
use a2s::A2SClient;

/// 日志记录函数:终端 + logs/check.log
fn log(msg: &str) {
    println!("{}", msg);
    let log_dir = "logs";
    let log_path = format!("{}/check.log", log_dir);
    fs::create_dir_all(log_dir).ok();

    if let Ok(mut file) = OpenOptions::new()
        .create(true)
        .append(true)
        .open(log_path)
    {
        let _ = writeln!(file, "{}", msg);
    }
}

/// 提取配置字段,如 ip="..." / port="..."
fn extract_field_from_config(path: &Path, field: &str) -> Option<String> {
    let content = fs::read_to_string(path).ok()?;
    let re = Regex::new(&format!(r#"{}="?([^"\r\n]+)"?"#, field)).ok()?;
    let caps = re.captures(&content)?;
    Some(caps.get(1)?.as_str().to_string())
}

/// 获取所有 csgoserver*.cfg 配置(含主服和编号服)
fn detect_port_configs() -> Vec<(Option<u32>, PathBuf)> {
    let mut result = Vec::new();
    let config_dir = Path::new("lgsm/config-lgsm/csgoserver");

    if let Ok(entries) = fs::read_dir(config_dir) {
        for entry in entries.flatten() {
            let path = entry.path();
            if let Some(file_name) = path.file_name().and_then(|n| n.to_str()) {
                if file_name == "csgoserver.cfg" {
                    result.push((None, path)); // 主服
                } else if let Some(cap) = Regex::new(r"^csgoserver-(\d+)\.cfg$")
                    .unwrap()
                    .captures(file_name)
                {
                    if let Ok(id) = cap[1].parse::<u32>() {
                        result.push((Some(id), path));
                    }
                }
            }
        }
    }

    result
}

/// 获取 restart 命令
fn get_restart_command(id: Option<u32>) -> String {
    match id {
        Some(n) => format!("./csgoserver-{} restart", n),
        None => "./csgoserver restart".to_string(),
    }
}

/// 执行重启命令
fn restart_server(id: Option<u32>) {
    let cmd = get_restart_command(id);
    log(&format!("[INFO] 执行重启命令: {}", cmd));
    let parts: Vec<&str> = cmd.split_whitespace().collect();
    if let Some((program, args)) = parts.split_first() {
        let _ = Command::new(program)
            .args(args)
            .spawn()
            .expect("重启命令执行失败");
    }
}

fn main() {
    // Step 1: 提取共用 IP
    let common_cfg = Path::new("lgsm/config-lgsm/csgoserver/common.cfg");
    let ip = match extract_field_from_config(common_cfg, "ip") {
        Some(ip) => ip,
        None => {
            log(&format!("[ERROR] 无法从 {} 中读取 IP", common_cfg.display()));
            return;
        }
    };

    // Step 2: 遍历所有服务器配置(获取 port + id)
    let servers = detect_port_configs();
    if servers.is_empty() {
        log("[WARN] 未找到任何 csgoserver*.cfg 配置文件!");
        return;
    }

    let client = A2SClient::new().expect("无法创建 A2S 客户端");

    for (id, cfg_path) in servers {
        // 提取端口
        let port = match extract_field_from_config(&cfg_path, "port")
            .and_then(|p| p.parse::<u16>().ok())
        {
            Some(p) => p,
            None => {
                log(&format!("[WARN] 无法从 {} 中读取 port", cfg_path.display()));
                continue;
            }
        };

        let address = format!("{}:{}", ip, port);
        log(&format!("[INFO] 正在检查服务器: {} ({})", address, cfg_path.display()));

        match client.players(&address) {
            Ok(players) => {
                if players.is_empty() {
                    log("[INFO] 无人在线,准备重启...");
                    restart_server(id);
                } else {
                    log(&format!(
                        "[INFO] 有玩家在线,跳过重启。在线玩家数量: {}",
                        players.len()
                    ));
                }
            }
            Err(e) => {
                log(&format!(
                    "[ERROR] 获取服务器玩家信息失败 ({}): {}",
                    address, e
                ));
            }
        }
    }
}

 

上传的附件:

CSGO插件分享-申明 1、本网站名称:CSGO插件分享-中文站  网址:https://bbs.csgocn.net
2、本站的宗旨在于为CSGO玩家提供一个插件分享的中文资源平台,多数插件来源于SourceMod论坛,并配以中文介绍和安装教程。
3、欢迎有能力的朋友共享有趣的CSGO插件资源。
4、本站资源大多为百度网盘,如发现链接失效,可以点: 这里进行反馈,我们会第一时间更新。
最新回复 (3)
返回