diff --git a/README.md b/README.md
index 9665411..0d7124f 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,8 @@
linux-tutorial
+> 📚 **linux-tutorial** 是一个 Linux 教程。
+>
> 🔁 项目同步维护在 [github](https://github.com/dunwu/linux-tutorial) | [gitee](https://gitee.com/turnon/linux-tutorial)
>
> 📖 [电子书](https://dunwu.github.io/linux-tutorial/) | [电子书(国内)](http://turnon.gitee.io/linux-tutorial/)
diff --git a/codes/linux/lib/env.sh b/codes/linux/lib/env.sh
new file mode 100644
index 0000000..4c41818
--- /dev/null
+++ b/codes/linux/lib/env.sh
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+
+# ------------------------------------------------------------------------------ 颜色状态
+
+# Regular Color
+C_BLACK="\033[0;30m"
+C_RED="\033[0;31m"
+C_GREEN="\033[0;32m"
+C_YELLOW="\033[0;33m"
+C_BLUE="\033[0;34m"
+C_MAGENTA="\033[0;35m"
+C_CYAN="\033[0;36m"
+C_WHITE="\033[0;37m"
+
+# Bold Color
+C_B_BLACK="\033[1;30m"
+C_B_RED="\033[1;31m"
+C_B_GREEN="\033[1;32m"
+C_B_YELLOW="\033[1;33m"
+C_B_BLUE="\033[1;34m"
+C_B_MAGENTA="\033[1;35m"
+C_B_CYAN="\033[1;36m"
+C_B_WHITE="\033[1;37m"
+
+# Underline Color
+C_U_BLACK="\033[4;30m"
+C_U_RED="\033[4;31m"
+C_U_GREEN="\033[4;32m"
+C_U_YELLOW="\033[4;33m"
+C_U_BLUE="\033[4;34m"
+C_U_MAGENTA="\033[4;35m"
+C_U_CYAN="\033[4;36m"
+C_U_WHITE="\033[4;37m"
+
+# Background Color
+C_BG_BLACK="\033[40m"
+C_BG_RED="\033[41m"
+C_BG_GREEN="\033[42m"
+C_BG_YELLOW="\033[43m"
+C_BG_BLUE="\033[44m"
+C_BG_MAGENTA="\033[45m"
+C_BG_CYAN="\033[46m"
+C_BG_WHITE="\033[47m"
+
+# Reset Color
+C_RESET="$(tput sgr0)"
+
+# ------------------------------------------------------------------------------ 常用状态值
+
+YES=0
+NO=1
+SUCCEED=0
+FAILED=1
diff --git a/codes/linux/lib/file.sh b/codes/linux/lib/file.sh
new file mode 100644
index 0000000..ecbcf6b
--- /dev/null
+++ b/codes/linux/lib/file.sh
@@ -0,0 +1,82 @@
+#!/usr/bin/env bash
+
+# 装载其它库
+ROOT=`dirname ${BASH_SOURCE[0]}`
+source ${ROOT}/env.sh
+
+# ------------------------------------------------------------------------------ 文件操作函数
+
+# 文件是否存在
+isFileExists() {
+ if [[ -e $1 ]]; then
+ return ${YES}
+ else
+ return ${NO}
+ fi
+}
+
+isFile() {
+ if [[ -f $1 ]]; then
+ return ${YES}
+ else
+ return ${NO}
+ fi
+}
+
+isDirectory() {
+ if [[ -d $1 ]]; then
+ return ${YES}
+ else
+ return ${NO}
+ fi
+}
+
+isFileReadable() {
+ if [[ -r $1 ]]; then
+ return ${YES}
+ else
+ return ${NO}
+ fi
+}
+
+isFileWritable() {
+ if [[ -w $1 ]]; then
+ return ${YES}
+ else
+ return ${NO}
+ fi
+}
+
+isFileExecutable() {
+ if [[ -x $1 ]]; then
+ return ${YES}
+ else
+ return ${NO}
+ fi
+}
+
+# 检查文件夹是否存在,不存在则创建
+createFolderIfNotExist() {
+ if [ ! -d "$1" ]; then
+ mkdir -p "$1"
+ fi
+}
+
+# 重建目录,如果目录已存在,则删除后重建;如果不存在,直接新建
+recreateDir() {
+ if [[ ! $1 ]]; then
+ printf "${C_B_RED}<<<< Please input dir path.${C_RESET}\n"
+ return ${FAILED}
+ fi
+
+ rm -rf $1
+ mkdir -p $1
+
+ isDirectory $1
+ if [[ "$?" != "${SUCCEED}" ]]; then
+ printf "${C_B_RED}<<<< create $1 failed.${C_RESET}\n"
+ return ${FAILED}
+ fi
+
+ return ${SUCCEED}
+}
diff --git a/codes/linux/lib/git.sh b/codes/linux/lib/git.sh
new file mode 100644
index 0000000..6e33ca7
--- /dev/null
+++ b/codes/linux/lib/git.sh
@@ -0,0 +1,112 @@
+#!/usr/bin/env bash
+
+# 装载其它库
+ROOT=`dirname ${BASH_SOURCE[0]}`
+source ${ROOT}/env.sh
+
+# ------------------------------------------------------------------------------ git 操作函数
+
+# 检查指定的路径是不是一个 git 项目
+checkGit() {
+ local source=$1
+ if [[ -d "${source}" ]]; then
+ cd ${source} || return ${NO}
+ # (1)删除git状态零时文件
+ if [[ -f "gitstatus.tmp" ]]; then
+ rm -rf gitstatus.tmp
+ fi
+
+ # (2)判断是否存在 .git 目录
+ if [[ -d "./.git" ]]; then
+ # (3)判断git是否可用
+ git status &> gitstatus.tmp
+ local gitStatus=false
+ grep -iwq 'not a git repository' gitstatus.tmp && gitStatus=false || gitStatus=true
+ rm -rf gitstatus.tmp
+ if [[ ${gitStatus} == true ]]; then
+ return ${YES}
+ else
+ return ${NO}
+ fi
+ fi
+
+ return ${NO}
+ fi
+
+ printf "${C_B_B_YELLOW}${source} is invalid dir.${C_RESET}\n"
+ return ${NO}
+}
+
+# clone 或 fetch 操作
+# 如果本地代码目录已经是 git 仓库,执行 pull;若不是,则执行 clone
+# 依次传入 Git 仓库、Git 项目组、Git 项目名、分支、本地代码目录
+cloneOrPullGit() {
+
+ local repository=$1
+ local group=$2
+ local project=$3
+ local branch=$4
+ local root=$5
+
+ if [[ ! ${repository} ]] || [[ ! ${group} ]] || [[ ! ${project} ]] || [[ ! ${branch} ]] || [[ ! ${root} ]]; then
+ printf "${C_B_YELLOW}>>>> Please input root, group, project, branch.${C_RESET}\n"
+ return ${FAILED}
+ fi
+
+ if [[ ! -d "${root}" ]]; then
+ printf "${C_B_YELLOW}>>>> ${root} is not directory.${C_RESET}\n"
+ return ${FAILED}
+ fi
+
+ local source=${root}/${group}/${project}
+ printf "${C_B_CYAN}>>>> project directory is ${source}.${C_RESET}\n"
+ printf "${C_B_CYAN}>>>> git url is ${repository}:${group}/${project}.git.${C_RESET}\n"
+ mkdir -p ${root}/${group}
+
+ checkGit ${source}
+ if [[ "${YES}" == "$?" ]]; then
+ # 如果 ${source} 是 git 项目,执行 pull 操作
+ cd ${source} || return ${FAILED}
+
+ git checkout -f ${branch}
+ if [[ "${SUCCEED}" != "$?" ]]; then
+ printf "${C_B_RED}<<<< git checkout ${branch} failed.${C_RESET}\n"
+ return ${FAILED}
+ fi
+ printf "${C_B_GREEN}>>>> git checkout ${branch} succeed.${C_RESET}\n"
+
+ git reset --hard
+ if [[ "${SUCCEED}" != "$?" ]]; then
+ printf "${C_B_RED}<<<< git reset --hard failed.${C_RESET}\n"
+ return ${FAILED}
+ fi
+ printf "${C_B_GREEN}>>>> git reset --hard succeed.${C_RESET}\n"
+
+ git pull
+ if [[ "${SUCCEED}" != "$?" ]]; then
+ printf "${C_B_RED}<<<< git pull failed.${C_RESET}\n"
+ return ${FAILED}
+ fi
+ printf "${C_B_GREEN}>>>> git pull succeed.${C_RESET}\n"
+ else
+ # 如果 ${source} 不是 git 项目,执行 clone 操作
+
+ git clone "${repository}:${group}/${project}.git" ${source}
+ if [[ "${SUCCEED}" != "$?" ]]; then
+ printf "${C_B_RED}<<<< git clone ${project} failed.${C_RESET}\n"
+ return ${FAILED}
+ fi
+ printf "${C_B_GREEN}>>>> git clone ${project} succeed.${C_RESET}\n"
+
+ cd ${source} || return ${FAILED}
+
+ git checkout -f ${branch}
+ if [[ "${SUCCEED}" != "$?" ]]; then
+ printf "${C_B_RED}<<<< git checkout ${branch} failed.${C_RESET}\n"
+ return ${FAILED}
+ fi
+ printf "${C_B_GREEN}>>>> git checkout ${branch} succeed.${C_RESET}\n"
+ fi
+
+ return ${SUCCEED}
+}
diff --git a/codes/linux/lib/nodejs.sh b/codes/linux/lib/nodejs.sh
new file mode 100644
index 0000000..38d3849
--- /dev/null
+++ b/codes/linux/lib/nodejs.sh
@@ -0,0 +1,108 @@
+#!/usr/bin/env bash
+
+# 装载其它库
+ROOT=`dirname ${BASH_SOURCE[0]}`
+source ${ROOT}/file.sh
+
+# ------------------------------------------------------------------------------ nodejs 操作函数
+
+# install Node Version Manager(nvm)
+installNvm() {
+ local nvmVersion=0.35.2
+ if [[ $1 ]]; then
+ local nvmVersion=$1
+ fi
+
+ recreateDir "~/.nvm"
+ curl -o- https://raw.githubusercontent.com/creationix/nvm/v${nvmVersion}/install.sh | bash
+ source ~/.nvm/nvm.sh
+ if [[ "$?" != "${YES}" ]]; then
+ return ${FAILED}
+ fi
+
+ # Check
+ nvm version
+ if [[ "$?" != "${YES}" ]]; then
+ return ${FAILED}
+ fi
+ return ${SUCCEED}
+}
+
+# Check nodejs version
+checkNodejsVersion() {
+ if [[ ! $1 ]]; then
+ printf "${C_B_RED}<<<< please specified expect nodejs version.${C_RESET}\n"
+ return ${FAILED}
+ fi
+
+ local expectVersion=$1
+
+ source /root/.bashrc
+ local nodeVersion=$(nvm version)
+ if [[ "$?" != "${YES}" ]]; then
+ printf "${C_B_YELLOW}>>>> nvm not installed.${C_RESET}\n"
+
+ local nvmVersion=v0.35.2
+ installNvm "${nvmVersion}"
+ if [[ "$?" != "${SUCCEED}" ]]; then
+ return ${FAILED}
+ fi
+ nodeVersion=$(nvm version)
+ fi
+
+ if [[ "${nodeVersion}" != "v${expectVersion}" ]]; then
+ printf "${C_B_YELLOW}>>>> current nodejs version is ${nodeVersion}, not ${expectVersion}.${C_RESET}\n"
+ nvm install ${expectVersion}
+ nvm use ${expectVersion}
+ fi
+
+ return ${SUCCEED}
+}
+
+# build nodejs project
+buildNodejsProject() {
+ if [[ ! $1 ]]; then
+ printf "${C_B_RED}<<<< please input nodejs project path.${C_RESET}\n"
+ return ${FAILED}
+ fi
+
+ if [[ ! $2 ]]; then
+ printf "${C_B_RED}<<<< please input nodejs version.${C_RESET}\n"
+ return ${FAILED}
+ fi
+
+ isDirectory $1
+ if [[ "$?" != "${YES}" ]]; then
+ printf "${C_B_RED}<<<< $1 is not valid path.${C_RESET}\n"
+ return ${FAILED}
+ fi
+
+ local project=$1
+ local nodeVersion=$2
+ printf "${C_B_BLUE}>>>> build nodejs project $1 begin.${C_RESET}\n"
+ cd ${project} || (printf "${C_B_RED}<<<< ${project} is not exists.${C_RESET}\n" && exit 1)
+
+ checkNodejsVersion ${nodeVersion}
+
+ npm install
+ if [[ "$?" != "${YES}" ]]; then
+ printf "${C_B_RED}<<<< update dependencies failed.${C_RESET}\n"
+ return ${FAILED}
+ else
+ printf "${C_B_GREEN}>>>> update dependencies succeed.${C_RESET}\n"
+ fi
+
+ npm run build
+ if [[ "$?" != "${YES}" ]]; then
+ printf "${C_B_RED}<<<< build failed.${C_RESET}\n"
+ return ${FAILED}
+ else
+ printf "${C_B_GREEN}<<<< build succeed.${C_RESET}\n"
+ fi
+ return ${SUCCEED}
+}
+
+# package nodejs artifact dir (default is dist)
+packageDist() {
+ zip -o -r -q ${branch}.zip *
+}
diff --git a/codes/linux/lib/string.sh b/codes/linux/lib/string.sh
new file mode 100644
index 0000000..9a75279
--- /dev/null
+++ b/codes/linux/lib/string.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+
+strIsEmpty() {
+ if [[ -z $1 ]]; then
+ return ${YES}
+ else
+ return ${NO}
+ fi
+}
+
+strIsNotEmpty() {
+ if [[ -n $1 ]]; then
+ return ${YES}
+ else
+ return ${NO}
+ fi
+}
+
+strIsBlank() {
+ if [[ ! $1 ]]; then
+ return ${YES}
+ else
+ return ${NO}
+ fi
+}
+
+strIsNotBlank() {
+ if [[ $1 ]]; then
+ return ${YES}
+ else
+ return ${NO}
+ fi
+}
+
+strEquals() {
+ if [[ "$1" = "$2" ]]; then
+ return ${YES}
+ else
+ return ${NO}
+ fi
+}
+
+strStartWith() {
+ if [[ "$1" == "$2*" ]]; then
+ return ${YES}
+ else
+ return ${NO}
+ fi
+}
+
diff --git a/codes/linux/libtest/README.md b/codes/linux/libtest/README.md
new file mode 100644
index 0000000..2051e94
--- /dev/null
+++ b/codes/linux/libtest/README.md
@@ -0,0 +1,11 @@
+# Git 脚本工具
+
+这里汇总一些常用的、简单的 git shell 脚本。
+
+更多功能强大的工具,可以参考 [资源](#资源)
+
+## 资源
+
+- [git-extras](https://github.com/tj/git-extras) - 丰富的 git 扩展支持
+- [gitflow](https://github.com/nvie/gitflow) - git-flow shell 版本
+- [gitflow-avh](https://github.com/petervanderdoes/gitflow-avh) - git-flow shell 版本
\ No newline at end of file
diff --git a/codes/linux/libtest/env-test.sh b/codes/linux/libtest/env-test.sh
new file mode 100644
index 0000000..e1a67f7
--- /dev/null
+++ b/codes/linux/libtest/env-test.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+
+# 装载其它库
+source ../lib/env.sh
+
+# ------------------------------------------------------------------------------ 颜色变量测试
+printf "${C_B_YELLOW}测试彩色打印:${C_RESET}\n"
+
+printf "${C_BLACK}Hello.${C_RESET}\n"
+printf "${C_RED}Hello.${C_RESET}\n"
+printf "${C_GREEN}Hello.${C_RESET}\n"
+printf "${C_YELLOW}Hello.${C_RESET}\n"
+printf "${C_BLUE}Hello.${C_RESET}\n"
+printf "${C_PURPLE}Hello.${C_RESET}\n"
+printf "${C_CYAN}Hello.${C_RESET}\n"
+
+printf "${C_B_BLACK}Hello.${C_RESET}\n"
+printf "${C_B_RED}Hello.${C_RESET}\n"
+printf "${C_B_GREEN}Hello.${C_RESET}\n"
+printf "${C_B_YELLOW}Hello.${C_RESET}\n"
+printf "${C_B_BLUE}Hello.${C_RESET}\n"
+printf "${C_B_PURPLE}Hello.${C_RESET}\n"
+printf "${C_B_CYAN}Hello.${C_RESET}\n"
+
+printf "${C_U_BLACK}Hello.${C_RESET}\n"
+printf "${C_U_RED}Hello.${C_RESET}\n"
+printf "${C_U_GREEN}Hello.${C_RESET}\n"
+printf "${C_U_YELLOW}Hello.${C_RESET}\n"
+printf "${C_U_BLUE}Hello.${C_RESET}\n"
+printf "${C_U_PURPLE}Hello.${C_RESET}\n"
+printf "${C_U_CYAN}Hello.${C_RESET}\n"
+
+printf "${C_BG_BLACK}Hello.${C_RESET}\n"
+printf "${C_BG_RED}Hello.${C_RESET}\n"
+printf "${C_BG_GREEN}Hello.${C_RESET}\n"
+printf "${C_BG_YELLOW}Hello.${C_RESET}\n"
+printf "${C_BG_BLUE}Hello.${C_RESET}\n"
+printf "${C_BG_PURPLE}Hello.${C_RESET}\n"
+printf "${C_BG_CYAN}Hello.${C_RESET}\n"
+
diff --git a/codes/linux/libtest/git-check.sh b/codes/linux/libtest/git-check.sh
new file mode 100644
index 0000000..9d3358f
--- /dev/null
+++ b/codes/linux/libtest/git-check.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+
+source ../lib/git.sh
+
+##################################### MAIN #####################################
+if [[ $1 ]]; then
+ DIR=$1
+else
+ DIR=$(pwd)
+fi
+
+printf "${C_B_BLUE}Current path is: ${DIR} ${C_RESET}\n"
+
+checkGit ${DIR}
+if [[ "${YES}" == "$?" ]]; then
+ printf "${C_B_GREEN}${DIR} is git project.${C_RESET}\n"
+ exit ${YES}
+else
+ printf "${C_B_RED}${DIR} is not git project.${C_RESET}\n"
+ exit ${NO}
+fi
diff --git a/codes/linux/libtest/git-update.sh b/codes/linux/libtest/git-update.sh
new file mode 100644
index 0000000..0c457cf
--- /dev/null
+++ b/codes/linux/libtest/git-update.sh
@@ -0,0 +1,37 @@
+#!/usr/bin/env bash
+
+source ../lib/env.sh
+source ../lib/git.sh
+
+doCloneOrPullGit() {
+ cloneOrPullGit $1 $2 $3 $4 $5
+ if [[ "$?" == "${SUCCEED}" ]]; then
+ printf "\n${C_GREEN}>>>> Update git project [$2/$3] succeed.${C_RESET}\n"
+ return ${SUCCEED}
+ else
+ printf "\n${C_RED}>>>> Update git project [$2/$3] failed.${C_RESET}\n"
+ return ${FAILED}
+ fi
+}
+
+##################################### MAIN #####################################
+ROOT=$(dirname ${BASH_SOURCE[0]})
+
+# 这里需要根据实际情况替换 Git 仓库、项目组、项目、代码分支
+REPOSITORY="git@gitee.com"
+
+printf "${C_CYAN}Current path is ${ROOT}.${C_RESET}\n"
+
+doCloneOrPullGit ${REPOSITORY} turnon linux-tutorial master ${ROOT}
+r1=$?
+doCloneOrPullGit ${REPOSITORY} turnon nginx-tutorial master ${ROOT}
+r2=$?
+
+if [[ "${r1}" == "${SUCCEED}" && "${r2}" == "${SUCCEED}" ]]; then
+ printf "\n${C_GREEN}Succeed.${C_RESET}\n"
+ exit ${SUCCEED}
+else
+ printf "\n${C_RED}Failed.${C_RESET}\n"
+ exit ${FAILED}
+fi
+
diff --git a/codes/linux/libtest/nodejs-test.sh b/codes/linux/libtest/nodejs-test.sh
new file mode 100644
index 0000000..696371f
--- /dev/null
+++ b/codes/linux/libtest/nodejs-test.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+# 装载其它库
+source ../lib/nodejs.sh
+
+# ------------------------------------------------------------------------------
+ROOT=$(pwd)
+
+path=${ROOT}
+if [[ $1 ]]; then
+ path=$1
+fi
+
+version=10.15.0
+if [[ $2 ]]; then
+ version=$2
+fi
+
+buildNodejsProject ${path} ${version}
diff --git a/codes/shell/git/check-git.sh b/codes/shell/git/check-git.sh
deleted file mode 100644
index 25f2256..0000000
--- a/codes/shell/git/check-git.sh
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/env bash
-
-# ------------------------------------------------------------------------------
-# ASCII 颜色变量
-BLACK="\033[1;30m"
-RED="\033[1;31m"
-GREEN="\033[1;32m"
-YELLOW="\033[1;33m"
-BLUE="\033[1;34m"
-PURPLE="\033[1;35m"
-CYAN="\033[1;36m"
-RESET="\033[0m"
-
-# 常量
-YES=0
-NO=1
-# ------------------------------------------------------------------------------
-
-printf "$BLUE"
-cat << EOF
-# ------------------------------------------------------------------------------
-# 检查当前目录是否为 git 工程
-# ------------------------------------------------------------------------------
-EOF
-printf "$RESET"
-
-# 检查指定的路径是不是一个 git 项目
-checkGit() {
- source=$1
- if [[ -d "${source}" ]]; then
- cd ${source} || return ${NO}
- # (1)删除git状态零时文件
- if [[ -f "gitstatus.tmp" ]]; then
- rm -rf gitstatus.tmp
- fi
-
- # (2)判断是否存在 .git 目录
- if [[ -d "./.git" ]]; then
- # (3)判断git是否可用
- git status &> gitstatus.tmp
- gitStatus=false
- grep -iwq 'not a git repository' gitstatus.tmp && gitStatus=false || gitStatus=true
- rm -rf gitstatus.tmp
- if [[ ${gitStatus} == true ]]; then
- return ${YES}
- else
- return ${NO}
- fi
- fi
- fi
- return ${NO}
-}
-
-##################################### MAIN #####################################
-ROOT=$(pwd)
-printf "${BLUE}当前目录为:${ROOT} ${RESET}\n"
-
-checkGit ${ROOT}
-if [[ "${YES}" == "$?" ]]; then
- printf "${GREEN}${ROOT} 是 git 工程。${RESET}\n"
- exit ${YES}
-else
- printf "${RED}${ROOT} 不是 git 工程。${RESET}\n"
- exit ${NO}
-fi
diff --git a/codes/shell/git/update-git.sh b/codes/shell/git/update-git.sh
deleted file mode 100644
index 0ea5188..0000000
--- a/codes/shell/git/update-git.sh
+++ /dev/null
@@ -1,156 +0,0 @@
-#!/usr/bin/env bash
-
-# ------------------------------------------------------------------------------
-# console color
-BLACK="\033[1;30m"
-RED="\033[1;31m"
-GREEN="\033[1;32m"
-YELLOW="\033[1;33m"
-BLUE="\033[1;34m"
-PURPLE="\033[1;35m"
-CYAN="\033[1;36m"
-RESET="$(tput sgr0)"
-
-# 常量
-YES=0
-NO=1
-SUCCEED=0
-FAILED=1
-# ------------------------------------------------------------------------------
-
-printf "$BLUE"
-cat << EOF
-################################################################################
-# 项目初始化脚本
-################################################################################
-EOF
-printf "$RESET"
-
-# 检查指定的路径是不是一个 git 项目
-checkGit() {
- source=$1
- if [[ -d "${source}" ]]; then
- cd ${source} || return ${NO}
- # (1)删除git状态零时文件
- if [[ -f "gitstatus.tmp" ]]; then
- rm -rf gitstatus.tmp
- fi
-
- # (2)判断是否存在 .git 目录
- if [[ -d "./.git" ]]; then
- # (3)判断git是否可用
- git status &> gitstatus.tmp
- gitStatus=false
- grep -iwq 'not a git repository' gitstatus.tmp && gitStatus=false || gitStatus=true
- rm -rf gitstatus.tmp
- if [[ ${gitStatus} == true ]]; then
- return ${YES}
- else
- return ${NO}
- fi
- fi
- fi
- return ${NO}
-}
-
-cloneOrFetchGit() {
- root=$1
- group=$2
- project=$3
- branch=$4
-
- if [[ ! -d "${root}" ]]; then
- printf "${YELLOW}>>>> ${root} is not directory.${RESET}\n"
- return ${FAILED}
- fi
-
- if [[ ! ${group} ]] || [[ ! ${project} ]] || [[ ! ${branch} ]]; then
- printf "${YELLOW}>>>> group, project, branch must not be empty.${RESET}\n"
- return ${FAILED}
- fi
-
- source=${root}/${group}/${project}
- printf "${CYAN}>>>> project directory is ${source}.${RESET}\n"
- printf "${CYAN}>>>> git url is ${REPOSITORY}:${group}/${project}.git.${RESET}\n"
- mkdir -p ${root}/${group}
-
- checkGit ${source}
- if [[ "${YES}" == "$?" ]]; then
- # 如果 ${source} 是 git 项目,执行 pull 操作
- cd ${source} || return ${FAILED}
-
- git checkout -f ${branch}
- if [[ "${SUCCEED}" != "$?" ]]; then
- printf "${RED}>>>> git checkout ${branch} failed.${RESET}\n"
- return ${FAILED}
- fi
- printf "${GREEN}>>>> git checkout ${branch} succeed.${RESET}\n"
-
- git reset --hard
- if [[ "${SUCCEED}" != "$?" ]]; then
- printf "${RED}>>>> git reset --hard failed.${RESET}\n"
- return ${FAILED}
- fi
- printf "${GREEN}>>>> git reset --hard succeed.${RESET}\n"
-
- git pull
- if [[ "${SUCCEED}" != "$?" ]]; then
- printf "${RED}>>>> git pull failed.${RESET}\n"
- return ${FAILED}
- fi
- printf "${GREEN}>>>> git pull succeed.${RESET}\n"
- else
- # 如果 ${source} 不是 git 项目,执行 clone 操作
-
- git clone "${REPOSITORY}:${group}/${project}.git" ${source}
- if [[ "${SUCCEED}" != "$?" ]]; then
- printf "${RED}>>>> git clone ${project} failed.${RESET}\n"
- return ${FAILED}
- fi
- printf "${GREEN}>>>> git clone ${project} succeed.${RESET}\n"
-
- cd ${source} || return ${FAILED}
-
- git checkout -f ${branch}
- if [[ "${SUCCEED}" != "$?" ]]; then
- printf "${RED}>>>> git checkout ${branch} failed.${RESET}\n"
- return ${FAILED}
- fi
- printf "${GREEN}>>>> git checkout ${branch} succeed.${RESET}\n"
- fi
-
- return ${SUCCEED}
-}
-
-doCloneOrFetchGit() {
- cloneOrFetchGit $1 $2 $3 $4
- if [[ "$?" == "${SUCCEED}" ]]; then
- printf "\n${GREEN}>>>> Update git project [$2/$3] succeed.${RESET}\n"
- return ${SUCCEED}
- else
- printf "\n${RED}>>>> Update git project [$2/$3] failed.${RESET}\n"
- return ${FAILED}
- fi
-}
-
-##################################### MAIN #####################################
-ROOT=$(pwd)
-
-# 这里需要根据实际情况替换 Git 仓库、项目组、项目、代码分支
-REPOSITORY="git@gitee.com"
-
-printf "${CYAN}Current path is ${ROOT}.${RESET}\n"
-
-doCloneOrFetchGit ${ROOT} turnon linux-tutorial master
-r1=$?
-doCloneOrFetchGit ${ROOT} turnon nginx-tutorial master
-r2=$?
-
-if [[ "${r1}" == "${SUCCEED}" && "${r2}" == "${SUCCEED}" ]]; then
- printf "\n${GREEN}Succeed.${RESET}\n"
- exit ${SUCCEED}
-else
- printf "\n${RED}Failed.${RESET}\n"
- exit ${FAILED}
-fi
-
diff --git a/codes/shell/lib/env.sh b/codes/shell/lib/env.sh
new file mode 100644
index 0000000..4c41818
--- /dev/null
+++ b/codes/shell/lib/env.sh
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+
+# ------------------------------------------------------------------------------ 颜色状态
+
+# Regular Color
+C_BLACK="\033[0;30m"
+C_RED="\033[0;31m"
+C_GREEN="\033[0;32m"
+C_YELLOW="\033[0;33m"
+C_BLUE="\033[0;34m"
+C_MAGENTA="\033[0;35m"
+C_CYAN="\033[0;36m"
+C_WHITE="\033[0;37m"
+
+# Bold Color
+C_B_BLACK="\033[1;30m"
+C_B_RED="\033[1;31m"
+C_B_GREEN="\033[1;32m"
+C_B_YELLOW="\033[1;33m"
+C_B_BLUE="\033[1;34m"
+C_B_MAGENTA="\033[1;35m"
+C_B_CYAN="\033[1;36m"
+C_B_WHITE="\033[1;37m"
+
+# Underline Color
+C_U_BLACK="\033[4;30m"
+C_U_RED="\033[4;31m"
+C_U_GREEN="\033[4;32m"
+C_U_YELLOW="\033[4;33m"
+C_U_BLUE="\033[4;34m"
+C_U_MAGENTA="\033[4;35m"
+C_U_CYAN="\033[4;36m"
+C_U_WHITE="\033[4;37m"
+
+# Background Color
+C_BG_BLACK="\033[40m"
+C_BG_RED="\033[41m"
+C_BG_GREEN="\033[42m"
+C_BG_YELLOW="\033[43m"
+C_BG_BLUE="\033[44m"
+C_BG_MAGENTA="\033[45m"
+C_BG_CYAN="\033[46m"
+C_BG_WHITE="\033[47m"
+
+# Reset Color
+C_RESET="$(tput sgr0)"
+
+# ------------------------------------------------------------------------------ 常用状态值
+
+YES=0
+NO=1
+SUCCEED=0
+FAILED=1
diff --git a/codes/shell/文件操作/log.txt b/codes/shell/文件操作/log.txt
new file mode 100644
index 0000000..353a7bc
--- /dev/null
+++ b/codes/shell/文件操作/log.txt
@@ -0,0 +1,66 @@
+Add git message title here
+
+# See links to relevant web pages, issue trackers, etc.
+See: https://github.com/
+See: [Git Page](https://github.com/)
+
+# List all co-authors, so people can contact with them
+Co-authored-by: Name
+
+# Why is this change happening, e.g. goals, use cases, stories, etc.?
+Why:
+
+# How is this change happening, e.g. implementations, algorithms, etc.?
+How:
+
+# Tags suitable for searching, such as hashtags, keywords, etc.
+Tags:
+
+# ## Help ##
+#
+# Subject line imperative uppercase verbs:
+#
+# Add = Create a capability e.g. feature, test, dependency.
+# Drop = Delete a capability e.g. feature, test, dependency.
+# Fix = Fix an issue e.g. bug, typo, accident, misstatement.
+# Bump = Increase the version of something e.g. a dependency.
+# Make = Change the build process, or tools, or infrastructure.
+# Start = Begin doing something; e.g. enable a toggle, feature flag, etc.
+# Stop = End doing something; e.g. disable a toggle, feature flag, etc.
+# Refactor = A change that MUST be just refactoring.
+# Reformat = A change that MUST be just format, e.g. indent line, trim space, etc.
+# Rephrase = A change that MUST be just textual, e.g. edit a comment, doc, etc.
+# Optimize = A change that MUST be just about performance, e.g. speed up code.
+# Document = A change that MUST be only in the documentation, e.g. help files.
+#
+# For the subject line:
+# * Use 50 characters maximum.
+# * Do not use a sentence-ending period.
+#
+# For the body text:
+# * Use as many lines as you like.
+# * Use 72 characters maximum per line for typical word wrap text.
+#
+#
+# ## About ##
+#
+# This is our git commit messages.
+# You can edit this template if you want
+#
+# ## Usage ##
+#
+# Put the template file here:
+#
+# ~/.git_commit_template.txt
+#
+# Configure git to use the template file by running:
+#
+# git config --global commit.template ~/.git_commit_template.txt
+#
+# Add the template file to the ~/.gitconfig file:
+#
+# [commit]
+# template = ~/.git_commit_template.txt
+#
+# you could put it in other location if you prefer
+#
diff --git a/codes/shell/输入和输出/创建本地临时文件.sh b/codes/shell/文件操作/创建临时文件.sh
similarity index 51%
rename from codes/shell/输入和输出/创建本地临时文件.sh
rename to codes/shell/文件操作/创建临时文件.sh
index 82533a9..cf294d7 100644
--- a/codes/shell/输入和输出/创建本地临时文件.sh
+++ b/codes/shell/文件操作/创建临时文件.sh
@@ -1,13 +1,10 @@
#!/usr/bin/env bash
-# creating and using a temp file
+tempFile=`mktemp test.XXXXXX`
-tempfile=`mktemp test.XXXXXX`
-
-exec 3> $tempfile
-
-echo "This script writes to temp file $tempfile"
+exec 3> ${tempFile}
+echo "This script writes to temp file ${tempFile}"
echo "This is the first line" >&3
echo "This is the second line" >&3
echo "This is the last line" >&3
@@ -15,8 +12,7 @@ echo "This is the last line" >&3
exec 3>&-
echo "Done creating temp file. The contents are:"
+cat ${tempFile}
-cat $tempfile
-
-rm -f $tempfile 2> /dev/null
+rm -f ${tempFile} 2> /dev/null
diff --git a/codes/shell/文件操作/创建临时目录.sh b/codes/shell/文件操作/创建临时目录.sh
new file mode 100644
index 0000000..de2454e
--- /dev/null
+++ b/codes/shell/文件操作/创建临时目录.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+tempDir=`mktemp -d dir.XXXXXX`
+cd ${tempDir} || exit 1
+
+tempFile1=`mktemp temp.XXXXXX`
+tempFile2=`mktemp temp.XXXXXX`
+exec 7> ${tempFile1}
+exec 8> ${tempFile2}
+
+echo "Sending data to directory $tempDir"
+echo "This is a test line of data for $tempFile1" >&7
+echo "This is a test line of data for $tempFile2" >&8
+
diff --git a/codes/shell/输入和输出/目录操作.sh b/codes/shell/文件操作/目录基本操作.sh
similarity index 50%
rename from codes/shell/输入和输出/目录操作.sh
rename to codes/shell/文件操作/目录基本操作.sh
index 81689be..cd02068 100644
--- a/codes/shell/输入和输出/目录操作.sh
+++ b/codes/shell/文件操作/目录基本操作.sh
@@ -1,23 +1,27 @@
#!/usr/bin/env bash
-###################################################################################
+# ------------------------------------------------------------------------------
# 目录操作示例
# @author: Zhang Peng
-###################################################################################
+# ------------------------------------------------------------------------------
# 创建目录(整个文件路径中的目录如果不存在,都会一一创建,如果目录已存在,则什么也不做)
mkdir -p /home/linux-tutorial/temp
-# 进入目录
-cd /home/linux-tutorial/temp
+# 进入目录,如果失败,则退出脚本
+cd /home/linux-tutorial/temp || exit 1
-# 查看目录路径
-current_dir=$(pwd)
-echo "当前目录是:${current_dir}"
+# 获取当前目录路径
+CURRENT_DIR=$(pwd)
+echo "当前目录是:${CURRENT_DIR}"
-# 查看目录上一级路径
-parent_dir=$(dirname $(pwd))
-echo "父目录是:${parent_dir}"
+# 获取上一级目录路径
+PARENT_DIR=$(dirname $(pwd))
+echo "父目录是:${PARENT_DIR}"
+
+# 获取当前执行脚本名
+DIR_NAME=$(basename $0)
+echo "当前执行脚本名是:${DIR_NAME}"
# 复制目录(复制 temp 目录所有内容,并命名新文件夹叫 temp2)
cp -rf /home/linux-tutorial/temp /home/linux-tutorial/temp2
diff --git a/codes/shell/文件操作/读文件.sh b/codes/shell/文件操作/读文件.sh
new file mode 100644
index 0000000..d9f14cd
--- /dev/null
+++ b/codes/shell/文件操作/读文件.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+FILE=log.txt
+
+count=1
+cat ${FILE} | while read line
+do
+ echo "$count: $line"
+ count=$[ $count + 1 ]
+done
+echo "Finished reading."
+
diff --git a/codes/shell/脚本函数/lib.sh b/codes/shell/脚本函数/lib.sh
new file mode 100644
index 0000000..ea297bb
--- /dev/null
+++ b/codes/shell/脚本函数/lib.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+
+add() {
+ echo $[ $1 + $2 ]
+}
+
+sub() {
+ echo $[ $1 - $2 ]
+}
+
+mul() {
+ echo $[ $1 * $2 ]
+}
+
+div() {
+ if [[ $2 -ne 0 ]]; then
+ echo $[ $1 / $2 ]
+ else
+ echo -1
+ fi
+}
diff --git a/codes/shell/脚本函数/使用库函数.sh b/codes/shell/脚本函数/使用库函数.sh
index d2b9e91..c479bd8 100644
--- a/codes/shell/脚本函数/使用库函数.sh
+++ b/codes/shell/脚本函数/使用库函数.sh
@@ -1,8 +1,9 @@
#!/usr/bin/env bash
-#using a library file the wrong way
+# 装载其它脚本
+source lib.sh
-../脚本库.sh
-
-result=`addem 10 15`
-echo "The result is $result"
+echo "20 + 10 = $(add 20 10)"
+echo "20 - 10 = $(sub 20 10)"
+echo "20 * 10 = $(mul 20 10)"
+echo "20 / 10 = $(div 20 10)"
diff --git a/codes/shell/脚本函数/脚本库.sh b/codes/shell/脚本函数/脚本库.sh
deleted file mode 100644
index 06cc93c..0000000
--- a/codes/shell/脚本函数/脚本库.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env bash
-
-# myscript functions
-
-function addem {
- echo $[ $1 + $2 ]
-}
-
-function multem {
- echo $[ $1 * $2 ]
-}
-
-function divem
-
-{
-if [ $2 -ne 0]; then
-echo $[ $1 / $2 ]
-else
-echo -1
-fi
-}
diff --git a/codes/shell/输入和输出/从文件中读取数据.sh b/codes/shell/输入和输出/从文件中读取数据.sh
deleted file mode 100644
index 2a63ea0..0000000
--- a/codes/shell/输入和输出/从文件中读取数据.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env bash
-
-# reading data from a file
-
-count=1
-cat test | while read line
-do
- echo "Line $count: $line"
- count=$[ $count + 1 ]
-done
-echo "Finished processing the file"
-
diff --git a/codes/shell/输入和输出/创建临时目录.sh b/codes/shell/输入和输出/创建临时目录.sh
deleted file mode 100644
index b841042..0000000
--- a/codes/shell/输入和输出/创建临时目录.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env bash
-
-# using a temporary directory
-
-tempdir=`mktemp -d dir.XXXXXX`
-cd $tempdir
-
-tempfile1=`mktemp temp.XXXXXX`
-tempfile2=`mktemp temp.XXXXXX`
-exec 7> $tempfile1
-exec 8> $tempfile2
-
-echo "Sending data to directory $tempdir"
-echo "This is a test line of data for $tempfile1" >&7
-echo "This is a test line of data for $tempfile2" >&8
-
diff --git a/codes/shell/输入和输出/在tmp目录创建临时文件.sh b/codes/shell/输入和输出/在tmp目录创建临时文件.sh
deleted file mode 100644
index 66d02dd..0000000
--- a/codes/shell/输入和输出/在tmp目录创建临时文件.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env bash
-
-# creating a temp file in /tmp
-
-tempfile=`mktemp -t tmp.XXXXXX`
-
-echo "This is a test file" > $tempfile
-echo "This is the second line of the test" >> $tempfile
-
-echo ” The temp is locate at : $tempfile “
-cat $tempfile
-rm -f $tempfile
diff --git a/docs/README.md b/docs/README.md
index a0da52b..10b2c7b 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,5 +1,7 @@
# linux-tutorial
+> 📚 **linux-tutorial** 是一个 Linux 教程。
+>
> 🔁 项目同步维护在 [github](https://github.com/dunwu/linux-tutorial) | [gitee](https://gitee.com/turnon/linux-tutorial)
>
> 📖 [电子书](https://dunwu.github.io/linux-tutorial/) | [电子书(国内)](http://turnon.gitee.io/linux-tutorial/)
diff --git a/docs/coverpage.md b/docs/coverpage.md
index 3f90a16..3ef7d97 100644
--- a/docs/coverpage.md
+++ b/docs/coverpage.md
@@ -1,7 +1,7 @@
-![logo](http://dunwu.test.upcdn.net/common/logo/zp.png)
+
# linux-tutorial
-> linux-tutorial 是一个 Linux 教程。
+> 📚 **linux-tutorial** 是一个 Linux 教程。
[开始阅读](README.md)
diff --git a/docs/docker/docker-dockerfile.md b/docs/docker/docker-dockerfile.md
index 60afc54..28bc6dc 100644
--- a/docs/docker/docker-dockerfile.md
+++ b/docs/docker/docker-dockerfile.md
@@ -658,6 +658,10 @@ FROM my-node
是的,只有这么一行。当在各个项目目录中,用这个只有一行的 `Dockerfile` 构建镜像时,之前基础镜像的那三行 `ONBUILD` 就会开始执行,成功的将当前项目的代码复制进镜像、并且针对本项目执行 `npm install`,生成应用镜像。
+
+
+有任何的问题或建议,欢迎给我留言 :laughing:
+
## 参考资料
- [Dockerfie 官方文档](https://docs.docker.com/engine/reference/builder/)
diff --git a/docs/index.html b/docs/index.html
index 94e2303..ee804fc 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -29,6 +29,7 @@
}
/*超链接悬浮样式*/
+ .cover-main a:hover,
.content a:hover,
.sidebar a:hover,
.sidebar ul li a:hover,
@@ -37,6 +38,10 @@
text-decoration: underline !important;
}
+ .sidebar-nav ul {
+ padding-left: 15px;
+ }
+
/*侧边栏样式*/
.sidebar .sidebar-nav h1 {
background-color: #f8f8f8;
@@ -44,17 +49,19 @@
padding-left: 10px;
text-align: center;
font-size: 12px;
- font-family: 'Microsoft YaHei', 'Trebuchet MS', Arial, 'Lucida Grande', Verdana, Lucida, Helvetica, sans-serif;
text-transform: uppercase;
}
/*文章标题加动态刷新颜色效果*/
+ section.cover h1 span,
.markdown-section h1 span {
+ font-weight: 600;
+ font-family: zillaslab, Palatino, 'Palatino Linotype', 'Microsoft YaHei', serif;
background-image: -webkit-linear-gradient(left, #9fa5d5, #c4cdd2 50%, #e8f5ca);
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
-webkit-background-size: 200% 100%;
- -webkit-animation: hue 3s infinite linear;
+ -webkit-animation: hue 5s infinite linear;
text-shadow: 2px 2px 2px transparent;
}
@@ -89,7 +96,8 @@
autoHeader: false,
maxLevel: 4,
subMaxLevel: 2,
- formatUpdated: '{MM}/{DD} {HH}:{mm}',
+ mergeNavbar: true,
+ formatUpdated: '{YYYY}/{MM}/{DD} {HH}:{mm}',
search: {
maxAge: 86400000,
paths: ['/'],
diff --git a/docs/sidebar.md b/docs/sidebar.md
index 9d62b48..c8cb4dc 100644
--- a/docs/sidebar.md
+++ b/docs/sidebar.md
@@ -1,5 +1,6 @@
# linux-tutorial
+- [简介](README.md)
- [**Linux 命令**](linux/cli/README.md)
- [查看 Linux 命令帮助信息](linux/cli/查看Linux命令帮助信息.md)
- [Linux 文件目录管理](linux/cli/Linux文件目录管理.md)