Last active
July 14, 2026 05:29
-
-
Save Yunuuuu/c3f6790d96c9bf176ac2d196cbfac00e to your computer and use it in GitHub Desktop.
Install or update Xray from the SourceForge mirror.
This file contains hidden or 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
| # Install or update Xray from the SourceForge mirror. | |
| # | |
| # Usage: | |
| # _install_xray [OPTIONS] | |
| # _install_xray -h | |
| # unset -f _install_xray | |
| # | |
| # Default mode: --user | |
| # | |
| # Default user layout: | |
| # ${XDG_DATA_HOME:-$HOME/.local/share}/xray/xray | |
| # ${XDG_DATA_HOME:-$HOME/.local/share}/xray/geoip.dat | |
| # ${XDG_DATA_HOME:-$HOME/.local/share}/xray/geosite.dat | |
| # ${XDG_CONFIG_HOME:-$HOME/.config}/xray/config.json | |
| # $HOME/.local/bin/xray -> ${XDG_DATA_HOME:-$HOME/.local/share}/xray/xray | |
| # | |
| # Default system layout: | |
| # /usr/local/share/xray/xray | |
| # /usr/local/share/xray/geoip.dat | |
| # /usr/local/share/xray/geosite.dat | |
| # /usr/local/etc/xray/config.json | |
| # /usr/local/bin/xray -> /usr/local/share/xray/xray | |
| # | |
| # Uninstall the default user installation: | |
| # systemctl --user disable --now xray 2>/dev/null || true | |
| # rm -f -- "$HOME/.local/bin/xray" | |
| # rm -rf -- "${XDG_DATA_HOME:-$HOME/.local/share}/xray" | |
| # | |
| # Also remove the user configuration: | |
| # rm -rf -- "${XDG_CONFIG_HOME:-$HOME/.config}/xray" | |
| # | |
| # Uninstall the default system installation: | |
| # sudo systemctl disable --now xray 2>/dev/null || true | |
| # sudo rm -f -- /usr/local/bin/xray | |
| # sudo rm -rf -- /usr/local/share/xray | |
| # | |
| # Also remove the system configuration: | |
| # sudo rm -rf -- /usr/local/etc/xray | |
| _install_xray() { | |
| local scope="user" | |
| local scope_set=0 | |
| local data_home="" | |
| local data_home_set=0 | |
| local bin_dir="" | |
| local bin_dir_set=0 | |
| local config_home="" | |
| local xray_home="" | |
| local binary_mode="" | |
| local data_dir_mode="" | |
| local config_dir_mode="" | |
| local bin_dir_mode="" | |
| local machine="" | |
| local archive_arch="" | |
| local source_binary="xray" | |
| local soft_float=0 | |
| local tmp="" | |
| local source_dir="" | |
| local latest_dir="" | |
| local download_path="" | |
| local new_xray="" | |
| local file="" | |
| local name="" | |
| local rc=1 | |
| local base="https://sourceforge.net/projects/xray-core.mirror/files" | |
| while (($# > 0)); do | |
| case "$1" in | |
| --user) | |
| if ((scope_set)) && [[ $scope != user ]]; then | |
| echo "Cannot use --user and --system together" >&2 | |
| return 2 | |
| fi | |
| scope="user" | |
| scope_set=1 | |
| shift | |
| ;; | |
| --system) | |
| if ((scope_set)) && [[ $scope != system ]]; then | |
| echo "Cannot use --user and --system together" >&2 | |
| return 2 | |
| fi | |
| scope="system" | |
| scope_set=1 | |
| shift | |
| ;; | |
| --data-home) | |
| if (($# < 2)); then | |
| echo "--data-home requires a value" >&2 | |
| return 2 | |
| fi | |
| data_home="$2" | |
| data_home_set=1 | |
| shift 2 | |
| ;; | |
| --data-home=*) | |
| data_home="${1#*=}" | |
| data_home_set=1 | |
| shift | |
| ;; | |
| --bin-dir) | |
| if (($# < 2)); then | |
| echo "--bin-dir requires a value" >&2 | |
| return 2 | |
| fi | |
| bin_dir="$2" | |
| bin_dir_set=1 | |
| shift 2 | |
| ;; | |
| --bin-dir=*) | |
| bin_dir="${1#*=}" | |
| bin_dir_set=1 | |
| shift | |
| ;; | |
| --soft-float) | |
| soft_float=1 | |
| shift | |
| ;; | |
| -h | --help) | |
| cat <<'HELP' | |
| Usage: | |
| _install_xray [OPTIONS] | |
| Options may appear in any order. | |
| Options: | |
| --user | |
| Install for the current user. This is the default mode. | |
| --system | |
| Install system-wide. Root privileges are required. | |
| --data-home PATH | |
| --data-home=PATH | |
| Set the parent directory of the Xray application directory. | |
| Application files are installed into: | |
| PATH/xray | |
| Defaults: | |
| user: ${XDG_DATA_HOME:-$HOME/.local/share} | |
| system: /usr/local/share | |
| --bin-dir PATH | |
| --bin-dir=PATH | |
| Create PATH/xray as a symbolic link to the installed executable. | |
| Defaults: | |
| user: $HOME/.local/bin | |
| system: /usr/local/bin | |
| Pass an empty value to skip link creation: | |
| --bin-dir "" | |
| --bin-dir= | |
| Skipping link creation does not remove an existing link. | |
| --soft-float | |
| Use xray_softfloat from a MIPS32 or MIPS32LE archive. | |
| -h, --help | |
| Show this help. | |
| Default user layout: | |
| ${XDG_DATA_HOME:-$HOME/.local/share}/xray/xray | |
| ${XDG_DATA_HOME:-$HOME/.local/share}/xray/geoip.dat | |
| ${XDG_DATA_HOME:-$HOME/.local/share}/xray/geosite.dat | |
| ${XDG_CONFIG_HOME:-$HOME/.config}/xray/config.json | |
| $HOME/.local/bin/xray -> ${XDG_DATA_HOME:-$HOME/.local/share}/xray/xray | |
| Default system layout: | |
| /usr/local/share/xray/xray | |
| /usr/local/share/xray/geoip.dat | |
| /usr/local/share/xray/geosite.dat | |
| /usr/local/etc/xray/config.json | |
| /usr/local/bin/xray -> /usr/local/share/xray/xray | |
| Examples: | |
| _install_xray | |
| _install_xray --user | |
| _install_xray --system | |
| _install_xray --bin-dir "" | |
| _install_xray --soft-float | |
| _install_xray \ | |
| --data-home "$HOME/.local/share" \ | |
| --bin-dir "$HOME/.local/bin" | |
| _install_xray \ | |
| --system \ | |
| --data-home /usr/local/share \ | |
| --bin-dir /usr/local/bin | |
| Run the default user installation: | |
| xray run -c "${XDG_CONFIG_HOME:-$HOME/.config}/xray/config.json" | |
| Run the default system installation: | |
| xray run -c /usr/local/etc/xray/config.json | |
| Uninstall the default user installation: | |
| systemctl --user disable --now xray 2>/dev/null || true | |
| rm -f -- "$HOME/.local/bin/xray" | |
| rm -rf -- "${XDG_DATA_HOME:-$HOME/.local/share}/xray" | |
| Also remove the user configuration: | |
| rm -rf -- "${XDG_CONFIG_HOME:-$HOME/.config}/xray" | |
| Uninstall the default system installation: | |
| sudo systemctl disable --now xray 2>/dev/null || true | |
| sudo rm -f -- /usr/local/bin/xray | |
| sudo rm -rf -- /usr/local/share/xray | |
| Also remove the system configuration: | |
| sudo rm -rf -- /usr/local/etc/xray | |
| HELP | |
| return 0 | |
| ;; | |
| --) | |
| shift | |
| if (($# > 0)); then | |
| echo "Unexpected positional argument: $1" >&2 | |
| return 2 | |
| fi | |
| ;; | |
| -*) | |
| echo "Unknown option: $1" >&2 | |
| return 2 | |
| ;; | |
| *) | |
| echo "Unexpected positional argument: $1" >&2 | |
| echo "Use --data-home or --bin-dir to specify paths" >&2 | |
| return 2 | |
| ;; | |
| esac | |
| done | |
| case "$scope" in | |
| user) | |
| if ((data_home_set == 0)); then | |
| data_home="${XDG_DATA_HOME:-$HOME/.local/share}" | |
| fi | |
| if ((bin_dir_set == 0)); then | |
| bin_dir="$HOME/.local/bin" | |
| fi | |
| config_home="${XDG_CONFIG_HOME:-$HOME/.config}/xray" | |
| binary_mode=700 | |
| data_dir_mode=700 | |
| config_dir_mode=700 | |
| bin_dir_mode=700 | |
| ;; | |
| system) | |
| if ((EUID != 0)); then | |
| echo "System installation requires root privileges" >&2 | |
| return 1 | |
| fi | |
| if ((data_home_set == 0)); then | |
| data_home="/usr/local/share" | |
| fi | |
| if ((bin_dir_set == 0)); then | |
| bin_dir="/usr/local/bin" | |
| fi | |
| config_home="/usr/local/etc/xray" | |
| binary_mode=755 | |
| data_dir_mode=755 | |
| config_dir_mode=755 | |
| bin_dir_mode=755 | |
| ;; | |
| esac | |
| if [[ -z $data_home ]]; then | |
| echo "Data home cannot be empty" >&2 | |
| return 2 | |
| fi | |
| data_home="${data_home%/}" | |
| xray_home="$data_home/xray" | |
| if [[ -n $bin_dir ]]; then | |
| bin_dir="${bin_dir%/}" | |
| fi | |
| machine="$(uname -m)" | |
| case "$machine" in | |
| x86_64 | amd64) | |
| archive_arch="64" | |
| ;; | |
| i386 | i486 | i586 | i686 | x86) | |
| archive_arch="32" | |
| ;; | |
| aarch64 | arm64) | |
| archive_arch="arm64-v8a" | |
| ;; | |
| armv8l | armv7* | armhf) | |
| archive_arch="arm32-v7a" | |
| ;; | |
| armv6*) | |
| archive_arch="arm32-v6" | |
| ;; | |
| armv5*) | |
| archive_arch="arm32-v5" | |
| ;; | |
| mips64el | mips64le) | |
| archive_arch="mips64le" | |
| ;; | |
| mips64) | |
| archive_arch="mips64" | |
| ;; | |
| mipsel | mipsle) | |
| archive_arch="mips32le" | |
| ;; | |
| mips) | |
| archive_arch="mips32" | |
| ;; | |
| ppc64le | powerpc64le) | |
| archive_arch="ppc64le" | |
| ;; | |
| ppc64 | powerpc64) | |
| archive_arch="ppc64" | |
| ;; | |
| riscv64) | |
| archive_arch="riscv64" | |
| ;; | |
| loongarch64 | loong64) | |
| archive_arch="loong64" | |
| ;; | |
| s390x) | |
| archive_arch="s390x" | |
| ;; | |
| *) | |
| echo "Unsupported architecture: $machine" >&2 | |
| return 1 | |
| ;; | |
| esac | |
| if ((soft_float)); then | |
| case "$archive_arch" in | |
| mips32 | mips32le) | |
| source_binary="xray_softfloat" | |
| ;; | |
| *) | |
| echo "--soft-float is supported only on MIPS32 and MIPS32LE" >&2 | |
| return 2 | |
| ;; | |
| esac | |
| fi | |
| tmp="$(mktemp -d)" || { | |
| echo "Failed to create a temporary directory" >&2 | |
| return 1 | |
| } | |
| source_dir="$tmp/xray" | |
| new_xray="$xray_home/.xray.new.$$" | |
| latest_dir="$( | |
| curl -fsSL "$base/" \ | |
| | grep -oE '/projects/xray-core\.mirror/files/v[0-9]+\.[0-9]+\.[0-9]+/' \ | |
| | sort -Vu \ | |
| | tail -n 1 | |
| )" | |
| if [[ -z $latest_dir ]]; then | |
| echo "Failed to find the latest Xray release" >&2 | |
| else | |
| download_path="$( | |
| curl -fsSL "https://sourceforge.net$latest_dir" \ | |
| | grep -oE "/projects/xray-core\.mirror/files/v[0-9]+\.[0-9]+\.[0-9]+/Xray-linux-${archive_arch}\.zip/download" \ | |
| | head -n 1 | |
| )" | |
| if [[ -z $download_path ]]; then | |
| echo "Failed to find Xray-linux-${archive_arch}.zip" >&2 | |
| elif ! curl -fL "https://sourceforge.net$download_path" -o "$tmp/xray.zip"; then | |
| echo "Failed to download Xray" >&2 | |
| elif ! mkdir -p -- "$source_dir"; then | |
| echo "Failed to create the Xray extraction directory" >&2 | |
| elif ! unzip -q "$tmp/xray.zip" -d "$source_dir"; then | |
| echo "Failed to extract the Xray archive" >&2 | |
| elif [[ ! -f $source_dir/$source_binary ]]; then | |
| echo "The Xray archive does not contain $source_binary" >&2 | |
| elif ! install -d -m "$data_dir_mode" "$xray_home"; then | |
| echo "Failed to create the Xray application directory" >&2 | |
| elif ! install -d -m "$config_dir_mode" "$config_home"; then | |
| echo "Failed to create the Xray configuration directory" >&2 | |
| elif [[ -n $bin_dir ]] && ! install -d -m "$bin_dir_mode" "$bin_dir"; then | |
| echo "Failed to create the command directory" >&2 | |
| elif ! install -m "$binary_mode" "$source_dir/$source_binary" "$new_xray"; then | |
| echo "Failed to stage the xray executable" >&2 | |
| else | |
| rc=0 | |
| while IFS= read -r -d '' file; do | |
| name="${file##*/}" | |
| case "$name" in | |
| xray | xray_softfloat) | |
| continue | |
| ;; | |
| config.json) | |
| if [[ ! -e $config_home/$name && ! -L $config_home/$name ]]; then | |
| install -m 600 "$file" "$config_home/$name" || rc=1 | |
| fi | |
| ;; | |
| *) | |
| rm -rf -- "$xray_home/$name" \ | |
| && cp -a -- "$file" "$xray_home/$name" \ | |
| || rc=1 | |
| ;; | |
| esac | |
| done < <(find "$source_dir" -mindepth 1 -maxdepth 1 -print0) | |
| if ((rc == 0)); then | |
| mv -fT -- "$new_xray" "$xray_home/xray" || rc=1 | |
| fi | |
| if ((rc == 0)) && [[ -n $bin_dir && $bin_dir != "$xray_home" ]]; then | |
| ln -sfnT -- "$xray_home/xray" "$bin_dir/xray" || rc=1 | |
| fi | |
| fi | |
| fi | |
| rm -rf -- "$tmp" | |
| rm -f -- "$new_xray" | |
| return "$rc" | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment