install-release.sh 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  1. #!/usr/bin/env bash
  2. # The files installed by the script conform to the Filesystem Hierarchy Standard:
  3. # https://wiki.linuxfoundation.org/lsb/fhs
  4. # The URL of the script project is:
  5. # https://github.com/XTLS/Xray-install
  6. # The URL of the script is:
  7. # https://raw.githubusercontent.com/XTLS/Xray-install/main/install-release.sh
  8. # If the script executes incorrectly, go to:
  9. # https://github.com/XTLS/Xray-install/issues
  10. # You can set this variable whatever you want in shell session right before running this script by issuing:
  11. # export DAT_PATH='/usr/local/share/xray'
  12. DAT_PATH=${DAT_PATH:-/usr/local/share/xray}
  13. # You can set this variable whatever you want in shell session right before running this script by issuing:
  14. # export JSON_PATH='/usr/local/etc/xray'
  15. JSON_PATH=${JSON_PATH:-/usr/local/etc/xray}
  16. # Set this variable only if you are starting xray with multiple configuration files:
  17. # export JSONS_PATH='/usr/local/etc/xray'
  18. # Set this variable only if you want this script to check all the systemd unit file:
  19. # export check_all_service_files='yes'
  20. # Gobal verbals
  21. if [[ -f '/etc/systemd/system/xray.service' ]] && [[ -f '/usr/local/bin/xray' ]]; then
  22. XRAY_IS_INSTALLED_BEFORE_RUNNING_SCRIPT=1
  23. else
  24. XRAY_IS_INSTALLED_BEFORE_RUNNING_SCRIPT=0
  25. fi
  26. # Xray current version
  27. CURRENT_VERSION=''
  28. # Xray latest release version
  29. RELEASE_LATEST=''
  30. # Xray latest prerelease/release version
  31. PRE_RELEASE_LATEST=''
  32. # Xray version will be installed
  33. INSTALL_VERSION=''
  34. # install
  35. INSTALL='0'
  36. # install-geodata
  37. INSTALL_GEODATA='0'
  38. # remove
  39. REMOVE='0'
  40. # help
  41. HELP='0'
  42. # check
  43. CHECK='0'
  44. # --force
  45. FORCE='0'
  46. # --beta
  47. BETA='0'
  48. # --install-user ?
  49. INSTALL_USER=''
  50. # --without-geodata
  51. NO_GEODATA='0'
  52. # --without-logfiles
  53. NO_LOGFILES='0'
  54. # --no-update-service
  55. N_UP_SERVICE='0'
  56. # --reinstall
  57. REINSTALL='0'
  58. # --version ?
  59. SPECIFIED_VERSION=''
  60. # --local ?
  61. LOCAL_FILE=''
  62. # --proxy ?
  63. PROXY=''
  64. # --purge
  65. PURGE='0'
  66. curl() {
  67. $(type -P curl) -L -q --retry 5 --retry-delay 10 --retry-max-time 60 "$@"
  68. }
  69. systemd_cat_config() {
  70. if systemd-analyze --help | grep -qw 'cat-config'; then
  71. systemd-analyze --no-pager cat-config "$@"
  72. echo
  73. else
  74. echo "${aoi}~~~~~~~~~~~~~~~~"
  75. cat "$@" "$1".d/*
  76. echo "${aoi}~~~~~~~~~~~~~~~~"
  77. echo "${red}warning: ${green}The systemd version on the current operating system is too low."
  78. echo "${red}warning: ${green}Please consider to upgrade the systemd or the operating system.${reset}"
  79. echo
  80. fi
  81. }
  82. check_if_running_as_root() {
  83. # If you want to run as another user, please modify $EUID to be owned by this user
  84. if [[ "$EUID" -ne '0' ]]; then
  85. echo "error: You must run this script as root!"
  86. exit 1
  87. fi
  88. }
  89. identify_the_operating_system_and_architecture() {
  90. if [[ "$(uname)" == 'Linux' ]]; then
  91. case "$(uname -m)" in
  92. 'i386' | 'i686')
  93. MACHINE='32'
  94. ;;
  95. 'amd64' | 'x86_64')
  96. MACHINE='64'
  97. ;;
  98. 'armv5tel')
  99. MACHINE='arm32-v5'
  100. ;;
  101. 'armv6l')
  102. MACHINE='arm32-v6'
  103. grep Features /proc/cpuinfo | grep -qw 'vfp' || MACHINE='arm32-v5'
  104. ;;
  105. 'armv7' | 'armv7l')
  106. MACHINE='arm32-v7a'
  107. grep Features /proc/cpuinfo | grep -qw 'vfp' || MACHINE='arm32-v5'
  108. ;;
  109. 'armv8' | 'aarch64')
  110. MACHINE='arm64-v8a'
  111. ;;
  112. 'mips')
  113. MACHINE='mips32'
  114. ;;
  115. 'mipsle')
  116. MACHINE='mips32le'
  117. ;;
  118. 'mips64')
  119. MACHINE='mips64'
  120. lscpu | grep -q "Little Endian" && MACHINE='mips64le'
  121. ;;
  122. 'mips64le')
  123. MACHINE='mips64le'
  124. ;;
  125. 'ppc64')
  126. MACHINE='ppc64'
  127. ;;
  128. 'ppc64le')
  129. MACHINE='ppc64le'
  130. ;;
  131. 'riscv64')
  132. MACHINE='riscv64'
  133. ;;
  134. 's390x')
  135. MACHINE='s390x'
  136. ;;
  137. *)
  138. echo "error: The architecture is not supported."
  139. exit 1
  140. ;;
  141. esac
  142. if [[ ! -f '/etc/os-release' ]]; then
  143. echo "error: Don't use outdated Linux distributions."
  144. exit 1
  145. fi
  146. # Do not combine this judgment condition with the following judgment condition.
  147. ## Be aware of Linux distribution like Gentoo, which kernel supports switch between Systemd and OpenRC.
  148. if [[ -f /.dockerenv ]] || grep -q 'docker\|lxc' /proc/1/cgroup && [[ "$(type -P systemctl)" ]]; then
  149. true
  150. elif [[ -d /run/systemd/system ]] || grep -q systemd <(ls -l /sbin/init); then
  151. true
  152. else
  153. echo "error: Only Linux distributions using systemd are supported."
  154. exit 1
  155. fi
  156. if [[ "$(type -P apt)" ]]; then
  157. PACKAGE_MANAGEMENT_INSTALL='apt -y --no-install-recommends install'
  158. PACKAGE_MANAGEMENT_REMOVE='apt purge'
  159. package_provide_tput='ncurses-bin'
  160. elif [[ "$(type -P dnf)" ]]; then
  161. PACKAGE_MANAGEMENT_INSTALL='dnf -y install'
  162. PACKAGE_MANAGEMENT_REMOVE='dnf remove'
  163. package_provide_tput='ncurses'
  164. elif [[ "$(type -P yum)" ]]; then
  165. PACKAGE_MANAGEMENT_INSTALL='yum -y install'
  166. PACKAGE_MANAGEMENT_REMOVE='yum remove'
  167. package_provide_tput='ncurses'
  168. elif [[ "$(type -P zypper)" ]]; then
  169. PACKAGE_MANAGEMENT_INSTALL='zypper install -y --no-recommends'
  170. PACKAGE_MANAGEMENT_REMOVE='zypper remove'
  171. package_provide_tput='ncurses-utils'
  172. elif [[ "$(type -P pacman)" ]]; then
  173. PACKAGE_MANAGEMENT_INSTALL='pacman -Syu --noconfirm'
  174. PACKAGE_MANAGEMENT_REMOVE='pacman -Rsn'
  175. package_provide_tput='ncurses'
  176. elif [[ "$(type -P emerge)" ]]; then
  177. PACKAGE_MANAGEMENT_INSTALL='emerge -qv'
  178. PACKAGE_MANAGEMENT_REMOVE='emerge -Cv'
  179. package_provide_tput='ncurses'
  180. else
  181. echo "error: The script does not support the package manager in this operating system."
  182. exit 1
  183. fi
  184. else
  185. echo "error: This operating system is not supported."
  186. exit 1
  187. fi
  188. }
  189. ## Demo function for processing parameters
  190. judgment_parameters() {
  191. local local_install='0'
  192. local temp_version='0'
  193. while [[ "$#" -gt '0' ]]; do
  194. case "$1" in
  195. 'install')
  196. INSTALL='1'
  197. ;;
  198. 'install-geodata')
  199. INSTALL_GEODATA='1'
  200. ;;
  201. 'remove')
  202. REMOVE='1'
  203. ;;
  204. 'help')
  205. HELP='1'
  206. ;;
  207. 'check')
  208. CHECK='1'
  209. ;;
  210. '--without-geodata')
  211. NO_GEODATA='1'
  212. ;;
  213. '--without-logfiles')
  214. NO_LOGFILES='1'
  215. ;;
  216. '--purge')
  217. PURGE='1'
  218. ;;
  219. '--version')
  220. if [[ -z "$2" ]]; then
  221. echo "error: Please specify the correct version."
  222. exit 1
  223. fi
  224. temp_version='1'
  225. SPECIFIED_VERSION="$2"
  226. shift
  227. ;;
  228. '-f' | '--force')
  229. FORCE='1'
  230. ;;
  231. '--beta')
  232. BETA='1'
  233. ;;
  234. '-l' | '--local')
  235. local_install='1'
  236. if [[ -z "$2" ]]; then
  237. echo "error: Please specify the correct local file."
  238. exit 1
  239. fi
  240. LOCAL_FILE="$2"
  241. shift
  242. ;;
  243. '-p' | '--proxy')
  244. if [[ -z "$2" ]]; then
  245. echo "error: Please specify the proxy server address."
  246. exit 1
  247. fi
  248. PROXY="$2"
  249. shift
  250. ;;
  251. '-u' | '--install-user')
  252. if [[ -z "$2" ]]; then
  253. echo "error: Please specify the install user.}"
  254. exit 1
  255. fi
  256. INSTALL_USER="$2"
  257. shift
  258. ;;
  259. '--reinstall')
  260. REINSTALL='1'
  261. ;;
  262. '--no-update-service')
  263. N_UP_SERVICE='1'
  264. ;;
  265. *)
  266. echo "$0: unknown option -- -"
  267. exit 1
  268. ;;
  269. esac
  270. shift
  271. done
  272. if ((INSTALL+INSTALL_GEODATA+HELP+CHECK+REMOVE==0)); then
  273. INSTALL='1'
  274. elif ((INSTALL+INSTALL_GEODATA+HELP+CHECK+REMOVE>1)); then
  275. echo 'You can only choose one action.'
  276. exit 1
  277. fi
  278. if [[ "$INSTALL" -eq '1' ]] && ((temp_version+local_install+REINSTALL+BETA>1)); then
  279. echo "--version,--reinstall,--beta and --local can't be used together."
  280. exit 1
  281. fi
  282. }
  283. check_install_user() {
  284. if [[ -z "$INSTALL_USER" ]]; then
  285. if [[ -f '/usr/local/bin/xray' ]]; then
  286. INSTALL_USER="$(grep '^[ '$'\t]*User[ '$'\t]*=' /etc/systemd/system/xray.service | tail -n 1 | awk -F = '{print $2}' | awk '{print $1}')"
  287. if [[ -z "$INSTALL_USER" ]]; then
  288. INSTALL_USER='root'
  289. fi
  290. else
  291. INSTALL_USER='nobody'
  292. fi
  293. fi
  294. if ! id $INSTALL_USER > /dev/null 2>&1; then
  295. echo "the user '$INSTALL_USER' is not effective"
  296. exit 1
  297. fi
  298. INSTALL_USER_UID="$(id -u $INSTALL_USER)"
  299. INSTALL_USER_GID="$(id -g $INSTALL_USER)"
  300. }
  301. install_software() {
  302. package_name="$1"
  303. file_to_detect="$2"
  304. type -P "$file_to_detect" > /dev/null 2>&1 && return
  305. if ${PACKAGE_MANAGEMENT_INSTALL} "$package_name" >/dev/null 2>&1; then
  306. echo "info: $package_name is installed."
  307. else
  308. echo "error: Installation of $package_name failed, please check your network."
  309. exit 1
  310. fi
  311. }
  312. get_current_version() {
  313. # Get the CURRENT_VERSION
  314. if [[ -f '/usr/local/bin/xray' ]]; then
  315. CURRENT_VERSION="$(/usr/local/bin/xray -version | awk 'NR==1 {print $2}')"
  316. CURRENT_VERSION="v${CURRENT_VERSION#v}"
  317. else
  318. CURRENT_VERSION=""
  319. fi
  320. }
  321. get_latest_version() {
  322. # Get Xray latest release version number
  323. local tmp_file
  324. tmp_file="$(mktemp)"
  325. if ! curl -x "${PROXY}" -sS -H "Accept: application/vnd.github.v3+json" -o "$tmp_file" 'https://api.github.com/repos/XTLS/Xray-core/releases/latest'; then
  326. "rm" "$tmp_file"
  327. echo 'error: Failed to get release list, please check your network.'
  328. exit 1
  329. fi
  330. RELEASE_LATEST="$(sed 'y/,/\n/' "$tmp_file" | grep 'tag_name' | awk -F '"' '{print $4}')"
  331. if [[ -z "$RELEASE_LATEST" ]]; then
  332. if grep -q "API rate limit exceeded" "$tmp_file"; then
  333. echo "error: github API rate limit exceeded"
  334. else
  335. echo "error: Failed to get the latest release version."
  336. echo "Welcome bug report:https://github.com/XTLS/Xray-install/issues"
  337. fi
  338. "rm" "$tmp_file"
  339. exit 1
  340. fi
  341. "rm" "$tmp_file"
  342. RELEASE_LATEST="v${RELEASE_LATEST#v}"
  343. if ! curl -x "${PROXY}" -sS -H "Accept: application/vnd.github.v3+json" -o "$tmp_file" 'https://api.github.com/repos/XTLS/Xray-core/releases'; then
  344. "rm" "$tmp_file"
  345. echo 'error: Failed to get release list, please check your network.'
  346. exit 1
  347. fi
  348. local releases_list
  349. releases_list=($(sed 'y/,/\n/' "$tmp_file" | grep 'tag_name' | awk -F '"' '{print $4}'))
  350. if [[ "${#releases_list[@]}" -eq '0' ]]; then
  351. if grep -q "API rate limit exceeded" "$tmp_file"; then
  352. echo "error: github API rate limit exceeded"
  353. else
  354. echo "error: Failed to get the latest release version."
  355. echo "Welcome bug report:https://github.com/XTLS/Xray-install/issues"
  356. fi
  357. "rm" "$tmp_file"
  358. exit 1
  359. fi
  360. local i
  361. for i in ${!releases_list[@]}
  362. do
  363. releases_list[$i]="v${releases_list[$i]#v}"
  364. grep -q "https://github.com/XTLS/Xray-core/releases/download/${releases_list[$i]}/Xray-linux-$MACHINE.zip" "$tmp_file" && break
  365. done
  366. "rm" "$tmp_file"
  367. PRE_RELEASE_LATEST="${releases_list[$i]}"
  368. }
  369. version_gt() {
  370. test "$(echo -e "$1\\n$2" | sort -V | head -n 1)" != "$1"
  371. }
  372. download_xray() {
  373. DOWNLOAD_LINK="https://github.com/XTLS/Xray-core/releases/download/$INSTALL_VERSION/Xray-linux-$MACHINE.zip"
  374. echo "Downloading Xray archive: $DOWNLOAD_LINK"
  375. if ! curl -x "${PROXY}" -R -H 'Cache-Control: no-cache' -o "$ZIP_FILE" "$DOWNLOAD_LINK"; then
  376. echo 'error: Download failed! Please check your network or try again.'
  377. return 1
  378. fi
  379. return 0
  380. echo "Downloading verification file for Xray archive: $DOWNLOAD_LINK.dgst"
  381. if ! curl -x "${PROXY}" -sSR -H 'Cache-Control: no-cache' -o "$ZIP_FILE.dgst" "$DOWNLOAD_LINK.dgst"; then
  382. echo 'error: Download failed! Please check your network or try again.'
  383. return 1
  384. fi
  385. if [[ "$(cat "$ZIP_FILE".dgst)" == 'Not Found' ]]; then
  386. echo 'error: This version does not support verification. Please replace with another version.'
  387. return 1
  388. fi
  389. # Verification of Xray archive
  390. CHECKSUM=$(cat "$ZIP_FILE".dgst | awk -F '= ' '/256=/ {print $2}')
  391. LOCALSUM=$(sha256sum "$ZIP_FILE" | awk '{printf $1}')
  392. if [[ "$CHECKSUM" != "$LOCALSUM" ]]; then
  393. echo 'error: SHA256 check failed! Please check your network or try again.'
  394. return 1
  395. fi
  396. }
  397. decompression() {
  398. if ! unzip -q "$1" -d "$TMP_DIRECTORY"; then
  399. echo 'error: Xray decompression failed.'
  400. "rm" -r "$TMP_DIRECTORY"
  401. echo "removed: $TMP_DIRECTORY"
  402. exit 1
  403. fi
  404. echo "info: Extract the Xray package to $TMP_DIRECTORY and prepare it for installation."
  405. }
  406. install_file() {
  407. NAME="$1"
  408. if [[ "$NAME" == 'xray' ]]; then
  409. install -m 755 "${TMP_DIRECTORY}/$NAME" "/usr/local/bin/$NAME"
  410. elif [[ "$NAME" == 'geoip.dat' ]] || [[ "$NAME" == 'geosite.dat' ]]; then
  411. install -m 644 "${TMP_DIRECTORY}/$NAME" "${DAT_PATH}/$NAME"
  412. fi
  413. }
  414. install_xray() {
  415. # Install Xray binary to /usr/local/bin/ and $DAT_PATH
  416. install_file xray
  417. # If the file exists, geoip.dat and geosite.dat will not be installed or updated
  418. if [[ "$NO_GEODATA" -eq '0' ]] && [[ ! -f "${DAT_PATH}/.undat" ]]; then
  419. install -d "$DAT_PATH"
  420. install_file geoip.dat
  421. install_file geosite.dat
  422. GEODATA='1'
  423. fi
  424. # Install Xray configuration file to $JSON_PATH
  425. # shellcheck disable=SC2153
  426. if [[ -z "$JSONS_PATH" ]] && [[ ! -d "$JSON_PATH" ]]; then
  427. install -d "$JSON_PATH"
  428. echo "{}" > "${JSON_PATH}/config.json"
  429. CONFIG_NEW='1'
  430. fi
  431. # Install Xray configuration file to $JSONS_PATH
  432. if [[ -n "$JSONS_PATH" ]] && [[ ! -d "$JSONS_PATH" ]]; then
  433. install -d "$JSONS_PATH"
  434. for BASE in 00_log 01_api 02_dns 03_routing 04_policy 05_inbounds 06_outbounds 07_transport 08_stats 09_reverse; do
  435. echo '{}' > "${JSONS_PATH}/${BASE}.json"
  436. done
  437. CONFDIR='1'
  438. fi
  439. # Used to store Xray log files
  440. if [[ "$NO_LOGFILES" -eq '0' ]]; then
  441. if [[ ! -d '/var/log/xray/' ]]; then
  442. install -d -m 700 -o "$INSTALL_USER_UID" -g "$INSTALL_USER_GID" /var/log/xray/
  443. install -m 600 -o "$INSTALL_USER_UID" -g "$INSTALL_USER_GID" /dev/null /var/log/xray/access.log
  444. install -m 600 -o "$INSTALL_USER_UID" -g "$INSTALL_USER_GID" /dev/null /var/log/xray/error.log
  445. LOG='1'
  446. else
  447. chown -R "$INSTALL_USER_UID:$INSTALL_USER_GID" /var/log/xray/
  448. fi
  449. fi
  450. }
  451. install_startup_service_file() {
  452. mkdir -p '/etc/systemd/system/xray.service.d'
  453. mkdir -p '/etc/systemd/system/[email protected]/'
  454. local temp_CapabilityBoundingSet="CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE"
  455. local temp_AmbientCapabilities="AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE"
  456. local temp_NoNewPrivileges="NoNewPrivileges=true"
  457. if [[ "$INSTALL_USER_UID" -eq '0' ]]; then
  458. temp_CapabilityBoundingSet="#${temp_CapabilityBoundingSet}"
  459. temp_AmbientCapabilities="#${temp_AmbientCapabilities}"
  460. temp_NoNewPrivileges="#${temp_NoNewPrivileges}"
  461. fi
  462. cat > /etc/systemd/system/xray.service << EOF
  463. [Unit]
  464. Description=Xray Service
  465. Documentation=https://github.com/xtls
  466. After=network.target nss-lookup.target
  467. [Service]
  468. User=$INSTALL_USER
  469. ${temp_CapabilityBoundingSet}
  470. ${temp_AmbientCapabilities}
  471. ${temp_NoNewPrivileges}
  472. ExecStart=/usr/local/bin/xray run -config /usr/local/etc/xray/config.json
  473. Restart=on-failure
  474. RestartPreventExitStatus=23
  475. LimitNPROC=10000
  476. LimitNOFILE=1000000
  477. [Install]
  478. WantedBy=multi-user.target
  479. EOF
  480. cat > /etc/systemd/system/[email protected] <<EOF
  481. [Unit]
  482. Description=Xray Service
  483. Documentation=https://github.com/xtls
  484. After=network.target nss-lookup.target
  485. [Service]
  486. User=$INSTALL_USER
  487. ${temp_CapabilityBoundingSet}
  488. ${temp_AmbientCapabilities}
  489. ${temp_NoNewPrivileges}
  490. ExecStart=/usr/local/bin/xray run -config /usr/local/etc/xray/%i.json
  491. Restart=on-failure
  492. RestartPreventExitStatus=23
  493. LimitNPROC=10000
  494. LimitNOFILE=1000000
  495. [Install]
  496. WantedBy=multi-user.target
  497. EOF
  498. chmod 644 /etc/systemd/system/xray.service /etc/systemd/system/[email protected]
  499. if [[ -n "$JSONS_PATH" ]]; then
  500. "rm" '/etc/systemd/system/xray.service.d/10-donot_touch_single_conf.conf' \
  501. '/etc/systemd/system/[email protected]/10-donot_touch_single_conf.conf'
  502. echo "# In case you have a good reason to do so, duplicate this file in the same directory and make your customizes there.
  503. # Or all changes you made will be lost! # Refer: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
  504. [Service]
  505. ExecStart=
  506. ExecStart=/usr/local/bin/xray run -confdir $JSONS_PATH" |
  507. tee '/etc/systemd/system/xray.service.d/10-donot_touch_multi_conf.conf' > \
  508. '/etc/systemd/system/[email protected]/10-donot_touch_multi_conf.conf'
  509. else
  510. "rm" '/etc/systemd/system/xray.service.d/10-donot_touch_multi_conf.conf' \
  511. '/etc/systemd/system/[email protected]/10-donot_touch_multi_conf.conf'
  512. echo "# In case you have a good reason to do so, duplicate this file in the same directory and make your customizes there.
  513. # Or all changes you made will be lost! # Refer: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
  514. [Service]
  515. ExecStart=
  516. ExecStart=/usr/local/bin/xray run -config ${JSON_PATH}/config.json" > \
  517. '/etc/systemd/system/xray.service.d/10-donot_touch_single_conf.conf'
  518. echo "# In case you have a good reason to do so, duplicate this file in the same directory and make your customizes there.
  519. # Or all changes you made will be lost! # Refer: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
  520. [Service]
  521. ExecStart=
  522. ExecStart=/usr/local/bin/xray run -config ${JSON_PATH}/%i.json" > \
  523. '/etc/systemd/system/[email protected]/10-donot_touch_single_conf.conf'
  524. fi
  525. echo "info: Systemd service files have been installed successfully!"
  526. echo "${red}warning: ${green}The following are the actual parameters for the xray service startup."
  527. echo "${red}warning: ${green}Please make sure the configuration file path is correctly set.${reset}"
  528. systemd_cat_config /etc/systemd/system/xray.service
  529. # shellcheck disable=SC2154
  530. if [[ x"${check_all_service_files:0:1}" = x'y' ]]; then
  531. echo
  532. echo
  533. systemd_cat_config /etc/systemd/system/[email protected]
  534. fi
  535. systemctl daemon-reload
  536. SYSTEMD='1'
  537. }
  538. start_xray() {
  539. if [[ -f '/etc/systemd/system/xray.service' ]]; then
  540. systemctl start "${XRAY_CUSTOMIZE:-xray}"
  541. sleep 1s
  542. if systemctl -q is-active "${XRAY_CUSTOMIZE:-xray}"; then
  543. echo 'info: Start the Xray service.'
  544. else
  545. echo 'error: Failed to start Xray service.'
  546. exit 1
  547. fi
  548. fi
  549. }
  550. stop_xray() {
  551. XRAY_CUSTOMIZE="$(systemctl list-units | grep 'xray@' | awk -F ' ' '{print $1}')"
  552. if [[ -z "$XRAY_CUSTOMIZE" ]]; then
  553. local xray_daemon_to_stop='xray.service'
  554. else
  555. local xray_daemon_to_stop="$XRAY_CUSTOMIZE"
  556. fi
  557. if ! systemctl stop "$xray_daemon_to_stop"; then
  558. echo 'error: Stopping the Xray service failed.'
  559. exit 1
  560. fi
  561. echo 'info: Stop the Xray service.'
  562. }
  563. install_geodata() {
  564. download_geodata() {
  565. if ! curl -x "${PROXY}" -R -H 'Cache-Control: no-cache' -o "${dir_tmp}/${2}" "${1}"; then
  566. echo 'error: Download failed! Please check your network or try again.'
  567. exit 1
  568. fi
  569. if ! curl -x "${PROXY}" -R -H 'Cache-Control: no-cache' -o "${dir_tmp}/${2}.sha256sum" "${1}.sha256sum"; then
  570. echo 'error: Download failed! Please check your network or try again.'
  571. exit 1
  572. fi
  573. }
  574. local download_link_geoip="https://github.com/v2fly/geoip/releases/latest/download/geoip.dat"
  575. local download_link_geosite="https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat"
  576. local file_ip='geoip.dat'
  577. local file_dlc='dlc.dat'
  578. local file_site='geosite.dat'
  579. local dir_tmp
  580. dir_tmp="$(mktemp -d)"
  581. [[ "$XRAY_IS_INSTALLED_BEFORE_RUNNING_SCRIPT" -eq '0' ]] && echo "warning: Xray was not installed"
  582. download_geodata $download_link_geoip $file_ip
  583. download_geodata $download_link_geosite $file_dlc
  584. cd "${dir_tmp}" || exit
  585. for i in "${dir_tmp}"/*.sha256sum; do
  586. if ! sha256sum -c "${i}"; then
  587. echo 'error: Check failed! Please check your network or try again.'
  588. exit 1
  589. fi
  590. done
  591. cd - > /dev/null
  592. install -d "$DAT_PATH"
  593. install -m 644 "${dir_tmp}"/${file_dlc} "${DAT_PATH}"/${file_site}
  594. install -m 644 "${dir_tmp}"/${file_ip} "${DAT_PATH}"/${file_ip}
  595. rm -r "${dir_tmp}"
  596. exit 0
  597. }
  598. check_update() {
  599. if [[ "$XRAY_IS_INSTALLED_BEFORE_RUNNING_SCRIPT" -eq '1' ]]; then
  600. get_current_version
  601. echo "info: The current version of Xray is $CURRENT_VERSION ."
  602. else
  603. echo 'warning: Xray is not installed.'
  604. fi
  605. get_latest_version
  606. echo "info: The latest release version of Xray is $RELEASE_LATEST ."
  607. echo "info: The latest pre-release/release version of Xray is $PRE_RELEASE_LATEST ."
  608. exit 0
  609. }
  610. remove_xray() {
  611. if systemctl list-unit-files | grep -qw 'xray'; then
  612. if [[ -n "$(pidof xray)" ]]; then
  613. stop_xray
  614. fi
  615. local delete_files=('/usr/local/bin/xray' '/etc/systemd/system/xray.service' '/etc/systemd/system/[email protected]' '/etc/systemd/system/xray.service.d' '/etc/systemd/system/[email protected]')
  616. [[ -d "$DAT_PATH" ]] && delete_files+=("$DAT_PATH")
  617. if [[ "$PURGE" -eq '1' ]]; then
  618. if [[ -z "$JSONS_PATH" ]]; then
  619. delete_files+=("$JSON_PATH")
  620. else
  621. delete_files+=("$JSONS_PATH")
  622. fi
  623. [[ -d '/var/log/xray' ]] && delete_files+=('/var/log/xray')
  624. fi
  625. systemctl disable xray
  626. if ! ("rm" -r "${delete_files[@]}"); then
  627. echo 'error: Failed to remove Xray.'
  628. exit 1
  629. else
  630. for i in ${!delete_files[@]}
  631. do
  632. echo "removed: ${delete_files[$i]}"
  633. done
  634. systemctl daemon-reload
  635. echo "You may need to execute a command to remove dependent software: $PACKAGE_MANAGEMENT_REMOVE curl unzip"
  636. echo 'info: Xray has been removed.'
  637. if [[ "$PURGE" -eq '0' ]]; then
  638. echo 'info: If necessary, manually delete the configuration and log files.'
  639. if [[ -n "$JSONS_PATH" ]]; then
  640. echo "info: e.g., $JSONS_PATH and /var/log/xray/ ..."
  641. else
  642. echo "info: e.g., $JSON_PATH and /var/log/xray/ ..."
  643. fi
  644. fi
  645. exit 0
  646. fi
  647. else
  648. echo 'error: Xray is not installed.'
  649. exit 1
  650. fi
  651. }
  652. # Explanation of parameters in the script
  653. show_help() {
  654. echo "usage: $0 ACTION [OPTION]..."
  655. echo
  656. echo 'ACTION:'
  657. echo ' install Install/Update Xray'
  658. echo ' install-geodata Install/Update geoip.dat and geosite.dat only'
  659. echo ' remove Remove Xray'
  660. echo ' help Show help'
  661. echo ' check Check if Xray can be updated'
  662. echo 'If no action is specified, then install will be selected'
  663. echo
  664. echo 'OPTION:'
  665. echo ' install:'
  666. echo ' --version Install the specified version of Xray, e.g., --version v1.0.0'
  667. echo ' -f, --force Force install even though the versions are same'
  668. echo ' --beta Install the pre-release version if it is exist'
  669. echo ' -l, --local Install Xray from a local file'
  670. echo ' -p, --proxy Download through a proxy server, e.g., -p http://127.0.0.1:8118 or -p socks5://127.0.0.1:1080'
  671. echo ' -u, --install-user Install Xray in specified user, e.g, -u root'
  672. echo ' --reinstall Reinstall current Xray version'
  673. echo " --no-update-service Don't change service files if they are exist"
  674. echo " --without-geodata Don't install/update geoip.dat and geosite.dat"
  675. echo " --without-logfiles Don't install /var/log/xray"
  676. echo ' install-geodata:'
  677. echo ' -p, --proxy Download through a proxy server'
  678. echo ' remove:'
  679. echo ' --purge Remove all the Xray files, include logs, configs, etc'
  680. echo ' check:'
  681. echo ' -p, --proxy Check new version through a proxy server'
  682. exit 0
  683. }
  684. main() {
  685. check_if_running_as_root
  686. identify_the_operating_system_and_architecture
  687. judgment_parameters "$@"
  688. install_software "$package_provide_tput" 'tput'
  689. red=$(tput setaf 1)
  690. green=$(tput setaf 2)
  691. aoi=$(tput setaf 6)
  692. reset=$(tput sgr0)
  693. # Parameter information
  694. [[ "$HELP" -eq '1' ]] && show_help
  695. [[ "$CHECK" -eq '1' ]] && check_update
  696. [[ "$REMOVE" -eq '1' ]] && remove_xray
  697. [[ "$INSTALL_GEODATA" -eq '1' ]] && install_geodata
  698. # Check if the user is effective
  699. check_install_user
  700. # Two very important variables
  701. TMP_DIRECTORY="$(mktemp -d)"
  702. ZIP_FILE="${TMP_DIRECTORY}/Xray-linux-$MACHINE.zip"
  703. # Install Xray from a local file, but still need to make sure the network is available
  704. if [[ -n "$LOCAL_FILE" ]]; then
  705. echo 'warn: Install Xray from a local file, but still need to make sure the network is available.'
  706. echo -n 'warn: Please make sure the file is valid because we cannot confirm it. (Press any key) ...'
  707. read -r
  708. install_software 'unzip' 'unzip'
  709. decompression "$LOCAL_FILE"
  710. else
  711. get_current_version
  712. if [[ "$REINSTALL" -eq '1' ]]; then
  713. if [[ -z "$CURRENT_VERSION" ]]; then
  714. echo "error: Xray is not installed"
  715. exit 1
  716. fi
  717. INSTALL_VERSION="$CURRENT_VERSION"
  718. echo "info: Reinstalling Xray $CURRENT_VERSION"
  719. elif [[ -n "$SPECIFIED_VERSION" ]]; then
  720. SPECIFIED_VERSION="v${SPECIFIED_VERSION#v}"
  721. if [[ "$CURRENT_VERSION" == "$SPECIFIED_VERSION" ]] && [[ "$FORCE" -eq '0' ]]; then
  722. echo "info: The current version is same as the specified version. The version is $CURRENT_VERSION ."
  723. exit 0
  724. fi
  725. INSTALL_VERSION="$SPECIFIED_VERSION"
  726. echo "info: Installing specified Xray version $INSTALL_VERSION for $(uname -m)"
  727. else
  728. install_software 'curl' 'curl'
  729. get_latest_version
  730. if [[ "$BETA" -eq '0' ]]; then
  731. INSTALL_VERSION="$RELEASE_LATEST"
  732. else
  733. INSTALL_VERSION="$PRE_RELEASE_LATEST"
  734. fi
  735. if ! version_gt "$INSTALL_VERSION" "$CURRENT_VERSION" && [[ "$FORCE" -eq '0' ]]; then
  736. echo "info: No new version. The current version of Xray is $CURRENT_VERSION ."
  737. exit 0
  738. fi
  739. echo "info: Installing Xray $INSTALL_VERSION for $(uname -m)"
  740. fi
  741. install_software 'curl' 'curl'
  742. install_software 'unzip' 'unzip'
  743. if ! download_xray; then
  744. "rm" -r "$TMP_DIRECTORY"
  745. echo "removed: $TMP_DIRECTORY"
  746. exit 1
  747. fi
  748. decompression "$ZIP_FILE"
  749. fi
  750. # Determine if Xray is running
  751. if systemctl list-unit-files | grep -qw 'xray'; then
  752. if [[ -n "$(pidof xray)" ]]; then
  753. stop_xray
  754. XRAY_RUNNING='1'
  755. fi
  756. fi
  757. install_xray
  758. ([[ "$N_UP_SERVICE" -eq '1' ]] && [[ -f '/etc/systemd/system/xray.service' ]]) || install_startup_service_file
  759. echo 'installed: /usr/local/bin/xray'
  760. # If the file exists, the content output of installing or updating geoip.dat and geosite.dat will not be displayed
  761. if [[ "$GEODATA" -eq '1' ]]; then
  762. echo "installed: ${DAT_PATH}/geoip.dat"
  763. echo "installed: ${DAT_PATH}/geosite.dat"
  764. fi
  765. if [[ "$CONFIG_NEW" -eq '1' ]]; then
  766. echo "installed: ${JSON_PATH}/config.json"
  767. fi
  768. if [[ "$CONFDIR" -eq '1' ]]; then
  769. echo "installed: ${JSON_PATH}/00_log.json"
  770. echo "installed: ${JSON_PATH}/01_api.json"
  771. echo "installed: ${JSON_PATH}/02_dns.json"
  772. echo "installed: ${JSON_PATH}/03_routing.json"
  773. echo "installed: ${JSON_PATH}/04_policy.json"
  774. echo "installed: ${JSON_PATH}/05_inbounds.json"
  775. echo "installed: ${JSON_PATH}/06_outbounds.json"
  776. echo "installed: ${JSON_PATH}/07_transport.json"
  777. echo "installed: ${JSON_PATH}/08_stats.json"
  778. echo "installed: ${JSON_PATH}/09_reverse.json"
  779. fi
  780. if [[ "$LOG" -eq '1' ]]; then
  781. echo 'installed: /var/log/xray/'
  782. echo 'installed: /var/log/xray/access.log'
  783. echo 'installed: /var/log/xray/error.log'
  784. fi
  785. if [[ "$SYSTEMD" -eq '1' ]]; then
  786. echo 'installed: /etc/systemd/system/xray.service'
  787. echo 'installed: /etc/systemd/system/[email protected]'
  788. fi
  789. "rm" -r "$TMP_DIRECTORY"
  790. echo "removed: $TMP_DIRECTORY"
  791. get_current_version
  792. echo "info: Xray $CURRENT_VERSION is installed."
  793. echo "You may need to execute a command to remove dependent software: $PACKAGE_MANAGEMENT_REMOVE curl unzip"
  794. if [[ "$XRAY_IS_INSTALLED_BEFORE_RUNNING_SCRIPT" -eq '1' ]] && [[ "$FORCE" -eq '0' ]] && [[ "$REINSTALL" -eq '0' ]]; then
  795. [[ "$XRAY_RUNNING" -eq '1' ]] && start_xray
  796. else
  797. systemctl start xray
  798. systemctl enable xray
  799. sleep 1s
  800. if systemctl -q is-active xray; then
  801. echo "info: Enable and start the Xray service"
  802. else
  803. echo "warning: Failed to enable and start the Xray service"
  804. fi
  805. fi
  806. }
  807. main "$@"