服务器应用操作命令
帕鲁更新命令
执行以下命令对 Ubuntu 服务器中的帕鲁游戏进行自动更新:
# 从指定 URL 下载并执行更新脚本
wget -O - https://pal.pet/pal-server/Ubuntu/update.sh | sh
FRP 端口映射
-
分别在服务端和客户端分别下载并解压 frp,然后进入解压后的目录:
# 下载 FRP 压缩包 wget https://github.com/fatedier/frp/releases/download/v0.61.1/frp_0.61.1_linux_amd64.tar.gz # 解压 FRP 压缩包 tar -zxvf frp_0.61.1_linux_amd64.tar.gz # 进入解压后的目录 cd frp_0.61.1_linux_amd64
-
配置服务端
在服务端上进行如下配置:-
配置服务端配置文件:
bindPort = 7000 # 设置 FRP 服务端口,确保该端口未被占用 auth.token = "xxxx" # 设置 Token,用于客户端和服务端的认证 webServer.addr = "0.0.0.0" # 设置 Web 后台监听地址,0.0.0.0 表示监听所有网络接口 webServer.port = 7500 # 设置 Web 后台监听端口 webServer.user = "admin" # 设置 Web 后台登录用户名 webServer.password = "123456" # 设置 Web 后台登录密码
全部服务端配置请参考:https://github.com/fatedier/frp/blob/dev/conf/frps_full_example.toml
-
启动/重启脚本:
创建脚本:# 创建 start_frps.sh 脚本 vim start_frps.sh
脚本内容:
点击查看代码
#!/bin/bash # 获取脚本所在目录 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" # 设置 frps 可执行文件路径 frps_BIN="$SCRIPT_DIR/frps" frps_CONFIG="$SCRIPT_DIR/frps.toml" # 配置文件路径 LOG_FILE="$SCRIPT_DIR/frps.log" # 日志文件路径 # 获取 frps 进程 ID get_frps_pid() { pgrep -f "$frps_BIN" 2>/dev/null # 查找 frps 进程 ID } # 停止 frps 进程 stop_frps() { local pid=$(get_frps_pid) # 获取 frps 进程 ID if [[ -n "$pid" ]]; then echo "Stopping frps (PID: $pid)..." # 停止 frps kill "$pid" 2>/dev/null # 终止 frps 进程 sleep 2 # 等待进程停止 kill -9 "$pid" 2>/dev/null # 强制停止进程(如果没有成功停止) else echo "frps is not running." # 如果没有找到 frps 进程 fi } # 启动 frps 进程 start_frps() { echo "Starting frps..." # 输出启动信息 nohup "$frps_BIN" -c "$frps_CONFIG" > "$LOG_FILE" 2>&1 & # 后台启动 frps 并记录日志 # 检查 frps 是否成功启动 sleep 2 # 等待一段时间 local new_pid=$(get_frps_pid) # 获取新的进程 ID if [[ -n "$new_pid" ]]; then echo "frps started (PID: $new_pid)" # 输出启动成功信息 else echo "frps failed to start." # 启动失败,输出失败信息 exit 1 # 退出脚本 fi } # 停止并重新启动 frps stop_frps start_frps
脚本设置可执行权限:
# 给 start_frps.sh 设置可执行权限 chmod +x start_frps.sh
-
-
配置客户端
-
配置客户端配置文件:
serverAddr = "x.x.x.x" # 设置 FRP 服务器地址 serverPort = 7000 # 设置 FRP 服务端口 [[proxies]] name = "test-tcp" # 隧道名称,客户端可以自定义 type = "tcp" # 使用 TCP 协议 localIP = "127.0.0.1" # 本地地址 localPort = 22 # 本地端口 remotePort = 6000 # 远程端口
全部客户端配置请参考:https://github.com/fatedier/frp/blob/dev/conf/frpc_full_example.toml
-
启动/重启脚本:
创建脚本:
# 创建 start_frpc.sh 脚本 vim start_frpc.sh
脚本内容:
点击查看代码
#!/bin/bash # 获取脚本所在目录 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" # 设置 frpc 可执行文件路径 frpc_BIN="$SCRIPT_DIR/frpc" frpc_CONFIG="$SCRIPT_DIR/frpc.toml" # 配置文件路径 LOG_FILE="$SCRIPT_DIR/frpc.log" # 日志文件路径 # 获取 frpc 进程 ID get_frpc_pid() { pgrep -f "$frpc_BIN" 2>/dev/null # 查找 frpc 进程 ID } # 停止 frpc 进程 stop_frpc() { local pid=$(get_frpc_pid) # 获取 frpc 进程 ID if [[ -n "$pid" ]]; then echo "Stopping frpc (PID: $pid)..." # 停止 frpc kill "$pid" 2>/dev/null # 终止 frpc 进程 sleep 2 # 等待进程停止 kill -9 "$pid" 2>/dev/null # 强制停止进程(如果没有成功停止) else echo "frpc is not running." # 如果没有找到 frpc 进程 fi } # 启动 frpc 进程 start_frpc() { echo "Starting frpc..." # 输出启动信息 nohup "$frpc_BIN" -c "$frpc_CONFIG" > "$LOG_FILE" 2>&1 & # 后台启动 frpc 并记录日志 # 检查 frpc 是否成功启动 sleep 2 # 等待一段时间 local new_pid=$(get_frpc_pid) # 获取新的进程 ID if [[ -n "$new_pid" ]]; then echo "frpc started (PID: $new_pid)" # 输出启动成功信息 else echo "frpc failed to start." # 启动失败,输出失败信息 exit 1 # 退出脚本 fi } # 停止并重新启动 frpc stop_frpc start_frpc
脚本设置可执行权限:
# 给 start_frpc.sh 设置可执行权限 chmod +x start_frpc.sh
-
根据CPU和GPU温度调整风扇转速
这段脚本的作用是根据 GPU 和 CPU 的温度自动调整计算机风扇的转速,以确保系统保持在合适的温度范围内,避免过热:
-
创建脚本文件,在服务器上创建一个目录来存放脚本,例如
/data/fan_control/
,然后在这个目录下创建脚本文件fan_control.sh
:点击查看代码
#!/bin/bash # 获取脚本所在目录 script_dir=$(dirname "$0") log_file="$script_dir/ipmi.log" current_time=$(date "+%Y-%m-%d %H:%M") max_temperature_gpu=0 max_temperature_cpu=0 sleep_interval=5 # 设置为5秒,可以根据实际需要进行调整 last_speed=0 # 初始化last_speed为0 # 创建日志文件(如果不存在) if [[ ! -f "$log_file" ]]; then touch "$log_file" fi # 禁用自动风扇调节 (设置风扇控制为手动) ipmitool raw 0x30 0x30 0x01 0x00 && echo "$current_time - 禁用自动风扇调节,设置为手动控制" >> "$log_file" # 获取最高的GPU温度 get_max_temperature_gpu() { max_temperature_gpu=0 # 使用nvidia-smi获取GPU温度 local gpu_temps=$(nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits 2>/dev/null) if [[ -z "$gpu_temps" ]]; then echo "$current_time - 无法检测到GPU温度" >> "$log_file" return fi for temp in $gpu_temps; do # 检查是否为有效浮点数 temp=$(echo "$temp" | sed 's/[^0-9.]//g') # 清除非数字字符 if [[ "$temp" =~ ^[0-9]+([.][0-9]+)?$ ]] && (( $(echo "$temp > $max_temperature_gpu" | bc -l) )); then max_temperature_gpu=$temp fi done if (( $(echo "$max_temperature_gpu == 0" | bc -l) )); then echo "$current_time - 检测到GPU温度但未能解析有效数值" >> "$log_file" fi } # 获取最高的CPU温度 get_max_temperature_cpu() { max_temperature_cpu=0 # 使用ipmitool sensor获取CPU温度 local cpu_temps=$(ipmitool sensor | grep -P '^Temp\s+\|' | awk '{print $3}') if [[ -z "$cpu_temps" ]]; then echo "$current_time - 无法检测到CPU温度" >> "$log_file" return fi for temp in $cpu_temps; do # 清除非数字字符,并检查是否为有效浮点数 temp=$(echo "$temp" | sed 's/[^0-9.]//g') # 清除非数字字符 if [[ "$temp" =~ ^[0-9]+([.][0-9]+)?$ ]] && (( $(echo "$temp > $max_temperature_cpu" | bc -l) )); then max_temperature_cpu=$temp fi done if (( $(echo "$max_temperature_cpu == 0" | bc -l) )); then echo "$current_time - 检测到CPU温度但未能解析有效数值" >> "$log_file" fi } # 风扇调整函数 adjust_fan_speed() { local max_temp=$1 # 最高温度 local temp_gpu=$2 # GPU最高温度 local temp_cpu=$3 # CPU最高温度 local speed=30 # 默认30% if (( $(echo "$max_temp > 55" | bc -l) && $(echo "$max_temp <= 65" | bc -l) )); then speed=50 # 50% elif (( $(echo "$max_temp > 65" | bc -l) && $(echo "$max_temp <= 75" | bc -l) )); then speed=80 # 80% elif (( $(echo "$max_temp > 75" | bc -l) )); then speed=100 # 100% fi # 只有当风扇转速发生变化时,才执行调整命令 if [[ "$speed" -ne "$last_speed" ]]; then ipmitool raw 0x30 0x30 0x02 0xff $(printf "0x%02x" $((speed))) echo "$current_time - 最高温度: $max_temp°C (GPU: ${temp_gpu}°C, CPU: ${temp_cpu}°C), 风扇转速调整为 ${speed}%" >> "$log_file" last_speed=$speed # 更新last_speed else echo "$current_time - 风扇转速没有变化,当前温度: 最高温度 $max_temp°C (GPU: ${temp_gpu}°C, CPU: ${temp_cpu}°C)" >> "$log_file" fi } # 循环调整风扇转速,每5秒检查一次 while true; do get_max_temperature_gpu get_max_temperature_cpu # 如果没有获取到GPU或CPU的温度,跳过调整 if (( $(echo "$max_temperature_gpu == 0" | bc -l) && $(echo "$max_temperature_cpu == 0" | bc -l) )); then echo "$current_time - 无法获取GPU或CPU温度,跳过风扇调整" >> "$log_file" sleep $sleep_interval continue fi # 选择最大温度作为依据 if (( $(echo "$max_temperature_gpu > $max_temperature_cpu" | bc -l) )); then max_temperature=$max_temperature_gpu else max_temperature=$max_temperature_cpu fi adjust_fan_speed $max_temperature $max_temperature_gpu $max_temperature_cpu sleep $sleep_interval done # crontab -e # @reboot /bin/bash /data/fan_control/fan_control.sh # crontab -l # tail -f /data/fan_control/ipmi.log
-
给脚本文件设置可执行权限:
chmod +x /data/fan_control/fan_control.sh
-
配置脚本开机自启动:
编辑 crontab 配置文件:crontab -e
在配置文件中写入:
@reboot /bin/bash /data/fan_control/fan_control.sh
-
检查日志文件:
tail -f /data/fan_control/ipmi.log
查看显存占用超过 1g 的 docker 容器信息
点击查看代码
#!/bin/bash
# 获取显存占用大于 1GB 的进程 PID 和显存占用大小
gpu_info=$(nvidia-smi --query-compute-apps=pid,used_memory,process_name --format=csv,noheader,nounits | awk -F ', ' '
{
mem_mib = $2 + 0;
if (mem_mib > 1024 && $3 ~ /python/) {
print $1, mem_mib
}
}')
if [ -z "$gpu_info" ]; then
echo "No GPU processes with memory usage > 1GB found."
exit 0
fi
echo "GPU Processes with Memory Usage > 1GB:"
echo "-------------------------------------"
echo "PID GPU Memory (MiB) Container ID Container Name Image"
echo "------------------------------------------------------------------------------------------"
while read -r pid gpu_memory; do
# 通过 cgroup 查找容器 ID(兼容不同格式的 Docker/containerd 路径)
container_id=$(cat /proc/$pid/cgroup 2>/dev/null | grep -oE '[0-9a-f]{64}' | head -n 1)
# 如果未找到 64 位 ID,尝试匹配 12 位短 ID
if [ -z "$container_id" ]; then
container_id=$(cat /proc/$pid/cgroup 2>/dev/null | grep -oE 'docker-([0-9a-f]{64})' | head -n 1 | cut -d '-' -f2)
fi
# 如果仍为空,尝试通过容器运行时接口查找
if [ -z "$container_id" ]; then
container_id=$(docker ps -q --no-trunc | xargs docker inspect --format '{{.Id}} {{.State.Pid}}' | awk -v pid="$pid" '$2 == pid {print $1}')
fi
if [ -n "$container_id" ]; then
# 截取 12 位短 ID(兼容 docker ps 输出)
short_id=$(echo "$container_id" | cut -c1-12)
container_info=$(docker inspect --format '{{.Name}} {{.Config.Image}}' "$container_id" 2>/dev/null)
container_name=$(echo "$container_info" | awk '{print $1}' | sed 's|/||g')
container_image=$(echo "$container_info" | awk '{print $2}')
echo "$pid $gpu_memory MiB $short_id $container_name $container_image"
else
echo "$pid $gpu_memory MiB Not a Docker container process"
fi
done <<< "$gpu_info"
echo "------------------------------------------------------------------------------------------"