install-release.sh 30 KB

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