xuede 4 years ago
commit
53628ddb8f
9 changed files with 1103 additions and 0 deletions
  1. 84 0
      16.04/install.sh
  2. 46 0
      16.04/install_elasticsearch.sh
  3. 46 0
      16.04/mysql_add_user.sh
  4. 46 0
      16.04/nginx_add_site.sh
  5. 43 0
      16.04/nginx_site_conf.tpl
  6. 710 0
      common/ansi.sh
  7. 29 0
      common/common.sh
  8. 33 0
      download.sh
  9. 66 0
      readme.md

+ 84 - 0
16.04/install.sh

@@ -0,0 +1,84 @@
+#!/bin/bash
+set -e
+
+CURRENT_DIR=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
+source ${CURRENT_DIR}/../common/common.sh
+
+[ $(id -u) != "0" ] && { ansi -n --bold --bg-red "请用 root 账户执行本脚本"; exit 1; }
+
+MYSQL_ROOT_PASSWORD=`random_string`
+
+function init_system {
+    export LC_ALL="en_US.UTF-8"
+    echo "LC_ALL=en_US.UTF-8" >> /etc/default/locale
+    locale-gen en_US.UTF-8
+    locale-gen zh_CN.UTF-8
+
+    ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
+
+    apt-get update
+    apt-get install -y software-properties-common
+
+    init_alias
+}
+
+function init_alias {
+    alias sudowww > /dev/null 2>&1 || {
+        echo "alias sudowww='sudo -H -u ${WWW_USER} sh -c'" >> ~/.bash_aliases
+    }
+}
+
+function init_repositories {
+    add-apt-repository -y ppa:ondrej/php
+    add-apt-repository -y ppa:nginx/stable
+    grep -rl ppa.launchpad.net /etc/apt/sources.list.d/ | xargs sed -i 's/http:\/\/ppa.launchpad.net/https:\/\/launchpad.proxy.ustclug.org/g'
+
+    #curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
+    #echo "deb https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list
+
+    #curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add -
+    #echo 'deb https://mirrors.tuna.tsinghua.edu.cn/nodesource/deb_10.x xenial main' > /etc/apt/sources.list.d/nodesource.list
+    #echo 'deb-src https://mirrors.tuna.tsinghua.edu.cn/nodesource/deb_10.x xenial main' >> /etc/apt/sources.list.d/nodesource.list
+
+    apt-get update
+}
+
+function install_basic_softwares {
+    apt-get install -y curl git build-essential unzip supervisor
+}
+
+function install_node_yarn {
+    apt-get install -y nodejs yarn
+    sudo -H -u ${WWW_USER} sh -c 'cd ~ && yarn config set registry https://registry.npm.taobao.org'
+}
+
+function install_php {
+    apt-get install -y php7.3-bcmath php7.3-cli php7.3-curl php7.3-fpm php7.3-gd php7.3-mbstring php7.3-mysql php7.3-opcache php7.3-pgsql php7.3-readline php7.3-xml php7.3-zip php7.3-sqlite3 php7.3-redis
+}
+
+function install_others {
+    apt-get remove -y apache2
+    debconf-set-selections <<< "mysql-server mysql-server/root_password password ${MYSQL_ROOT_PASSWORD}"
+    debconf-set-selections <<< "mysql-server mysql-server/root_password_again password ${MYSQL_ROOT_PASSWORD}"
+    apt-get install -y nginx mysql-server redis-server
+    chown -R ${WWW_USER}.${WWW_USER_GROUP} /var/www/
+    systemctl enable nginx.service
+}
+
+function install_composer {
+    curl https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin/ --filename=composer
+    chmod +x /usr/local/bin/composer
+    sudo -H -u ${WWW_USER} sh -c  'cd ~ && composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/'
+}
+
+call_function init_system "正在初始化系统" ${LOG_PATH}
+call_function init_repositories "正在初始化软件源" ${LOG_PATH}
+call_function install_basic_softwares "正在安装基础软件" ${LOG_PATH}
+call_function install_php "正在安装 PHP" ${LOG_PATH}
+call_function install_others "正在安装 Mysql / Nginx / Redis / Memcached / Beanstalkd / Sqlite3" ${LOG_PATH}
+#call_function install_node_yarn "正在安装 Nodejs / Yarn" ${LOG_PATH}
+call_function install_composer "正在安装 Composer" ${LOG_PATH}
+
+ansi --green --bold -n "安装完毕"
+ansi --green --bold "Mysql root 密码:"; ansi -n --bold --bg-yellow --black ${MYSQL_ROOT_PASSWORD}
+ansi --green --bold -n "请手动执行 source ~/.bash_aliases 使 alias 指令生效。"

+ 46 - 0
16.04/install_elasticsearch.sh

@@ -0,0 +1,46 @@
+#!/bin/bash
+
+CURRENT_DIR=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
+source ${CURRENT_DIR}/../common/common.sh
+
+VERSION=$1
+VERSION=${VERSION:-6}
+
+[ $(id -u) != "0" ] && { ansi -n --bold --bg-red "请用 root 账户执行本脚本"; exit 1; }
+
+# 设置 JAVA_HOME
+export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/jvm/java-8-openjdk-amd64/bin:/usr/lib/jvm/java-8-openjdk-amd64/db/bin:/usr/lib/jvm/java-8-openjdk-amd64/jre/bin"
+export J2SDKDIR="/usr/lib/jvm/java-8-openjdk-amd64"
+export J2REDIR="/usr/lib/jvm/java-8-openjdk-amd64/jre*"
+export JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64"
+export DERBY_HOME="/usr/lib/jvm/java-8-openjdk-amd64/db"
+
+function install_java {
+    apt-get install -y openjdk-8-jre
+}
+
+function install_es {
+    curl -sS https://artifacts.elastic.co/GPG-KEY-elasticsearch | apt-key add -
+    echo "deb https://mirrors.tuna.tsinghua.edu.cn/elasticstack/${VERSION}.x/apt stable main" > /etc/apt/sources.list.d/elastic-${VERSION}.x.list
+    apt-get update
+    apt-get install -y elasticsearch
+    service elasticsearch start
+}
+
+function install_es_plugins {
+    ESVersion=$(/usr/share/elasticsearch/bin/elasticsearch -V|awk -F',' '{print $1}'| awk '{print $2}')
+
+    [[ -e /usr/share/elasticsearch/plugins/analysis-ik ]] || {
+        /usr/share/elasticsearch/bin/elasticsearch-plugin install --batch https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v${ESVersion}/elasticsearch-analysis-ik-${ESVersion}.zip
+    }
+    mkdir -p /etc/elasticsearch/analysis/
+    touch /etc/elasticsearch/analysis/synonyms.txt
+
+    service elasticsearch restart
+}
+
+call_function install_java "正在安装 JAVA" ${LOG_PATH}
+call_function install_es "正在安装 Elasticsearch ${VERSION}" ${LOG_PATH}
+call_function install_es_plugins "正在安装 Elasticsearch 插件" ${LOG_PATH}
+
+ansi --green --bold -n "安装完毕"

+ 46 - 0
16.04/mysql_add_user.sh

@@ -0,0 +1,46 @@
+#!/bin/bash
+
+CURRENT_DIR=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
+source ${CURRENT_DIR}/../common/common.sh
+
+read -r -p "请输入 Mysql root 密码:" MYSQL_ROOT_PASSWORD
+
+mysql --user="root" --password="${MYSQL_ROOT_PASSWORD}" -e "quit" >> ${LOG_PATH} 2>&1 || {
+    ansi -n --bold --bg-red "密码不正确"
+    exit 1
+}
+
+read -r -p "请输入要新建的用户名:" MYSQL_NORMAL_USER
+
+[[ $MYSQL_NORMAL_USER =~ ^[a-zA-Z\0-9_\-]+$ ]] || {
+    ansi -n --bold --bg-red "用户名包含非法字符"
+    exit 1
+}
+
+MYSQL_NORMAL_USER_PASSWORD=`random_string`
+
+read -r -p "是否创建同名数据库并赋予权限?[y/N] " response
+case "$response" in
+    [yY][eE][sS]|[yY])
+        CREATE_DB=1
+        ;;
+    *)
+        CREATE_DB=0
+        ;;
+esac
+
+mysql --user="root" --password="${MYSQL_ROOT_PASSWORD}" -e "CREATE USER '${MYSQL_NORMAL_USER}' IDENTIFIED BY '${MYSQL_NORMAL_USER_PASSWORD}';" >> ${LOG_PATH} 2>&1
+
+ansi -n --bold --green "用户创建成功";
+
+ansi --green --bold "用户名:"; ansi -n --bg-yellow --black ${MYSQL_NORMAL_USER}
+ansi --green --bold "密码:"; ansi -n --bg-yellow --black ${MYSQL_NORMAL_USER_PASSWORD}
+
+if [[ CREATE_DB -eq 1 ]]; then
+    DATABASE_NAME=${MYSQL_NORMAL_USER}
+    mysql --user="root" --password="${MYSQL_ROOT_PASSWORD}" -e "CREATE DATABASE \`${DATABASE_NAME}\`;" >> ${LOG_PATH} 2>&1
+    mysql --user="root" --password="${MYSQL_ROOT_PASSWORD}" -e "GRANT ALL ON \`${DATABASE_NAME}\`.* TO '${MYSQL_NORMAL_USER}';" >> ${LOG_PATH} 2>&1
+    mysql --user="root" --password="${MYSQL_ROOT_PASSWORD}" -e "FLUSH PRIVILEGES;" >> ${LOG_PATH} 2>&1
+fi
+
+ansi -n --bold --green "数据库 ${DATABASE_NAME} 创建成功";

+ 46 - 0
16.04/nginx_add_site.sh

@@ -0,0 +1,46 @@
+#!/bin/bash
+
+CURRENT_DIR=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
+source ${CURRENT_DIR}/../common/common.sh
+
+[ $(id -u) != "0" ] && { ansi -n --bold --bg-red "请用 root 账户执行本脚本"; exit 1; }
+
+read -r -p "请输入项目名:" project
+
+[[ $project =~ ^[a-zA-Z\0-9_\-\.]+$ ]] || {
+    ansi -n --bold --bg-red "项目名包含非法字符"
+    exit 1
+}
+
+read -r -p "请输入站点域名(多个域名用空格隔开):" domains
+
+project_dir="/var/www/${project}"
+
+ansi -n --bold --green "域名列表:${domains}"
+ansi -n --bold --green "项目名:${project}"
+ansi -n --bold --green "项目目录:${project_dir}"
+
+read -r -p "是否确认? [y/N] " response
+case "$response" in
+    [yY][eE][sS]|[yY]) 
+        ;;
+    *)
+        ansi -n --bold --bg-red "用户取消"
+        exit 1
+        ;;
+esac
+
+cat ${CURRENT_DIR}/nginx_site_conf.tpl |
+    sed "s|{{domains}}|${domains}|g" |
+    sed "s|{{project}}|${project}|g" |
+    sed "s|{{project_dir}}|${project_dir}|g" > /etc/nginx/sites-available/${project}.conf
+
+ln -sf /etc/nginx/sites-available/${project}.conf /etc/nginx/sites-enabled/${project}.conf
+
+ansi -n --bold --green "配置文件创建成功";
+
+mkdir -p ${project_dir} && chown -R ${WWW_USER}.${WWW_USER_GROUP} ${project_dir}
+
+systemctl restart nginx.service
+
+ansi -n --bold --green "Nginx 重启成功";

+ 43 - 0
16.04/nginx_site_conf.tpl

@@ -0,0 +1,43 @@
+server {
+    listen 80;
+    server_name {{domains}};
+    root "{{project_dir}}/public";
+
+    index index.html index.htm index.php;
+
+    charset utf-8;
+
+    location / {
+        try_files $uri $uri/ /index.php?$query_string;
+    }
+
+    location = /favicon.ico { access_log off; log_not_found off; }
+    location = /robots.txt  { access_log off; log_not_found off; }
+
+    access_log /var/log/nginx/{{project}}.log;
+    error_log /var/log/nginx/{{project}}-error.log error;
+
+    sendfile off;
+
+    client_max_body_size 100m;
+
+    location ~ \.php$ {
+        fastcgi_split_path_info ^(.+\.php)(/.+)$;
+        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
+        fastcgi_index index.php;
+        include fastcgi_params;
+        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
+        fastcgi_param DOCUMENT_ROOT $realpath_root;
+
+        fastcgi_intercept_errors off;
+        fastcgi_buffer_size 16k;
+        fastcgi_buffers 4 16k;
+        fastcgi_connect_timeout 300;
+        fastcgi_send_timeout 300;
+        fastcgi_read_timeout 300;
+    }
+
+    location ~ /\.ht {
+        deny all;
+    }
+}

+ 710 - 0
common/ansi.sh

@@ -0,0 +1,710 @@
+#!/usr/bin/env bash
+#
+# ANSI code generator
+#
+# © Copyright 2015 Tyler Akins
+# Licensed under the MIT license with an additional non-advertising clause
+# See http://github.com/fidian/ansi
+
+ansi::addCode() {
+    local N
+
+    if [[ "$1" == *=* ]]; then
+        N="${1#*=}"
+        N="${N//,/;}"
+    else
+        N=""
+    fi
+
+    OUTPUT="$OUTPUT$CSI$N$2"
+}
+
+ansi::addColor() {
+    OUTPUT="$OUTPUT$CSI${1}m"
+
+    if [ ! -z "$2" ]; then
+        SUFFIX="$CSI${2}m$SUFFIX"
+    fi
+}
+
+ansi::colorTable() {
+    local FNB_LOWER FNB_UPPER PADDED
+
+    FNB_LOWER="$(ansi::colorize 2 22 f)n$(ansi::colorize 1 22 b)"
+    FNB_UPPER="$(ansi::colorize 2 22 F)N$(ansi::colorize 1 22 B)"
+    printf 'bold %s               ' "$(ansi::colorize 1 22 Sample)"
+    printf 'faint %s              ' "$(ansi::colorize 2 22 Sample)"
+    printf 'italic %s\n'            "$(ansi::colorize 3 23 Sample)"
+    printf 'underline %s          ' "$(ansi::colorize 4 24 Sample)"
+    printf 'blink %s              ' "$(ansi::colorize 5 25 Sample)"
+    printf 'inverse %s\n'           "$(ansi::colorize 7 27 Sample)"
+    printf 'invisible %s\n'         "$(ansi::colorize 8 28 Sample)"
+    printf 'strike %s             ' "$(ansi::colorize 9 29 Sample)"
+    printf 'fraktur %s            ' "$(ansi::colorize 20 23 Sample)"
+    printf 'double-underline%s\n'   "$(ansi::colorize 21 24 Sample)"
+    printf 'frame %s              ' "$(ansi::colorize 51 54 Sample)"
+    printf 'encircle %s           ' "$(ansi::colorize 52 54 Sample)"
+    printf 'overline%s\n'           "$(ansi::colorize 53 55 Sample)"
+    printf '\n'
+    printf '             black   red     green   yellow  blue    magenta cyan    white\n'
+    for BG in 40:black 41:red 42:green 43:yellow 44:blue 45:magenta 46:cyan 47:white xx:no-bg; do
+        PADDED="bg-${BG:3}           "
+        PADDED="${PADDED:0:13}"
+        printf '%s' "$PADDED"
+        BG=${BG:0:2}
+        if [[ "$BG" == "xx" ]]; then
+            BG=""
+        fi
+        for FG in 30 31 32 33 34 35 36 37; do
+            printf '%s%s;%sm' "$CSI"       "$BG"      "${FG}"
+            printf '%s'       "$FNB_LOWER"
+            printf '%s%sm'    "$CSI"       "$(( FG + 60 ))"
+            printf '%s'       "$FNB_UPPER"
+            printf '%s0m  '   "${CSI}"
+        done
+        printf '\n'
+        if [[ -n "$BG" ]]; then
+            printf '  +intense   '
+            for FG in 30 31 32 33 34 35 36 37; do
+                printf '%s%s;%sm' "$CSI"       "$(( BG + 60 ))" "${FG}"
+                printf '%s'       "$FNB_LOWER"
+                printf '%s%sm'    "$CSI"       "$(( FG + 60 ))"
+                printf '%s'       "$FNB_UPPER"
+                printf '%s0m  '   "${CSI}"
+            done
+            printf '\n'
+        fi
+    done
+    printf '\n'
+    printf 'Legend:\n'
+    printf '    Normal color:  f = faint, n = normal, b = bold.\n'
+    printf '    Intense color:  F = faint, N = normal, B = bold.\n'
+}
+
+ansi::colorize() {
+    printf '%s%sm%s%s%sm' "$CSI" "$1" "$3" "$CSI" "$2"
+}
+
+ansi::isAnsiSupported() {
+    local cont c str
+
+    if ! test -t 1; then
+        # stdout is not a terminal
+        return 1
+    fi
+
+    if hash tput &> /dev/null; then
+        if [[ "$(tput colors)" -lt 8 ]]; then
+            return 1
+        fi
+
+        return 0
+    fi
+
+    # Query the console and see if we get ANSI codes back.
+    # CSI 0 c == CSI c == Primary Device Attributes.
+    # Idea:  CSI c
+    # Response = CSI ? 6 [234] ; 2 2 c
+    # The "22" means ANSI color, but terminals don't need to send that back.
+    printf "%s0c" "$CSI"
+    str=
+    cont=true
+
+    while $cont && read -n 1 -s -t 0.1 c; do
+        if [[ -n "$c" ]]; then
+            str+=$c
+        else
+            cont=false
+        fi
+    done
+
+    set | grep ^str=
+
+    # If we get anything back, the terminal is consuming the color codes and
+    # will probably do its best. Let's assume there's color.
+    [[ "$str" == "$CSI?6"[234]";"* ]]
+}
+
+ansi::report() {
+    local BUFF C
+
+    REPORT=""
+    printf "%s%s" "$CSI" "$1"
+    read -r -N ${#2} -s -t 1 BUFF
+
+    if [ "$BUFF" != "$2" ]; then
+        return 1
+    fi
+
+    read -r -N ${#3} -s -t 1 BUFF
+
+    while [ "$BUFF" != "$3" ]; do
+        REPORT="$REPORT${BUFF:0:1}"
+        read -r -N 1 -s -t 1 C || exit 1
+        BUFF="${BUFF:1}$C"
+    done
+}
+
+ansi::showHelp() {
+    cat <<EOF
+Generate ANSI escape codes
+
+Please keep in mind that your terminal must support the code in order for you
+to see the effect properly.
+
+Usage
+    ansi [OPTIONS] [TEXT TO OUTPUT]
+
+Option processing stops at the first unknown option or at "--".  Options
+are applied in order as specified on the command line.  Unless --no-restore
+is used, the options are unapplied in reverse order, restoring your
+terminal to normal.
+
+Optional parameters are surrounded in brackets and use reasonable defaults.
+For instance, using --down will move the cursor down one line and --down=10
+moves the cursor down 10 lines.
+
+Display Manipulation
+    --insert-chars[=N], --ich[=N]
+                             Insert blanks at cursor, shifting the line right.
+    --erase-display[=N], --ed[=N]
+                             Erase in display. 0=below, 1=above, 2=all,
+                             3=saved.
+    --erase-line[=N], --el[=N]
+                             Erase in line. 0=right, 1=left, 2=all.
+    --insert-lines[=N], --il[=N]
+    --delete-lines[=N], --dl[=N]
+    --delete-chars[=N], --dch[=N]
+    --scroll-up[=N], --su[=N]
+    --scroll-down[=N], --sd[=N]
+    --erase-chars[=N], --ech[=N]
+    --repeat[=N], --rep[=N]  Repeat preceding character N times.
+
+Cursor:
+    --up[=N], --cuu[=N]
+    --down[=N], --cud[=N]
+    --forward[=N], --cuf[=N]
+    --backward[=N], --cub[=N]
+    --next-line[=N], --cnl[=N]
+    --prev-line[=N], --cpl[=N]
+    --column[=N], --cha[=N]
+    --position[=[ROW],[COL]], --cup[=[ROW],[=COL]]
+    --tab-forward[=N]        Move forward N tab stops.
+    --tab-backward[=N]       Move backward N tab stops.
+    --column-relative[=N], --hpr[=N]
+    --line[=N], --vpa[=N]
+    --line-relative[=N], --vpr[=N]
+    --save-cursor            Saves the cursor position.  Restores the cursor
+                             after writing text to the terminal unless
+                             --no-restore is also used.
+    --restore-cursor         Just restores the cursor.
+    --hide-cursor            Will automatically show cursor unless --no-restore
+                             is also used.
+    --show-cursor
+
+Colors:
+    Attributes:
+        --bold, --faint, --italic, --underline, --blink, --inverse,
+        --invisible, --strike, --fraktur, --double-underline, --frame,
+        --encircle, --overline
+    Foreground:
+        --black, --red, --green, --yellow, --blue, --magenta, --cyan, --white,
+        --black-intense, --red-intense, --green-intense, --yellow-intense,
+        --blue-intense, --magenta-intense, --cyan-intense, --white-intense
+    Background:
+        --bg-black, --bg-red, --bg-green, --bg-yellow, --bg-blue,
+        --bg-magenta, --bg-cyan, --bg-white, --bg-black-intense,
+        --bg-red-intense, --bg-green-intense, --bg-yellow-intense,
+        --bg-blue-intense, --bg-magenta-intense, --bg-cyan-intense,
+        --bg-white-intense
+    Reset:
+        --reset-attrib       Removes bold, italics, etc.
+        --reset-foreground   Sets foreground to default color.
+        --reset-background   Sets background to default color.
+        --reset-color        Resets attributes, foreground, background.
+
+Report:
+    ** NOTE:  These require reading from stdin.  Results are sent to stdout.
+    ** If no response from terminal in 1 second, these commands fail.
+    --report-position        ROW,COL
+    --report-window-state    "open" or "iconified"
+    --report-window-position X,Y
+    --report-window-pixels   HEIGHT,WIDTH
+    --report-window-chars    ROWS,COLS
+    --report-screen-chars    ROWS,COLS of the entire screen
+    --report-icon
+    --report-title
+
+Miscellaneous:
+    --color-table            Display a color table.
+    --icon=NAME              Set the terminal's icon name.
+    --title=TITLE            Set the terminal's window title.
+    --no-restore             Do not issue reset codes when changing colors.
+                             For example, if you change the color to green,
+                             normally the color is restored to default
+                             afterwards.  With this flag, the color will
+                             stay green even when the command finishes.
+    -n, --newline            Add a newline at the end.
+    --bell                   Add the terminal's bell sequence to the output.
+    --reset                  Reset colors, clear screen, show cursor, move
+                             cursor to 1,1.
+EOF
+}
+
+ansi() {
+    # Handle long options until we hit an unrecognized thing
+    local CONTINUE=true
+    local RESTORE=true
+    local NEWLINE=false
+    local ESC=$'\033'
+    local CSI="${ESC}["
+    local OSC="${ESC}]"
+    local ST="${ESC}\\"
+    local OUTPUT=""
+    local SUFFIX=""
+    local BELL=$'\007'
+
+    while $CONTINUE; do
+        case "$1" in
+            --help | -h | -\?)
+                ansi::showHelp
+                ;;
+
+            # Display Manipulation
+            --insert-chars | --insert-chars=* | --ich | --ich=*)
+                ansi::addCode "$1" @
+                ;;
+
+            --erase-display | --erase-display=* | --ed | --ed=*)
+                ansi::addCode "$1" J
+                ;;
+
+            --erase-line | --erase-line=* | --el | --el=*)
+                ansi::addCode "$1" K
+                ;;
+
+            --insert-lines | --insert-lines=* | --il | --il=*)
+                ansi::addCode "$1" L
+                ;;
+
+            --delete-lines | --delete-lines=* | --dl | --dl=*)
+                ansi::addCode "$1" M
+                ;;
+
+            --delete-chars | --delete-chars=* | --dch | --dch=*)
+                ansi::addCode "$1" P
+                ;;
+
+            --scroll-up | --scroll-up=* | --su | --su=*)
+                ansi::addCode "$1" S
+                ;;
+
+            --scroll-down | --scroll-down=* | --sd | --sd=*)
+                ansi::addCode "$1" T
+                ;;
+
+            --erase-chars | --erase-chars=* | --ech | --ech=*)
+                ansi::addCode "$1" X
+                ;;
+
+            --repeat | --repeat=* | --rep | --rep=N)
+                ansi::addCode "$1" b
+                ;;
+
+            # Cursor Positioning
+            --up | --up=* | --cuu | --cuu=*)
+                ansi::addCode "$1" A
+                ;;
+
+            --down | --down=* | --cud | --cud=*)
+                ansi::addCode "$1" B
+                ;;
+
+            --forward | --forward=* | --cuf | --cuf=*)
+                ansi::addCode "$1" C
+                ;;
+
+            --backward | --backward=*| --cub | --cub=*)
+                ansi::addCode "$1" D
+                ;;
+
+            --next-line | --next-line=* | --cnl | --cnl=*)
+                ansi::addCode "$1" E
+                ;;
+
+            --prev-line | --prev-line=* | --cpl | --cpl=*)
+                ansi::addCode "$1" F
+                ;;
+
+            --column | --column=* | --cha | --cha=*)
+                ansi::addCode "$1" G
+                ;;
+
+            --position | --position=* | --cup | --cup=*)
+                ansi::addCode "$1" H
+                ;;
+
+            --tab-forward | --tab-forward=* | --cht | --cht=*)
+                ansi::addCode "$1" I
+                ;;
+
+            --tab-backward | --tab-backward=* | --cbt | --cbt=*)
+                ansi::addCode "$1" Z
+                ;;
+
+            --column-relative | --column-relative=* | --hpr | --hpr=*)
+                ansi::addCode "$1" 'a'
+                ;;
+
+            --line | --line=* | --vpa | --vpa=*)
+                ansi::addCode "$1" 'd'
+                ;;
+
+            --line-relative | --line-relative=* | --vpr | --vpr=*)
+                ansi::addCode "$1" 'e'
+                ;;
+
+            --save-cursor)
+                OUTPUT="$OUTPUT${CSI}s"
+                SUFFIX="${CSI}u$SUFFIX"
+                ;;
+
+            --restore-cursor)
+                OUTPUT="$OUTPUT${CSI}u"
+                ;;
+
+            --hide-cursor)
+                OUTPUT="$OUTPUT${CSI}?25l"
+                SUFFIX="${CSI}?25h"
+                ;;
+
+            --show-cursor)
+                OUTPUT="$OUTPUT${CSI}?25h"
+                ;;
+
+            # Colors - Attributes
+            --bold)
+                ansi::addColor 1 22
+                ;;
+
+            --faint)
+                ansi::addColor 2 22
+                ;;
+
+            --italic)
+                ansi::addColor 3 23
+                ;;
+
+            --underline)
+                ansi::addColor 4 24
+                ;;
+
+            --blink)
+                ansi::addColor 5 25
+                ;;
+
+            --inverse)
+                ansi::addColor 7 27
+                ;;
+
+            --invisible)
+                ansi::addColor 8 28
+                ;;
+
+            --strike)
+                ansi::addColor 9 20
+                ;;
+
+            --fraktur)
+                ansi::addColor 20 23
+                ;;
+
+            --double-underline)
+                ansi::addColor 21 24
+                ;;
+
+            --frame)
+                ansi::addColor 51 54
+                ;;
+
+            --encircle)
+                ansi::addColor 52 54
+                ;;
+
+            --overline)
+                ansi::addColor 53 55
+                ;;
+
+            # Colors - Foreground
+            --black)
+                ansi::addColor 30 39
+                ;;
+
+            --red)
+                ansi::addColor 31 39
+                ;;
+
+            --green)
+                ansi::addColor 32 39
+                ;;
+
+            --yellow)
+                ansi::addColor 33 39
+                ;;
+
+            --blue)
+                ansi::addColor 34 39
+                ;;
+
+            --magenta)
+                ansi::addColor 35 39
+                ;;
+
+            --cyan)
+                ansi::addColor 36 39
+                ;;
+
+            --white)
+                ansi::addColor 37 39
+                ;;
+
+            --black-intense)
+                ansi::addColor 90 39
+                ;;
+
+            --red-intense)
+                ansi::addColor 91 39
+                ;;
+
+            --green-intense)
+                ansi::addColor 92 39
+                ;;
+
+            --yellow-intense)
+                ansi::addColor 93 39
+                ;;
+
+            --blue-intense)
+                ansi::addColor 94 39
+                ;;
+
+            --magenta-intense)
+                ansi::addColor 95 39
+                ;;
+
+            --cyan-intense)
+                ansi::addColor 96 39
+                ;;
+
+            --white-intense)
+                ansi::addColor 97 39
+                ;;
+
+            # Colors - Background
+            --bg-black)
+                ansi::addColor 40 49
+                ;;
+
+            --bg-red)
+                ansi::addColor 41 49
+                ;;
+
+            --bg-green)
+                ansi::addColor 42 49
+                ;;
+
+            --bg-yellow)
+                ansi::addColor 43 49
+                ;;
+
+            --bg-blue)
+                ansi::addColor 44 49
+                ;;
+
+            --bg-magenta)
+                ansi::addColor 45 49
+                ;;
+
+            --bg-cyan)
+                ansi::addColor 46 49
+                ;;
+
+            --bg-white)
+                ansi::addColor 47 49
+                ;;
+
+            --bg-black-intense)
+                ansi::addColor 100 49
+                ;;
+
+            --bg-red-intense)
+                ansi::addColor 101 49
+                ;;
+
+            --bg-green-intense)
+                ansi::addColor 102 49
+                ;;
+
+            --bg-yellow-intense)
+                ansi::addColor 103 49
+                ;;
+
+            --bg-blue-intense)
+                ansi::addColor 104 49
+                ;;
+
+            --bg-magenta-intense)
+                ansi::addColor 105 49
+                ;;
+
+            --bg-cyan-intense)
+                ansi::addColor 106 49
+                ;;
+
+            --bg-white-intense)
+                ansi::addColor 107 49
+                ;;
+
+            # Colors - Reset
+            --reset-attrib)
+                OUTPUT="$OUTPUT${CSI}22;23;24;25;27;28;29;54;55m"
+                ;;
+
+            --reset-foreground)
+                OUTPUT="$OUTPUT${CSI}39m"
+                ;;
+
+            --reset-background)
+                OUTPUT="$OUTPUT${CSI}39m"
+                ;;
+
+            --reset-color)
+                OUTPUT="$OUTPUT${CSI}0m"
+                ;;
+
+            # Reporting
+            --report-position)
+                ansi::report 6n "$CSI" R || exit 1
+                printf '%s\n' "${REPORT//;/,}"
+                ;;
+
+            --report-window-state)
+                ansi::report 11t "$CSI" t || exit 1
+                case "$REPORT" in
+                    1)
+                        printf 'open\n'
+                        ;;
+
+                    2)
+                        printf 'iconified\n'
+                        ;;
+
+                    *)
+                        printf 'unknown (%s)\n' "$REPORT"
+                        ;;
+                esac
+                ;;
+
+            --report-window-position)
+                ansi::report 13t "${CSI}3;" t || exit 1
+                printf '%s\n' "${REPORT//;/,}"
+                ;;
+
+            --report-window-pixels)
+                ansi::report 14t "${CSI}4;" t || exit 1
+                printf '%s\n' "${REPORT//;/,}"
+                ;;
+
+            --report-window-chars)
+                ansi::report 18t "${CSI}8;" t || exit 1
+                printf '%s\n'  "${REPORT//;/,}"
+                ;;
+
+            --report-screen-chars)
+                ansi::report 19t "${CSI}9;" t || exit 1
+                printf '%s\n' "${REPORT//;/,}"
+                ;;
+
+            --report-icon)
+                ansi::report 20t "${OSC}L" "$ST" || exit 1
+                printf '%s\n' "$REPORT"
+                ;;
+
+            --report-title)
+                ansi::report 21t "${OSC}l" "$ST" || exit 1
+                printf '%s\n' "$REPORT"
+                ;;
+
+            # Miscellaneous
+            --color-table)
+                ansi::colorTable
+                ;;
+
+            --icon=*)
+                OUTPUT="$OUTPUT${OSC}1;${1#*=}$ST"
+                ;;
+
+            --title=*)
+                OUTPUT="$OUTPUT${OSC}2;${1#*=}$ST"
+                ;;
+
+            --no-restore)
+                RESTORE=false
+                ;;
+
+            -n | --newline)
+                NEWLINE=true
+                ;;
+
+            --bell)
+                OUTPUT="$OUTPUT$BELL"
+                ;;
+
+            --reset)
+                # 0m - reset all colors and attributes
+                # 2J - clear terminal
+                # 1;1H - move to 1,1
+                # ?25h - show cursor
+                OUTPUT="$OUTPUT${CSI}0m${CSI}2J${CSI}1;1H${CSI}?25h"
+                ;;
+
+            --)
+                CONTINUE=false
+                shift
+                ;;
+
+            *)
+                CONTINUE=false
+                ;;
+        esac
+
+        if $CONTINUE; then
+            shift
+        fi
+    done
+
+    if ansi::isAnsiSupported; then
+        printf '%s' "$OUTPUT" "${1-}"
+        shift || :
+
+        if [[ "$#" -gt 0 ]]; then
+            printf "${IFS:0:1}%s" "${@}"
+        fi
+
+        if $RESTORE; then
+            printf '%s' "$SUFFIX"
+        fi
+    else
+        printf '%s' "${1+"$@"}"
+    fi
+
+    if $NEWLINE; then
+        printf '\n'
+    fi
+}
+
+
+# Run if not sourced
+if [[ "$0" == "${BASH_SOURCE[0]}" ]]; then
+    ansi "$@"
+fi

+ 29 - 0
common/common.sh

@@ -0,0 +1,29 @@
+#!/bin/bash
+
+COMMON_DIR=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
+source ${COMMON_DIR}/ansi.sh
+
+export LOG_PATH=/var/log/laravel-ubuntu-init.log
+export WWW_USER="www-data"
+export WWW_USER_GROUP="www-data"
+
+function call_function {
+    func=$1
+    desc=$2
+    log_file=$3
+    echo -n "===> ${desc}..."
+    $func >> ${log_file} 2>&1
+    ret=$?
+    echo -n '    ['
+    if [[ $ret -eq 0 ]]; then
+        ansi --bold --green "DONE"
+    else
+        ansi --bold --red "ERROR"
+    fi
+    echo ']'
+}
+
+random_string(){
+    length=${1:-32}
+    echo `cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w ${length} | head -n 1`
+}

+ 33 - 0
download.sh

@@ -0,0 +1,33 @@
+#!/bin/bash
+
+{ # this ensures the entire script is downloaded #
+
+lsb_release -d | grep 'Ubuntu' >& /dev/null
+[[ $? -ne 0 ]] && { echo "仅支持 Ubuntu 16.04 系统"; exit 1; }
+
+DISTRO=$(lsb_release -c -s)
+[[ ${DISTRO} -ne "xenial" ]] && { echo "仅支持 Ubuntu 16.04 系统"; exit 1; }
+
+green="\e[1;32m"
+nc="\e[0m"
+
+echo -e "${green}===> 开始下载...${nc}"
+cd $HOME
+wget -q https://github.com/summerblue/laravel-ubuntu-init/archive/master.tar.gz -O laravel-ubuntu-init.tar.gz
+rm -rf laravel-ubuntu-init
+tar zxf laravel-ubuntu-init.tar.gz
+mv laravel-ubuntu-init-master laravel-ubuntu-init
+rm -f laravel-ubuntu-init.tar.gz
+echo -e "${green}===> 下载完毕${nc}"
+echo ""
+echo -e "${green}安装脚本位于: ${HOME}/laravel-ubuntu-init${nc}"
+
+[ $(id -u) != "0" ] && {
+    source ${HOME}/laravel-ubuntu-init/common/ansi.sh
+    ansi -n --bold --bg-yellow --black "当前账户并非 root,请用 root 账户执行安装脚本(使用命令:sudo -H -s 切换为 root)"
+} || {
+    bash ./laravel-ubuntu-init/16.04/install.sh
+}
+
+cd - > /dev/null
+} # this ensures the entire script is downloaded #

+ 66 - 0
readme.md

@@ -0,0 +1,66 @@
+
+![group](https://cloud.githubusercontent.com/assets/324764/18408949/02d3cb2a-7770-11e6-96e2-54bbcfbfa1d1.png)
+
+## 简介
+
+适用于 Ubuntu 16.04 的 LNMP 安装脚本,并设置了国内镜像加速。
+
+请确保所有命令都以 root 账户执行,如果登录账户不是 root,则需要执行 `sudo -H -s` 切换为 root 账户后再下载安装。
+
+## 软件列表
+
+* Git
+* PHP 7.4
+* Nginx
+* MySQL
+* Sqlite3
+* Composer
+* Nodejs 10
+* Yarn
+* Redis
+* Beanstalkd
+* Memcached
+
+## 可选软件列表
+
+以下软件需手动执行安装脚本:
+
+* Elasticsearch:`./16.04/install_elasticsearch.sh`,默认为 6.x,如果要安装 7.x 则执行 `./16.04/install_elasticsearch.sh 7`
+
+## 安装步骤
+
+```
+wget -qO- https://raw.githubusercontent.com/summerblue/laravel-ubuntu-init/master/download.sh - | bash
+```
+
+此脚本会将安装脚本下载到当前用户的 Home 目录下的 `laravel-ubuntu-init` 目录并自动执行安装脚本,在安装结束之后会在屏幕上输出 Mysql root 账号的密码,请妥善保存。
+
+如果当前不是 root 账户则不会自动安装,需要切换到 root 账户后执行 `./16.04/install.sh`。
+
+## 日常使用
+
+### 1. 新增 Nginx 站点
+
+```
+./16.04/nginx_add_site.sh
+```
+
+会提示输入站点名称(只能是英文、数字、`-` 和 `_`)、域名(多个域名用空格隔开),确认无误后会创建对应的 Nginx 配置并重启 Nginx。
+
+### 2. 新增 Mysql 用户、数据库
+
+```
+./16.04/mysql_add_user.sh
+```
+
+会提示输入 root 密码,如果错误将无法继续。输入需要创建的 Mysql 用户名,以及确认是否需要创建对应用户名的数据库。
+
+创建完毕之后会将新用户的密码输出到屏幕上,请妥善保存。
+
+### 3. 以 www-data 身份执行命令
+
+本项目提供了一个 `sudowww` 的 `alias`,当需要以 `www-data` 用户身份执行命令时(如 `git clone 项目`、`php artisan config:cache` 等),可以直接在命令前加上 `sudowww`,同时在原命令两端加上单引号,如:
+
+```
+sudowww 'php artisan config:cache'
+```