diff --git a/README.md b/README.md index 0649f7b5..c5ce0571 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ ShellCrash is designed to be compatible with the vast majority of network device > Install via wget (jsDelivr CDN source) ```sh export url='[https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master](https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master)' \ - && wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh \ + && wget -q --no-check-certificate -O /tmp/install.sh $url/install_en.sh \ && bash /tmp/install.sh \ && . /etc/profile &> /dev/null ``` @@ -67,7 +67,7 @@ export url='[https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master](https:/ ```sh export url='[https://gh.jwsc.eu.org/master](https://gh.jwsc.eu.org/master)' \ - && bash -c "$(curl -kfsSl $url/install.sh)" \ + && bash -c "$(curl -kfsSl $url/install_en.sh)" \ && . /etc/profile &> /dev/null ``` @@ -77,7 +77,7 @@ export url='[https://gh.jwsc.eu.org/master](https://gh.jwsc.eu.org/master)' \ > GitHub Source (Recommended for overseas environments or environments with proxy access) ```sh export url='[https://raw.githubusercontent.com/juewuy/ShellCrash/master](https://raw.githubusercontent.com/juewuy/ShellCrash/master)' \ - && sh -c "$(curl -kfsSl $url/install.sh)" \ + && sh -c "$(curl -kfsSl $url/install_en.sh)" \ && . /etc/profile &> /dev/null ``` @@ -85,14 +85,14 @@ export url='[https://raw.githubusercontent.com/juewuy/ShellCrash/master](https:/ ```sh export url='[https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master](https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master)' \ - && sh -c "$(curl -kfsSl $url/install.sh)" \ + && sh -c "$(curl -kfsSl $url/install_en.sh)" \ && . /etc/profile &> /dev/null ``` > Or Author's private source ```sh export url='[https://gh.jwsc.eu.org/master](https://gh.jwsc.eu.org/master)' \ - && sh -c "$(curl -kfsSl $url/install.sh)" \ + && sh -c "$(curl -kfsSl $url/install_en.sh)" \ && . /etc/profile &> /dev/null ``` @@ -100,7 +100,7 @@ export url='[https://gh.jwsc.eu.org/master](https://gh.jwsc.eu.org/master)' \ > GitHub Source (Recommended for overseas environments or environments with proxy access) ```sh export url='[https://raw.githubusercontent.com/juewuy/ShellCrash/master](https://raw.githubusercontent.com/juewuy/ShellCrash/master)' \ - && wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh \ + && wget -q --no-check-certificate -O /tmp/install.sh $url/install_en.sh \ && sh /tmp/install.sh \ && . /etc/profile &> /dev/null ``` @@ -108,7 +108,7 @@ export url='[https://raw.githubusercontent.com/juewuy/ShellCrash/master](https:/ > Or jsDelivr CDN source ```sh export url='[https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master](https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master)' \ - && wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh \ + && wget -q --no-check-certificate -O /tmp/install.sh $url/install_en.sh \ && sh /tmp/install.sh \ && . /etc/profile &> /dev/null ``` @@ -118,7 +118,7 @@ export url='[https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master](https:/ > Author's private HTTP beta source ```sh export url='[http://t.jwsc.eu.org](http://t.jwsc.eu.org)' \ - && wget -q -O /tmp/install.sh $url/install.sh \ + && wget -q -O /tmp/install.sh $url/install_en.sh \ && sh /tmp/install.sh \ && . /etc/profile &> /dev/null ``` @@ -132,7 +132,7 @@ apk add --no-cache wget openrc ca-certificates tzdata nftables iproute2 dcron # Execute installation command export url='[https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master](https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master)' \ - && wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh \ + && wget -q --no-check-certificate -O /tmp/install.sh $url/install_en.sh \ && sh /tmp/install.sh \ && . /etc/profile &> /dev/null ``` diff --git a/install_en.sh b/install_en.sh new file mode 100644 index 00000000..90ccdbde --- /dev/null +++ b/install_en.sh @@ -0,0 +1,373 @@ +#!/bin/sh +# Copyright (C) Juewuy + +echo "***********************************************" +echo "** Welcome to **" +echo "** ShellCrash **" +echo "** by Juewuy **" +echo "***********************************************" + +[ -z "$url" ] && url="https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master" + +# Internal Tools +cecho() { + printf '%b\n' "$*" +} +dir_avail() { + df -h >/dev/null 2>&1 && h="$2" + df -P $h "${1:-.}" 2>/dev/null | awk 'NR==2 {print $4}' +} +ckcmd() { + if command -v sh >/dev/null 2>&1; then + command -v "$1" >/dev/null 2>&1 + else + type "$1" >/dev/null 2>&1 + fi +} +webget() { + # Parameter [$1] Download Path, [$2] Online URL + # Parameter [$3] Display Output, [$4] Disable Redirects + if curl --version >/dev/null 2>&1; then + [ "$3" = "echooff" ] && progress='-s' || progress='-#' + [ -z "$4" ] && redirect='-L' || redirect='' + result=$(curl -w %{http_code} --connect-timeout 5 "$progress" "$redirect" -ko "$1" "$2") + [ -n "$(echo $result | grep -e ^2)" ] && result="200" + else + if wget --version >/dev/null 2>&1; then + [ "$3" = "echooff" ] && progress='-q' || progress='-q --show-progress' + [ "$4" = "rediroff" ] && redirect='--max-redirect=0' || redirect='' + certificate='--no-check-certificate' + timeout='--timeout=3' + fi + [ "$3" = "echoon" ] && progress='' + [ "$3" = "echooff" ] && progress='-q' + wget "$progress" "$redirect" "$certificate" "$timeout" -O "$1" "$2" + [ $? -eq 0 ] && result="200" + fi +} +error_down() { + cecho "Please refer to \033[32mhttps://github.com/juewuy/ShellCrash/blob/master/README.md" + cecho "\033[33mUse an alternative source to reinstall!\033[0m" +} + +# Installation and Initialization +set_alias() { + while true; do + echo "-----------------------------------------------" + cecho "\033[36mPlease select an alias or enter a custom one:\033[0m" + echo "-----------------------------------------------" + cecho " 1 【\033[32mcrash\033[0m】" + cecho " 2 【\033[32m sc \033[0m】" + cecho " 3 【\033[32m mm \033[0m】" + cecho " 0 Exit Installation" + echo "-----------------------------------------------" + read -p "Enter number or custom alias > " res + case "$res" in + 0) + echo "Installation cancelled" + exit 1 + ;; + 1) + my_alias=crash + ;; + 2) + my_alias=sc + ;; + 3) + my_alias=mm + ;; + *) + my_alias=$res + ;; + esac + cmd=$(ckcmd "$my_alias" | grep 'menu.sh') + ckcmd "$my_alias" && [ -z "$cmd" ] && { + cecho "\033[33mThis alias conflicts with a system command; please choose another!\033[0m" + sleep 1 + continue + } + break + done +} +gettar() { + webget /tmp/ShellCrash.tar.gz "$url/ShellCrash.tar.gz" >/dev/null 2>&1 + if [ "$result" != "200" ]; then + cecho "\033[33mFile download failed!\033[0m" + error_down + exit 1 + else + "$CRASHDIR"/start.sh stop 2>/dev/null + # Extract + echo "-----------------------------------------------" + echo "Starting file extraction!" + mkdir -p "$CRASHDIR" >/dev/null + tar -zxf '/tmp/ShellCrash.tar.gz' -C "$CRASHDIR"/ || tar -zxf '/tmp/ShellCrash.tar.gz' --no-same-owner -C "$CRASHDIR"/ + if [ -s "$CRASHDIR"/init.sh ]; then + set_alias + . "$CRASHDIR"/init.sh >/dev/null + [ "$?" != 0 ] && cecho "\033[33mInitialization failed, try local installation!\033[0m" && exit 1 + else + rm -rf /tmp/ShellCrash.tar.gz + cecho "\033[33mFile extraction failed!\033[0m" + error_down + exit 1 + fi + fi +} +set_usb_dir() { + while true; do + cecho "Please select installation directory" + du -hL /mnt | awk '{print " "NR" "$2" "$1}' + read -p "Enter number > " num + dir=$(du -hL /mnt | awk '{print $2}' | sed -n "$num"p) + if [ -z "$dir" ]; then + cecho "\033[31mInvalid input! Please try again!\033[0m" + continue + fi + break 1 + done +} +set_xiaomi_dir() { + cecho "\033[33mXiaomi device detected, please select installation location\033[0m" + [ -d /data ] && cecho " 1 Install to /data, Free space: $(dir_avail /data -h) (Supports soft-hardening)" + [ -d /userdisk ] && cecho " 2 Install to /userdisk, Free space: $(dir_avail /userdisk -h) (Supports soft-hardening)" + [ -d /data/other_vol ] && cecho " 3 Install to /data/other_vol, Free space: $(dir_avail /data/other_vol -h) (Supports soft-hardening)" + cecho " 4 Custom directory (Not recommended for beginners!)" + cecho " 0 Exit" + echo "-----------------------------------------------" + read -p "Enter number > " num + case "$num" in + 1) + dir=/data + ;; + 2) + dir=/userdisk + ;; + 3) + dir=/data/other_vol + ;; + 4) + set_cust_dir + ;; + *) + exit 1 + ;; + esac +} +set_asus_usb() { + while true; do + echo -e "Please select USB directory" + du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print " "NR" "$2" "$1}' + read -p "Enter number > " num + dir=$(du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print $2}' | sed -n "$num"p) + if [ ! -f "$dir/asusware.arm/etc/init.d/S50downloadmaster" ]; then + echo -e "\033[31mDownload Master startup file not found: $dir/asusware.arm/etc/init.d/S50downloadmaster. Check settings!\033[0m" + sleep 1 + else + break + fi + done +} +set_asus_dir() { + cecho "\033[33mAsus firmware detected, please select installation method\033[0m" + cecho " 1 Via USB + Download Master (Supports all firmware, ARM only, USB required)" + cecho " 2 Via startup script (Merlin firmware only)" + cecho " 0 Exit" + echo "-----------------------------------------------" + read -p "Enter number > " num + case "$num" in + 1) + echo -e "Please install and enable Download Master in the router web UI first, then select the storage directory!" + sleep 2 + set_asus_usb + ;; + 2) + cecho "If auto-start fails after reboot, please use USB + Download Master method instead!" + sleep 2 + dir=/jffs + ;; + *) + exit 1 + ;; + esac +} +set_cust_dir() { + while true; do + echo "-----------------------------------------------" + echo 'Path | Free Space:' + df -h | awk '{print $6,$4}' | sed 1d + echo 'Path must start with "/". Files in virtual memory (/tmp, /opt, /sys...) will be lost on reboot!!!' + read -p "Enter custom path > " dir + if [ "$(dir_avail "$dir")" = 0 ] || [ -n "$(echo "$dir" | grep -Eq '^/(tmp|opt|sys)(/|$)')" ]; then + cecho "\033[31mInvalid path! Please try again!\033[0m" + continue + fi + break 1 + done +} + +setdir() { + while true; do + echo "-----------------------------------------------" + cecho "\033[33mNote: ShellCrash requires at least 1MB of disk space\033[0m" + case "$systype" in + Padavan) dir=/etc/storage ;; + mi_snapshot) set_xiaomi_dir ;; + asusrouter) set_asus_dir ;; + ng_snapshot) dir=/tmp/mnt ;; + *) + cecho " 1 Install in \033[32m/etc\033[0m (Best for root users)" + cecho " 2 Install in \033[32m/usr/share\033[0m (Standard Linux systems)" + cecho " 3 Install in \033[32mUser Directory\033[0m (Best for non-root users)" + cecho " 4 Install on \033[32mExternal Storage\033[0m" + cecho " 5 Manual path entry" + cecho " 0 Exit" + echo "----------------------------------------------" + read -p "Enter number > " num + # Set Dir + case "$num" in + 1) + dir=/etc + ;; + 2) + dir=/usr/share + ;; + 3) + dir=~/.local/share + mkdir -p ~/.config/systemd/user + ;; + 4) + set_usb_dir + ;; + 5) + set_cust_dir + ;; + *) + echo "Installation cancelled" + exit 1 + ;; + esac + ;; + esac + + if [ ! -w "$dir" ]; then + cecho "\033[31mNo write permission for $dir! Please reset!\033[0m" + sleep 1 + else + cecho "Target directory: \033[32m$dir\033[0m | Free space: $(dir_avail "$dir" -h)" + read -p "Confirm installation? (1/0) > " res + if [ "$res" = "1" ]; then + CRASHDIR="$dir"/ShellCrash + break + fi + fi + done +} +install() { + echo "-----------------------------------------------" + echo "Retrieving installation files from server..." + echo "-----------------------------------------------" + gettar + echo "-----------------------------------------------" + echo "ShellCrash installed successfully!" + [ "$profile" = "~/.bashrc" ] && echo "Please run [. ~/.bashrc > /dev/null] to update environment variables!" + [ -n "$(ls -l /bin/sh | grep -oE 'zsh')" ] && echo "Please run [. ~/.zshrc > /dev/null] to update environment variables!" + echo "-----------------------------------------------" + cecho "\033[33mType \033[30;47m $my_alias \033[0;33m to start management dashboard!!!\033[0m" + echo "-----------------------------------------------" +} +setversion() { + echo "-----------------------------------------------" + cecho "\033[33mSelect version to install:\033[0m" + cecho " 1 \033[32mBeta (Recommended)\033[0m" + cecho " 2 \033[36mStable\033[0m" + cecho " 3 \033[31mDev (Unstable)\033[0m" + echo "-----------------------------------------------" + read -p "Enter number > " num + case "$num" in + 2) + url=$(echo "$url" | sed 's/master/stable/') + ;; + 3) + url=$(echo "$url" | sed 's/master/dev/') + ;; + *) ;; + esac +} + +# Pre-Install Checks +check_systype() { + [ -f "/etc/storage/started_script.sh" ] && { + systype=Padavan # Padavan Firmware + initdir='/etc/storage/started_script.sh' + } + [ -d "/jffs" ] && { + systype=asusrouter # Asus Firmware + [ -f "/jffs/.asusrouter" ] && initdir='/jffs/.asusrouter' + [ -d "/jffs/scripts" ] && initdir='/jffs/scripts/nat-start' + } + [ -f "/data/etc/crontabs/root" ] && systype=mi_snapshot # Xiaomi device + [ -w "/var/mnt/cfg/firewall" ] && systype=ng_snapshot # NETGEAR device +} +check_user() { + if [ "$USER" != "root" ] && [ -z "$systype" ]; then + echo "Current User: $USER" + cecho "\033[31mPlease use the root user (do not use sudo directly!) to install!\033[0m" + echo "-----------------------------------------------" + read -p "Install anyway? Unknown errors may occur! (1/0) > " res + [ "$res" != "1" ] && exit 1 + fi +} +check_version() { + echo "$url" | grep -q 'master' && setversion + webget /tmp/version "$url/version" echooff + [ "$result" = "200" ] && versionsh=$(cat /tmp/version) + rm -rf /tmp/version + + # Output + cecho "Latest Version: \033[32m$versionsh\033[0m" + echo "-----------------------------------------------" + cecho "\033[44mFor issues, please join the TG group: \033[42;30m t.me/ShellClash \033[0m" + cecho "\033[37mSupports various OpenWrt-based router devices" + cecho "\033[33mSupports Debian, Centos and standard Linux systems\033[0m" +} +check_dir() { + if [ -n "$CRASHDIR" ]; then + echo "-----------------------------------------------" + cecho "Old installation detected at \033[36m$CRASHDIR\033[0m. Overwrite?" + cecho "\033[32mConfiguration files will NOT be removed during overwrite!\033[0m" + echo " 1 Overwrite Installation" + echo " 2 Uninstall old version and reinstall" + echo " 0 Cancel" + read -p "Enter number > " num + case "$num" in + 1) + install + ;; + 2) + [ "$CRASHDIR" != "/" ] && rm -rf "$CRASHDIR" + echo "-----------------------------------------------" + cecho "\033[31mOld version uninstalled!\033[0m" + setdir + install + ;; + 9) + echo "Test Mode: Changing installation path $CRASHDIR" + setdir + install + ;; + *) + cecho "\033[31mInstallation cancelled!\033[0m" + exit 1 + ;; + esac + else + setdir + install + fi +} + +check_systype +check_user +check_version +check_dir