#!/bin/bash
#set -e  # 遇到错误立即退出

if [ -n "$SSH_CONNECTION" ] || [ -n "$SSH_TTY" ]; then
	stty erase ^h
fi

#注释的冒号表示法，请在 : ' 和结束的 ' 之间编写块注释
: '
bash <(curl -s 449977.xyz)
bash <(wget -qO- 449977.xyz)
'

<<DELIMITER
bash <(curl -s 449977.xyz)
bash <(wget -qO- 449977.xyz)
DELIMITER

# bash fonts colors
red='\e[31m'
yellow='\e[33m'
gray='\e[90m'
green='\e[92m'
blue='\e[94m'
magenta='\e[95m'
cyan='\e[96m'
none='\e[0m'

_red() { echo -e ${red}$@${none}; }
_blue() { echo -e ${blue}$@${none}; }
_cyan() { echo -e ${cyan}$@${none}; }
_green() { echo -e ${green}$@${none}; }
_yellow() { echo -e ${yellow}$@${none}; }
_magenta() { echo -e ${magenta}$@${none}; }

_red_bg() { echo -e "\e[41;37m$@${none}"; }
_green_bg() { echo -e "\e[42;37m$@${none}"; }
_green_bgn() { echo -n -e "\e[42;37m$@${none}"; }
_yellow_bg() { echo -e "\e[43;37m$@${none}"; }
_blue_bg() { echo -e "\e[44;37m$@${none}"; }
_purple_bg() { echo -e "\e[45;37m$@${none}"; }

is_err=$(_red_bg 错误!)
is_warn=$(_red_bg 警告!)

err() {
    echo -e "\n$is_err $@\n" && exit 1
}
warn() {
    echo -e "\n$is_warn $@\n"
}

# root
[[ $EUID != 0 ]] && err "当前非 ${yellow}ROOT用户.${none}"

# apt-get, ubuntu/debian
cmd=$(type -P apt-get)
[[ ! $cmd ]] && err "此脚本仅支持 ${yellow}(Ubuntu or Debian)${none}."

# wget add --no-check-certificate
_wget() {
	wget --no-check-certificate "$@"
}

# set pipefail so pipeline failures are caught by run_and_check
set -o pipefail

run_and_check() {
	# Execute command and exit with error printing on failure
	echo "+ $*"
	if ! "$@"; then
		echo -e "\n$is_err Command failed: $*\n" >&2
		exit 1
	fi
	return 0
}


function _get_pid_by_bin() {
    local bin="$1"                     # 参数：程序文件路径或名称
    local rbin
    rbin="$(readlink -f "$bin" 2>/dev/null)" || return 1

    # 遍历所有匹配名称的进程
    for pid in $(pgrep -f "$(basename "$bin")"); do
        local exe
        exe="$(readlink -f "/proc/$pid/exe" 2>/dev/null || true)"
        if [[ "$exe" == "$rbin" ]]; then
            echo "$pid"
        fi
    done
}

function _kill() {
	local pid
	pid=$(_get_pid_by_bin "$1") || return 1
	if [ -z "$pid" ]; then
		return 1
	fi

	# Try graceful termination (SIGTERM) first, then fallback to SIGKILL
	kill "$pid" 2>/dev/null || true
	# wait up to 5s for process to stop
	for i in 1 2 3 4 5; do
		if ! kill -0 "$pid" 2>/dev/null; then
			return 0
		fi
		sleep 1
	done

	# fallback to SIGKILL
	kill -9 "$pid" 2>/dev/null || true
}

mem=`cat /proc/meminfo|grep MemTotal|awk '{print $2}'`
let mem=(mem+384292)/1024/1024


function _is_virt() {
	status=`lscpu | grep Hypervisor| tr [A-Z] [a-z]`
	if [[ x"$status" == x*kvm* ]] || 
	[[ x"$status" == x*vmware* ]];then
		is_virt=1
	else
		is_virt=0
	fi
}

function WriteInI(){
    fid=$1
    section=$2
    option=$3
    value=$4
    #if [ ${fid#*.} != ini ] ; then  
    #    echo "不是ini文件" 
    #    return 2 
    #fi 
	test ! -f "$fid" && echo "不存在文件$fid" && return 2
    if [ $# -eq 4 ] ; then
        local src=$(cat $fid | awk '/\['$section'\]/{f=1;next} /\[*\]/{f=0} f')  #先搜寻是否存在option
        if [ ${#src} -eq 0 ] ;then #没有匹配到section，直接新建并添加内容
            echo "[$section]" >> $fid
            echo "$option=$value"  >> $fid
            return 0
        else
            local src=$(cat -n $fid | awk '/\['$section'\]/{f=1;next} /\[*\]/{f=0} f' | grep $option | grep '=')
            if [  ${#src} -eq 0 ] ; then #没有对应的 option 直接添加
                local last=$(cat -n $fid | awk '/\['$section'\]/{f=1;next} /\[*\]/{f=0} f' | tail -n 1)
                last=$(echo $last | cut -d' ' -f1)
                sed -i "${last}a $option=$value" $fid 
                return 0
            fi 
            local old_value=$(echo $src | cut -d'=' -f2 |cut -d'#' -f1 | cut -d';' -f1  )
            local idx=$(echo $src | cut -d' ' -f1)
			local newcontext="$(cat "$fid" | sed -n "${idx}p" | sed "s/$old_value/$value/" | awk '{gsub(/^\s+|\s+$/, "");print}')"
			# escape '/' and '&' for sed replacement and quote file name
			local escaped_newcontext
			escaped_newcontext=$(printf '%s' "$newcontext" | sed 's/[&/]/\\&/g')
			sed -i "${idx}c $escaped_newcontext" "$fid"
            return 0       
        fi  
    fi 
}

function __find_openssl_ver(){
	for file in $(_wget -q -O- "https://openssl-library.org/source/"|grep "https://github.com/openssl/openssl/releases/download/"|grep -v "alpha"|grep -v "beta"); do
		openssl_url=`echo $file|awk -F\" '{print $2}'`
		if [[ $openssl_url == *github.com* ]];then
			break
		fi
	done
	openssl_ver=`echo $openssl_url|awk -F\/ '{print $8}'`	
}

##########################################
function _Debian(){
lastest_version=`_wget -q https://www.debian.org -O-|grep https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/|awk -F/ '{print $8}'|awk -F- '{print $2}'`
count=`echo "$lastest_version" | grep -o "\." | wc -l`
if [ "$count" -eq 2 ]; then
	if [[ ${lastest_version:0-2:2} == ".0" ]]; then
		lastest_version=${lastest_version%\.*}
	fi
	
fi
current_version=`cat /etc/debian_version`
echo -n "Current Debian Version: "; _green_bg "$current_version"
if [ "$lastest_version" == "$current_version" ]; then
	echo -n "Lastest Debian Version: "; _green_bg "$lastest_version"
else
	echo -n "Lastest Debian Version: "; _red_bg $lastest_version
fi

echo ""

	_is_virt
if [ "$is_virt" == "1" ]; then
	if [ -f /etc/modprobe.d/blacklist.conf ]; then #文件存在
		if [ `grep -xc "blacklist i2c-piix4" /etc/modprobe.d/blacklist.conf` -eq '0' ]; then
			echo ""
			_purple_bg "Disable smbus host controller not enabled"
			echo blacklist i2c-piix4 > /etc/modprobe.d/blacklist.conf
			update-initramfs -u -k all
		fi

	else
		echo ""
		_purple_bg "Disable smbus host controller not enabled"
		echo blacklist i2c-piix4 > /etc/modprobe.d/blacklist.conf
		update-initramfs -u -k all
	fi
fi



echo ""
_purple_bg "Install utils"
#iptables-persistent 
apt-get -o Acquire::ForceIPv4=true update
apt-get -o Acquire::ForceIPv4=true install net-tools curl sudo vim ethtool gcc make zlib1g-dev unzip jq openssl libssl-dev tcpdump git dnsutils -y
apt-get -o Acquire::ForceIPv4=true install g++ autoconf automake libtool libffi-dev libunwind-dev cmake parted libncurses-dev pkg-config -y
apt-get -o Acquire::ForceIPv4=true install arptables -y
apt-get -o Acquire::ForceIPv4=true install linux-headers-$(uname -r) -y


sed -i "s/# export LS_OPTIONS='--color=auto'/export LS_OPTIONS='--color=auto'/" /root/.bashrc
sed -i 's/# eval "$(dircolors)"/eval "$(dircolors)"/' /root/.bashrc
sed -i "s/# alias ls='ls \$LS_OPTIONS'/alias ls='ls \$LS_OPTIONS'/" /root/.bashrc
sed -i "s/# alias ll='ls \$LS_OPTIONS -l'/alias ll='ls \$LS_OPTIONS -l'/" /root/.bashrc
sed -i "s/# alias l='ls \$LS_OPTIONS -lA'/alias l='ls \$LS_OPTIONS -lA'/" /root/.bashrc

WriteInI /usr/lib/systemd/system/rc-local.service Install WantedBy multi-user.target
if [ ! -f /etc/rc.local ]; then
	cat > /etc/rc.local <<EOF
#!/bin/sh
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
 
exit 0
EOF
fi

chmod +x /etc/rc.local
systemctl enable rc-local
systemctl start rc-local.service

userdel -f -r user 2>/dev/null

_red_bg "Debian DONE!"
}

function _ssh_common(){
#grep -x：完全匹配整行。
if [ `grep -xc "#PermitRootLogin yes" /etc/ssh/sshd_config` -eq '1' ];then
	sed -i 's/#PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config
elif [ `grep -xc "#PermitRootLogin no" /etc/ssh/sshd_config` -eq '1' ]; then
	sed -i 's/#PermitRootLogin no/PermitRootLogin yes/' /etc/ssh/sshd_config
elif [ `grep -xc "PermitRootLogin yes" /etc/ssh/sshd_config` -eq '0' ];then
	echo PermitRootLogin yes >> /etc/ssh/sshd_config
fi

sed -i 's/#UseDNS no/UseDNS no/' /etc/ssh/sshd_config
sed -i 's/UseDNS yes/UseDNS no/' /etc/ssh/sshd_config

#＃server每隔20秒发送一次请求给client，然后client响应，从而保持连接
sed -i 's/#ClientAliveInterval 0/ClientAliveInterval 20/' /etc/ssh/sshd_config
sed -i 's/ClientAliveInterval 0/ClientAliveInterval 20/' /etc/ssh/sshd_config

}

##########################################
function _ssh_public_key() {
echo ""
_purple_bg "PermitRootLogin"

_ssh_common


sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sed -i 's/PubkeyAuthentication no/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config

key1="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBtqiZTCT6MRh+V6tM4CCDTxiE14Y5mqYJ+DH8TZqUZn user@email.com"
key2="ecdsa-sha2-nistp521 [payload removed: 232 characters] ssh"
if [ ! -f "/root/.ssh/authorized_keys" ];then #"文件不存在"
	mkdir /root/.ssh/ > /dev/null 2>&1
	echo $key1 > /root/.ssh/authorized_keys
	echo $key2 >> /root/.ssh/authorized_keys
else
	if [ `grep -c "AAAAC3NzaC1lZDI1NTE5AAAAIBtqiZTCT6MRh+V6tM4CCDTxiE14Y5mqYJ+DH8TZqUZn" /root/.ssh/authorized_keys` -eq '0' ];then #"文件存在，且不含证书1"
		echo $key1 >> /root/.ssh/authorized_keys
	fi
	if [ `grep -c "[payload removed: 232 characters]" /root/.ssh/authorized_keys` -eq '0' ];then #"文件存在，且不含证书2"
		echo $key2 >> /root/.ssh/authorized_keys
	fi
fi
chmod 600 /root/.ssh/authorized_keys

/etc/init.d/ssh restart

echo ""
_green_bg "###############"
cat /root/.ssh/authorized_keys
_green_bg "###############"

echo ""
_red_bg "SSH PUBLIC KEY DONE!"

}

function _ssh_password() {
echo ""
_purple_bg "PermitRootLogin"

_ssh_common


sed -i 's/PubkeyAuthentication yes/#PubkeyAuthentication yes/' /etc/ssh/sshd_config
sed -i 's/PubkeyAuthentication no/#PubkeyAuthentication yes/' /etc/ssh/sshd_config
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config

rm -f /root/.ssh/authorized_keys

/etc/init.d/ssh restart

echo ""
_red_bg "SSH PASSWORD DONE!"

}





##########################################
function _openssl() {
mkdir /root/src 2>/dev/null;cd /root/src
echo ""
_purple_bg "find openssl_version"
__find_openssl_ver
echo $openssl_ver
local build_dir="/root/src/$openssl_ver"
trap 'if [ -d "$build_dir" ]; then echo "\n$is_warn openssl build failed, cleaning up $build_dir"; rm -rf "$build_dir"; fi; trap - ERR; exit 1' ERR

echo ""
_purple_bg "Clean"
for file in $(ls /root/src/openssl-* 2>/dev/null); do
	if [[ $file != *$openssl_ver* ]];then
		rm -rf $file 2>/dev/null
	fi	
done


echo ""
cd /root/src
if [ ! -f "$openssl_ver.tar.gz" ];then
	_purple_bg "Downloading"
	run_and_check _wget "$openssl_url" -O "/root/src/$openssl_ver.tar.gz"
fi

if [ ! -d "$openssl_ver" ];then
	_purple_bg "Unzip $openssl_ver.tar.gz"
	run_and_check tar -zxf "$openssl_ver.tar.gz"
	trap - ERR
fi

_red_bg "OenSSL DONE!"
}

function _update_ngx() {

cat << EOF > /usr/local/bin/ngx
#!/bin/bash
stty erase ^h

none='\e[0m'
_red_bg() { echo -e "\e[41;37m\$@\${none}"; }
_red_bgn() { echo -e -n "\e[41;37m\$@\${none}"; }
_green_bg() { echo -e "\e[42;37m\$@\${none}"; }
_green_bgn() { echo -e -n "\e[42;37m\$@\${none}"; }
_yellow_bg() { echo -e "\e[43;37m\$@\${none}"; }
_yellow_bgn() { echo -e -n "\e[43;37m\$@\${none}"; }
_blue_bg() { echo -e "\e[46;37m\$@\${none}"; }
_blue_bgn() { echo -e -n "\e[46;37m\$@\${none}"; }
_purple_bg() { echo -e "\e[45;37m\$@\${none}"; }
_purple_bgn() { echo -e -n "\e[45;37m\$@\${none}"; }
_blankn() { echo -e -n "\t"; }

function _nginx_pid_init(){
	masterpid=\`ps -ef | grep "nginx: master process" | grep -v grep | awk 'BEGIN{ORS=" "}{print \$2}' | awk '{gsub(/\ \$/, "");print}'\`
	workerpid=\`ps -ef | grep "nginx: worker process" | grep -v grep | awk 'BEGIN{ORS=" "}{print \$2}' | awk '{gsub(/\ \$/, "");print}'\`
}
function _nginx_pid() {
	if [ ! -z "\$masterpid" ] && [ ! -z "\$workerpid" ]; then
		echo -n "Nginx "; _red_bgn "Master";echo -n " pid: "; echo \$masterpid;
		echo -n "Nginx "; _purple_bgn "Worker";echo -n " pids:"; echo \$workerpid;
		#echo \$allpid_str
	fi
}
function _nginx_port() {
	OLDIFS="\$IFS"  #备份旧的IFS变量
	IFS=\$'\n'   #修改分隔符为换行符
	for line in \`netstat -lntup|grep nginx:|grep -v "::"\`; do
		protocol=\`echo \$line|awk '{print \$1}'\`
		if [ "\$protocol" = "tcp" ]; then
			protocol="t"
		else
			protocol="u"		
		fi

		port=\`echo \$line|awk '{print \$4}'|awk -F: '{print \$2}'\`

		if [[ \${ports[@]/\${port}/} == \${ports[@]} ]]; then
			#数组\$ports中不存在字符串\$port
			ports+=(\${port}\${protocol})
		fi
	done
	if [ \${#ports} -gt 0 ]; then
		if [ -z \$1 ]; then
			_green_bgn "Nginx Ports:"; echo -n " ";echo \${ports[@]}
		fi
	fi
	IFS=\$OLDIFS
}
function _nginx_start() {
	ulimit -HSn 100353
	/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf &
	sleep 0.3
	_nginx_pid
	_nginx_port
}
function _nginx_stop.f() {
	if [[ ! -z "\$masterpid" || ! -z "\$workerpid" ]]; then
		_red_bg "Stopping Nginx force"
		if [ ! -z "\$masterpid" ]; then
			kill -TERM -\$masterpid 2>/dev/null || true
			sleep 1
			if kill -0 -\$masterpid 2>/dev/null; then
				kill -9 -\$masterpid 2>/dev/null || true
			fi
		fi
		if [ ! -z "\$workerpid" ]; then
			kill -TERM \$workerpid 2>/dev/null || true
			sleep 1
			if kill -0 \$workerpid 2>/dev/null; then
				kill -9 \$workerpid 2>/dev/null || true
			fi
		fi
	fi
}

function _nginx_test(){
	result=\`/usr/local/nginx/sbin/nginx -t 2>&1\`
	
	if [[ x"\$result" == x*"nginx.conf syntax is ok"* ]] && [[ x"\$result" == x*"nginx.conf test is successful"* ]];then
		_green_bg "Test OK"
	else
		_red_bg "Test Failed"
		echo "\$result"
	fi
}


if [ \$# -eq 0 ]; then
	echo 'Usage: nginx [Start(st)|Stop(sp)|Stop.f(sf)|Restart(rt)|Test(t)|Update(u)|Reload(r)|Port(p)|Pid|Status(ss)|Version(v)|top {seconds}]'
fi

while true
do
	if [ \$# -eq 0 ]; then
		#clear
		echo ""
		echo "Nginx:"
		echo -e " 1:Start(st)\t 2:Stop(sp)\t 3:Stop.f(sf)\t 4:Restart(rt)\t 5:Test(t)\t 6:Update(u)\t 7:Reload(r)\t 8:Port(p)"
		echo -e " 9:Pid\t\t10:Status(ss)\t11:Version(v)\t 12:Top\t\t13:Quit(Q)"
		echo ""
		read -p "Input:" choice
	else
		choice=\$1
	fi	
	
	choice=\${choice,,}	#转为小写
	case \$choice in
		"1"|"start"|"st")
			_nginx_pid_init
			if [ ! -z \$masterpid ]; then
				_red_bg "Nginx is Running"
			else
				_green_bg "Starting Nginx"
				_nginx_start
			fi
			;;
		"2"|"stop"|"sp")
			_nginx_pid_init
			if [ ! -z \$masterpid ]; then
				_red_bg "Stopping Nginx"
				kill -QUIT \`cat /usr/local/nginx/logs/nginx.pid\`
				sleep 0.5
				
				_nginx_pid_init
				
				if [ -z \$masterpid ]; then
					_green_bg "Nginx is Stopped"
				fi
			else
				_red_bg "Nginx is Running"
			fi
			;;
		"3"|"stop.f"|"sf")
			_nginx_pid_init
			if [ ! -z \$masterpid ]; then
				_red_bg "Stopping Nginx Forced"
				_nginx_stop.f
			else
				_red_bg "Nginx Not Running"
			fi
			;;
		"4"|"restart"|"rt")
			_purple_bg "Stopping Nginx force and restart"
			_nginx_pid_init
			
			if [ ! -z "\$masterpid" ]; then
				kill -QUIT \`cat /usr/local/nginx/logs/nginx.pid\`
				sleep 0.5
			fi
			
			_nginx_pid_init
			if [ ! -z "\$masterpid" ]; then
				_nginx_stop.f
				sleep 0.3
			fi
			
			_nginx_pid_init
			if [ -z "\$masterpid" ]; then
				_green_bg "Starting Nginx"
				_nginx_start
			fi
			;;
		"5"|"test"|"t")
			_nginx_test
			#/usr/local/nginx/sbin/nginx -t
			;;
		"6"|"update"|"u")
			_purple_bg "Updating Nginx binary file"
			kill -USR2 \`cat /usr/local/nginx/logs/nginx.pid\`
			;;
		"7"|"reload"|"r")
			_purple_bg "Reloading Nginx"
			kill -HUP \`cat /usr/local/nginx/logs/nginx.pid\`
			;;
		"8"|"port"|"p")
			_nginx_port
			;;
		"9"|"pid")
			_nginx_pid_init
			
			if [ ! -z "\$masterpid" ]; then
				_nginx_pid
			else
				_red_bg "Nginx Not Running"
			fi
			;;
		"10"|"status"|"ss")
			_nginx_pid_init
			if [ ! -z "\$masterpid" ]; then
				_green_bg "Nginx is Running"
				_nginx_pid
			else
				_red_bg "Nginx Not Running"
			fi
			;;
		"11"|"version"|"v")
			current_nginx=`/usr/local/nginx/sbin/nginx -v 2>&1|awk -F/ '{print \$2}'`
			echo -n "Current Nginx Version: "; _green_bg "\$current_nginx"

			remote_nginx=`_wget -q -O- https://nginx.org/en/download.html|grep '"/en/CHANGES"'|awk -F"/download/nginx-" '{print \$2}'|awk -F\" '{print \$1}'|sed "s/.tar.gz//g"|grep -oP ^[0-9]+\.[0-9]+.\[0-9]+\$`

			if [ "\$current_nginx" == "\$remote_nginx" ]; then
				echo -n "Lastest Nginx Version: "; _green_bg "\$remote_nginx"
			else
				echo -n "Lastest Nginx Version: "; _red_bg "\$remote_nginx"
			fi

			;;
		"12"|"top")
			_nginx_pid_init
			if [ ! -z "\$masterpid" ]; then
				_blue_bg "In \"top\" command, press \"Q\" to QUIT. Now press Any Key to Continue ... "
				read -s -n1 -p ""
				if [ "\$2" -gt 0 ] 2>/dev/null ;then
					top -p \$masterpid,\${workerpid//\ /,} -n \$2
				else
					top -p \$masterpid,\${workerpid//\ /,}
				fi
			fi
			;;
		"13"|"quit"|"q")
			echo ""
			exit
			;;			
			
		*)
			echo "invalid option \$choice"
			;;
	esac
	
	if [ \$# -gt 0 ]; then
		exit
	fi
done


EOF

chmod 755 /usr/local/bin/ngx


	
}

##########################################

function _nginx() {
mkdir /root/src 2>/dev/null;cd /root/src

remote_nginx=`_wget -q -O- https://nginx.org/en/download.html|grep '"/en/CHANGES"'|awk -F"/download/nginx-" '{print $2}'|awk -F\" '{print $1}'|sed "s/.tar.gz//g"|grep -oP ^[0-9]+\.[0-9]+.\[0-9]+$`
local build_dir="/root/src/nginx-$remote_nginx"
trap 'if [ -d "$build_dir" ]; then echo "\n$is_warn nginx build failed, cleaning up $build_dir"; rm -rf "$build_dir"; fi; trap - ERR; exit 1' ERR
if [ -f /usr/local/nginx/sbin/nginx ]; then
	current_nginx=`/usr/local/nginx/sbin/nginx -v 2>&1|awk -F/ '{print $2}'`
	echo -n "Current Nginx Version: "; _green_bg "$current_nginx"

	if [ "$current_nginx" == "$remote_nginx" ]; then
		echo -n "Lastest Nginx Version: "; _green_bg "$remote_nginx"
	else
		echo -n "Lastest Nginx Version: "; _red_bg "$remote_nginx"
	fi
else
	echo -n "Lastest Nginx Version: "; _green_bg "$remote_nginx"
	_red_bg "Nginx not Found" 
fi


read -s -n1 -p "Press Any Key to Continue ... "

echo ""
_purple_bg "apt update"
apt-get -o Acquire::ForceIPv4=true install net-tools gcc make libpcre3 libpcre3-dev zlib1g-dev lsof openssl libssl-dev git g++ -y

echo ""
_purple_bg "ngx_brotli"
rm -rf /root/src/ngx_brotli 2>/dev/null
run_and_check git clone --recurse-submodules -j8 https://github.com/google/ngx_brotli
cd ngx_brotli/deps/brotli
mkdir out && cd out
run_and_check cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DCMAKE_C_FLAGS="-Ofast -m64 -march=native -mtune=native -flto=auto -funroll-loops -ffunction-sections -fdata-sections -Wl,--gc-sections" -DCMAKE_INSTALL_PREFIX=./installed ..

run_and_check cmake --build . --config Release --target brotlienc
cd ../../../..

if [ $? -ne 0 ]; then
	echo "error ngx_brotli"
	exit
fi

echo ""
_purple_bg "gperftools"
apt-get install libunwind-dev -y
cd /root/src
rm -rf gperftools 2>/dev/null
run_and_check git clone https://github.com/gperftools/gperftools.git
cd gperftools
run_and_check ./autogen.sh
run_and_check ./configure
run_and_check make -j$(nproc)
	run_and_check make install
	trap - ERR
rm -f /lib/x86_64-linux-gnu/libprofiler.so.0  2>/dev/null
ln -sv $(find /usr/local/lib/ -type f -name "libprofiler.so*"|grep "/usr/local/lib"|sed -n '1p') /lib/x86_64-linux-gnu/libprofiler.so.0

if [ $? -ne 0 ]; then
	echo "error gperftools"
	exit
fi

echo ""
_purple_bg "find openssl"
__find_openssl_ver

if [ ! -d "/root/src/$openssl_ver" ];then
	_openssl
fi

echo ""
_purple_bg "Clean"
for file in $(ls /root/src/nginx-* 2>/dev/null); do
	if [[ $file != *$remote_nginx* ]];then
		rm -rf $file 2>/dev/null
	fi	
done


echo ""
cd /root/src
if [ ! -f "nginx-$remote_nginx.tar.gz" ];then
	_purple_bg "Downloading"
 run_and_check _wget http://nginx.org/download/nginx-$remote_nginx.tar.gz -O /root/src/nginx-$remote_nginx.tar.gz
fi

if [ ! -d "nginx-$remote_nginx.tar.gz" ];then
	_purple_bg "Unzip nginx-$remote_nginx.tar.gz"
	run_and_check tar xzf nginx-$remote_nginx.tar.gz
fi

cd /root/src/nginx-$remote_nginx

echo ""
_purple_bg "configure & make nginx"

run_and_check ./configure --prefix=/usr/local/nginx --group=daemon --user=daemon --with-http_realip_module --with-http_sub_module \
--with-http_stub_status_module --with-ld-opt=-lrt --with-threads --with-pcre --with-stream --with-http_ssl_module \
--with-http_gzip_static_module --with-google_perftools_module --with-http_v2_module --with-http_v3_module \
--with-openssl=/root/src/$openssl_ver \
--add-module=/root/src/ngx_brotli \
--with-cc-opt='-g -O2 -march=westmere -flto=auto -funsafe-math-optimizations -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2'

run_and_check make -j$(nproc)
run_and_check make install

_update_ngx

cat << EOF > /usr/local/nginx/conf/nginx.conf
user daemon daemon;
worker_processes  4;

error_log	/dev/null crit;
#error_log	logs/error.log;
#error_log  logs/error.log debug;
#error_log	logs/error.log  notice;
#error_log	logs/error.log  info;
pid		logs/nginx.pid;


events {
	use epoll;
	worker_connections  51200;
}


http {
	include			mime.types;
	include         proxy.conf;
	include         fastcgi.conf;
	default_type	application/octet-stream;
	log_format  main  '\$remote_addr - \$remote_user [\$time_local] \$request '
	                  '"\$status" \$body_bytes_sent "\$http_referer" '
	                  '"\$http_user_agent" "\$http_x_forwarded_for"';
	#access_log	/dev/null;

	client_header_buffer_size 32k;
	large_client_header_buffers 4 32k;
	sendfile			on;
	tcp_nopush			on;
	tcp_nodelay			on;
	send_timeout			30;
	keepalive_timeout		120;
	#limit_conn_zone \$binary_remote_addr zone=one:50m;
	#limit_conn  one  1;
	fastcgi_intercept_errors on;

	server_tokens off;

	brotli			on;
	brotli_comp_level	6;
	brotli_buffers		16 8k;
	brotli_min_length	20;
	brotli_types		text/plain text/javascript text/css text/xml text/x-component application/javascript application/x-javascript application/xml application/json application/xhtml+xml application/rss+xml application/atom+xml application/x-font-ttf application/vnd.ms-fontobject image/svg+xml image/x-icon font/opentype;

	gzip			on;
	gzip_min_length		1000;
	gzip_disable		msie6;
	gzip_http_version	1.1;
	gzip_static		on;
	gzip_proxied		any;
	gzip_types text/plain text/css application/x-javascript text/xml application/xml+rss text/javascript application/javascript application/xml;
	gzip_buffers		16 8k;


	#配置共享会话缓存大小
	ssl_session_cache   shared:SSL:10m;
	#配置会话超时时间
	ssl_session_timeout 10m;
	ssl_certificate ssl/11806.com.cer;
	ssl_certificate_key ssl/11806.com.key;



	client_body_buffer_size		512k;
	client_max_body_size		3000m;
	client_header_timeout		30;
	client_body_timeout		30;


	include vhost/*.conf;
}
EOF
mkdir /usr/local/nginx/conf/vhost 2>/dev/null

cat << EOF > /usr/local/nginx/conf/proxy.conf
proxy_send_timeout		300;
proxy_read_timeout		300;
proxy_buffer_size		32k;
proxy_buffers			16		128k;
proxy_busy_buffers_size		512k;
proxy_temp_file_write_size	512k;
proxy_connect_timeout		30s;
proxy_redirect			off;
proxy_set_header		Host		\$host;
proxy_set_header		X-Real-IP	\$remote_addr;
proxy_set_header		X-Forwarded-For	\$proxy_add_x_forwarded_for;
EOF

masterpid=`ps -ef | grep "nginx: master process" | grep -v grep | awk 'BEGIN{ORS=" "}{print $2}' | awk '{gsub(/\ $/, "");print}'`
if [ -n "$masterpid" ]; then
	kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
fi


_red_bg "nginx DONE!"
}


function _mysql5() {
mkdir /root/src 2>/dev/null;cd /root/src

echo ""
mysql5_ver=`_wget -q -O- https://downloads.mysql.com/archives/community/|grep "<option value"|grep "5.7."|head -n 1|awk -F\" '{print $2}'|grep -oP ^[0-9]+\.[0-9]+.\[0-9]+$`
local build_dir="/root/src/mysql-$mysql5_ver"
trap 'if [ -d "$build_dir" ]; then echo "\n$is_warn mysql build failed, cleaning up $build_dir"; rm -rf "$build_dir"; fi; trap - ERR; exit 1' ERR
_red_bg "Lastest MySQL5 Version: $mysql5_ver"


read -s -n1 -p "Press Any Key to Continue ... "

echo ""
_purple_bg "apt update"
apt install cmake build-essential libncurses-dev pkg-config m4 bison libudev-dev libsasl2-dev libldap2-dev -y
mkdir -p /data/database/

echo ""
_purple_bg "Clean"
for file in $(ls /root/src/mysql-boost-* 2>/dev/null); do
	if [[ $file != *$mysql5_ver* ]];then
		rm -rf $file
	fi
done

echo ""
cd /root/src
if [ ! -f "mysql-boost-$mysql5_ver.tar.gz" ];then
	_purple_bg "Downloading"
	run_and_check _wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-boost-$mysql5_ver.tar.gz -O /root/src/mysql-boost-$mysql5_ver.tar.gz
fi

if [ ! -d "mysql-boost-$mysql5_ver.tar.gz" ];then
	_purple_bg "Unzip mysql-boost-$mysql5_ver.tar.gz"
	run_and_check tar xzf mysql-boost-$mysql5_ver.tar.gz
fi
cd /root/src/mysql-$mysql5_ver

read -p "Input Mysql Password: " password

echo ""
_purple_bg "configure & make mysql5"

run_and_check cmake . \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql/ \
-DMYSQL_DATADIR=/data/database/ \
-DDOWNLOAD_BOOST=1 \
-DWITH_BOOST=/root/src/mysql-$mysql5_ver/boost \
-DSYSCONFDIR=/etc \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DWITH_FEDERATED_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DMYSQL_UNIX_ADDR=/dev/shm/mysql.sock \
-DENABLE_DTRACE=0 \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_unicode_ci \
-DWITH_EMBEDDED_SERVER=1

if [ "$mem" -ge 16 ]; then
	echo $(nproc) Threads
	run_and_check make -j$(nproc)
	#make -j4
else
	echo 4 Threads
	run_and_check make -j4
fi

	run_and_check make install
	trap - ERR

groupadd mysql&&useradd mysql -g mysql -M -s /sbin/nologin
chown -R mysql:mysql /usr/local/mysql/
chown -R mysql:mysql /data/database

/usr/local/mysql/bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/data/database/ --explicit_defaults_for_timestamp=true > /root/mysql.txt 2>&1
mysqlpwd=`cat /root/mysql.txt |grep root@localhost|awk '{print $11}'`

cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld

cat << EOF > /etc/my.cnf
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/8.0/en/server-configuration-defaults.html
# https://blog.csdn.net/gzt19881123/article/details/109511245

[mysqld]
tls_version=TLSv1.2,TLSv1.3
skip-host-cache
skip-name-resolve
basedir = /usr/local/mysql
datadir = /data/database
socket = /dev/shm/mysql.sock
pid-file = /data/database/mysqld.pid

#只能用IP地址检查客户端的登录，不用主机名
skip_name_resolve = 1

user=mysql

#数据库字符集对应一些排序等规则，注意要和character-set-server对应
collation_server = utf8mb4_unicode_ci

#default_storage_engine = MyISAM
#character_set_server = utf8mb4

#TIMESTAMP如果没有显示声明NOT NULL，允许NULL值
explicit_defaults_for_timestamp = true

#--###########################-- 可能用到的MyISAM性能设置 开始 --#############################

#对MyISAM表起作用，但是内部的临时磁盘表是MyISAM表，也要使用该值。
#可以使用检查状态值 created_tmp_disk_tables 得知详情
key_buffer_size = 16M

#对MyISAM表起作用，但是内部的临时磁盘表是MyISAM表，也要使用该值，
#例如大表order by、缓存嵌套查询、大容量插入分区。
read_buffer_size = 8M

#对MyISAM表起作用 读取优化
read_rnd_buffer_size = 256K

#对MyISAM表起作用 插入优化
bulk_insert_buffer_size = 64M

# The number of open tables for all threads
# For example, for 200 concurrent running connections, specify a table cache size of at least 200 * N, 
# where N is the maximum number of tables per join in any of the queries which you execute. 
table_open_cache = 600

# The number of table definitions that can be stored in the definition cache 
# MIN(400 + table_open_cache / 2, 2000)
table_definition_cache = 700

# 为了减少会话之间的争用，可以将opentables缓存划分为table_open_cache/table_open_cache_instances个小缓存
table_open_cache_instances = 64

# 每个线程的堆栈大小 如果线程堆栈太小，则会限制执行复杂SQL语句
thread_stack = 512K

# 禁止外部系统锁
external-locking = FALSE

#SQL数据包发送的大小，如果有BLOB对象建议修改成1G
max_allowed_packet = 128M

#order by 或group by 时用到
#建议先调整为4M，后期观察调整
sort_buffer_size = 4M

#inner left right join时用到
#建议先调整为4M，后期观察调整
join_buffer_size = 4M

# How many threads the server should cache for reuse.
# 如果您的服务器每秒达到数百个连接，则通常应将thread_cache_size设置得足够高，以便大多数新连接使用缓存线程
# default value = 8 + ( max_connections / 100) 上限为100
thread_cache_size = 20

#MySQL连接闲置超过一定时间后(单位：秒)将会被强行关闭
#MySQL默认的wait_timeout  值为8个小时, interactive_timeout参数需要同时配置才能生效
interactive_timeout = 1800
wait_timeout = 1800

#内部内存临时表的最大值。
#比如大数据量的group by ,order by时可能用到临时表，
#超过了这个值将写入磁盘，系统IO压力增大
tmp_table_size = 64M
max_heap_table_size = 64M


net_buffer_length = 4K
myisam_sort_buffer_size = 16M
#skip-name-resolve
max_connections = 500
max_connect_errors = 100
open_files_limit = 65535

[client]
socket = /dev/shm/mysql.sock

[mysqldump]
quick
max_allowed_packet = 500M

EOF

/etc/init.d/mysqld start
/usr/local/mysql/bin/mysql --connect-expired-password -uroot -p${mysqlpwd} -e "SET PASSWORD FOR root@localhost = PASSWORD('$password');use mysql;UPDATE user SET host='%' WHERE user='root';flush privileges;" 2>/dev/null

rm -f /root/mysql.txt

_red_bg "Debian DONE!"

}

function _php8() {
mkdir /root/src 2>/dev/null;cd /root/src

echo ""

if [ -f /usr/local/php8/bin/php ]; then
	current_php=`/usr/local/php8/bin/php -v|head -n 1|awk '{print $2}'`
	echo -n "Current PHP Version: "; _green_bg "$current_php"
	echo ""
fi

_yellow_bg "Remote PHP Version: "
_wget -q -O- 'https://www.php.net/downloads.php'|grep Changelog|awk '{printf("%s %s\n", $1, $2)}'

echo ""
echo "PHP Version, the First 2 Parts, e.g: 8.1"
read -p "Input PHP Version: " phpver
if [ "$phpver" == "" ]; then
	latest_php=`_wget -q -O- 'https://www.php.net/downloads.php'|grep Changelog|head -n 1|awk '{print $2}'|grep -oP ^[0-9]+\.[0-9]+.\[0-9]+$` #获取最新版
else
	latest_php=`_wget -q -O- 'https://www.php.net/downloads.php'|grep Changelog|grep "PHP $phpver"|head -n 1|awk '{print $2}'` #获取特定的版本版本
fi

local build_dir="/root/src/php-$latest_php"
trap 'if [ -d "$build_dir" ]; then echo "\n$is_warn php8 build failed, cleaning up $build_dir"; rm -rf "$build_dir"; fi; trap - ERR; exit 1' ERR

echo ""
echo -n "Current PHP Version: "; _green_bg "$current_php"
if [ x"$latest_php" == x"$current_php" ]; then
	echo -n "Lastest PHP Version: "; _green_bg "$latest_php"
else
	echo -n "Lastest PHP Version: "; _red_bg $latest_php
fi

read -s -n1 -p "Press Any Key to Continue ... "

echo ""
_purple_bg "apt update"
apt install pkg-config libxml2-dev libsqlite3-dev libcurl4-openssl-dev libonig-dev autoconf libpng-dev libsodium-dev -y


echo ""
_purple_bg "find openssl"
__find_openssl_ver

if [ ! -d "/root/src/$openssl_ver" ];then
	_openssl
fi

echo ""
_purple_bg "Clean"
for file in $(ls /root/src/php-* 2>/dev/null); do
	if [[ $file != *$latest_php* ]];then
		rm -rf $file
	fi
done


echo ""
cd /root/src
if [ ! -f "php-$latest_php.tar.xz" ];then
	_purple_bg "Downloading"
	run_and_check _wget https://www.php.net/distributions/php-$latest_php.tar.xz -O /root/src/php-$latest_php.tar.xz
fi

if [ ! -d "php-$latest_php" ];then
	_purple_bg "Unzip php-$latest_php.tar.xz"
	run_and_check tar xJf php-$latest_php.tar.xz
fi
cd /root/src/php-$latest_php

openssldir=`ls /root/src/openssl*.tar.gz|head -n1|sed "s/.tar.gz//g"`

echo ""
_purple_bg "configure & make php8"
run_and_check ./configure --prefix=/usr/local/php8 --with-config-file-path=/usr/local/php8/etc --enable-fpm \
--with-zlib --enable-mbstring --enable-ftp --enable-gd \
--with-curl --with-iconv --enable-exif --enable-shmop \
--enable-pdo --enable-mysqlnd --with-mysqli --with-pdo-mysql \
--enable-sockets --with-sqlite3 --enable-pcntl --with-sodium \
--with-openssl=/root/src/$openssl_ver \
--enable-shmop 

run_and_check make -j$(nproc)
	run_and_check make install
	trap - ERR

echo ""
_purple_bg "php8 ext"
if [ -f /sbin/php8 ]; then
	rm -f /sbin/php8
fi
ln -s /usr/local/php8/bin/php /sbin/php8
cp -f sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm8
chmod 755 /etc/init.d/php-fpm8
if [ ! -f /usr/local/php8/ext ]; then
	mkdir /usr/local/php8/ext
fi
groupadd nobody 2>/dev/null

_wget -q http://449977.xyz/php.ini -O /usr/local/php8/etc/php.ini

cd ext/sqlite3
mv config0.m4 config.m4
run_and_check /usr/local/php8/bin/phpize
run_and_check ./configure --with-php-config=/usr/local/php8/bin/php-config
run_and_check make -j$(nproc)
cp modules/sqlite3.so /usr/local/php8/ext/
cd ..

<<DELIMITER
cd ext/mysqli
/usr/local/php8/bin/phpize
./configure --with-php-config=/usr/local/php8/bin/php-config
make -j$(nproc)
cp modules/mysqli.so /usr/local/php8/ext/

	if [[ -f /usr/local/php8/ext/mysqli.so ]] && [[ -z `grep extension=mysqli.so /usr/local/php8/etc/php.ini` ]]; then
		sed -i 's/;extension=xsl/;extension=xsl\nextension=mysqli.so/' /usr/local/php8/etc/php.ini
	fi

cd ../pdo_mysql/
/usr/local/php8/bin/phpize
./configure --with-php-config=/usr/local/php8/bin/php-config
make -j$(nproc)
cp modules/pdo_mysql.so /usr/local/php8/ext/

	if [[ -f /usr/local/php8/ext/pdo_mysql.so ]] && [[ -z `grep extension=pdo_mysql.so /usr/local/php8/etc/php.ini` ]]; then
		sed -i 's/;extension=xsl/;extension=xsl\nextension=pdo_mysql.so/' /usr/local/php8/etc/php.ini
	fi
DELIMITER

cat << EOF > /usr/local/bin/fpm8
echo "Usage: fpm8 {start|stop|stop.f|restart|reload}";
if [ "\$1" = "" ]; then
	exit
elif [ "\$1" = "start" ]; then
echo "start php-fpm8";
ulimit -HSn 100353
/etc/init.d/php-fpm8 start
elif [ "\$1" = "stop" ]; then
echo "stop php-fpm8";
/etc/init.d/php-fpm8 stop
elif [ "\$1" = "stop.f" ]; then
echo "force-quit php-fpm8";
/etc/init.d/php-fpm8 force-quit
elif [ "\$1" = "restart" ]; then
echo "restart php-fpm8";
/etc/init.d/php-fpm8 restart
elif [ "\$1" = "reload" ]; then
echo "reload php-fpm8";
/etc/init.d/php-fpm8 reload
fi
EOF
chmod 755 /usr/local/bin/fpm8


cat << EOF > /usr/local/php8/etc/php-fpm.conf
;;;;;;;;;;;;;;;;;;;;;
; FPM Configuration ;
;;;;;;;;;;;;;;;;;;;;;

; All relative paths in this configuration file are relative to PHP's install
; prefix (/usr/local/php). This prefix can be dynamically changed by using the
; '-p' argument from the command line.

;;;;;;;;;;;;;;;;;;
; Global Options ;
;;;;;;;;;;;;;;;;;;

[global]
; Pid file
; Note: the default prefix is /usr/local/php/var
; Default Value: none
pid = run/php-fpm.pid

; Error log file
; If it's set to "syslog", log is sent to syslogd instead of being written
; in a local file.
; Note: the default prefix is /usr/local/php/var
; Default Value: log/php-fpm.log
error_log = log/php-fpm.log

; syslog_facility is used to specify what type of program is logging the
; message. This lets syslogd specify that messages from different facilities
; will be handled differently.
; See syslog(3) for possible values (ex daemon equiv LOG_DAEMON)
; Default Value: daemon
;syslog.facility = daemon

; syslog_ident is prepended to every message. If you have multiple FPM
; instances running on the same server, you can change the default value
; which must suit common needs.
; Default Value: php-fpm
;syslog.ident = php-fpm

; Log level
; Possible Values: alert, error, warning, notice, debug
; Default Value: notice
;log_level = notice

; If this number of child processes exit with SIGSEGV or SIGBUS within the time
; interval set by emergency_restart_interval then FPM will restart. A value
; of '0' means 'Off'.
; Default Value: 0
;emergency_restart_threshold = 0

; Interval of time used by emergency_restart_interval to determine when
; a graceful restart will be initiated.  This can be useful to work around
; accidental corruptions in an accelerator's shared memory.
; Available Units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
;emergency_restart_interval = 0

; Time limit for child processes to wait for a reaction on signals from master.
; Available units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
;process_control_timeout = 0

; The maximum number of processes FPM will fork. This has been design to control
; the global number of processes when using dynamic PM within a lot of pools.
; Use it with caution.
; Note: A value of 0 indicates no limit
; Default Value: 0
; process.max = 128

; Specify the nice(2) priority to apply to the master process (only if set)
; The value can vary from -19 (highest priority) to 20 (lower priority)
; Note: - It will only work if the FPM master process is launched as root
;       - The pool process will inherit the master process priority
;         unless it specified otherwise
; Default Value: no set
; process.priority = -19

; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging.
; Default Value: yes
;daemonize = yes

; Set open file descriptor rlimit for the master process.
; Default Value: system defined value
rlimit_files = 10240

; Set max core size rlimit for the master process.
; Possible Values: 'unlimited' or an integer greater or equal to 0
; Default Value: system defined value
;rlimit_core = 0

; Specify the event mechanism FPM will use. The following is available:
; - select     (any POSIX os)
; - poll       (any POSIX os)
; - epoll      (linux >= 2.5.44)
; - kqueue     (FreeBSD >= 4.1, OpenBSD >= 2.9, NetBSD >= 2.0)
; - /dev/poll  (Solaris >= 7)
; - port       (Solaris >= 10)
; Default Value: not set (auto detection)
;events.mechanism = epoll

; When FPM is build with systemd integration, specify the interval,
; in second, between health report notification to systemd.
; Set to 0 to disable.
; Available Units: s(econds), m(inutes), h(ours)
; Default Unit: seconds
; Default value: 10
;systemd_interval = 10

;;;;;;;;;;;;;;;;;;;;
; Pool Definitions ;
;;;;;;;;;;;;;;;;;;;;

; Multiple pools of child processes may be started with different listening
; ports and different management options.  The name of the pool will be
; used in logs and stats. There is no limitation on the number of pools which
; FPM can handle. Your system will tell you anyway :)

; Include one or more files. If glob(3) exists, it is used to include a bunch of
; files from a glob(3) pattern. This directive can be used everywhere in the
; file.
; Relative path can also be used. They will be prefixed by:
;  - the global prefix if it's been set (-p argument)
;  - /usr/local/php otherwise
include=/usr/local/php8/etc/php-fpm.d/*.conf
EOF

_wget -q http://449977.xyz/php.ini -O /usr/local/php8/etc/php.ini

cat << EOF > /usr/local/php8/etc/php-fpm.d/www.conf
; Start a new pool named 'www'.
; the variable $pool can we used in any directive and will be replaced by the
; pool name ('www' here)
[www]

; Per pool prefix
; It only applies on the following directives:
; - 'access.log'
; - 'slowlog'
; - 'listen' (unixsocket)
; - 'chroot'
; - 'chdir'
; - 'php_values'
; - 'php_admin_values'
; When not set, the global prefix (or /usr/local/php) applies instead.
; Note: This directive can also be relative to the global prefix.
; Default Value: none
;prefix = /path/to/pools/$pool

; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
user = nobody
group = nobody

; The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific IPv4 address on
;                            a specific port;
;   '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses
;                            (IPv6 and IPv4-mapped) on a specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
; listen = 127.0.0.1:9000
listen = /dev/shm/php.sock

; Set listen(2) backlog.
; Default Value: 511 (-1 on FreeBSD and OpenBSD)
;listen.backlog = 511

; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many
; BSD-derived systems allow connections regardless of permissions.
; Default Values: user and group are set as the running user
;                 mode is set to 0660
listen.owner = daemon
listen.group = daemon
listen.mode = 0666
; When POSIX Access Control Lists are supported you can set them using
; these options, value is a comma separated list of user/group names.
; When set, listen.owner and listen.group are ignored
;listen.acl_users =
;listen.acl_groups =

; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect.
; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
; must be separated by a comma. If this value is left blank, connections will be
; accepted from any ip address.
; Default Value: any
;listen.allowed_clients = 127.0.0.1

; Specify the nice(2) priority to apply to the pool processes (only if set)
; The value can vary from -19 (highest priority) to 20 (lower priority)
; Note: - It will only work if the FPM master process is launched as root
;       - The pool processes will inherit the master process priority
;         unless it specified otherwise
; Default Value: no set
; process.priority = -19

; Choose how the process manager will control the number of child processes.
; Possible Values:
;   static  - a fixed number (pm.max_children) of child processes;
;   dynamic - the number of child processes are set dynamically based on the
;             following directives. With this process management, there will be
;             always at least 1 children.
;             pm.max_children      - the maximum number of children that can
;                                    be alive at the same time.
;             pm.start_servers     - the number of children created on startup.
;             pm.min_spare_servers - the minimum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is less than this
;                                    number then some children will be created.
;             pm.max_spare_servers - the maximum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is greater than this
;                                    number then some children will be killed.
;  ondemand - no children are created at startup. Children will be forked when
;             new requests will connect. The following parameter are used:
;             pm.max_children           - the maximum number of children that
;                                         can be alive at the same time.
;             pm.process_idle_timeout   - The number of seconds after which
;                                         an idle process will be killed.
; Note: This value is mandatory.
pm = dynamic

; The number of child processes to be created when pm is set to 'static' and the
; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'.
; This value sets the limit on the number of simultaneous requests that will be
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
; CGI. The below defaults are based on a server without much resources. Don't
; forget to tweak pm.* to fit your needs.
; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
; Note: This value is mandatory.
pm.max_children = 5120

; The number of child processes created on startup.
; Note: Used only when pm is set to 'dynamic'
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
pm.start_servers = 20

; The desired minimum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.min_spare_servers = 5

; The desired maximum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.max_spare_servers = 35

; The number of seconds after which an idle process will be killed.
; Note: Used only when pm is set to 'ondemand'
; Default Value: 10s
;pm.process_idle_timeout = 10s;

; The number of requests each child process should execute before respawning.
; This can be useful to work around memory leaks in 3rd party libraries. For
; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
; Default Value: 0
;pm.max_requests = 6000

; The URI to view the FPM status page. If this value is not set, no URI will be
; recognized as a status page. It shows the following informations:
;   pool                 - the name of the pool;
;   process manager      - static, dynamic or ondemand;
;   start time           - the date and time FPM has started;
;   start since          - number of seconds since FPM has started;
;   accepted conn        - the number of request accepted by the pool;
;   listen queue         - the number of request in the queue of pending
;                          connections (see backlog in listen(2));
;   max listen queue     - the maximum number of requests in the queue
;                          of pending connections since FPM has started;
;   listen queue len     - the size of the socket queue of pending connections;
;   idle processes       - the number of idle processes;
;   active processes     - the number of active processes;
;   total processes      - the number of idle + active processes;
;   max active processes - the maximum number of active processes since FPM
;                          has started;
;   max children reached - number of times, the process limit has been reached,
;                          when pm tries to start more children (works only for
;                          pm 'dynamic' and 'ondemand');
; Value are updated in real time.
; Example output:
;   pool:                 www
;   process manager:      static
;   start time:           01/Jul/2011:17:53:49 +0200
;   start since:          62636
;   accepted conn:        190460
;   listen queue:         0
;   max listen queue:     1
;   listen queue len:     42
;   idle processes:       4
;   active processes:     11
;   total processes:      15
;   max active processes: 12
;   max children reached: 0
;
; By default the status page output is formatted as text/plain. Passing either
; 'html', 'xml' or 'json' in the query string will return the corresponding
; output syntax. Example:
;   http://www.foo.bar/status
;   http://www.foo.bar/status?json
;   http://www.foo.bar/status?html
;   http://www.foo.bar/status?xml
;
; By default the status page only outputs short status. Passing 'full' in the
; query string will also return status for each pool process.
; Example:
;   http://www.foo.bar/status?full
;   http://www.foo.bar/status?json&full
;   http://www.foo.bar/status?html&full
;   http://www.foo.bar/status?xml&full
; The Full status returns for each process:
;   pid                  - the PID of the process;
;   state                - the state of the process (Idle, Running, ...);
;   start time           - the date and time the process has started;
;   start since          - the number of seconds since the process has started;
;   requests             - the number of requests the process has served;
;   request duration     - the duration in µs of the requests;
;   request method       - the request method (GET, POST, ...);
;   request URI          - the request URI with the query string;
;   content length       - the content length of the request (only with POST);
;   user                 - the user (PHP_AUTH_USER) (or '-' if not set);
;   script               - the main script called (or '-' if not set);
;   last request cpu     - the %cpu the last request consumed
;                          it's always 0 if the process is not in Idle state
;                          because CPU calculation is done when the request
;                          processing has terminated;
;   last request memory  - the max amount of memory the last request consumed
;                          it's always 0 if the process is not in Idle state
;                          because memory calculation is done when the request
;                          processing has terminated;
; If the process is in Idle state, then informations are related to the
; last request the process has served. Otherwise informations are related to
; the current request being served.
; Example output:
;   ************************
;   pid:                  31330
;   state:                Running
;   start time:           01/Jul/2011:17:53:49 +0200
;   start since:          63087
;   requests:             12808
;   request duration:     1250261
;   request method:       GET
;   request URI:          /test_mem.php?N=10000
;   content length:       0
;   user:                 -
;   script:               /home/fat/web/docs/php/test_mem.php
;   last request cpu:     0.00
;   last request memory:  0
;
; Note: There is a real-time FPM status monitoring sample web page available
;       It's available in: /usr/local/php/share/php/fpm/status.html
;
; Note: The value must start with a leading slash (/). The value can be
;       anything, but it may not be a good idea to use the .php extension or it
;       may conflict with a real PHP file.
; Default Value: not set
;pm.status_path = /status

; The ping URI to call the monitoring page of FPM. If this value is not set, no
; URI will be recognized as a ping page. This could be used to test from outside
; that FPM is alive and responding, or to
; - create a graph of FPM availability (rrd or such);
; - remove a server from a group if it is not responding (load balancing);
; - trigger alerts for the operating team (24/7).
; Note: The value must start with a leading slash (/). The value can be
;       anything, but it may not be a good idea to use the .php extension or it
;       may conflict with a real PHP file.
; Default Value: not set
;ping.path = /ping

; This directive may be used to customize the response of a ping request. The
; response is formatted as text/plain with a 200 response code.
; Default Value: pong
;ping.response = pong

; The access log file
; Default: not set
;access.log = log/$pool.access.log

; The access log format.
; The following syntax is allowed
;  %%: the '%' character
;  %C: %CPU used by the request
;      it can accept the following format:
;      - %{user}C for user CPU only
;      - %{system}C for system CPU only
;      - %{total}C  for user + system CPU (default)
;  %d: time taken to serve the request
;      it can accept the following format:
;      - %{seconds}d (default)
;      - %{miliseconds}d
;      - %{mili}d
;      - %{microseconds}d
;      - %{micro}d
;  %e: an environment variable (same as $_ENV or $_SERVER)
;      it must be associated with embraces to specify the name of the env
;      variable. Some exemples:
;      - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e
;      - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e
;  %f: script filename
;  %l: content-length of the request (for POST request only)
;  %m: request method
;  %M: peak of memory allocated by PHP
;      it can accept the following format:
;      - %{bytes}M (default)
;      - %{kilobytes}M
;      - %{kilo}M
;      - %{megabytes}M
;      - %{mega}M
;  %n: pool name
;  %o: output header
;      it must be associated with embraces to specify the name of the header:
;      - %{Content-Type}o
;      - %{X-Powered-By}o
;      - %{Transfert-Encoding}o
;      - ....
;  %p: PID of the child that serviced the request
;  %P: PID of the parent of the child that serviced the request
;  %q: the query string
;  %Q: the '?' character if query string exists
;  %r: the request URI (without the query string, see %q and %Q)
;  %R: remote IP address
;  %s: status (response code)
;  %t: server time the request was received
;      it can accept a strftime(3) format:
;      %d/%b/%Y:%H:%M:%S %z (default)
;      The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag
;      e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t
;  %T: time the log has been written (the request has finished)
;      it can accept a strftime(3) format:
;      %d/%b/%Y:%H:%M:%S %z (default)
;      The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag
;      e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t
;  %u: remote user
;
; Default: "%R - %u %t \"%m %r\" %s"
;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%"

; The log file for slow requests
; Default Value: not set
; Note: slowlog is mandatory if request_slowlog_timeout is set
;slowlog = log/$pool.log.slow

; The timeout for serving a single request after which a PHP backtrace will be
; dumped to the 'slowlog' file. A value of '0s' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0
;request_slowlog_timeout = 0

; The timeout for serving a single request after which the worker process will
; be killed. This option should be used when the 'max_execution_time' ini option
; does not stop script execution for some reason. A value of '0' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0
;request_terminate_timeout = 0

; Set open file descriptor rlimit.
; Default Value: system defined value
;rlimit_files = 1024

; Set max core size rlimit.
; Possible Values: 'unlimited' or an integer greater or equal to 0
; Default Value: system defined value
;rlimit_core = 0

; Chroot to this directory at the start. This value must be defined as an
; absolute path. When this value is not set, chroot is not used.
; Note: you can prefix with '$prefix' to chroot to the pool prefix or one
; of its subdirectories. If the pool prefix is not set, the global prefix
; will be used instead.
; Note: chrooting is a great security feature and should be used whenever
;       possible. However, all PHP paths will be relative to the chroot
;       (error_log, sessions.save_path, ...).
; Default Value: not set
;chroot =

; Chdir to this directory at the start.
; Note: relative path can be used.
; Default Value: current directory or / when chroot
;chdir = /var/www

; Redirect worker stdout and stderr into main error log. If not set, stdout and
; stderr will be redirected to /dev/null according to FastCGI specs.
; Note: on highloaded environement, this can cause some delay in the page
; process time (several ms).
; Default Value: no
;catch_workers_output = yes

; Clear environment in FPM workers
; Prevents arbitrary environment variables from reaching FPM worker processes
; by clearing the environment in workers before env vars specified in this
; pool configuration are added.
; Setting to "no" will make all environment variables available to PHP code
; via getenv(), $_ENV and $_SERVER.
; Default Value: yes
;clear_env = no

; Limits the extensions of the main script FPM will allow to parse. This can
; prevent configuration mistakes on the web server side. You should only limit
; FPM to .php extensions to prevent malicious users to use other extensions to
; exectute php code.
; Note: set an empty value to allow all extensions.
; Default Value: .php
;security.limit_extensions = .php .php3 .php4 .php5 .php7

; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
; the current environment.
; Default Value: clean env
;env[HOSTNAME] = $HOSTNAME
;env[PATH] = /usr/local/bin:/usr/bin:/bin
;env[TMP] = /tmp
;env[TMPDIR] = /tmp
;env[TEMP] = /tmp

; Additional php.ini defines, specific to this pool of workers. These settings
; overwrite the values previously defined in the php.ini. The directives are the
; same as the PHP SAPI:
;   php_value/php_flag             - you can set classic ini defines which can
;                                    be overwritten from PHP call 'ini_set'.
;   php_admin_value/php_admin_flag - these directives won't be overwritten by
;                                     PHP call 'ini_set'
; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no.

; Defining 'extension' will load the corresponding shared extension from
; extension_dir. Defining 'disable_functions' or 'disable_classes' will not
; overwrite previously defined php.ini values, but will append the new value
; instead.

; Note: path INI options can be relative and will be expanded with the prefix
; (pool, global or /usr/local/php)

; Default Value: nothing is defined by default except the values in php.ini and
;                specified at startup with the -d argument
;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com
;php_flag[display_errors] = off
;php_admin_value[error_log] = /var/log/fpm-php.www.log
;php_admin_flag[log_errors] = on
;php_admin_value[memory_limit] = 32M
EOF


echo "fpm8"
fpm8
_red_bg "php8 DONE!"
}

function _info(){

	if command -v lsb_release >/dev/null 2>&1; then
	lsb_release -a || true
	echo -n "current debian: ";cat /etc/debian_version
	fi

	#kernel
	echo ""
	latest_kernel=$(
  apt-cache depends linux-image-amd64 \
  | awk -F': ' '/Depends: linux-image-[0-9]/{print $2}' \
  | sed 's/^linux-image-//' \
  | sort -V | tail -1
)
	current_kernel=`uname -sr|awk '{print $2}'|awk -F- '{printf("%s-%s", $1, $2)}'`
	current_kernel=${current_kernel,,}
	echo -n "current kernel: "; _green_bg "$current_kernel"
	if [ "$latest_kernel" == "$current_kernel" ]; then
		echo -n "lastest kernel: "; _green_bg ${latest_kernel}
	else
		echo -n "lastest kernel: "; _red_bg ${latest_kernel}
	fi
	_yellow_bg "list all kernels:"
	dpkg -l | grep linux-image
	
	echo ""
	#debian
	lastest_version=`_wget -q https://www.debian.org -O-|grep https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/|awk -F/ '{print $8}'|awk -F- '{print $2}'`
	count=`echo "$lastest_version" | grep -o "\." | wc -l`
	if [ "$count" -eq 2 ]; then
		if [[ ${lastest_version:0-2:2} == ".0" ]]; then
			lastest_version=${lastest_version%\.*}
		fi
		
	fi
	current_version=`cat /etc/debian_version`
	echo -n "Current Debian Version: "; _green_bg "$current_version"
	if [ "$lastest_version" == "$current_version" ]; then
		echo -n "Lastest Debian Version: "; _green_bg $lastest_version
	else
		echo -n "Lastest Debian Version: "; _red_bg $lastest_version
	fi

	echo ""
	#nginx
	remote_nginx=`_wget -q -O- https://nginx.org/en/download.html|grep '"/en/CHANGES"'|awk -F"/download/nginx-" '{print $2}'|awk -F\" '{print $1}'|sed "s/.tar.gz//g"|grep -oP ^[0-9]+\.[0-9]+.\[0-9]+$`
	
	if [ -f /usr/local/nginx/sbin/nginx ]; then
		current_nginx=`/usr/local/nginx/sbin/nginx -v 2>&1|awk -F/ '{print $2}'`
		echo -n "Current Nginx Version: "; _green_bg "$current_nginx"

		if [ "$current_nginx" == "$remote_nginx" ]; then
			echo -n "Lastest Nginx Version: "; _green_bg "$remote_nginx"
		else
			echo -n "Lastest Nginx Version: "; _red_bg "$remote_nginx"
		fi
	else
		echo -n "Lastest Nginx Version: "; _green_bg "$remote_nginx"
		_red_bg "Nginx not Found" 
	fi
	
	echo ""
	#php
	latest_php=$(
  curl -fsSL 'https://www.php.net/downloads.php?source=Y' |
  grep -oP 'php-\K[0-9]+\.[0-9]+\.[0-9]+(?=\.tar\.(gz|bz2|xz))' |
  head -n1
)
	
	if [ -f /usr/local/php8/bin/php ]; then
		current_php=`/usr/local/php8/bin/php -v|head -n 1|awk '{print $2}'`
		echo -n "Current PHP Version: "; _green_bg "$current_php"

		if [ "$latest_php" == "$current_php" ]; then
			echo -n "Lastest PHP Version: "; _green_bg "$latest_php"
		else
			echo -n "Lastest PHP Version: "; _red_bg $latest_php
		fi
	else
		echo -n "Lastest PHP Version: "; _green_bg $latest_php
		_red_bg "PHP8 not Found" 
	fi
	
	echo ""
	#mysql
	lastest_mysql5=`_wget -q -O- https://downloads.mysql.com/archives/community/|grep "<option value"|grep "5.7."|head -n 1|awk -F\" '{print $2}'|grep -oP ^[0-9]+\.[0-9]+.\[0-9]+$`
	
	if [ -f /usr/local/mysql/bin/mysql ]; then
		current_mysql=`/usr/local/mysql/bin/mysql --version|awk '{print $5}'|sed 's/,//g'`
		echo -n "Current MySQL5 Version: "; _green_bg "$current_mysql"

		if [ "$lastest_mysql5" == "$current_mysql" ]; then
			echo -n "Lastest MySQL5 Version: "; _green_bg $lastest_mysql5
		else
			echo -n "Lastest MySQL5 Version: "; _red_bg $lastest_mysql5
		fi
	else
		echo -n "Lastest MySQL5 Version: "; _green_bg $lastest_mysql5
		_red_bg "MySQL5 not Found" 
	fi
	
	
	echo ""
}

function _kernel_update() {
	apt update
	
	#kernel
	echo ""
	latest_kernel=$(
  apt-cache depends linux-image-amd64 \
  | awk -F': ' '/Depends: linux-image-[0-9]/{print $2}' \
  | sed 's/^linux-image-//' \
  | sort -V | tail -1
)
	current_kernel=`uname -sr|awk '{print $2}'|awk -F- '{printf("%s-%s", $1, $2)}'`
	current_kernel=${current_kernel,,}
	echo -n "current kernel: "; _green_bg $current_kernel
	if [ "$latest_kernel" == "$current_kernel" ]; then
		echo -n "lastest kernel: "; _green_bg ${latest_kernel}
	else
		echo -n "lastest kernel: "; _red_bg ${latest_kernel}
	fi

	read -s -n1 -p "Press Any Key to Continue ... "

	apt upgrade -y

	if [ "$latest_kernel" != "$current_kernel" ]; then
		apt install "linux-image-${latest_kernel}-amd64" -y
		_yellow_bg "list all kernels:"
		dpkg -l | grep linux-image
		_red_bg "Please Reboot the Computer, Input 0 "
	fi

	#update-grub

}

function _kernel_purge(){
	read -s -n1 -p "Press Any Key to Clean Up Useless Kernels ... "
	apt autoclean
	apt-get -o Acquire::ForceIPv4=true install linux-headers-$(uname -r) -y
	apt --purge autoremove -y

	echo ""
	echo -n "current kernel: "; _green_bg `uname -sr`
	apt -y remove --purge $(dpkg -l | grep linux-image | awk '{print$2}' | grep -v $(uname -r)) 
	update-grub
	_yellow_bg "list all kernels:"
	dpkg -l | grep linux-image
	
}


function _color(){
	echo ""
	_red_bg "_red_bg"
	_green_bg "_green_bg"
	_yellow_bg "_yellow_bg"
	_blue_bg "_blue_bg"
	_purple_bg "_purple_bg"
	echo ""
}

function _clean(){
	rm -f /var/log/auth*
	rm -f /var/log/btmp* /var/log/wtmp*
	
	#只保留近一周的日志
	journalctl --vacuum-time=1w

	#只保留500MB的日志
	journalctl --vacuum-size=500M 2>/dev/null
	echo ""
	
	_green_bg "Log directorys"
	du -h -t 10M /var/log/
	
}

function _forward_on(){
	sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf > /dev/null 2>&1
	sed -i 's/net.ipv4.ip_forward=0/net.ipv4.ip_forward=1/' /etc/sysctl.conf > /dev/null 2>&1
	echo -e "net.ipv4.ip_forward=1\nnet.ipv6.conf.all.forwarding=1" | tee /etc/sysctl.d/99-forward.conf > /dev/null 2>&1
	sysctl -p > /dev/null 2>&1
	sysctl --system > /dev/null 2>&1
}

function _forward_off(){
	sed -i 's/net.ipv4.ip_forward=1/#net.ipv4.ip_forward=1/' /etc/sysctl.conf > /dev/null 2>&1
	sed -i 's/net.ipv4.ip_forward=0/#net.ipv4.ip_forward=1/' /etc/sysctl.conf > /dev/null 2>&1
	rm -f /etc/sysctl.d/99-forward.conf > /dev/null 2>&1
	sysctl -p > /dev/null 2>&1
	sysctl --system > /dev/null 2>&1
}

function _mcrypt(){
	mkdir /root/src 2>/dev/null;cd /root/src

	read -s -n1 -p "Press Any Key to Continue ... "
	
	echo ""
	_purple_bg "Get Lastest Version"

	mcrypt_ver=`_wget -q -O- https://pecl.php.net/package/mcrypt|grep "/package/mcrypt&so"|sed "s/&period;/./g"|awk -F\> '{print $2}'|awk -F\< '{print $1}'|head -n 1`
	_red_bg "mcrypt: $mcrypt_ver"
	
	cd /root/src
	run_and_check _wget https://pecl.php.net/get/mcrypt-$mcrypt_ver.tgz
	run_and_check tar xzf mcrypt-$mcrypt_ver.tgz
	cd mcrypt-$mcrypt_ver
	
	run_and_check /usr/local/php8/bin/phpize
	run_and_check ./configure --with-php-config=/usr/local/php8/bin/php-config
	run_and_check make -j$(nproc)
	cp modules/mcrypt.so /usr/local/php8/ext/
	
	if [ -f /usr/local/php8/ext/mcrypt.so ]; then
		sed -i "s/;extension=xsl/;extension=xsl\nextension=mcrypt.so/" /usr/local/php8/etc/php.ini
	fi
}

function _make_d(){
	_lanip
	subdomain=""
	if [ x"$islan" == x"1" ]; then #lan
		subdomain="lan."
	fi
	
	if [ ! -f /usr/local/bin/d ]; then #本地无缓存
	cat << EOF > /usr/local/bin/d
#!/bin/bash
if [ -n "\$SSH_CONNECTION" ] || [ -n "\$SSH_TTY" ]; then
	stty erase ^h
fi
if [ \$# -gt 0 ]; then
	bash <(wget http://${subdomain}449977.xyz -q -O-) "\$@"
else
	bash <(wget http://${subdomain}449977.xyz -q -O-)
fi
EOF
	chmod 755 /usr/local/bin/d
	fi
}


function _iptables_retore() {
	for file in /etc/iptables/*; do
		if [ -f "$file" ]; then
			if [[ x"$file" == x*/etc/iptables/rules_* ]];then
				echo "iptables-restore < $file"
				iptables-restore < $file
			fi
		fi
	done
}

function _lanip(){
	lan1_ip=`ip addr show ens192 2>/dev/null|grep "scope global"|awk '{print $2}'`
	lan2_ip=`ip addr show ens224 2>/dev/null|grep "scope global"|awk '{print $2}'`
	if [[ x"$lan1_ip" == x*10.* ]] || [[ x"$lan2_ip" == x*10.* ]];then
		islan=1
	else
		islan=0
	fi
}

function _exe2rc() {
	read -p "Input Filename:" filename
	path=$(pwd)
	
	if [ ! -f "$path/$filename" ]; then
		_red_bg $path/$filename not found
	else	
		if [[ -z `grep "$path/$filename" /etc/rc.local` ]]; then
			sed -i "s*^exit 0*$path/$filename\nexit 0*" /etc/rc.local
			_green_bg "ADD $path/$filename to rc.local DONE!"
			echo ""
		fi
	fi
}

function _iptables_to_rc() {
	for file in /etc/iptables/*; do
		if [ -f "$file" ]; then
			if [[ x"$file" == x*/etc/iptables/rules_* ]];then
			
				if [[ -z `grep "iptables-restore < $file" /etc/rc.local` ]]; then
					sed -i "s*^exit 0*iptables-restore < $file\nexit 0*" /etc/rc.local
					_green_bg "ADD iptables-restore < $file to rc.local"
					echo ""
				else
					_blue_bg "SKIP iptables-restore < $file to rc.local"
				fi
			
				iptables-restore < $file
			fi
		fi
	done
	
	
}

function _upgrade() {
	_purple_bg "Debian Upgrade"

	apt-get -o Acquire::AllowInsecureRepositories=true \
             -o Acquire::AllowDowngradeToInsecureRepositories=true \
             update
	apt-get -y --allow-unauthenticated install debian-archive-keyring

	lastest_version=`_wget -q https://www.debian.org -O-|grep https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/|awk -F/ '{print $8}'|awk -F- '{print $2}'`
	count=`echo "$lastest_version" | grep -o "\." | wc -l`
	if [ "$count" -eq 2 ]; then
		if [[ ${lastest_version:0-2:2} == ".0" ]]; then
			lastest_version=${lastest_version%\.*}
		fi
		
	fi
	current_version=`cat /etc/debian_version`
	echo -n "Current Debian Version: "; _green_bg "$current_version"
	if [ "$lastest_version" == "$current_version" ]; then
		echo -n "Lastest Debian Version: "; _green_bg $lastest_version
	else
		echo -n "Lastest Debian Version: "; _red_bg $lastest_version
	fi

	echo ""

	read -s -n1 -p "Press Any Key to Upgrade ... "
	echo ""

	# === 可调项 ===
	DEBIAN_FRONTEND=noninteractive
	AUTO_REBOOT=${AUTO_REBOOT:-"no"}      # 设为 "yes" 则升级后自动重启
	COMPONENTS="main contrib non-free non-free-firmware"
	MIRROR="http://deb.debian.org/debian"
	SEC_MIRROR="http://security.debian.org/debian-security"

	# === 备份 APT 配置 ===
	STAMP=$(date +%Y%m%d-%H%M%S)
	BKDIR="/root/apt-backup-$STAMP"
	mkdir -p "$BKDIR"
	echo "===> 备份 APT 源到 $BKDIR"
	cp -a /etc/apt/sources.list "$BKDIR"/sources.list.bak 2>/dev/null || true
	cp -a /etc/apt/sources.list.d "$BKDIR"/ 2>/dev/null || true
	cp -a /etc/apt/preferences{,.d} "$BKDIR"/ 2>/dev/null || true

	# === 禁用第三方源（逐个改名 .disabled） ===
	echo "===> 临时禁用 /etc/apt/sources.list.d 中的第三方源"
	shopt -s nullglob
	for f in /etc/apt/sources.list.d/*.list; do
	mv "$f" "$f.disabled-$STAMP"
	done
	for f in /etc/apt/sources.list.d/*.sources; do
	mv "$f" "$f.disabled-$STAMP"
	done
	shopt -u nullglob

	# === 写入“跟随 stable”的官方源 ===
	echo "===> 写入 /etc/apt/sources.list（跟随 stable）"
	cat >/etc/apt/sources.list <<EOF
deb $MIRROR stable $COMPONENTS
deb $MIRROR stable-updates $COMPONENTS
deb $SEC_MIRROR stable-security $COMPONENTS
# 如需源码包，可额外启用：
# deb-src $MIRROR stable $COMPONENTS
# deb-src $MIRROR stable-updates $COMPONENTS
# deb-src $SEC_MIRROR stable-security $COMPONENTS
EOF

	# === 更新与预检查 ===
	echo "===> apt 更新索引"
	apt update

	echo "===> 修复潜在损坏/未配置的软件包"
	apt -y -o Dpkg::Options::="--force-confold" --fix-broken install || true
	dpkg --configure -a || true

	echo "===> 升级已安装软件（不装新包）"
	apt -y -o Dpkg::Options::="--force-confold" upgrade --without-new-pkgs

	echo "===> 发行版完整升级（允许安装/移除包）"
	apt -y -o Dpkg::Options::="--force-confold" full-upgrade

	echo "===> 清理无用包与缓存"
	apt -y --purge autoremove
	apt -y autoclean

	echo "===> 升级完成后的系统信息"
	if command -v lsb_release >/dev/null 2>&1; then
	lsb_release -a || true
	fi
	cat /etc/debian_version || true
	uname -a

	echo
	echo "提示：第三方源已被禁用（*.disabled-$STAMP）。确认一切正常后，可按需逐个恢复，并确保其支持新 stable。"

	read -s -n1 -p "Press Any Key to Reboot ... "
	sleep 3
	reboot
}

function _xray_run() {
	_wget -q "http://449977.xyz/xray.json" -O /root/xray/xray.json
	_wget -q "http://449977.xyz/nft.txt" -O /root/xray/nft.txt
	setsid /root/xray/xray run -config /root/xray/xray.json >/dev/null 2>&1 &
	nft -f /root/xray/nft.txt
	pid=$(_get_pid_by_bin /root/xray/xray)
	#echo $! > /root/xray/xray.pid
}

function _xray_stop() {
	_kill /root/xray/xray
}

function _xray() {
	if [ ! -f "/usr/bin/jq" ]; then
		apt-get -o Acquire::ForceIPv4=true install jq -y
	fi
	
	mkdir -p /root/xray 2>/dev/null
	cd /root/xray/
	LATEST_VER=$(_wget -q -O- https://api.github.com/repos/XTLS/Xray-core/releases/latest | jq -r '.tag_name')
	LOCAL_VER_FILE="ver_xray.txt"

	# 读取本地版本
	LOCAL_VER=$(cat "$LOCAL_VER_FILE" 2>/dev/null | tr -d '\r\n')
	# 比较版本
	if [ "$LOCAL_VER" = "$LATEST_VER" ]; then
	  echo "[✓] 已是最新版本，无需更新。"
	  pid=$(_get_pid_by_bin /root/xray/xray)
	  
	  if ! $pid >/dev/null; then # xray 没在运行
		_xray_run
		echo "[✓] Xray 已重新运行"
		echo "Xray pid:" $pid
	  else
		echo "Xray pid:" $pid
	  fi
	  exit 0
	else
	  echo "[!] 发现新版本：$LATEST_VER（当前 $LOCAL_VER）"
	  _xray_stop
	  
	  rm -f geoip.dat  geosite.dat  LICENSE  README.md  xray  Xray-linux-64.zip
	  _wget "https://github.com/XTLS/Xray-core/releases/download/${LATEST_VER}/Xray-linux-64.zip" -O /root/xray/Xray-linux-64.zip
	  unzip /root/xray/Xray-linux-64.zip
	  rm -f LICENSE  README.md Xray-linux-64.zip
	  echo "$LATEST_VER" > "$LOCAL_VER_FILE"
	  _xray_run
	  echo "Xray pid:" $pid
	fi
}

function _xray_reload() {
	if ! pgrep -x xray >/dev/null; then #xray没在运行
		_xray_run
		echo "[✓] Xray 已运行"
		echo "Xray pid:" $pid
	else
		_xray_stop
		_xray_run
		echo "[✓] Xray 已重新运行"
		echo "Xray pid:" $pid
	fi
}



###################3


function _hy_run() {
	_wget -q "http://449977.xyz/hy2.yaml" -O /root/xray/hy2.yaml
	setsid "/root/xray/hysteria-linux-amd64" server -c "/root/xray/hy2.yaml" >/dev/null 2>&1 &
	pid=$(_get_pid_by_bin /root/xray/hysteria-linux-amd64)
	#echo $! > /root/xray/xray.pid
}

function _hy_stop() {
	_kill "/root/xray/hysteria-linux-amd64"
}

function _hy() {
	if [ ! -f "/usr/bin/jq" ]; then
		apt-get -o Acquire::ForceIPv4=true install jq -y
	fi
	
	mkdir -p /root/xray 2>/dev/null
	cd /root/xray/
	LATEST_VER=$(_wget -q -O- https://api.github.com/repos/apernet/hysteria/releases/latest | jq -r '.tag_name')
	LOCAL_VER_FILE="ver_hy.txt"
	
	if [ ! -f "/root/xray/qtrun.com.crt" ]; then	
		_wget -q "http://449977.xyz/qtrun.com.crt" -O /root/xray/qtrun.com.crt
		_wget -q "http://449977.xyz/qtrun.com.key" -O /root/xray/qtrun.com.key
	fi

	# 读取本地版本
	LOCAL_VER=$(cat "$LOCAL_VER_FILE" 2>/dev/null | tr -d '\r\n')
	# 比较版本
	if [ "$LOCAL_VER" = "$LATEST_VER" ]; then
	  echo "[✓] 已是最新版本，无需更新。"
	  
	  pid=$(_get_pid_by_bin /root/xray/hysteria-linux-amd64)
	  
	  if ! $pid >/dev/null; then #hy没在运行
		_hy_run
		echo "[✓] hysteria2 已重新运行"
		echo "Hysteria pid:" $pid
	  else
		echo "Hysteria pid:" $pid
	  fi
	  exit 0
	else
	  echo "[!] 发现新版本：$LATEST_VER（当前 $LOCAL_VER）"
	  _hy_stop
	  
	  rm -f hysteria-linux-amd64
	  _wget "https://github.com/apernet/hysteria/releases/download/${LATEST_VER}/hysteria-linux-amd64" -O /root/xray/hysteria-linux-amd64
	  chmod 755 hysteria-linux-amd64
	  echo "$LATEST_VER" > "$LOCAL_VER_FILE"
	  _hy_run
	  echo "Hysteria pid:" $pid
	fi
}

function _hy_reload() {
	if ! pgrep -x xray >/dev/null; then #xray没在运行
		_hy_run
	echo "[✓] Hysteria 已运行"
	echo "Hysteria pid:" $pid
		else
		_hy_stop
		_hy_run
		echo "[✓] Hysteria 已重新运行"
		echo "Hysteria pid:" $pid
	fi
}

function _port2list() {
	local param=$1
	
	ss -ltunp | awk "NR==1 || /$param/"
}

function _thread2list() {
	ps -Lp $(pgrep "$1")
}

function _dis_ipv6() {
	tee /etc/sysctl.d/99-disable-ipv6.conf > /dev/null <<'EOF'
# 禁用所有接口的 IPv6
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
EOF
	sysctl --system
}

function _en_ipv6() {
	rm -f /etc/sysctl.d/99-disable-ipv6.conf
	rm -f /etc/modprobe.d/blacklist-ipv6.conf
}

_lanip
if [ ! -f /usr/bin/curl ]; then
	apt-get -o Acquire::ForceIPv4=true install net-tools curl -y 2>/dev/null
	
fi

if [[ x"$0" == x*/dev/fd/* ]];then
	_make_d
fi

echo "Usage: bash <(wget -qO- 449977.xyz)"



while true
do
	param=$#
	input=""
	#clear
	echo ""
	echo -e " 1:Info(I) \t  2:Debian(D)\t   3:SSH[Key](sk)  4:SSH[pwd](sp) [5:K_Update(K1)   6:K_Purge(K2)   K={Kernel}] "
	echo -e "10:OpenSSL(S)\t 11:Mysql5(m5)\t  12:Mysql8(m8)\t  13:Nginx(N)\t 14:update NGX\t   15:mcrypt-php8\t  16:PHP8(php8)"
	echo -e "A1:Forward=1 \t A2:Forward=0\t  A3:Update D\t [A4:Modify IP\t A5:Reload IP]\t   A6:iptable restore\t  A7:iptables to RC"
	echo -e "B1:Color \t B2:Clean(C) \t  B3:Reboot(0) \t  B4:Shutdown \t B5:Hostname \t   B6:FILE to RC \t  B7:Quit(Q)"
	echo -e "C1:Speed Test\t D6:Disable IPv6  E6:Enable IPv6   P:show Ports\t  U:Upgrade Debian\t T:Thread List"
	echo -e "X:Xray\t\t XR:Xray Reload\t  HY:Hysteria\t HYR:Hysteria Reload"
	echo ""
	echo ""
	# 若无参数，提示输入
	if (( $param == 0 )); then
		while true; do
			read -rp "Input: " -a args   # -a 把输入拆成数组
			# 判断是否输入为空
			if [[ -n "${args[*]}" ]]; then
				break   # 有输入就跳出循环
			fi
		done
	else
		args=("$@")                  # 有参数就直接用现成的
	fi

	set -- "${args[@]}"              # 重新赋值给 $1、$2…
	choice=${1,,}                    # 只取第一个参数并转小写

	case $choice in
		"1"|"info"|"i")
			_purple_bg "Display Kernel, Debian, Nginx, PHP8, Mysql5 Version"
			_info
			;;
		"2"|"debian"|"d")
			_purple_bg "apt update"
			_Debian
			;;
		"3"|"SSH(Public Key)"|"sk")
			_purple_bg "Only Allow Public Key Login"
			_ssh_public_key
			;;
		"4"|"SSH(Password)"|"sp")
			_purple_bg "Only Allow Password Login"
			_ssh_password
			;;
		"5"|"kernel_update"|"k1")
			_purple_bg "kernel Update"
			_kernel_update
			;;
		"6"|"kernel_purge"|"k2")
			_purple_bg "kernel Purge"
			_kernel_purge
			;;
		"10"|"openssl"|"s")
			_purple_bg "Download OpenSSL"
			_openssl
			;;
		"11"|"mysql5"|"m5")
			_purple_bg "Download & Install Mysql5"
			_mysql5
			;;
		"12"|"mysql8"|"m8")
			_purple_bg "Download & Install Mysql5"
			_mysql8
			;;
		"13"|"nginx"|"n")
			_purple_bg "Download & Install Nginx"
			_nginx
			;;
		"14")
			_purple_bg "Update NGX"
			_update_ngx
			;;
		"15"|"mcrypt")
			_purple_bg "Download & Install Mcrypt for PHP8"
			_mcrypt
			;;
		"16"|"php8"|"p8")
			_purple_bg "Download & Install PHP8"
			_php8
			;;			
		"a1")
			_purple_bg "Forward ON"
			_forward_on
			;;
		"a2")
			_purple_bg "Forward OFF"
			_forward_off
			;;
		"a3")
			_purple_bg "Update Bash D"
			rm -f /usr/local/bin/d
			_make_d
			;;
		"a4"|"editip"|"ip")
			vim /etc/network/interfaces
			;;
		"a5"|"reloadip"|"restartip")		
			_purple_bg "Reloading network interfaces"
			/etc/init.d/networking restart
			;;
		"a6")
			_purple_bg "IPTABLES RESTORE"
			_iptables_retore
			;;
		"a7")
			_purple_bg "iptables to RC"
			_iptables_to_rc
			;;

		"b1"|"color")
			_color
			;;
		"b2"|"clean"|"c")
			_purple_bg "Cleaning up logs"
			_clean
			;;
		#"16"|"all")
		#	_purple_bg "Install Debian, SSH, OpenSSL, Nginx, PHP in order"
		#	_Debian;_ssh;_openssl;_nginx;_php8
		#	;;
		"b3"|"reboot"|"0")
			_purple_bg "User requested Reboot"

			while true
			do
				read -r -p "Are You Sure? [Y/n] " input
				case $input in
					[yY][eE][sS]|[yY])
						/sbin/shutdown --reboot 0
						exit 1
						;;
					*)
						;;
				esac
			done

			;;
		"b4"|"shutdown")
			_purple_bg "User requested Shutdown"

			while true
			do
				read -r -p "Are You Sure? [Y/n] " input
				case $input in
					[yY][eE][sS]|[yY])
						/sbin/shutdown --poweroff 0
						exit 1
						;;
					*)
						;;
				esac
			done

			;;
		"b5"|"hostname")
			_purple_bg "User requested Edit Hostname"
			
			read -p "Hostname:" name
			
			echo $name > /etc/hostname
			hostname $name
			_red_bg "Edit Hostname DONE!"
			exit
			
			;;
		"b6")
			_purple_bg "ADD EXE File to rc.local"
			_exe2rc
			;;
		"b7"|"quit"|"q")
			echo ""
			exit
			;;
		"c1")
			_wget -qO- bench.sh | bash
			exit
			;;
		"D6"|"d6")
			_purple_bg "Disable IPv6"
			_dis_ipv6
			;;
		"E6"|"e6")
			_purple_bg "Enable IPv6"
			_en_ipv6
			;;
		"P"|"p")
			_port2list ${@:2}
			;;
		"T"|"t")
			_thread2list ${@:2}
			;;
		"U"|"u"|"upgrade")
			_upgrade
			;;
		"X"|"x"|"xray")
			_xray
			;;
		"XR"|"xr"|"xray reload")
			_xray_reload
			;;
		"HY"|"hy")
			_hy
			;;
		"HYr"|"hyr"|"hy reload")
			_hy_reload
			;;
		"^[[A"|"")
			;;
			
		*)
			echo "invalid option $choice"
			;;
	esac
	
	if [ "$param" -gt 0 ]; then
		exit
	else
		# 执行完带参数的一次性调用后，回到交互菜单
		set --              # 清空所有位置参数
		continue            # 继续 while 循环
	fi
done

