install.sh 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. #!/usr/bin/env bash
  2. export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
  3. export TMOUT=0
  4. current_dir=$(cd `dirname "${BASH_SOURCE}"` ; pwd)
  5. log_path="${current_dir}"/install.log
  6. function InstallLog(){
  7. [[ $# -ne 2 ]] && return 0
  8. case $1 in
  9. -E|-e)
  10. echo -e "$(date +%Y-%m-%d\ %H:%M:%S) [ERROR] [${FUNCNAME[2]}]: ${2}" >> "${log_path}"
  11. echo -e "\033[1;31m$(date +%Y-%m-%d\ %H:%M:%S) [ERROR] [${FUNCNAME[1]}]: ${2}\033[0m"
  12. ;;
  13. -I|-i)
  14. echo -e "$(date +%Y-%m-%d\ %H:%M:%S) [INFO] [${FUNCNAME[2]}]: ${2}" >> "${log_path}"
  15. echo -e "\033[1;32m$(date +%Y-%m-%d\ %H:%M:%S) [INFO] [${FUNCNAME[1]}]: ${2}\033[0m"
  16. ;;
  17. -C|-c)
  18. echo -e "$(date +%Y-%m-%d\ %H:%M:%S) [INPUT] [${FUNCNAME[2]}]: ${2}" >> "${log_path}"
  19. echo -e "\033[1;34m$(date +%Y-%m-%d\ %H:%M:%S) [INPUT] [${FUNCNAME[1]}]: ${2}\033[0m"
  20. ;;
  21. -W|-w)
  22. echo -e "$(date +%Y-%m-%d\ %H:%M:%S) [WARN] [${FUNCNAME[2]}]: ${2}" >> "${log_path}"
  23. echo -e "\033[1;33m$(date +%Y-%m-%d\ %H:%M:%S) [WARN] [${FUNCNAME[1]}]: ${2}\033[0m"
  24. ;;
  25. *)
  26. echo -e "$(date +%Y-%m-%d\ %H:%M:%S)[Other] [${FUNCNAME[2]}]: ${2}" >> "${log_path}"
  27. echo -e "$(date +%Y-%m-%d\ %H:%M:%S)[Other] [${FUNCNAME[1]}]: ${2}"
  28. esac
  29. }
  30. function CheckRunning() {
  31. TMPFILE=/tmp/install.run
  32. if [ -e $TMPFILE ]; then
  33. InstallLog -e "Other instance is running!"
  34. exit 0
  35. else
  36. touch $TMPFILE
  37. chmod 600 $TMPFILE
  38. fi
  39. # shellcheck disable=SC2064
  40. trap "rm -f ${TMPFILE}; exit" 0 1 2 3 15
  41. if [ "$(id -u)" != "0" ]; then
  42. InstallLog -e "Require user root to run the script."
  43. exit 1
  44. fi
  45. }
  46. CheckRunning
  47. Kill_PM()
  48. {
  49. if ps aux | grep -E "yum|dnf" | grep -qv "grep"; then
  50. kill -9 $(ps -ef|grep -E "yum|dnf"|grep -v grep|awk '{print $2}')
  51. if [ -s /var/run/yum.pid ]; then
  52. rm -f /var/run/yum.pid
  53. fi
  54. elif ps aux | grep -E "apt-get|dpkg|apt" | grep -qv "grep"; then
  55. kill -9 $(ps -ef|grep -E "apt-get|apt|dpkg"|grep -v grep|awk '{print $2}')
  56. if [[ -s /var/lib/dpkg/lock-frontend || -s /var/lib/dpkg/lock ]]; then
  57. rm -f /var/lib/dpkg/lock-frontend
  58. rm -f /var/lib/dpkg/lock
  59. dpkg --configure -a
  60. fi
  61. fi
  62. }
  63. Press_Start()
  64. {
  65. echo ""
  66. InstallLog -i "Press any key to start...or Press Ctrl+c to cancel"
  67. OLDCONFIG=`stty -g`
  68. stty -icanon -echo min 1 time 0
  69. dd count=1 2>/dev/null
  70. stty ${OLDCONFIG}
  71. }
  72. Install_LSB()
  73. {
  74. echo "[+] Installing lsb..."
  75. if [ "$PM" == "yum" ]; then
  76. yum -y install redhat-lsb
  77. elif [ "$PM" == "apt" ]; then
  78. apt-get update
  79. apt-get --no-install-recommends install -y lsb-release
  80. fi
  81. }
  82. Get_Dist_Version()
  83. {
  84. if command -v lsb_release >/dev/null 2>&1; then
  85. DISTRO_Version=$(lsb_release -sr)
  86. elif [ -f /etc/lsb-release ]; then
  87. . /etc/lsb-release
  88. DISTRO_Version="$DISTRIB_RELEASE"
  89. elif [ -f /etc/os-release ]; then
  90. . /etc/os-release
  91. DISTRO_Version="$VERSION_ID"
  92. fi
  93. if [[ "${DISTRO}" = "" || "${DISTRO_Version}" = "" ]]; then
  94. if command -v python2 >/dev/null 2>&1; then
  95. DISTRO_Version=$(python2 -c 'import platform; print platform.linux_distribution()[1]')
  96. elif command -v python3 >/dev/null 2>&1; then
  97. DISTRO_Version=$(python3 -c 'import platform; print(platform.linux_distribution()[1])')
  98. else
  99. Install_LSB
  100. DISTRO_Version=`lsb_release -rs`
  101. fi
  102. fi
  103. printf -v "${DISTRO}_Version" '%s' "${DISTRO_Version}"
  104. }
  105. Get_Dist_Name()
  106. {
  107. if grep -Eqi "Alibaba" /etc/issue || grep -Eq "Alibaba Cloud Linux" /etc/*-release; then
  108. DISTRO='Alibaba'
  109. PM='yum'
  110. elif grep -Eqi "Aliyun" /etc/issue || grep -Eq "Aliyun Linux" /etc/*-release; then
  111. DISTRO='Aliyun'
  112. PM='yum'
  113. elif grep -Eqi "Amazon Linux" /etc/issue || grep -Eq "Amazon Linux" /etc/*-release; then
  114. DISTRO='Amazon'
  115. PM='yum'
  116. elif grep -Eqi "Fedora" /etc/issue || grep -Eq "Fedora" /etc/*-release; then
  117. DISTRO='Fedora'
  118. PM='yum'
  119. elif grep -Eqi "Oracle Linux" /etc/issue || grep -Eq "Oracle Linux" /etc/*-release; then
  120. DISTRO='Oracle'
  121. PM='yum'
  122. elif grep -Eqi "rockylinux" /etc/issue || grep -Eq "Rocky Linux" /etc/*-release; then
  123. DISTRO='Rocky'
  124. PM='yum'
  125. elif grep -Eqi "almalinux" /etc/issue || grep -Eq "AlmaLinux" /etc/*-release; then
  126. DISTRO='Alma'
  127. PM='yum'
  128. elif grep -Eqi "openEuler" /etc/issue || grep -Eq "openEuler" /etc/*-release; then
  129. DISTRO='openEuler'
  130. PM='yum'
  131. elif grep -Eqi "Anolis OS" /etc/issue || grep -Eq "Anolis OS" /etc/*-release; then
  132. DISTRO='Anolis'
  133. PM='yum'
  134. elif grep -Eqi "Kylin Linux Advanced Server" /etc/issue || grep -Eq "Kylin Linux Advanced Server" /etc/*-release; then
  135. DISTRO='Kylin'
  136. PM='yum'
  137. elif grep -Eqi "OpenCloudOS" /etc/issue || grep -Eq "OpenCloudOS" /etc/*-release; then
  138. DISTRO='OpenCloudOS'
  139. PM='yum'
  140. elif grep -Eqi "Huawei Cloud EulerOS" /etc/issue || grep -Eq "Huawei Cloud EulerOS" /etc/*-release; then
  141. DISTRO='HCE'
  142. PM='yum'
  143. elif grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then
  144. DISTRO='CentOS'
  145. PM='yum'
  146. if grep -Eq "CentOS Stream" /etc/*-release; then
  147. isCentosStream='y'
  148. fi
  149. elif grep -Eqi "Red Hat Enterprise Linux" /etc/issue || grep -Eq "Red Hat Enterprise Linux" /etc/*-release; then
  150. DISTRO='RHEL'
  151. PM='yum'
  152. elif grep -Eqi "Ubuntu" /etc/issue || grep -Eq "Ubuntu" /etc/*-release; then
  153. DISTRO='Ubuntu'
  154. PM='apt'
  155. elif grep -Eqi "Raspbian" /etc/issue || grep -Eq "Raspbian" /etc/*-release; then
  156. DISTRO='Raspbian'
  157. PM='apt'
  158. elif grep -Eqi "Deepin" /etc/issue || grep -Eq "Deepin" /etc/*-release; then
  159. DISTRO='Deepin'
  160. PM='apt'
  161. elif grep -Eqi "Mint" /etc/issue || grep -Eq "Mint" /etc/*-release; then
  162. DISTRO='Mint'
  163. PM='apt'
  164. elif grep -Eqi "Kali" /etc/issue || grep -Eq "Kali" /etc/*-release; then
  165. DISTRO='Kali'
  166. PM='apt'
  167. elif grep -Eqi "Debian" /etc/issue || grep -Eq "Debian" /etc/*-release; then
  168. DISTRO='Debian'
  169. PM='apt'
  170. elif grep -Eqi "UnionTech OS|UOS" /etc/issue || grep -Eq "UnionTech OS|UOS" /etc/*-release; then
  171. DISTRO='UOS'
  172. if command -v apt >/dev/null 2>&1; then
  173. PM='apt'
  174. elif command -v yum >/dev/null 2>&1; then
  175. PM='yum'
  176. fi
  177. elif grep -Eqi "Kylin Linux Desktop" /etc/issue || grep -Eq "Kylin Linux Desktop" /etc/*-release; then
  178. DISTRO='Kylin'
  179. PM='apt'
  180. else
  181. DISTRO='unknow'
  182. fi
  183. Get_OS_Bit
  184. }
  185. Get_RHEL_Version()
  186. {
  187. Get_Dist_Name
  188. if [ "${DISTRO}" = "RHEL" ]; then
  189. if grep -Eqi "release 5." /etc/redhat-release; then
  190. echo "Current Version: RHEL Ver 5"
  191. RHEL_Ver='5'
  192. elif grep -Eqi "release 6." /etc/redhat-release; then
  193. echo "Current Version: RHEL Ver 6"
  194. RHEL_Ver='6'
  195. elif grep -Eqi "release 7." /etc/redhat-release; then
  196. echo "Current Version: RHEL Ver 7"
  197. RHEL_Ver='7'
  198. elif grep -Eqi "release 8." /etc/redhat-release; then
  199. echo "Current Version: RHEL Ver 8"
  200. RHEL_Ver='8'
  201. elif grep -Eqi "release 9." /etc/redhat-release; then
  202. echo "Current Version: RHEL Ver 9"
  203. RHEL_Ver='9'
  204. fi
  205. RHEL_Version="$(cat /etc/redhat-release | sed 's/.*release\ //' | sed 's/\ .*//')"
  206. fi
  207. }
  208. Get_OS_Bit()
  209. {
  210. if [[ `getconf WORD_BIT` = '32' && `getconf LONG_BIT` = '64' ]] ; then
  211. Is_64bit='y'
  212. ARCH='x86_64'
  213. DB_ARCH='x86_64'
  214. else
  215. Is_64bit='n'
  216. ARCH='i386'
  217. DB_ARCH='i686'
  218. fi
  219. if uname -m | grep -Eqi "arm|aarch64"; then
  220. Is_ARM='y'
  221. if uname -m | grep -Eqi "armv7|armv6"; then
  222. ARCH='armhf'
  223. elif uname -m | grep -Eqi "aarch64"; then
  224. ARCH='aarch64'
  225. DB_ARCH='aarch64'
  226. else
  227. ARCH='arm'
  228. fi
  229. fi
  230. }
  231. Get_Server_Type()
  232. {
  233. if [[ $(hostname) =~ "iZbp" ]]
  234. then
  235. SERVER_TYPE="aliyun"
  236. elif [[ $(hostname) =~ "lacew" ]]
  237. then
  238. SERVER_TYPE="aliyun"
  239. elif [[ $(hostname) =~ "VM-" ]]
  240. then
  241. SERVER_TYPE="qcloud"
  242. else
  243. SERVER_TYPE="unknown"
  244. fi
  245. }
  246. PressInstall() {
  247. InstallLog -I "按任意键开始安装,按Ctrl+C中止安装"
  248. local OLDCONFIG
  249. OLDCONFIG=$(stty -g)
  250. stty cbreak
  251. # dd if=/dev/tty bs=1 count=1 2> /dev/null
  252. stty -raw
  253. stty echo
  254. # stty -icanon -echo min 1 time 0
  255. dd count=1 2>/dev/null
  256. stty "${OLDCONFIG}"
  257. }
  258. #检测端口
  259. function CheckPort() {
  260. local port
  261. port=$1
  262. InstallLog -I "检测端口 [$port]"
  263. local checkResult
  264. checkResult=$(netstat -tlpn | grep "\b$port\b")
  265. if [ -n "$checkResult" ]; then
  266. InstallLog -E "端口 $port 被占用"
  267. exit 1
  268. fi
  269. }
  270. function CheckEmpty() {
  271. if [ -z "$1" ]; then
  272. InstallLog -E "$2"
  273. exit 1
  274. fi
  275. }
  276. #检查API
  277. CheckAPI() {
  278. # shellcheck disable=SC1083
  279. local code
  280. code=$(curl -I -m 5 -X POST -o /dev/null -s -w "%{http_code}" "$1")
  281. if [ "${code}" != 200 ]; then
  282. code=$(curl -I -m 5 -o /dev/null -s -w "%{http_code}" "$1&check")
  283. if [ "${code}" != 200 ]; then
  284. InstallLog -E "API $1 检查失败,返回代码 ${code}, 中止安装"
  285. exit
  286. else
  287. InstallLog -I "API $1 检查通过"
  288. fi
  289. else
  290. InstallLog -I "API $1 检查通过"
  291. fi
  292. }
  293. #更新repo源
  294. function UpdateRepo() {
  295. Get_Dist_Name
  296. Get_Server_Type
  297. local install=0
  298. InstallLog -I "修改 ${DISTRO} 镜像源,服务器类型 ${SERVER_TYPE}"
  299. if [ "${DISTRO}" == "Debian" ]; then
  300. #阿里云
  301. if [[ ${SERVER_TYPE} == "aliyun" ]]; then
  302. if [ -f /etc/apt/sources.list ] && grep -Eqi "mirrors.cloud.aliyuncs.com" /etc/apt/sources.list; then
  303. InstallLog -i "Aliyun apt repo already installed, skip..."
  304. else
  305. InstallLog -i "Change /etc/apt/sources.list to mirrors.cloud.aliyuncs.com"
  306. sed -i "s#deb https\?://.*/debian#deb http://mirrors.cloud.aliyuncs.com/debian#" /etc/apt/sources.list
  307. sed -i "s/^deb-src/#deb-src/" /etc/apt/sources.list
  308. apt update
  309. fi
  310. #腾讯云
  311. elif [[ ${SERVER_TYPE} == "qcloud" ]]; then
  312. if [ -f /etc/apt/sources.list ] && grep -Eqi "mirrors.tencentyun.com" /etc/apt/sources.list; then
  313. InstallLog -i "Tencent apt repo already installed, skip..."
  314. else
  315. InstallLog -i "Change /etc/apt/sources.list to mirrors.tencentyun.com"
  316. sed -i "s#deb https\?://.*/debian#deb http://mirrors.tencentyun.com/debian#" /etc/apt/sources.list
  317. sed -i "s/^deb-src/#deb-src/" /etc/apt/sources.list
  318. apt update
  319. fi
  320. fi
  321. elif [ "${DISTRO}" == "Ubuntu" ]; then
  322. #阿里云
  323. if [[ ${SERVER_TYPE} == "aliyun" ]]; then
  324. if [ -f /etc/apt/sources.list ] && grep -Eqi "mirrors.cloud.aliyuncs.com" /etc/apt/sources.list; then
  325. InstallLog -i "Aliyun apt repo already installed, skip..."
  326. else
  327. InstallLog -i "Change /etc/apt/sources.list to mirrors.cloud.aliyuncs.com"
  328. sed -i "s#deb http\?://.*/ubuntu/#deb http://mirrors.cloud.aliyuncs.com/ubuntu/#" /etc/apt/sources.list
  329. sed -i "s/^deb-src/#deb-src/" /etc/apt/sources.list
  330. apt update
  331. fi
  332. #腾讯云
  333. elif [[ ${SERVER_TYPE} == "qcloud" ]]; then
  334. if [ -f /etc/apt/sources.list ] && grep -Eqi "mirrors.tencentyun.com" /etc/apt/sources.list; then
  335. InstallLog -i "Tencent apt repo already installed, skip..."
  336. else
  337. InstallLog -i "Change /etc/apt/sources.list to mirrors.tencentyun.com"
  338. sed -i "s#deb https\?://.*/ubuntu#deb http://mirrors.tencentyun.com/ubuntu#" /etc/apt/sources.list
  339. sed -i "s/^deb-src/#deb-src/" /etc/apt/sources.list
  340. apt update
  341. fi
  342. fi
  343. elif [ "${DISTRO}" == "CentOS" ]; then
  344. #阿里云
  345. if [[ ${SERVER_TYPE} == "aliyun" ]]; then
  346. if [ -f /etc/yum.repos.d/CentOS-Base.repo ] && grep -Eqi "mirrors.cloud.aliyuncs.com" /etc/yum.repos.d/CentOS-Base.repo; then
  347. InstallLog -i "Aliyun yum repo already installed, skip..."
  348. else
  349. # shellcheck disable=SC2004
  350. install=$(($install + 1))
  351. wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.cloud.aliyuncs.com/repo/Centos-7.repo
  352. fi
  353. if [ -f /etc/yum.repos.d/ius.repo ] && grep -Eqi "mirrors.cloud.aliyuncs.com" /etc/yum.repos.d/ius.repo; then
  354. InstallLog -i "Aliyun ius repo already installed, skip..."
  355. else
  356. # shellcheck disable=SC2004
  357. install=$(($install + 1))
  358. yum install -y http://mirrors.cloud.aliyuncs.com/ius/ius-release-el7.rpm
  359. sed -i 's|baseurl.*/ius|baseurl=http://mirrors.cloud.aliyuncs.com/ius|g' /etc/yum.repos.d/ius*
  360. rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
  361. fi
  362. if [ -f /etc/yum.repos.d/epel.repo ] && grep -Eqi "mirrors.cloud.aliyuncs.com" /etc/yum.repos.d/epel.repo; then
  363. InstallLog -i "Aliyun epel repo already installed, skip..."
  364. else
  365. # shellcheck disable=SC2004
  366. install=$(($install + 1))
  367. wget -O /etc/yum.repos.d/epel.repo http://mirrors.cloud.aliyuncs.com/repo/epel-7.repo
  368. sed -i 's|#\?baseurl.*/epel|baseurl=http://mirrors.cloud.aliyuncs.com/epel|' /etc/yum.repos.d/epel*
  369. fi
  370. elif [[ ${SERVER_TYPE} == "qcloud" ]]; then
  371. #腾讯云
  372. if [ -f /etc/yum.repos.d/CentOS-Base.repo ] && grep -Eqi "mirrors.cloud.tencent.com" /etc/yum.repos.d/CentOS-Base.repo; then
  373. InstallLog -i "Tencent yum repo already installed, skip..."
  374. else
  375. # shellcheck disable=SC2004
  376. install=$(($install + 1))
  377. wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.cloud.tencent.com/repo/centos7_base.repo
  378. fi
  379. if [ -f /etc/yum.repos.d/ius.repo ] && grep -Eqi "mirrors.cloud.tencent.com" /etc/yum.repos.d/ius.repo; then
  380. InstallLog -i "Tencent ius repo already installed, skip..."
  381. else
  382. # shellcheck disable=SC2004
  383. install=$(($install + 1))
  384. yum install -y https://mirrors.cloud.tencent.com/ius/ius-release-el7.rpm
  385. rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
  386. sed -i 's|baseurl.*/ius|baseurl=http://mirrors.cloud.tencent.com/ius|g' /etc/yum.repos.d/ius*
  387. fi
  388. if [ -f /etc/yum.repos.d/epel.repo ] && grep -Eqi "mirrors.cloud.tencent.com" /etc/yum.repos.d/epel.repo; then
  389. InstallLog -i "Tencent epel repo already installed, skip..."
  390. else
  391. # shellcheck disable=SC2004
  392. install=$(($install + 1))
  393. wget -O /etc/yum.repos.d/epel.repo http://mirrors.cloud.tencent.com/repo/epel-7.repo
  394. sed -i 's|baseurl.*/epel|baseurl=http://mirrors.cloud.tencent.com/epel|g' /etc/yum.repos.d/epel*
  395. fi
  396. elif [[ ${SERVER_TYPE} == "unknown" ]]; then
  397. InstallLog -e "服务器类型不支持"
  398. exit
  399. fi
  400. if [ "$install" -gt 0 ]; then
  401. if [ "$PM" == "yum" ];then
  402. yum clean all
  403. yum makecache
  404. fi
  405. fi
  406. fi
  407. }
  408. function InstallNecessary() {
  409. Get_Dist_Name
  410. Get_Server_Type
  411. InstallLog -I "安装必要支持软件"
  412. ${PM} install -y ca-certificates &> /dev/null
  413. if ! command -v wget >/dev/null; then
  414. InstallLog -I "安装wget"
  415. ${PM} install -y wget &> /dev/null
  416. fi
  417. if ! command -v curl >/dev/null; then
  418. InstallLog -I "安装curl"
  419. ${PM} install -y curl &> /dev/null
  420. fi
  421. if ! command -v netstat >/dev/null; then
  422. InstallLog -I "安装net-tools"
  423. ${PM} install -y net-tools &> /dev/null
  424. fi
  425. if ! command -v screen >/dev/null; then
  426. InstallLog -I "安装screen"
  427. ${PM} install -y screen &> /dev/null
  428. fi
  429. if ! command -v vim >/dev/null; then
  430. InstallLog -I "安装vi"
  431. ${PM} install -y vim &> /dev/null
  432. fi
  433. echo 'set mouse=""' >> ~/.vimrc
  434. if ! command -v gpg >/dev/null; then
  435. InstallLog -I "安装gnupg"
  436. ${PM} install -y gnupg &> /dev/null
  437. fi
  438. if ! command -v git >/dev/null; then
  439. InstallLog -I "安装git"
  440. if [ "${DISTRO}" == "Debian" ] || [ "${DISTRO}" == "Ubuntu" ]; then
  441. ${PM} install -y git &> /dev/null
  442. elif [ "${DISTRO}" == "CentOS" ]; then
  443. ${PM} install -y git236 &> /dev/null
  444. fi
  445. fi
  446. if ! command -v rz >/dev/null; then
  447. InstallLog -I "安装lrzsz"
  448. ${PM} install -y lrzsz &> /dev/null
  449. fi
  450. if ! command -v docker >/dev/null; then
  451. InstallLog -I "安装docker和docker-compose"
  452. if [ "${DISTRO}" == "Debian" ]; then
  453. if [[ ${SERVER_TYPE} == "aliyun" ]]; then
  454. curl -fsSL http://mirrors.cloud.aliyuncs.com/docker-ce/linux/debian/gpg | gpg --yes --dearmor -o /usr/share/keyrings/aliyun-docker-ce-keyring.gpg
  455. echo "deb [arch=amd64 signed-by=/usr/share/keyrings/aliyun-docker-ce-keyring.gpg] http://mirrors.cloud.aliyuncs.com/docker-ce/linux/debian/ \
  456. $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/aliyun-docker-ce.list > /dev/null
  457. elif [[ ${SERVER_TYPE} == "qcloud" ]]; then
  458. curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/debian/gpg | gpg --yes --dearmor -o /usr/share/keyrings/aliyun-docker-ce-keyring.gpg
  459. echo "deb [arch=amd64 signed-by=/usr/share/keyrings/aliyun-docker-ce-keyring.gpg] http://mirrors.aliyun.com/docker-ce/linux/debian/ \
  460. $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/aliyun-docker-ce.list > /dev/null
  461. elif [[ ${SERVER_TYPE} == "unknown" ]]; then
  462. InstallLog -e "服务器类型不支持"
  463. exit
  464. fi
  465. apt update
  466. apt install -y docker-ce docker-ce-cli containerd.io
  467. elif [ "${DISTRO}" == "Ubuntu" ]; then
  468. if [[ ${SERVER_TYPE} == "aliyun" ]]; then
  469. curl -fsSL http://mirrors.cloud.aliyuncs.com/docker-ce/linux/ubuntu/gpg | gpg --yes --dearmor -o /usr/share/keyrings/aliyun-docker-ce-keyring.gpg
  470. echo "deb [arch=amd64 signed-by=/usr/share/keyrings/aliyun-docker-ce-keyring.gpg] http://mirrors.cloud.aliyuncs.com/docker-ce/linux/ubuntu/ \
  471. $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/aliyun-docker-ce.list > /dev/null
  472. elif [[ ${SERVER_TYPE} == "qcloud" ]]; then
  473. curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | gpg --yes --dearmor -o /usr/share/keyrings/aliyun-docker-ce-keyring.gpg
  474. echo "deb [arch=amd64 signed-by=/usr/share/keyrings/aliyun-docker-ce-keyring.gpg] http://mirrors.aliyun.com/docker-ce/linux/ubuntu/ \
  475. $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/aliyun-docker-ce.list > /dev/null
  476. elif [[ ${SERVER_TYPE} == "unknown" ]]; then
  477. InstallLog -e "服务器类型不支持"
  478. exit
  479. fi
  480. apt update
  481. apt install -y docker-ce docker-ce-cli containerd.io
  482. elif [ "${DISTRO}" == "CentOS" ]; then
  483. yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  484. #yum list docker-ce --showduplicates | sort -r
  485. yum -y install docker-ce-26.1.4-1.el7 &> /dev/null
  486. fi
  487. if [ ! -f /usr/bin/docker-compose ];then
  488. wget -O /usr/bin/docker-compose http://mi.lacecdn.com/docker/docker-compose-linux-x86_64-v2.32.4
  489. chmod +x /usr/bin/docker-compose
  490. fi
  491. systemctl enable docker
  492. systemctl start docker
  493. apt upgrade
  494. fi
  495. }
  496. #克隆代码
  497. function CloneCode() {
  498. InstallLog -I "克隆代码..."
  499. if [ -d ${LACEMI_CODE_PROD_PATH} ]; then
  500. InstallLog -E "安装目录 ${LACEMI_CODE_PROD_PATH} 已存在,中止安装..."
  501. exit
  502. fi
  503. if [ -d /tmp/lacemi ]; then
  504. rm -rf /tmp/lacemi
  505. fi
  506. git clone "${LACEMI_CODE_URL}" /tmp/lacemi
  507. InstallLog -I "复制代码至目录 ${LACEMI_CODE_PROD_PATH} "
  508. mv -f /tmp/lacemi "${LACEMI_CODE_PROD_PATH}"
  509. chmod 777 -R "${LACEMI_CODE_PROD_PATH}/sapi/runtime"
  510. chmod 777 -R "${LACEMI_CODE_PROD_PATH}/sapi/web"
  511. }
  512. function CloneShareCode() {
  513. InstallLog -I "克隆共享版代码..."
  514. if [ -d ${LACEMI_CODE_SHARE_PATH} ]; then
  515. InstallLog -E "安装目录 ${LACEMI_CODE_SHARE_PATH} 已存在,中止安装..."
  516. exit
  517. fi
  518. if [ -d /tmp/lacemi ]; then
  519. rm -rf /tmp/lacemi
  520. fi
  521. git clone "${LACEMI_SHARE_CODE_URL}" /tmp/lacemi
  522. InstallLog -I "复制代码至目录 ${LACEMI_CODE_SHARE_PATH} "
  523. mv -f /tmp/lacemi "${LACEMI_CODE_SHARE_PATH}"
  524. chmod 777 -R "${LACEMI_CODE_SHARE_PATH}/sapi/runtime"
  525. chmod 777 -R "${LACEMI_CODE_SHARE_PATH}/sapi/web"
  526. }
  527. function SecuritySSHLogin()
  528. {
  529. if [ -s /root/.ssh/authorized_keys ]; then
  530. InstallLog -I "成功禁用密码登录"
  531. chattr -i /etc/ssh/sshd_config
  532. sed -i "s/#\+PasswordAuthentication \w\+/PasswordAuthentication no/g" /etc/ssh/sshd_config
  533. systemctl restart sshd
  534. else
  535. InstallLog -W "由于未启用SSH公钥登录,不允许禁用密码登录"
  536. fi
  537. iFlag=$(lsattr /etc/ssh/sshd_config | cut -d "-" -f 5)
  538. if [ "$iFlag" != "i" ]; then
  539. chattr +i /etc/ssh/sshd_config
  540. fi
  541. iFlag=$(lsattr /root/.ssh/authorized_keys | cut -d "-" -f 5)
  542. if [ "$iFlag" != "i" ]; then
  543. chattr +i /root/.ssh/authorized_keys
  544. fi
  545. grep 'PasswordAuthentication ' /etc/ssh/sshd_config
  546. }
  547. #下载公钥并允许公钥登录
  548. function EnableSSHLogin() {
  549. InstallLog -I "允许SSH登陆"
  550. CheckEmpty "${LACEMI_KEY}" "安装密钥为空,安装中止"
  551. local rsaPublicKey
  552. rsaPublicKey=$(curl -s -H "Accept:text/html" "${LACEMI_API}" -X POST -d "{\"op\": \"get-pub\",\"key\":\"${LACEMI_KEY}\"}")
  553. InstallLog -E "$rsaPublicKey"
  554. # rsaPublicKey=$(curl -s -H "Accept:text/html" "${getPubApi}")
  555. if [ -z "${rsaPublicKey}" ]; then
  556. InstallLog -E "无法获取公钥,安装中止"
  557. exit 1
  558. fi
  559. # shellcheck disable=SC2046
  560. if [ $(echo "${rsaPublicKey}" | grep -c 'ssh-rsa') -eq 0 ]; then
  561. InstallLog -E "公钥格式不正确,安装中止"
  562. exit 1
  563. fi
  564. local checkString="${rsaPublicKey:50:36}"
  565. InstallLog -I "检查公钥字符串 ${checkString}"
  566. # shellcheck disable=SC2046
  567. if [ $(grep -c "${checkString}" /root/.ssh/authorized_keys) -gt 0 ]; then
  568. InstallLog -W "公钥已存在,跳过"
  569. else
  570. InstallLog -I "公钥不存在,附加"
  571. chattr -i /root/.ssh/authorized_keys
  572. cat >>/root/.ssh/authorized_keys <<EOF
  573. ${rsaPublicKey}
  574. EOF
  575. fi
  576. }
  577. function InstallCrontabTask() {
  578. if [ -f /var/spool/cron/root ]; then
  579. sed -i "/systemctl restart docker/d" /var/spool/cron/root
  580. fi
  581. echo "0 4 * * * systemctl restart docker" >>/var/spool/cron/root
  582. }
  583. Get_Dist_Name
  584. if [ "${DISTRO}" = "unknow" ]; then
  585. Echo_Red "Unable to get Linux distribution name, or do NOT support the current distribution."
  586. exit 1
  587. fi
  588. ################
  589. VERSION="v3.1.0"
  590. RELEASE="2025-03-18"
  591. SEED=$(date +%Y%m%d%H%M%S)
  592. LACEMI_API_VERSION="v32"
  593. LACEMI_METHOD="install"
  594. LACEMI_CODE_DEV_PATH="/home/lacemi_api_dev_${LACEMI_API_VERSION}"
  595. LACEMI_CODE_SHARE_PATH="/home/lacemi_api_share_${LACEMI_API_VERSION}"
  596. LACEMI_CODE_PROD_PATH="/home/lacemi_api_prod_${LACEMI_API_VERSION}"
  597. LACEMI_API="https://api.hlace.com/v1/install"
  598. LACEMI_SHARE_CODE_URL="https://gogs.hlace.com/centrenda/lacemi_share_${LACEMI_API_VERSION}.git"
  599. LACEMI_DEV_CODE_URL="https://gogs.hlace.com/centrenda/lacemi_dev_${LACEMI_API_VERSION}.git"
  600. LACEMI_CODE_URL="https://gogs.hlace.com/centrenda/lacemi_${LACEMI_API_VERSION}.git"
  601. LACEMI_QUIET="0"
  602. LACEMI_DOMAIN=""
  603. LACEMI_DOMAIN_NAME=""
  604. LACEMI_KEY=""
  605. ################
  606. start_date=$(date +'%Y-%m-%d %H:%M:%S')
  607. step=0
  608. steps=12
  609. VERSION_POSTGRESQL="17.4.0"
  610. VERSION_MARIADB="11.6.2"
  611. VERSION_MONGODB="8.0.5"
  612. VERSION_NGINX="1.27.4"
  613. VERSION_REDIS="7.4.2"
  614. VERSION_PHP="8.1.31"
  615. Usage() {
  616. cat <<EOF
  617. $(basename "$0") [options]
  618. Usage:
  619. -k, --key target key
  620. -m, --method=[install|upgrade|append] method to execute, options for install or upgrade, default to execute install
  621. -H, --help show usage
  622. -Q, --quiet execute with quiet mode without pressing key to autostart
  623. -V, --version print version information
  624. EOF
  625. # 短格式中,选项值为可选的选项,选项值只能紧接选项而不可使用任何符号将其他选项隔开;如-p80,不要写成-p
  626. # 短格式中,选项值为必有的选项,选项值既可紧接选项也可以使用空格与选项隔开;如-i192.168.1.,也可写成-i 192.168.1.1
  627. # 长格式中,选项值为可选的选项,选项值只能使用=号连接选项;如--port=,不可写成性--port80或--port
  628. # 长格式中,选项值为必有的选项,选项值既可使用=号连接选项也可使用空格连接选项;如--ip=192.168.1.1,也可写成--ip 192.168.1.1
  629. # 为简便起见,建议凡是短格式都使用“选项+选项值”的形式(-p80),凡是长格式都使用“选项+=+选项值”的形式(--port=)
  630. }
  631. main() {
  632. echo ""
  633. local optstring="k:m:H::Q::V::"
  634. local optstringLong="key:,method:,help::,quiet::,version::"
  635. local GETOPT_OUT
  636. GETOPT_OUT=$(getopt --options $optstring --longoptions $optstringLong -- "$@")
  637. local exitCode=$?
  638. if [ $exitCode -ne 0 ]; then
  639. Usage
  640. exit 1
  641. fi
  642. eval set -- "$GETOPT_OUT"
  643. while true; do
  644. case "$1" in
  645. -k | --key)
  646. LACEMI_KEY="$2"
  647. shift
  648. ;;
  649. -m | --method)
  650. LACEMI_METHOD="$2"
  651. shift
  652. ;;
  653. -H | --help)
  654. Usage
  655. exit
  656. ;;
  657. -Q | --quiet)
  658. LACEMI_QUIET="1"
  659. shift
  660. ;;
  661. -V | --version)
  662. InstallLog -I "Version: ${VERSION}, Release: ${RELEASE}"
  663. exit
  664. ;;
  665. --)
  666. shift
  667. break
  668. ;;
  669. *)
  670. InstallLog -E "非法参数: $1"
  671. Usage
  672. ;;
  673. esac
  674. shift
  675. done
  676. UpdateRepo
  677. InstallNecessary
  678. # PullDockerImage
  679. # PullCode
  680. if [ ! -d /root/server_blocks ]; then
  681. mkdir /root/server_blocks
  682. fi
  683. if [ "${LACEMI_METHOD}" == "install" ]; then
  684. #全新安装
  685. InstallLog -I "全新安装"
  686. CheckAPI "${LACEMI_API}"
  687. CheckEmpty "${LACEMI_KEY}" "安装密钥为空,请使用-k指定安装密钥"
  688. LACEMI_DOMAIN=$(curl -s -H "Accept:text/html" "${LACEMI_API}" -X POST -d "{\"op\": \"get-domain\",\"key\":\"${LACEMI_KEY}\"}")
  689. LACEMI_DOMAIN_NAME=$(echo "${LACEMI_DOMAIN}" | cut -d \. -f 1)
  690. InstallLog -I "获取域名:${LACEMI_DOMAIN}"
  691. InstallLog -C "安装参数\n\n域名全称:${LACEMI_DOMAIN}\n域名前缀:${LACEMI_DOMAIN_NAME}\n安装密钥:${LACEMI_KEY}\n代码地址:${LACEMI_CODE_URL}\n安装目录:${LACEMI_CODE_PROD_PATH}\n当前版本:${LACEMI_API_VERSION}\n访问接口:${LACEMI_API}\n"
  692. PressInstall
  693. rm -rf /root/server_blocks/*
  694. CloneCode
  695. InstallLog -I "获取docker-compose.yml"
  696. curl -s -H "Accept:text/html" "${LACEMI_API}" -X POST -d "{\"op\": \"get-template\",\"key\":\"${LACEMI_KEY}\",\"data\":\"INSTALL_DOCKER_COMPOSE_TEMPLATE\"}" -o /root/docker-compose.yml
  697. InstallLog -I "获取local.lic"
  698. curl -s -H "Accept:text/html" "${LACEMI_API}" -X POST -d "{\"op\": \"get-template\",\"key\":\"${LACEMI_KEY}\",\"data\":\"INSTALL_LOCAL_LICENSE\"}" -o "/root/local.lic"
  699. docker-compose up -d
  700. InstallLog -I "获取${LACEMI_DOMAIN_NAME}.conf"
  701. curl -s -H "Accept:text/html" "${LACEMI_API}" -X POST -d "{\"op\": \"get-template\",\"key\":\"${LACEMI_KEY}\",\"data\":\"INSTALL_NGINX_TEMPLATE\"}" -o "/root/server_blocks/${LACEMI_DOMAIN_NAME}.conf"
  702. InstallLog -I "获取default.conf"
  703. curl -s -H "Accept:text/html" "${LACEMI_API}" -X POST -d "{\"op\": \"get-template\",\"key\":\"${LACEMI_KEY}\",\"data\":\"INSTALL_NGINX_DEFAULT_TEMPLATE\"}" -o /root/server_blocks/default.conf
  704. InstallLog -I "获取授权文件"
  705. curl -s -H "Accept:text/html" "${LACEMI_API}" -X POST -d "{\"op\": \"get-license\",\"key\":\"${LACEMI_KEY}\"}" -o "${LACEMI_DOMAIN_NAME}.lic"
  706. runCmd=$(curl -s -H "Accept:text/html" "${LACEMI_API}" -X POST -d "{\"op\": \"get-template\",\"key\":\"${LACEMI_KEY}\",\"data\":\"INSTALL_DOCKER_RUN_CMD\"}")
  707. InstallLog -I "生成docker run命令: ${runCmd}"
  708. if [[ -n $(docker ps -a -q -f "name=${LACEMI_DOMAIN_NAME}") ]];then
  709. echo "Docker container ${LACEMI_DOMAIN_NAME} is running, aborting."
  710. else
  711. ${runCmd}
  712. fi
  713. docker restart root-nginx-1
  714. sleep 5
  715. docker exec "${LACEMI_DOMAIN_NAME}" /app/bin/utool.sh fI
  716. elif [ "${LACEMI_METHOD}" == "append" ]; then
  717. #增量安装
  718. InstallLog -i "增量安装"
  719. CheckAPI "${LACEMI_API}"
  720. CheckEmpty "${LACEMI_KEY}" "安装密钥为空,请使用-k指定安装密钥"
  721. LACEMI_DOMAIN=$(curl -s -H "Accept:text/html" "${LACEMI_API}" -X POST -d "{\"op\": \"get-domain\",\"key\":\"${LACEMI_KEY}\"}")
  722. LACEMI_DOMAIN_NAME=$(echo "${LACEMI_DOMAIN}" | cut -d \. -f 1)
  723. InstallLog -I "获取域名:${LACEMI_DOMAIN}"
  724. InstallLog -C "安装参数\n\n域名全称:${LACEMI_DOMAIN}\n域名前缀:${LACEMI_DOMAIN_NAME}\n安装密钥:${LACEMI_KEY}\n代码地址:${LACEMI_CODE_URL}\n安装目录:${LACEMI_CODE_PROD_PATH}\n当前版本:${LACEMI_API_VERSION}\n访问接口:${LACEMI_API}\n"
  725. PressInstall
  726. InstallLog -I "获取${LACEMI_DOMAIN_NAME}.conf"
  727. curl -s -H "Accept:text/html" "${LACEMI_API}" -X POST -d "{\"op\": \"get-template\",\"key\":\"${LACEMI_KEY}\",\"data\":\"INSTALL_NGINX_TEMPLATE\"}" -o "/root/server_blocks/${LACEMI_DOMAIN_NAME}.conf"
  728. InstallLog -I "获取授权文件"
  729. curl -s -H "Accept:text/html" "${LACEMI_API}" -X POST -d "{\"op\": \"get-license\",\"key\":\"${LACEMI_KEY}\"}" -o "${LACEMI_DOMAIN_NAME}.lic"
  730. runCmd=$(curl -s -H "Accept:text/html" "${LACEMI_API}" -X POST -d "{\"op\": \"get-template\",\"key\":\"${LACEMI_KEY}\",\"data\":\"INSTALL_DOCKER_RUN_CMD\"}")
  731. InstallLog -I "生成docker run命令: ${runCmd}"
  732. if [[ -n $(docker ps -a -q -f "name=${LACEMI_DOMAIN_NAME}") ]];then
  733. echo "Docker container ${LACEMI_DOMAIN_NAME} is running, aborting."
  734. else
  735. ${runCmd}
  736. fi
  737. docker restart root-nginx-1
  738. sleep 5
  739. docker exec "${LACEMI_DOMAIN_NAME}" /app/bin/utool.sh fI
  740. elif [ "${LACEMI_METHOD}" == "share" ]; then
  741. #增量安装
  742. InstallLog -i "共享版"
  743. if [ ! -d "${LACEMI_CODE_SHARE_PATH}" ];then
  744. CloneShareCode
  745. fi
  746. CheckAPI "${LACEMI_API}"
  747. CheckEmpty "${LACEMI_KEY}" "安装密钥为空,请使用-k指定安装密钥"
  748. LACEMI_DOMAIN=$(curl -s -H "Accept:text/html" "${LACEMI_API}" -X POST -d "{\"op\": \"get-domain\",\"key\":\"${LACEMI_KEY}\"}")
  749. LACEMI_DOMAIN_NAME=$(echo "${LACEMI_DOMAIN}" | cut -d \. -f 1)
  750. InstallLog -I "获取域名:${LACEMI_DOMAIN}"
  751. InstallLog -C "安装参数\n\n域名全称:${LACEMI_DOMAIN}\n域名前缀:${LACEMI_DOMAIN_NAME}\n安装密钥:${LACEMI_KEY}\n代码地址:${LACEMI_SHARE_CODE_URL}\n安装目录:${LACEMI_CODE_SHARE_PATH}\n当前版本:${LACEMI_API_VERSION}\n访问接口:${LACEMI_API}\n"
  752. PressInstall
  753. InstallLog -I "获取${LACEMI_DOMAIN_NAME}.conf"
  754. curl -s -H "Accept:text/html" "${LACEMI_API}" -X POST -d "{\"op\": \"get-template\",\"key\":\"${LACEMI_KEY}\",\"data\":\"INSTALL_NGINX_TEMPLATE\"}" -o "/root/server_blocks/${LACEMI_DOMAIN_NAME}.conf"
  755. runCmd=$(curl -s -H "Accept:text/html" "${LACEMI_API}" -X POST -d "{\"op\": \"get-template\",\"key\":\"${LACEMI_KEY}\",\"data\":\"INSTALL_DOCKER_RUN_CMD\"}")
  756. InstallLog -I "生成docker run命令: ${runCmd}"
  757. if [[ -n $(docker ps -a -q -f "name=${LACEMI_DOMAIN_NAME}") ]];then
  758. echo "Docker container ${LACEMI_DOMAIN_NAME} is running, aborting."
  759. else
  760. ${runCmd}
  761. fi
  762. docker restart root-nginx-1
  763. sleep 5
  764. docker exec "${LACEMI_DOMAIN_NAME}" /app/bin/utool.sh fI
  765. fi
  766. # EnableSSHLogin
  767. # SecuritySSHLogin
  768. }
  769. # shellcheck disable=SC2068
  770. clear
  771. echo "+------------------------------------------------------------------------+"
  772. echo "| LACEMI ${VERSION}(${RELEASE}) for ${DISTRO} Linux Server |"
  773. echo "+------------------------------------------------------------------------+"
  774. echo "| A tool to install lacemi on Linux |"
  775. echo "+------------------------------------------------------------------------+"
  776. echo "| For more information please visit https://hlace.com |"
  777. echo "+------------------------------------------------------------------------+"
  778. main "$@"