update
This commit is contained in:
55
dev/README.md
Normal file
55
dev/README.md
Normal 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
157
dev/acme.sh
Normal 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
242
dev/ansible.md
Normal 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"
|
||||
```
|
||||
- 临时对1,3号主机执行shell命令
|
||||
```
|
||||
ansible 1,3 -m shell -a "你的命令"
|
||||
```
|
||||
- 临时对1,3号主机执行普通命令
|
||||
```
|
||||
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
48
dev/ansible.sh
Normal 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
366
dev/bbr.sh
Normal 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
278
dev/cf-setup.ps1
Normal 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
133
dev/cf-tunnel.sh
Normal 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
29
dev/check_ntpdate.sh
Normal 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
1161
dev/docker.sh
Normal file
File diff suppressed because it is too large
Load Diff
121
dev/go.sh
Normal file
121
dev/go.sh
Normal 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
127
dev/image.sh
Normal 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
82
dev/mbit.sh
Normal 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
5702
dev/mirrors.sh
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user