diff --git a/ssr/google_bbr b/ssr/google_bbr new file mode 100644 index 0000000..78b8429 --- /dev/null +++ b/ssr/google_bbr @@ -0,0 +1,372 @@ +#!/usr/bin/env bash +# +# Auto install latest kernel for TCP BBR +# +# System Required: CentOS 6+, Debian8+, Ubuntu16+ +# +# Copyright (C) 2016-2021 Teddysun +# +# URL: https://teddysun.com/489.html +# + +cur_dir="$(cd -P -- "$(dirname -- "$0")" && pwd -P)" + +_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 not supported." + fi + if [ -n "${virt}" -a "${virt}" = "openvz" ] || [ -d "/proc/vz" ]; then + _error "Virtualization method is OpenVZ, which is not supported." + fi + [ -z "$(_os)" ] && _error "Not supported OS" + 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 "Not supported OS" + ;; + 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.38-1.el7.x86_64.rpm" + rpm_kernel_devel_name="kernel-ml-devel-5.15.38-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 "The system needs to reboot." + read -p "Do you want to restart system? [y/n]" is_reboot + if [[ ${is_reboot} == "y" || ${is_reboot} == "Y" ]]; then + reboot + else + _info "Reboot has been canceled..." + exit 0 + fi +} + +install_bbr() { + if check_bbr_status; then + echo + _info "TCP BBR has already been enabled. nothing to do..." + exit 0 + fi + if check_kernel_version; then + echo + _info "The kernel version is greater than 4.9, directly setting TCP BBR..." + sysctl_config + _info "Setting TCP BBR completed..." + exit 0 + fi + check_os + install_kernel + sysctl_config + reboot_os +} + +[[ $EUID -ne 0 ]] && _error "This script must be run as root" +opsy=$( _os_full ) +arch=$( uname -m ) +lbit=$( getconf LONG_BIT ) +kern=$( uname -r ) + +clear +echo "---------- System Information ----------" +echo " OS : $opsy" +echo " Arch : $arch ($lbit Bit)" +echo " Kernel : $kern" +echo "----------------------------------------" +echo " Automatically enable TCP BBR script" +echo +echo " URL: https://teddysun.com/489.html" +echo "----------------------------------------" +echo +echo "Press any key to start...or Press Ctrl+C to cancel" +char=$(get_char) + +install_bbr 2>&1 | tee ${cur_dir}/install_bbr.log