This commit is contained in:
starry
2025-07-16 12:35:21 +00:00
commit 1f7b4314c3
49 changed files with 18341 additions and 0 deletions

55
dev/README.md Normal file
View File

@@ -0,0 +1,55 @@
### 一键安装ansible
见 [ansible.md](./ansible.md)
---
### 常用运维脚本
- 一键切换系统源脚本
```
bash <(curl -sSL https://github.com/sky22333/shell/raw/main/dev/mirrors.sh)
```
- 切换官方系统源
```
bash <(curl -sSL https://github.com/sky22333/shell/raw/main/dev/mirrors.sh) --use-official-source true
```
- 一键安装Docker和配置镜像地址
```
bash <(curl -sSL https://github.com/sky22333/shell/raw/main/dev/docker.sh)
```
- acme.sh 证书一键申请脚本
```
bash <(curl -sSL https://github.com/sky22333/shell/raw/main/dev/acme.sh)
```
- Linux切换到标准内核
```
bash <(curl -sSL https://github.com/sky22333/shell/raw/main/dev/image.sh)
```
- 一键安装go环境
```
bash <(curl -sSL https://github.com/sky22333/shell/raw/main/dev/go.sh)
```
- 一键启用BBR
```
bash <(curl -sSL https://github.com/sky22333/shell/raw/main/dev/bbr.sh)
```
- 一键内网穿透(无需域名和服务器)
```
bash <(curl -sSL https://github.com/sky22333/shell/raw/main/dev/cf-tunnel.sh)
```
- `win`系统`PowerShell`在线脚本,需要以管理员模式打开`PowerShell`
```
iwr -useb https://ghproxy.net/https://raw.githubusercontent.com/sky22333/shell/main/dev/cf-setup.ps1 | iex
```

157
dev/acme.sh Normal file
View File

@@ -0,0 +1,157 @@
#!/bin/bash
if [ "$(id -u)" != "0" ]; then
echo -e "\033[0;31m请以 root 用户运行此脚本\033[0m"
exit 1
fi
install_requirements() {
local install_cmd=""
local pkg_manager=""
local os_type=$(grep '^ID=' /etc/os-release | cut -d'=' -f2)
if [ "$os_type" == "ubuntu" ] || [ "$os_type" == "debian" ]; then
pkg_manager="apt"
install_cmd="apt install -y"
elif [ "$os_type" == "centos" ]; then
pkg_manager="yum"
install_cmd="yum install -y"
else
echo -e "\033[0;31m不支持的操作系统: $os_type\033[0m"
exit 1
fi
if ! command -v lsof &> /dev/null; then
$install_cmd lsof
fi
if ! command -v curl &> /dev/null; then
$install_cmd curl
fi
# 检查并安装 socat
if ! command -v socat &> /dev/null; then
echo -e "\033[0;32msocat 未安装,正在安装...\033[0m"
$install_cmd socat
else
echo -e "\033[0;32msocat 已安装\033[0m"
fi
}
# 生成12位纯英文的随机邮箱
generate_random_email() {
local random_email=$(tr -dc 'a-z' < /dev/urandom | fold -w 12 | head -n 1)
echo "${random_email}@gmail.com"
}
check_acme_installation() {
if ! command -v acme.sh &> /dev/null; then
echo -e "\033[0;32macme.sh 未安装,正在安装...\033[0m"
curl https://get.acme.sh | sh
source ~/.bashrc
else
echo -e "\033[0;32macme.sh 已安装\033[0m"
fi
}
# 检查端口 80 是否被占用,并提供释放端口的选项
check_port_80() {
local pid
pid=$(lsof -ti:80)
if [ -n "$pid" ]; then
echo -e "\033[0;31m端口 80 已被占用PID为: $pid\033[0m"
read -p "是否强制释放端口 80? (Y/n): " response
case "$response" in
[yY][eE][sS]|[yY])
echo "正在释放端口 80..."
kill -9 $pid
;;
*)
echo "未释放端口,脚本将退出。"
exit 1
;;
esac
fi
}
register_ca() {
local ca="$1"
local email="$2"
echo -e "\033[0;32m正在注册 CA 机构 $ca 使用电子邮件 $email...\033[0m"
~/.acme.sh/acme.sh --register-account -m "$email" --server "$ca"
}
generate_ssl_certificate() {
local domain_name="$1"
local ca="$2"
echo -e "\033[0;32m正在为 $domain_name 生成 SSL 证书...\033[0m"
~/.acme.sh/acme.sh --issue --force --standalone -d "$domain_name" --server "$ca"
if [ $? -ne 0 ]; then
echo -e "\033[0;31mSSL 证书生成失败\033[0m"
exit 1
fi
local cert_path="/root/.acme.sh/${domain_name}_ecc/fullchain.cer"
local key_path="/root/.acme.sh/${domain_name}_ecc/${domain_name}.key"
~/.acme.sh/acme.sh --install-cert -d "$domain_name" \
--key-file "$key_path" \
--fullchain-file "$cert_path"
# 打印 fullchain.cer 和 .key 文件的绝对路径
echo -e "\033[0;32m证书路径: $cert_path\033[0m"
echo -e "\033[0;32m密钥路径: $key_path\033[0m"
}
# 主流程
install_requirements
echo -e "\033[0;32m请输入您的域名确保已经解析到本机IP:\033[0m"
read -p "" domain_name
# 检查端口 80
check_port_80
# 检查证书和密钥是否已经存在
cert_path="/root/.acme.sh/${domain_name}_ecc/fullchain.cer"
key_path="/root/.acme.sh/${domain_name}_ecc/${domain_name}.key"
if [ -f "$cert_path" ] && [ -f "$key_path" ]; then
echo -e "\033[0;32m证书已存在:\033[0m"
echo -e "\033[0;32m证书全链路径: $cert_path\033[0m"
echo -e "\033[0;32m密钥文件路径: $key_path\033[0m"
exit 0
fi
# 生成随机邮箱
user_email=$(generate_random_email)
echo -e "\033[0;32m生成的邮箱: $user_email\033[0m"
# 检查 acme.sh 安装
check_acme_installation
# CA 机构选择
echo -e "\033[0;32m请选择 CA 机构:\033[0m"
echo -e "\033[0;32m1) Let's Encrypt\033[0m"
echo -e "\033[0;32m2) Buypass\033[0m"
echo -e "\033[0;32m3) ZeroSSL\033[0m"
echo -e "\033[0;32m选择 CA 机构 (回车默认选1):\033[0m"
read -p "" ca_choice
case $ca_choice in
2)
CA="buypass"
;;
3)
CA="zerossl"
;;
*)
CA="letsencrypt"
;;
esac
register_ca "$CA" "$user_email"
generate_ssl_certificate "$domain_name" "$CA"

242
dev/ansible.md Normal file
View File

@@ -0,0 +1,242 @@
## 🔵脚本加密-编译为可执行文件
- 下载环境
```
sudo apt update
sudo apt install shc gcc -yq
```
- 用法
| 命令 | 描述 | 示例 |
|-------------------------------|-------------------------------------------------------------------|---------------------------------------------------------------|
| `shc -f <script>` | 编译指定的 Shell 脚本文件。 | `shc -f script.sh` |
| `shc -o <output>` | 指定输出的可执行文件名。 | `shc -f script.sh -o myscript` |
| `shc -e <YYYY-MM-DD>` | 设置脚本的过期日期,格式为 `YYYY-MM-DD`。 | `shc -f script.sh -e 2024-12-31` |
| `shc -m "<message>"` | 设置当脚本过期时显示的消息。 | `shc -f script.sh -e 2024-12-31 -m "脚本已过期"` |
| `shc -r` | 允许在编译后的脚本中保留运行时的环境变量。 | `shc -r -f script.sh` |
| `shc -T` | 不生成中间的 C 源代码文件。 | `shc -f script.sh -T` |
| `shc -v` | 显示详细信息,帮助调试。 | `shc -v -f script.sh` |
| `shc -x` | 对脚本中的字符串进行 XOR 加密以增加安全性。 | `shc -x -f script.sh` |
| `shc -l <lib>` | 添加特定的库文件链接到编译的二进制文件中。 | `shc -f script.sh -l /usr/lib/somelibrary.so` |
- 远程执行加密脚本
```
curl -fsSL http://公网IP/my.sh -o my.sh && chmod +x my.sh && ./my.sh
```
需要系统一致
---
---
## 🔵ansible批量管理主机运维工具
- ### ✨一键安装脚本
```
bash <(curl -sSL https://github.com/sky22333/shell/raw/main/dev/ansible.sh)
```
### 1安装并创建配置文件
```
sudo apt update
sudo apt install ansible -y
```
```
mkdir -p /etc/ansible && cd /etc/ansible && touch ansible.cfg hosts renwu.yml
```
> `ansible.cfg` 配置Ansible的全局设置。
> `hosts` 定义要管理的主机和主机组。
> `renwu.yml或playbook` 描述要在主机上执行的任务和操作步骤。
### 2禁用被控主机密钥检查
`ansible.cfg`中添加以下配置
```
[defaults]
host_key_checking = False
ansible_ssh_common_args = '-o StrictHostKeyChecking=no'
```
### 3配置被控主机清单
`hosts`中添加被控主机示例
```
[myservers]
1 ansible_host=192.168.1.1 ansible_user=root ansible_port=22 ansible_ssh_pass=password1
2 ansible_host=192.168.1.2 ansible_user=root ansible_port=22 ansible_ssh_pass=password2
3 ansible_host=192.168.1.3 ansible_user=root ansible_port=22 ansible_ssh_pass=password3
4 ansible_host=192.168.1.4 ansible_user=root ansible_port=22 ansible_ssh_pass=password4
5 ansible_host=192.168.1.5 ansible_user=root ansible_port=22 ansible_ssh_pass=password5
```
### 4使用ping模块测试所有被控主机连通性
> (可选)查看所有被控机的信息 `ansible-inventory --list -i /etc/ansible/hosts`
```
ansible -m ping all
```
### 5创建被控主机任务配置文件
`renwu.yml`中添加任务示例
```
---
# 定义要执行任务的主机组
- hosts: myservers
become: yes
tasks:
- name: 更新包列表
apt:
update_cache: yes
- name: 安装所需的软件包
apt:
name:
- curl
- wget
- zip
- tar
state: present
- name: 将脚本复制到远程主机
copy:
# 本地脚本路径
src: /etc/ansible/ss.sh
# 远程主机上的目标路径
dest: /tmp/ss.sh
# 设置脚本权限为可执行
mode: '0755'
- name: 在远程主机上执行脚本
shell: /tmp/ss.sh # 在远程主机上执行脚本
```
或者直接执行远程脚本示例
```
---
# 定义要执行任务的主机组
- hosts: myservers
become: yes # 以管理员权限运行命令
tasks:
- name: 更新包列表
apt:
update_cache: yes
- name: 安装所需的软件包
apt:
name:
- curl
- wget
- zip
- tar
state: present
- name: 在被控主机上执行远程脚本
shell: bash <(wget -qO- https://github.com/sky22333/shell/raw/main/vmess-ws.sh)
args:
executable: /bin/bash # 确保使用bash执行命令
```
### 6用法示例
- 对所有被控机器运行`renwu.yml`中的任务
```
ansible-playbook renwu.yml
```
- 临时对所有主机执行普通命令
```
ansible all -a "pwd"
```
- 临时对所有主机运行远程脚本
```
ansible all -m shell -a "bash <(wget -qO- https://github.com/sky22333/shell/raw/main/vmess-ws.sh)"
```
- 临时将本地脚本复制给所有被控主机并执行
```
ansible all -m copy -a "src=/etc/ansible/script.sh dest=/tmp/script.sh mode=0755"
ansible all -m shell -a "/tmp/script.sh"
```
- 临时对13号主机执行shell命令
```
ansible 1,3 -m shell -a "你的命令"
```
- 临时对13号主机执行普通命令
```
ansible 1,3 -a "pwd"
```
> 命令结尾后面追加`-v`选项会显示被控机器详细的执行信息
---
#### 命令解释
> `-m` 用于指定 Ansible 模块
> `-a` 用于指定传递给模块的参数或命令
| 模块 | 指令 | 中文解释 | 用法示例 |
|-------------------|---------|----------------------------------------------|---------------------------------------------------|
| `shell` | `-a` | 执行 shell 命令。支持管道、重定向等 shell 特性。 | `ansible all -m shell -a "pwd"` |
| `command` | `-a` | 执行命令,不通过 shell。默认模块 | `ansible all -m command -a "ls -l"` |
| `copy` | `-a` | 复制文件或目录到目标主机。 | `ansible all -m copy -a "src=/local/file dest=/remote/file mode=0644"` |
| `file` | `-a` | 管理文件和目录的属性(如权限、所有权等)。 | `ansible all -m file -a "path=/remote/file state=absent"` |
| `yum` | `-a` | 使用 Yum 包管理器安装、更新或删除软件包(适用于 RHEL/CentOS。 | `ansible all -m yum -a "name=nginx state=present"` |
| `apt` | `-a` | 使用 APT 包管理器安装、更新或删除软件包(适用于 Debian/Ubuntu。 | `ansible all -m apt -a "name=nginx state=latest"` |
| `service` | `-a` | 管理服务(如启动、停止、重启服务)。 | `ansible all -m service -a "name=nginx state=started"` |
| `systemd` | `-a` | 管理 systemd 服务(如启动、停止、重启服务)。| `ansible all -m systemd -a "name=nginx state=started"` |
| `user` | `-a` | 管理用户账户(如创建、删除用户)。 | `ansible all -m user -a "name=alice state=present"` |
| `group` | `-a` | 管理用户组(如创建、删除组)。 | `ansible all -m group -a "name=admin state=present"` |
| `git` | `-a` | 管理 Git 仓库(如克隆、拉取、提交等)。 | `ansible all -m git -a "repo=https://github.com/user/repo.git dest=/path/to/repo"` |
| `template` | `-a` | 使用 Jinja2 模板引擎渲染模板文件。 | `ansible all -m template -a "src=template.j2 dest=/etc/config"` |
| `cron` | `-a` | 管理 cron 任务。 | `ansible all -m cron -a "name='Backup' minute='0' hour='2' job='/usr/bin/backup.sh'"` |
| `wait_for` | `-a` | 等待某个条件满足(如端口开放、文件存在等)。 | `ansible all -m wait_for -a "port=80 delay=10 timeout=300"` |
| `docker_container`| `-a` | 管理 Docker 容器(如启动、停止、删除容器)。 | `ansible all -m docker_container -a "name=my_container state=started"` |
| `docker_image` | `-a` | 管理 Docker 镜像(如拉取、删除镜像)。 | `ansible all -m docker_image -a "name=nginx tag=latest state=present"` |
| `lineinfile` | `-a` | 在文件中插入、删除或修改行。 | `ansible all -m lineinfile -a "path=/etc/hosts line='127.0.0.1 localhost' state=present"` |
| `ini_file` | `-a` | 修改 INI 配置文件。 | `ansible all -m ini_file -a "path=/etc/myconfig.ini section=database option=host value=localhost"` |
| `debug` | `-a` | 打印调试信息。 | `ansible all -m debug -a "msg='This is a debug message'"` |
---
---
#### 执行结果解释
- **ok**: 表示在该主机上成功完成的任务数。
- **changed**: 表示在该主机上有多少任务进行了更改(如文件被复制、脚本被执行)。
- **unreachable**: 表示无法连接的主机数量。
- **failed**: 表示任务失败的数量。
- **skipped**: 表示被跳过的任务数量。
- **rescued**: 表示在任务失败后被恢复的数量。
- **ignored**: 表示被忽略的任务数量。
- 绿色:任务顺利完成
- 橙色:任务执行后有变化,比如文件被修改或某些服务被重启。
- 红色:任务执行失败,一般会终止剩余的所有任务。
#### 如果所有被控机端口和密码都一样
`/etc/ansible/hosts`配置可以这样写
```
[all:vars]
ansible_user=root
ansible_ssh_pass=your_password
ansible_port=22
[myservers]
1 ansible_host=192.168.1.101
2 ansible_host=192.168.1.102
3 ansible_host=192.168.1.103
```

48
dev/ansible.sh Normal file
View File

@@ -0,0 +1,48 @@
#!/bin/bash
# 安装 Ansible
sudo apt update && apt install ansible -yq
# 创建 Ansible 配置文件和目录
mkdir -p /etc/ansible
cd /etc/ansible || exit
# 创建 ansible.cfg 文件并添加配置
cat <<EOL > ansible.cfg
[defaults]
host_key_checking = False
ansible_ssh_common_args = '-o StrictHostKeyChecking=no'
EOL
# 创建 hosts 文件并添加被控主机
cat <<EOL > hosts
[myservers]
1 ansible_host=192.168.1.1 ansible_user=root ansible_port=22 ansible_ssh_pass=password1
2 ansible_host=192.168.1.2 ansible_user=root ansible_port=22 ansible_ssh_pass=password2
3 ansible_host=192.168.1.3 ansible_user=root ansible_port=22 ansible_ssh_pass=password3
EOL
# 创建 renwu.yml 文件并添加任务
cat <<EOL > renwu.yml
---
# 定义要执行任务的主机组
- hosts: myservers
become: yes
gather_facts: no # 禁用事实收集以避免依赖 Python
tasks:
- name: 将脚本复制到远程主机
copy:
# 本地脚本路径
src: ./proxy.sh
# 远程主机上的目标路径
dest: /tmp/ss.sh
# 设置脚本权限为可执行
mode: '0755'
- name: 在远程主机上执行脚本
raw: /tmp/ss.sh # 在远程主机上执行脚本
EOL
# 输出成功信息
echo "Ansible 配置文件和任务文件已成功创建并配置完成。"

366
dev/bbr.sh Normal file
View File

@@ -0,0 +1,366 @@
#!/usr/bin/env bash
#
# 自动安装 TCP BBR 的最新内核
#
# 系统要求CentOS 6+、Debian8+、Ubuntu16+
#
cur_dir=$(pwd)
_red() {
printf '\033[1;31;31m%b\033[0m' "$1"
}
_green() {
printf '\033[1;31;32m%b\033[0m' "$1"
}
_yellow() {
printf '\033[1;31;33m%b\033[0m' "$1"
}
_info() {
_green "[Info] "
printf -- "%s" "$1"
printf "\n"
}
_warn() {
_yellow "[Warning] "
printf -- "%s" "$1"
printf "\n"
}
_error() {
_red "[Error] "
printf -- "%s" "$1"
printf "\n"
exit 1
}
_exists() {
local cmd="$1"
if eval type type > /dev/null 2>&1; then
eval type "$cmd" > /dev/null 2>&1
elif command > /dev/null 2>&1; then
command -v "$cmd" > /dev/null 2>&1
else
which "$cmd" > /dev/null 2>&1
fi
local rt=$?
return ${rt}
}
_os() {
local os=""
[ -f "/etc/debian_version" ] && source /etc/os-release && os="${ID}" && printf -- "%s" "${os}" && return
[ -f "/etc/redhat-release" ] && os="centos" && printf -- "%s" "${os}" && return
}
_os_full() {
[ -f /etc/redhat-release ] && awk '{print ($1,$3~/^[0-9]/?$3:$4)}' /etc/redhat-release && return
[ -f /etc/os-release ] && awk -F'[= "]' '/PRETTY_NAME/{print $3,$4,$5}' /etc/os-release && return
[ -f /etc/lsb-release ] && awk -F'[="]+' '/DESCRIPTION/{print $2}' /etc/lsb-release && return
}
_os_ver() {
local main_ver="$( echo $(_os_full) | grep -oE "[0-9.]+")"
printf -- "%s" "${main_ver%%.*}"
}
_error_detect() {
local cmd="$1"
_info "${cmd}"
eval ${cmd}
if [ $? -ne 0 ]; then
_error "Execution command (${cmd}) failed, please check it and try again."
fi
}
_is_digit(){
local input=${1}
if [[ "$input" =~ ^[0-9]+$ ]]; then
return 0
else
return 1
fi
}
_is_64bit(){
if [ $(getconf WORD_BIT) = '32' ] && [ $(getconf LONG_BIT) = '64' ]; then
return 0
else
return 1
fi
}
_version_ge(){
test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"
}
get_valid_valname(){
local val=${1}
local new_val=$(eval echo $val | sed 's/[-.]/_/g')
echo ${new_val}
}
get_hint(){
local val=${1}
local new_val=$(get_valid_valname $val)
eval echo "\$hint_${new_val}"
}
#Display Memu
display_menu(){
local soft=${1}
local default=${2}
eval local arr=(\${${soft}_arr[@]})
local default_prompt
if [[ "$default" != "" ]]; then
if [[ "$default" == "last" ]]; then
default=${#arr[@]}
fi
default_prompt="(default ${arr[$default-1]})"
fi
local pick
local hint
local vname
local prompt="which ${soft} you'd select ${default_prompt}: "
while :
do
echo -e "\n------------ ${soft} setting ------------\n"
for ((i=1;i<=${#arr[@]};i++ )); do
vname="$(get_valid_valname ${arr[$i-1]})"
hint="$(get_hint $vname)"
[[ "$hint" == "" ]] && hint="${arr[$i-1]}"
echo -e "${green}${i}${plain}) $hint"
done
echo
read -p "${prompt}" pick
if [[ "$pick" == "" && "$default" != "" ]]; then
pick=${default}
break
fi
if ! _is_digit "$pick"; then
prompt="Input error, please input a number"
continue
fi
if [[ "$pick" -lt 1 || "$pick" -gt ${#arr[@]} ]]; then
prompt="Input error, please input a number between 1 and ${#arr[@]}: "
continue
fi
break
done
eval ${soft}=${arr[$pick-1]}
vname="$(get_valid_valname ${arr[$pick-1]})"
hint="$(get_hint $vname)"
[[ "$hint" == "" ]] && hint="${arr[$pick-1]}"
echo -e "\nyour selection: $hint\n"
}
get_latest_version() {
latest_version=($(wget -qO- https://kernel.ubuntu.com/~kernel-ppa/mainline/ | awk -F'\"v' '/v[4-9]./{print $2}' | cut -d/ -f1 | grep -v - | sort -V))
[ ${#latest_version[@]} -eq 0 ] && _error "Get latest kernel version failed."
kernel_arr=()
for i in ${latest_version[@]}; do
if _version_ge $i 5.15; then
kernel_arr+=($i);
fi
done
display_menu kernel last
if _is_64bit; then
deb_name=$(wget -qO- https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/ | grep "linux-image" | grep "generic" | awk -F'\">' '/amd64.deb/{print $2}' | cut -d'<' -f1 | head -1)
deb_kernel_url="https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/${deb_name}"
deb_kernel_name="linux-image-${kernel}-amd64.deb"
modules_deb_name=$(wget -qO- https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/ | grep "linux-modules" | grep "generic" | awk -F'\">' '/amd64.deb/{print $2}' | cut -d'<' -f1 | head -1)
deb_kernel_modules_url="https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/${modules_deb_name}"
deb_kernel_modules_name="linux-modules-${kernel}-amd64.deb"
else
deb_name=$(wget -qO- https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/ | grep "linux-image" | grep "generic" | awk -F'\">' '/i386.deb/{print $2}' | cut -d'<' -f1 | head -1)
deb_kernel_url="https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/${deb_name}"
deb_kernel_name="linux-image-${kernel}-i386.deb"
modules_deb_name=$(wget -qO- https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/ | grep "linux-modules" | grep "generic" | awk -F'\">' '/i386.deb/{print $2}' | cut -d'<' -f1 | head -1)
deb_kernel_modules_url="https://kernel.ubuntu.com/~kernel-ppa/mainline/v${kernel}/${modules_deb_name}"
deb_kernel_modules_name="linux-modules-${kernel}-i386.deb"
fi
[ -z "${deb_name}" ] && _error "Getting Linux kernel binary package name failed, maybe kernel build failed. Please choose other one and try again."
}
get_char() {
SAVEDSTTY=`stty -g`
stty -echo
stty cbreak
dd if=/dev/tty bs=1 count=1 2> /dev/null
stty -raw
stty echo
stty $SAVEDSTTY
}
check_bbr_status() {
local param=$(sysctl net.ipv4.tcp_congestion_control | awk '{print $3}')
if [[ x"${param}" == x"bbr" ]]; then
return 0
else
return 1
fi
}
check_kernel_version() {
local kernel_version=$(uname -r | cut -d- -f1)
if _version_ge ${kernel_version} 4.9; then
return 0
else
return 1
fi
}
# Check OS version
check_os() {
if _exists "virt-what"; then
virt="$(virt-what)"
elif _exists "systemd-detect-virt"; then
virt="$(systemd-detect-virt)"
fi
if [ -n "${virt}" -a "${virt}" = "lxc" ]; then
_error "Virtualization method is LXC, which is 不支持."
fi
if [ -n "${virt}" -a "${virt}" = "openvz" ] || [ -d "/proc/vz" ]; then
_error "Virtualization method is OpenVZ, 不支持."
fi
[ -z "$(_os)" ] && _error "系统不支持"
case "$(_os)" in
ubuntu)
[ -n "$(_os_ver)" -a "$(_os_ver)" -lt 16 ] && _error "Not supported OS, please change to Ubuntu 16+ and try again."
;;
debian)
[ -n "$(_os_ver)" -a "$(_os_ver)" -lt 8 ] && _error "Not supported OS, please change to Debian 8+ and try again."
;;
centos)
[ -n "$(_os_ver)" -a "$(_os_ver)" -lt 6 ] && _error "Not supported OS, please change to CentOS 6+ and try again."
;;
*)
_error "系统不支持"
;;
esac
}
sysctl_config() {
sed -i '/net.core.default_qdisc/d' /etc/sysctl.conf
sed -i '/net.ipv4.tcp_congestion_control/d' /etc/sysctl.conf
echo "net.core.default_qdisc = fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control = bbr" >> /etc/sysctl.conf
sysctl -p >/dev/null 2>&1
}
install_kernel() {
case "$(_os)" in
centos)
if [ -n "$(_os_ver)" ]; then
if ! _exists "perl"; then
_error_detect "yum install -y perl"
fi
if [ "$(_os_ver)" -eq 6 ]; then
_error_detect "rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org"
rpm_kernel_url="https://dl.lamp.sh/files/"
if _is_64bit; then
rpm_kernel_name="kernel-ml-4.18.20-1.el6.elrepo.x86_64.rpm"
rpm_kernel_devel_name="kernel-ml-devel-4.18.20-1.el6.elrepo.x86_64.rpm"
else
rpm_kernel_name="kernel-ml-4.18.20-1.el6.elrepo.i686.rpm"
rpm_kernel_devel_name="kernel-ml-devel-4.18.20-1.el6.elrepo.i686.rpm"
fi
_error_detect "wget -c -t3 -T60 -O ${rpm_kernel_name} ${rpm_kernel_url}${rpm_kernel_name}"
_error_detect "wget -c -t3 -T60 -O ${rpm_kernel_devel_name} ${rpm_kernel_url}${rpm_kernel_devel_name}"
[ -s "${rpm_kernel_name}" ] && _error_detect "rpm -ivh ${rpm_kernel_name}" || _error "Download ${rpm_kernel_name} failed, please check it."
[ -s "${rpm_kernel_devel_name}" ] && _error_detect "rpm -ivh ${rpm_kernel_devel_name}" || _error "Download ${rpm_kernel_devel_name} failed, please check it."
rm -f ${rpm_kernel_name} ${rpm_kernel_devel_name}
[ ! -f "/boot/grub/grub.conf" ] && _error "/boot/grub/grub.conf not found, please check it."
sed -i 's/^default=.*/default=0/g' /boot/grub/grub.conf
elif [ "$(_os_ver)" -eq 7 ]; then
rpm_kernel_url="https://dl.lamp.sh/kernel/el7/"
if _is_64bit; then
rpm_kernel_name="kernel-ml-5.15.60-1.el7.x86_64.rpm"
rpm_kernel_devel_name="kernel-ml-devel-5.15.60-1.el7.x86_64.rpm"
else
_error "Not supported architecture, please change to 64-bit architecture."
fi
_error_detect "wget -c -t3 -T60 -O ${rpm_kernel_name} ${rpm_kernel_url}${rpm_kernel_name}"
_error_detect "wget -c -t3 -T60 -O ${rpm_kernel_devel_name} ${rpm_kernel_url}${rpm_kernel_devel_name}"
[ -s "${rpm_kernel_name}" ] && _error_detect "rpm -ivh ${rpm_kernel_name}" || _error "Download ${rpm_kernel_name} failed, please check it."
[ -s "${rpm_kernel_devel_name}" ] && _error_detect "rpm -ivh ${rpm_kernel_devel_name}" || _error "Download ${rpm_kernel_devel_name} failed, please check it."
rm -f ${rpm_kernel_name} ${rpm_kernel_devel_name}
/usr/sbin/grub2-set-default 0
fi
fi
;;
ubuntu|debian)
_info "Getting latest kernel version..."
get_latest_version
if [ -n "${modules_deb_name}" ]; then
_error_detect "wget -c -t3 -T60 -O ${deb_kernel_modules_name} ${deb_kernel_modules_url}"
fi
_error_detect "wget -c -t3 -T60 -O ${deb_kernel_name} ${deb_kernel_url}"
_error_detect "dpkg -i ${deb_kernel_modules_name} ${deb_kernel_name}"
rm -f ${deb_kernel_modules_name} ${deb_kernel_name}
_error_detect "/usr/sbin/update-grub"
;;
*)
;; # do nothing
esac
}
reboot_os() {
echo
_info "系统需要重启才能生效"
read -p "是否立即重启系统? [y/n]" is_reboot
if [[ ${is_reboot} == "y" || ${is_reboot} == "Y" ]]; then
reboot
else
_info "重启已取消..."
exit 0
fi
}
install_bbr() {
if check_bbr_status; then
echo
_info "TCP BBR 已启用。无需执行..."
exit 0
fi
if check_kernel_version; then
echo
_info "内核版本大于4.9直接设置TCP BBR……"
sysctl_config
_info "设置 TCP BBR 成功..."
exit 0
fi
check_os
install_kernel
sysctl_config
reboot_os
}
[[ $EUID -ne 0 ]] && _error "此脚本必须以root用户运行"
opsy=$( _os_full )
arch=$( uname -m )
lbit=$( getconf LONG_BIT )
kern=$( uname -r )
clear
echo "---------- 系统信息 ----------"
echo " 系统: $opsy"
echo " 架构: $arch ($lbit Bit)"
echo " 内核: $kern"
echo "-------------------------------------"
echo " 一键开启 TCP BBR 脚本"
echo "-------------------------------------"
echo
echo "按任意键启用BBR...或者 Ctrl+C 取消"
char=$(get_char)
install_bbr 2>&1 | tee ${cur_dir}/install_bbr.log

278
dev/cf-setup.ps1 Normal file
View File

@@ -0,0 +1,278 @@
# PowerShell: "iwr -useb https://raw.githubusercontent.com/sky22333/shell/main/dev/cf-setup.ps1 | iex"
# Path: "C:\ProgramData\cloudflared\"
$ProgressPreference = 'SilentlyContinue'
$ErrorActionPreference = 'Stop'
function Write-ColorMessage {
param (
[Parameter(Mandatory=$true)]
[string]$Message,
[ValidateSet('Black','DarkBlue','DarkGreen','DarkCyan','DarkRed','DarkMagenta','DarkYellow','Gray','DarkGray','Blue','Green','Cyan','Red','Magenta','Yellow','White')]
[string]$Color = 'White'
)
try {
$originalColor = $null
if ($Host.UI -and $Host.UI.RawUI -and $Host.UI.RawUI.ForegroundColor) {
$originalColor = $Host.UI.RawUI.ForegroundColor
$Host.UI.RawUI.ForegroundColor = $Color
}
Write-Host $Message
if ($originalColor -ne $null) {
$Host.UI.RawUI.ForegroundColor = $originalColor
}
} catch {
try {
Write-Host $Message -ForegroundColor $Color
} catch {
Write-Host $Message
}
}
}
function Download-File {
param (
[string]$Url,
[string]$OutputPath
)
try {
if ($PSVersionTable.PSVersion.Major -ge 3) {
$webClient = New-Object System.Net.WebClient
$webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
$webClient.DownloadFile($Url, $OutputPath)
$webClient.Dispose()
} else {
$webClient = New-Object System.Net.WebClient
$webClient.DownloadFile($Url, $OutputPath)
$webClient.Dispose()
}
return $true
} catch {
Write-ColorMessage "Download failed: $($_.Exception.Message)" Red
return $false
}
}
function Test-AdminRights {
try {
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
} catch {
return $false
}
}
Write-Host "====== CloudFlared Tunnel Setup Tool ======" -ForegroundColor Cyan
Write-Host "Initializing..." -ForegroundColor Yellow
$cloudflaredUrl = "https://github.com/cloudflare/cloudflared/releases/download/2025.6.1/cloudflared-windows-amd64.exe"
$installDir = "$env:ProgramData\cloudflared"
$cloudflaredBin = Join-Path $installDir "cloudflared.exe"
$logPath = Join-Path $installDir "cloudflared.log"
$serviceName = "CloudflaredTunnel"
$psVersion = $PSVersionTable.PSVersion.Major
Write-Host "Detected PowerShell version: $psVersion" -ForegroundColor Green
try {
if (-not (Test-Path $installDir)) {
New-Item -ItemType Directory -Path $installDir -Force | Out-Null
Write-ColorMessage "Created installation directory: $installDir" Green
}
} catch {
Write-ColorMessage "Cannot create installation directory, may need administrator privileges" Red
Write-ColorMessage "Error: $($_.Exception.Message)" Red
exit 1
}
Write-ColorMessage "`nChecking cloudflared..." Yellow
if (Test-Path $cloudflaredBin) {
Write-ColorMessage "cloudflared.exe already exists: $cloudflaredBin" Green
try {
$fileInfo = Get-Item $cloudflaredBin
$fileSize = [math]::Round($fileInfo.Length / 1MB, 2)
Write-ColorMessage "File size: ${fileSize} MB" Cyan
} catch {
}
} else {
Write-ColorMessage "Starting download of cloudflared..." Cyan
Write-ColorMessage "Download URL: $cloudflaredUrl" Gray
Write-ColorMessage "Save location: $cloudflaredBin" Gray
$downloadSuccess = Download-File -Url $cloudflaredUrl -OutputPath $cloudflaredBin
if ($downloadSuccess) {
Write-ColorMessage "Download complete!" Green
try {
$fileInfo = Get-Item $cloudflaredBin
$fileSize = [math]::Round($fileInfo.Length / 1MB, 2)
Write-ColorMessage "File size: ${fileSize} MB" Cyan
} catch {
}
} else {
Write-ColorMessage "Download failed, please check your network connection or download manually" Red
Write-ColorMessage "Manual download URL: $cloudflaredUrl" Yellow
exit 1
}
}
Write-ColorMessage "`nChecking existing services..." Yellow
try {
$serviceExists = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
if ($serviceExists) {
Write-ColorMessage "Detected existing cloudflared service: $serviceName" Yellow
Write-ColorMessage "Service status: $($serviceExists.Status)" Cyan
do {
$uninstall = Read-Host "Do you want to uninstall the old service? (y/n)"
} while ($uninstall -notin @('y','Y','n','N','yes','no'))
if ($uninstall -in @('y','Y','yes')) {
Write-ColorMessage "Uninstalling old service..." Cyan
try {
Stop-Service -Name $serviceName -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 2
$scResult = & "$env:SystemRoot\System32\sc.exe" delete $serviceName
if (Test-Path $logPath) {
Remove-Item -Path $logPath -Force -ErrorAction SilentlyContinue
}
Write-ColorMessage "Service uninstallation complete" Green
} catch {
Write-ColorMessage "Error uninstalling service: $($_.Exception.Message)" Red
}
} else {
Write-ColorMessage "Keeping existing service, only updating run address" Yellow
}
}
} catch {
Write-ColorMessage "Error checking service: $($_.Exception.Message)" Red
}
Write-ColorMessage "`nPlease select run mode:" Yellow
Write-Host "1) Temporary run (foreground with trycloudflare domain display)"
Write-Host "2) Background run (register as system service)"
do {
$mode = Read-Host "Please enter 1 or 2 ?"
} while ($mode -notin @('1','2'))
do {
$localAddr = Read-Host "Please enter local service address (e.g.: 127.0.0.1:8080)"
} while ([string]::IsNullOrWhiteSpace($localAddr))
if ($mode -eq "1") {
Write-ColorMessage "`nRunning cloudflared in temporary mode..." Cyan
Write-ColorMessage "Starting cloudflared process..." Yellow
Write-ColorMessage "Local service address: $localAddr" Green
try {
Write-ColorMessage "Running cloudflared directly with output to console..." Yellow
Write-ColorMessage "Press Ctrl+C to stop the tunnel" Yellow
& $cloudflaredBin tunnel --url $localAddr
} catch {
Write-ColorMessage "Error starting process: $($_.Exception.Message)" Red
}
} elseif ($mode -eq "2") {
Write-ColorMessage "`nRegistering as system service and running in background..." Cyan
if (-not (Test-AdminRights)) {
Write-ColorMessage "Warning: Administrator privileges may be required to create system services" Yellow
Write-ColorMessage "If this fails, please run this script as administrator" Yellow
}
try {
$serviceCommand = "`"$cloudflaredBin`" tunnel --url $localAddr --logfile `"$logPath`""
$scResult = & "$env:SystemRoot\System32\sc.exe" create $serviceName binPath= $serviceCommand start= auto
if ($LASTEXITCODE -eq 0) {
Write-ColorMessage "Service created successfully" Green
} else {
Write-ColorMessage "Service creation may have failed, exit code: $LASTEXITCODE" Yellow
}
Start-Sleep -Seconds 2
Write-ColorMessage "Starting service..." Yellow
Start-Service -Name $serviceName -ErrorAction Stop
Write-ColorMessage "Service started successfully, waiting for log output..." Green
$domain = $null
for ($i = 0; $i -lt 30; $i++) {
Start-Sleep -Seconds 1
if (Test-Path $logPath) {
try {
$logContent = Get-Content $logPath -Raw -ErrorAction SilentlyContinue
if ($logContent -and $logContent -match 'https://[a-zA-Z0-9-]+\.trycloudflare\.com') {
$domain = $matches[0]
Write-ColorMessage "`n=== Service Running Successfully ===" Green
Write-ColorMessage "Public access URL: $domain" Green
Write-ColorMessage "Local service address: $localAddr" Cyan
Write-ColorMessage "Log file location: $logPath" Gray
break
}
} catch {
}
}
if ($i % 3 -eq 0) {
Write-Host "." -NoNewline
}
}
Write-Host ""
if (-not $domain) {
Write-ColorMessage "No access domain detected, please check the log manually: $logPath" Yellow
Write-ColorMessage "The service may need more time to establish connection" Cyan
try {
$serviceStatus = Get-Service -Name $serviceName
Write-ColorMessage "Service status: $($serviceStatus.Status)" Cyan
} catch {
Write-ColorMessage "Unable to get service status" Red
}
}
Write-ColorMessage "`nService management commands:" Yellow
Write-ColorMessage "Stop service: Stop-Service -Name $serviceName" Gray
Write-ColorMessage "Start service: Start-Service -Name $serviceName" Gray
Write-ColorMessage "Delete service: sc.exe delete $serviceName" Gray
} catch {
Write-ColorMessage "Failed to create or start service" Red
Write-ColorMessage "Error: $($_.Exception.Message)" Red
Write-ColorMessage "Please make sure you have administrator privileges" Yellow
try {
& "$env:SystemRoot\System32\sc.exe" delete $serviceName 2>$null
} catch {
}
}
} else {
Write-ColorMessage "Invalid option, please enter 1 or 2" Red
exit 1
}
Write-ColorMessage "`nScript execution complete" Green

133
dev/cf-tunnel.sh Normal file
View File

@@ -0,0 +1,133 @@
#!/bin/bash
# https://github.com/sky22333/shell
set -e
# === 颜色定义 ===
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[1;34m'
NC='\033[0m' # 清除颜色
CLOUDFLARED_URL="https://github.com/cloudflare/cloudflared/releases/download/2025.6.1/cloudflared-linux-amd64"
CLOUDFLARED_BIN="/usr/local/bin/cloudflared"
SERVICE_PATH="/etc/systemd/system/cloudflared-tunnel.service"
LOG_PATH="/var/log/cloudflared.log"
# 检查 cloudflared 是否已存在
if [[ -f "$CLOUDFLARED_BIN" ]]; then
echo -e "${GREEN}已存在文件,跳过下载。${NC}"
else
echo -e "${BLUE}正在下载 cloudflared...${NC}"
if ! curl -L "$CLOUDFLARED_URL" -o "$CLOUDFLARED_BIN"; then
echo -e "${RED}下载失败,请检查网络连接或 URL。${NC}"
exit 1
fi
chmod +x "$CLOUDFLARED_BIN"
fi
# 检查服务是否存在
SERVICE_EXISTS=false
if sudo systemctl list-units --full --all | grep -q 'cloudflared-tunnel.service'; then
SERVICE_EXISTS=true
echo -e "${YELLOW}已检测到 cloudflared-tunnel systemd 服务${NC}"
read -p "是否要卸载旧服务?(y/n): " UNINSTALL
if [[ "$UNINSTALL" == "y" || "$UNINSTALL" == "Y" ]]; then
echo -e "${BLUE}正在卸载旧服务...${NC}"
sudo systemctl stop cloudflared-tunnel || true
sudo systemctl disable cloudflared-tunnel || true
sudo rm -f "$SERVICE_PATH"
sudo rm -f "$LOG_PATH"
sudo systemctl daemon-reload
SERVICE_EXISTS=false
echo -e "${GREEN}服务卸载完成${NC}"
else
echo -e "${YELLOW}将保留旧服务配置,仅修改穿透地址${NC}"
fi
fi
# 用户选择运行模式
echo ""
echo -e "${YELLOW}请选择运行模式:${NC}"
echo "1) 临时运行(前台运行并显示临时访问域名)"
echo "2) 后台运行(自动配置后台服务并显示访问域名)"
read -p "请输入 1 或 2: " MODE
# 输入内网地址
read -p "请输入要穿透的本地地址(例如 127.0.0.1:8080: " LOCAL_ADDR
if [[ "$MODE" == "1" ]]; then
echo -e "${BLUE}正在前台运行 cloudflared...${NC}"
LOGFILE=$(mktemp)
stdbuf -oL "$CLOUDFLARED_BIN" tunnel --url "$LOCAL_ADDR" 2>&1 | tee "$LOGFILE" &
PID=$!
echo -e "${YELLOW}等待 cloudflared 输出访问域名...${NC}"
for i in {1..30}; do
DOMAIN=$(grep -oP 'https://[a-zA-Z0-9-]+\.trycloudflare\.com' "$LOGFILE" | head -n1)
if [[ -n "$DOMAIN" ]]; then
echo ""
echo -e "${GREEN}成功获取公网临时访问域名:$DOMAIN${NC}"
echo ""
wait $PID
exit 0
fi
sleep 1
done
echo -e "${RED}超时未能获取临时域名,日志保存在:$LOGFILE${NC}"
kill $PID 2>/dev/null || true
exit 1
elif [[ "$MODE" == "2" ]]; then
echo -e "${BLUE}正在配置 systemd 服务...${NC}"
if [[ "$SERVICE_EXISTS" == false ]]; then
sudo bash -c "cat > $SERVICE_PATH" <<EOF
[Unit]
Description=Cloudflared Tunnel Service
After=network.target
[Service]
ExecStart=$CLOUDFLARED_BIN tunnel --url $LOCAL_ADDR
Restart=always
StandardOutput=append:$LOG_PATH
StandardError=append:$LOG_PATH
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now cloudflared-tunnel
else
echo -e "${YELLOW}更新 systemd 服务配置中的穿透地址...${NC}"
sudo truncate -s 0 "$LOG_PATH" || sudo bash -c "> $LOG_PATH"
sudo sed -i "s|ExecStart=.*|ExecStart=$CLOUDFLARED_BIN tunnel --url $LOCAL_ADDR|" "$SERVICE_PATH"
sudo systemctl daemon-reload
sudo systemctl restart cloudflared-tunnel
fi
echo -e "${GREEN}服务已启动,日志保存在 $LOG_PATH${NC}"
echo -e "${YELLOW}等待 cloudflared 输出访问域名...${NC}"
for i in {1..30}; do
DOMAIN=$(grep -oP 'https://[a-zA-Z0-9-]+\.trycloudflare\.com' "$LOG_PATH" | head -n1)
if [[ -n "$DOMAIN" ]]; then
echo ""
echo -e "${GREEN}成功获取公网访问域名:$DOMAIN${NC}"
echo ""
exit 0
fi
sleep 1
done
echo -e "${RED}超时未能获取公网访问域名,请稍后手动查看:$LOG_PATH${NC}"
exit 1
else
echo -e "${RED}无效输入,请输入 1 或 2${NC}"
exit 1
fi

29
dev/check_ntpdate.sh Normal file
View File

@@ -0,0 +1,29 @@
#!/bin/bash
# 封装脚本过期函数
check_ntpdate() {
# 设置过期时间
local expire_date="2025-04-10 12:00:00"
# date -d "$(curl -sI https://www.bing.com | grep -i '^date:' | cut -d' ' -f2-)" +'%Y-%m-%d %H:%M:%S UTC+8'
# 获取时间戳(从 https://www.cloudflare.com/cdn-cgi/trace 获取)
timestamp=$(curl -s https://www.cloudflare.com/cdn-cgi/trace | grep -oP 'ts=\K\d+')
# 如果获取时间戳失败,则停止运行脚本
if [[ -z "$timestamp" ]]; then
echo "网络错误,无法获取当前时间戳。"
exit 1
fi
# 转换时间戳为 YYYY-MM-DD HH:MM:SS 格式(北京时间)
current_time=$(TZ="Asia/Shanghai" date -d @$timestamp "+%Y-%m-%d %H:%M:%S")
# 判断当前时间是否超过过期日期
if [[ "$current_time" > "$expire_date" ]]; then
echo "当前脚本已过期,请联系开发者。"
exit 1
fi
}
# 调用函数执行检查
check_ntpdate

1161
dev/docker.sh Normal file

File diff suppressed because it is too large Load Diff

121
dev/go.sh Normal file
View File

@@ -0,0 +1,121 @@
#!/bin/bash
# Go 自动安装配置脚本 (适用于Debian/Ubuntu)
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
if ! grep -qiE 'debian|ubuntu' /etc/os-release; then
echo -e "${RED}错误本脚本仅适用于Debian/Ubuntu系统${NC}"
exit 1
fi
if [ "$(id -u)" -ne 0 ]; then
echo -e "${RED}请使用 sudo 或以 root 用户运行此脚本${NC}"
exit 1
fi
DEFAULT_VERSION="1.24.0"
read -p "请输入要安装的 Go 版本 [默认: ${DEFAULT_VERSION}]: " GO_VERSION
GO_VERSION=${GO_VERSION:-$DEFAULT_VERSION}
if ! [[ "$GO_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo -e "${RED}错误:版本号格式不正确,版本号可在 https://golang.org/dl 查看${NC}"
exit 1
fi
GO_TAR="go${GO_VERSION}.linux-amd64.tar.gz"
GO_URL="https://dl.google.com/go/${GO_TAR}"
if command -v go &>/dev/null; then
echo -e "${YELLOW}检测到已安装Go当前版本: $(go version)${NC}"
read -p "是否要卸载当前版本? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo -e "${YELLOW}卸载旧版Go...${NC}"
rm -rf /usr/local/go
sed -i '/# GoLang/d' /etc/profile
sed -i '/export GOROOT/d' /etc/profile
sed -i '/export GOPATH/d' /etc/profile
sed -i '/export PATH=\$GOROOT/d' /etc/profile
else
echo -e "${YELLOW}保留现有安装,退出脚本${NC}"
exit 0
fi
fi
echo -e "${YELLOW}检查是否存在旧的安装包...${NC}"
cd /tmp
if [ -f "${GO_TAR}" ]; then
echo -e "${YELLOW}删除旧的安装包:${GO_TAR}${NC}"
rm -f "${GO_TAR}"
fi
echo -e "${GREEN}开始下载 Go ${GO_VERSION} 安装包...${NC}"
wget --progress=bar:force "${GO_URL}"
if [ $? -ne 0 ]; then
echo -e "${RED}下载失败,请检查网络连接和版本号是否正确${NC}"
echo "可用的Go版本可在 https://golang.org/dl/ 查看"
exit 1
fi
echo -e "${GREEN}安装 Go 到 /usr/local...${NC}"
rm -rf /usr/local/go
tar -C /usr/local -xzf "${GO_TAR}"
echo -e "${GREEN}配置环境变量...${NC}"
cat >> /etc/profile <<EOF
# GoLang Environment
export GOROOT=/usr/local/go
export GOPATH=\$HOME/go
export PATH=\$GOROOT/bin:\$GOPATH/bin:\$PATH
EOF
for USER_HOME in /home/* /root; do
USER=$(basename "${USER_HOME}")
if [ -d "${USER_HOME}" ]; then
cat >> "${USER_HOME}/.profile" <<EOF
# GoLang Environment
export GOROOT=/usr/local/go
export GOPATH=\$HOME/go
export PATH=\$GOROOT/bin:\$GOPATH/bin:\$PATH
EOF
chown "${USER}:${USER}" "${USER_HOME}/.profile"
fi
done
echo -e "${GREEN}创建 GOPATH 目录...${NC}"
for USER_HOME in /home/* /root; do
if [ -d "${USER_HOME}" ]; then
mkdir -p "${USER_HOME}/go"{,/bin,/pkg,/src}
chown -R "$(basename "${USER_HOME}"):$(basename "${USER_HOME}")" "${USER_HOME}/go"
fi
done
source /etc/profile
echo -e "${GREEN}验证安装...${NC}"
if ! command -v go &>/dev/null; then
echo -e "${RED}Go 安装失败,请检查错误信息${NC}"
exit 1
fi
echo -e "${GREEN}Go 安装成功!版本信息:${NC}"
go version
echo -e "
${GREEN}安装完成Go ${GO_VERSION} 已成功安装并配置。${NC}
${YELLOW}提示:
1. 新终端会话会自动加载 Go 环境变量
2. 当前会话可执行 ${NC}${GREEN}source ~/.profile${NC}${YELLOW} 立即生效
3. Go 工作目录 (GOPATH) 已创建在 ${NC}${GREEN}~/go${NC}
如需卸载,请删除 ${YELLOW}/usr/local/go${NC} 目录。
"

127
dev/image.sh Normal file
View File

@@ -0,0 +1,127 @@
#!/bin/bash
# Debian/Ubuntu 内核切换脚本
# 功能:从 Cloud 内核切换到标准内核
# 适用Debian 11+/Ubuntu 18.04+
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m'
check_root() {
if [ "$(id -u)" -ne 0 ]; then
echo -e "${RED}错误:必须使用 root 权限运行此脚本${NC}"
exit 1
fi
}
check_cloud_kernel() {
if ! uname -r | grep -q 'cloud'; then
echo -e "${GREEN}提示:系统已在标准内核运行 ($(uname -r))${NC}"
exit 0
fi
}
purge_cloud_kernel() {
echo -e "${YELLOW}步骤1/4彻底移除 Cloud 内核...${NC}"
# 找出所有 Cloud 内核包
local cloud_pkgs=$(dpkg -l | awk '/linux-(image|headers)-[0-9].*cloud/ {print $2}')
if [ -n "$cloud_pkgs" ]; then
echo -e "正在卸载: ${cloud_pkgs}"
apt purge -y $cloud_pkgs
apt autoremove -y --purge
else
echo -e "${GREEN}提示:未找到 Cloud 内核包${NC}"
fi
}
lock_cloud_kernel() {
echo -e "${YELLOW}步骤2/4锁定 Cloud 内核...${NC}"
# 检查是否还有额外的 Cloud 内核包,如果有则标记为 hold
cloud_kernels=$(apt list --installed 2>/dev/null | grep -i 'linux-image' | grep -i 'cloud' | cut -d'/' -f1)
if [ -n "$cloud_kernels" ]; then
echo "找到以下 Cloud 内核包,正在锁定:$cloud_kernels"
apt-mark hold $cloud_kernels
else
echo -e "${GREEN}提示:未找到任何 Cloud 内核包,跳过锁定步骤。${NC}"
fi
}
force_install_standard() {
echo -e "${YELLOW}步骤3/4安装标准内核...${NC}"
# 根据系统类型选择包名
local image_pkg="linux-image-amd64"
local headers_pkg="linux-headers-amd64"
if grep -q 'ID=ubuntu' /etc/os-release; then
image_pkg="linux-image-generic"
headers_pkg="linux-headers-generic"
fi
# 强制安装并跳过配置提问
DEBIAN_FRONTEND=noninteractive apt install -y --reinstall --allow-downgrades \
"$image_pkg" "$headers_pkg"
# 确保 initramfs 更新
local std_kernel=$(ls /boot/vmlinuz-* | grep -v cloud | sort -V | tail -1 | sed 's|/boot/vmlinuz-||')
update-initramfs -u -k "$std_kernel"
}
nuclear_grub_update() {
echo -e "${YELLOW}步骤4/4重建 GRUB...${NC}"
# 备份原配置
mkdir -p /root/grub_backup
cp -a /boot/grub /root/grub_backup/grub.bak.$(date +%s)
# 生成干净的 GRUB 配置
cat > /etc/default/grub <<'EOF'
GRUB_DEFAULT=0
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR=lsb_release -i -s 2> /dev/null || echo Debian
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
GRUB_CMDLINE_LINUX=""
GRUB_DISABLE_OS_PROBER=true
GRUB_DISABLE_RECOVERY=true
EOF
# 完全重建配置
grub-mkconfig -o /boot/grub/grub.cfg
# 确保使用第一个菜单项
grub-set-default 0
update-grub
# 特殊处理 UEFI 系统
if [ -d /sys/firmware/efi ]; then
echo -e "检测到 UEFI 系统,更新引导加载程序..."
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=debian --recheck
fi
}
main() {
echo -e "\n${GREEN}=== Debian/Ubuntu 内核切换脚本 ===${NC}"
check_root
check_cloud_kernel
# 执行核心修复步骤
purge_cloud_kernel
lock_cloud_kernel
force_install_standard
nuclear_grub_update
# 最终验证
echo -e "\n${GREEN}=== 操作完成 ===${NC}"
echo -e "请手动重启系统:"
echo -e "1. 重启系统: ${YELLOW}reboot${NC}"
echo -e "2. 检查内核: ${YELLOW}uname -r${NC}"
touch /root/.kernel_switch_success
}
main "$@"

82
dev/mbit.sh Normal file
View File

@@ -0,0 +1,82 @@
#!/bin/bash
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 检查是否以root权限运行
if [ "$(id -u)" != "0" ]; then
echo -e "${RED}此脚本需要root权限运行请输入 sudo -i 后再执行此脚本${NC}" 1>&2
exit 1
fi
# 检查是否安装了iproute2
if ! command -v tc &> /dev/null
then
echo -e "${BLUE}iproute2未安装正在安装...${NC}"
if ! apt update -q && apt install -yq iproute2; then
echo -e "${RED}安装iproute2失败。请检查您的网络连接和系统状态。${NC}"
exit 1
fi
else
echo -e "${BLUE}iproute2已安装。${NC}"
fi
# 获取默认网络接口
INTERFACE=$(ip route | grep default | awk '{print $5}' | head -n1)
if [ -z "$INTERFACE" ]; then
echo -e "${RED}错误:无法检测到默认网络接口。${NC}"
exit 1
fi
echo -e "${BLUE}检测到默认网络接口: $INTERFACE${NC}"
# 检查是否存在限速规则
if tc qdisc show dev $INTERFACE | grep -q "htb"; then
echo -e "${YELLOW}当前存在限速规则:${NC}"
tc -s qdisc ls dev $INTERFACE
echo -e "${GREEN}如果要更改配置请先清除限速规则,请运行以下命令,然后重新执行脚本。${NC}"
echo -e "${YELLOW}sudo tc qdisc del dev $INTERFACE root${NC}"
exit 0
fi
printf "${GREEN}请输入要限制带宽的端口号(多个端口用逗号分隔): ${NC}"
read PORTS
printf "${GREEN}请输入限速值单位为M: ${NC}"
read LIMIT
if [ -z "$PORTS" ] || [ -z "$LIMIT" ]; then
echo -e "${RED}错误:端口号和限速值不能为空。${NC}"
exit 1
fi
if ! [[ "$LIMIT" =~ ^[0-9]+$ ]]; then
echo -e "${RED}错误:限速值必须是一个数字。${NC}"
exit 1
fi
IFS=',' read -ra PORT_ARRAY <<< "$PORTS"
# 创建根qdisc
tc qdisc add dev "$INTERFACE" root handle 1: htb default 12
tc class add dev "$INTERFACE" parent 1: classid 1:1 htb rate "${LIMIT}"mbit
tc class add dev "$INTERFACE" parent 1:1 classid 1:12 htb rate "${LIMIT}"mbit
for PORT in "${PORT_ARRAY[@]}"
do
if ! [[ "$PORT" =~ ^[0-9]+$ ]] || [ "$PORT" -lt 1 ] || [ "$PORT" -gt 65535 ]; then
echo -e "${RED}错误:无效的端口号 $PORT。端口号必须在1-65535之间。${NC}"
continue
fi
tc filter add dev "$INTERFACE" protocol ip parent 1:0 prio 1 u32 match ip dport "$PORT" 0xffff flowid 1:12
echo -e "${GREEN}网络接口 $INTERFACE 的端口 $PORT 带宽限制已设置为 ${LIMIT}Mbit。${NC}"
done
echo -e "${YELLOW}如果要更改配置请先清除限速规则,请运行以下命令,然后重新执行脚本。${NC}"
echo -e "${YELLOW}sudo tc qdisc del dev $INTERFACE root${NC}"

5702
dev/mirrors.sh Normal file

File diff suppressed because it is too large Load Diff