Created
May 18, 2023 00:00
-
-
Save iykex/0b6f182669a24a565d0b7ce5699a031d to your computer and use it in GitHub Desktop.
#Auto install latest kernel for TCP BBR | #System Required: CentOS 6+, Debian8+, Ubuntu16+ | #Copyright (C) 2016-2021 Teddysun <[email protected]> | # URL: https://teddysun.com/489.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# | |
# Auto install latest kernel for TCP BBR | |
# | |
# System Required: CentOS 6+, Debian8+, Ubuntu16+ | |
# | |
# Copyright (C) 2016-2021 Teddysun <[email protected]> | |
# | |
# 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.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 "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 "Installing Google BBR TCP congestion control algorithm" | |
install_bbr 2>&1 | tee ${cur_dir}/install_bbr.log |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment