update
parent
e1773d60e6
commit
18d2a58725
|
@ -0,0 +1,29 @@
|
||||||
|
#!/usr/bin/expect -f
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------
|
||||||
|
# expect 交互式脚本示例 - 自动远程登录,并在其他机器上创建一个文件
|
||||||
|
# @author Zhang Peng
|
||||||
|
# -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# 设置变量
|
||||||
|
set USER "root"
|
||||||
|
set PWD "XXXXXX"
|
||||||
|
set HOST "127.0.0.2"
|
||||||
|
# 设置超时时间
|
||||||
|
set timeout 400
|
||||||
|
|
||||||
|
# 远程登录
|
||||||
|
spawn ssh -p 22 $USER@$HOST
|
||||||
|
expect {
|
||||||
|
"yes/no" { send "yes\r"; exp_continue }
|
||||||
|
"password:" { send "$PWD\r" }
|
||||||
|
}
|
||||||
|
|
||||||
|
# 在其他机器上创建
|
||||||
|
expect "#"
|
||||||
|
send "touch /home/demo.txt\r"
|
||||||
|
expect "#"
|
||||||
|
send "echo hello world >> /home/demo.txt\r"
|
||||||
|
expect "#"
|
||||||
|
# 退出
|
||||||
|
send "exit\r"
|
|
@ -1,25 +1,18 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# 构建 Docker 镜像 脚本
|
|
||||||
# @author Zhang Peng
|
|
||||||
# @since 2020/1/14
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# 装载其它库
|
|
||||||
LINUX_SCRIPTS_LIB_DIR=`dirname ${BASH_SOURCE[0]}`
|
LINUX_SCRIPTS_LIB_DIR=`dirname ${BASH_SOURCE[0]}`
|
||||||
source ${LINUX_SCRIPTS_LIB_DIR}/utils.sh
|
source ${LINUX_SCRIPTS_LIB_DIR}/utils.sh
|
||||||
|
|
||||||
dockerBuild() {
|
dockerBuild() {
|
||||||
if [[ ! $1 ]] || [[ ! $2 ]] || [[ ! $3 ]]; then
|
if [[ ! $1 ]] || [[ ! $2 ]] || [[ ! $3 ]]; then
|
||||||
logError "you must input following params in order:"
|
logError "you must input following params in order:"
|
||||||
echo -e "${C_B_RED}"
|
echo -e "${ENV_COLOR_B_RED}"
|
||||||
echo " (1) source"
|
echo " (1) source"
|
||||||
echo " (2) repository"
|
echo " (2) repository"
|
||||||
echo " (3) tag"
|
echo " (3) tag"
|
||||||
echo -e "\nEg. dockerBuild /home/workspace dunwu/dockerApp 0.0.1"
|
echo -e "\nEg. dockerBuild /home/workspace tdh60dev01:5000/fide/fide-processor fide-0.0.6-SNAPSHOT"
|
||||||
echo -e "${C_RESET}"
|
echo -e "${ENV_COLOR_RESET}"
|
||||||
return ${FAILED}
|
return ${ENV_FAILED}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local source=$1
|
local source=$1
|
||||||
|
@ -27,15 +20,15 @@ dockerBuild() {
|
||||||
local tag=$3
|
local tag=$3
|
||||||
|
|
||||||
dockerCheck ${source}
|
dockerCheck ${source}
|
||||||
if [[ "${SUCCEED}" != "$?" ]]; then
|
if [[ "${ENV_SUCCEED}" != "$?" ]]; then
|
||||||
return ${FAILED}
|
return ${ENV_FAILED}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd ${source}
|
cd ${source}
|
||||||
callAndLog docker build -t ${repository}:${tag} .
|
callAndLog docker build -t ${repository}:${tag} .
|
||||||
if [[ "${SUCCEED}" != "$?" ]]; then
|
if [[ "${ENV_SUCCEED}" != "$?" ]]; then
|
||||||
logError "docker build -t ${repository}:${tag} failed"
|
logError "docker build -t ${repository}:${tag} failed"
|
||||||
return ${FAILED}
|
return ${ENV_FAILED}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd -
|
cd -
|
||||||
|
@ -44,18 +37,17 @@ dockerBuild() {
|
||||||
dockerPush() {
|
dockerPush() {
|
||||||
if [[ ! $1 ]] || [[ ! $2 ]]; then
|
if [[ ! $1 ]] || [[ ! $2 ]]; then
|
||||||
logError "you must input following params in order:"
|
logError "you must input following params in order:"
|
||||||
echo -e "${C_B_RED}"
|
echo -e "${ENV_COLOR_B_RED}"
|
||||||
echo " (1) repository"
|
echo " (1) repository"
|
||||||
echo " (2) tag"
|
echo " (2) tag"
|
||||||
echo -e "\nEg. dockerBuild dunwu/dockerApp 0.0.1"
|
echo -e "\nEg. dockerBuild tdh60dev01:5000/fide/fide-processor fide-0.0.6-SNAPSHOT"
|
||||||
echo -e "${C_RESET}"
|
echo -e "${ENV_COLOR_RESET}"
|
||||||
return ${FAILED}
|
return ${ENV_FAILED}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local repository=$1
|
local repository=$1
|
||||||
local tag=$2
|
local tag=$2
|
||||||
|
|
||||||
# 如果 docker 镜像已存在,则删除镜像
|
|
||||||
local dockerHashId=$(docker image ls | grep ${repository} | grep ${tag} | awk '{print $3}')
|
local dockerHashId=$(docker image ls | grep ${repository} | grep ${tag} | awk '{print $3}')
|
||||||
if [[ ! ${dockerHashId} ]]; then
|
if [[ ! ${dockerHashId} ]]; then
|
||||||
logInfo "try to delete existed image: ${repository}:${tag}"
|
logInfo "try to delete existed image: ${repository}:${tag}"
|
||||||
|
@ -66,22 +58,22 @@ dockerPush() {
|
||||||
callAndLog docker push ${repository}:${tag}
|
callAndLog docker push ${repository}:${tag}
|
||||||
}
|
}
|
||||||
|
|
||||||
# 判断指定路径下是否为 docker 工程
|
# check Dockerfile
|
||||||
# @param $1: 第一个参数为 docker 项目路径
|
# @param $1: project path
|
||||||
dockerCheck() {
|
dockerCheck() {
|
||||||
local source=$1
|
local source=$1
|
||||||
if [[ -d "${source}" ]]; then
|
if [[ -d "${source}" ]]; then
|
||||||
cd ${source}
|
cd ${source}
|
||||||
if [[ -f "${source}/Dockerfile" ]]; then
|
if [[ -f "${source}/Dockerfile" ]]; then
|
||||||
return ${YES}
|
return ${ENV_YES}
|
||||||
else
|
else
|
||||||
logError "Dockerfile is not exists"
|
logError "Dockerfile is not exists"
|
||||||
return ${NO}
|
return ${ENV_NO}
|
||||||
fi
|
fi
|
||||||
cd -
|
cd -
|
||||||
return ${YES}
|
return ${ENV_YES}
|
||||||
else
|
else
|
||||||
logError "${source} is not valid docker project"
|
logError "${source} is not valid docker project"
|
||||||
return ${NO}
|
return ${ENV_NO}
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,23 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------
|
||||||
# Git 基本操作脚本
|
# git operation utils
|
||||||
# @author Zhang Peng
|
# @author Zhang Peng
|
||||||
# ------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------ load libs
|
||||||
|
|
||||||
# 装载其它库
|
|
||||||
LINUX_SCRIPTS_LIB_DIR=`dirname ${BASH_SOURCE[0]}`
|
LINUX_SCRIPTS_LIB_DIR=`dirname ${BASH_SOURCE[0]}`
|
||||||
|
|
||||||
if [[ ! -x ${LINUX_SCRIPTS_LIB_DIR}/utils.sh ]]; then
|
if [[ ! -x ${LINUX_SCRIPTS_LIB_DIR}/utils.sh ]]; then
|
||||||
logError "必要脚本库 ${LINUX_SCRIPTS_LIB_DIR}/utils.sh 不存在!"
|
logError "${LINUX_SCRIPTS_LIB_DIR}/utils.sh not exists!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
source ${LINUX_SCRIPTS_LIB_DIR}/utils.sh
|
source ${LINUX_SCRIPTS_LIB_DIR}/utils.sh
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------ git 操作函数
|
|
||||||
|
# ------------------------------------------------------------------------------ functions
|
||||||
|
|
||||||
GIT_LOCAL_BRANCH=
|
GIT_LOCAL_BRANCH=
|
||||||
getGitLocalBranch() {
|
getGitLocalBranch() {
|
||||||
|
@ -27,37 +29,36 @@ getGitOriginBranch() {
|
||||||
GIT_ORIGIN_BRANCH=$(git rev-parse --abbrev-ref --symbolic-full-name "@{u}")
|
GIT_ORIGIN_BRANCH=$(git rev-parse --abbrev-ref --symbolic-full-name "@{u}")
|
||||||
}
|
}
|
||||||
|
|
||||||
# 检查指定的路径是不是一个 git 项目
|
# check specified path is git project or not
|
||||||
checkGit() {
|
checkGit() {
|
||||||
local source=$1
|
local source=$1
|
||||||
if [[ -d "${source}" ]]; then
|
if [[ -d "${source}" ]]; then
|
||||||
cd ${source} || return ${NO}
|
cd ${source} || return ${ENV_NO}
|
||||||
# (1)删除git状态零时文件
|
# (1) delete gitstatus.tmp
|
||||||
if [[ -f "gitstatus.tmp" ]]; then
|
if [[ -f "gitstatus.tmp" ]]; then
|
||||||
rm -rf gitstatus.tmp
|
rm -rf gitstatus.tmp
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# (2)判断git是否可用
|
# (2) check git status
|
||||||
git status &> gitstatus.tmp
|
git status &> gitstatus.tmp
|
||||||
local gitStatus=false
|
local gitStatus=false
|
||||||
grep -iwq 'not a git repository' gitstatus.tmp && gitStatus=false || gitStatus=true
|
grep -iwq 'not a git repository' gitstatus.tmp && gitStatus=false || gitStatus=true
|
||||||
rm -rf gitstatus.tmp
|
rm -rf gitstatus.tmp
|
||||||
if [[ ${gitStatus} == true ]]; then
|
if [[ ${gitStatus} == true ]]; then
|
||||||
return ${YES}
|
return ${ENV_YES}
|
||||||
else
|
else
|
||||||
return ${NO}
|
return ${ENV_NO}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return ${NO}
|
return ${ENV_NO}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
logError "${source} is invalid dir."
|
logWarn "${source} is not exists."
|
||||||
return ${NO}
|
return ${ENV_NO}
|
||||||
}
|
}
|
||||||
|
|
||||||
# clone 或 fetch 操作
|
# execute git clone or fetch
|
||||||
# 如果本地代码目录已经是 git 仓库,执行 pull;若不是,则执行 clone
|
# params: Git repository, git group, git project, git branch, local path
|
||||||
# 依次传入 Git 仓库、Git 项目组、Git 项目名、分支、本地代码目录
|
|
||||||
cloneOrPullGit() {
|
cloneOrPullGit() {
|
||||||
|
|
||||||
local repository=$1
|
local repository=$1
|
||||||
|
@ -68,12 +69,12 @@ cloneOrPullGit() {
|
||||||
|
|
||||||
if [[ ! ${repository} ]] || [[ ! ${group} ]] || [[ ! ${project} ]] || [[ ! ${branch} ]] || [[ ! ${root} ]]; then
|
if [[ ! ${repository} ]] || [[ ! ${group} ]] || [[ ! ${project} ]] || [[ ! ${branch} ]] || [[ ! ${root} ]]; then
|
||||||
logError "Please input root, group, project, branch."
|
logError "Please input root, group, project, branch."
|
||||||
return ${FAILED}
|
return ${ENV_FAILED}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! -d "${root}" ]]; then
|
if [[ ! -d "${root}" ]]; then
|
||||||
logError "${root} is not directory."
|
logError "${root} is not directory."
|
||||||
return ${FAILED}
|
return ${ENV_FAILED}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local source=${root}/${group}/${project}
|
local source=${root}/${group}/${project}
|
||||||
|
@ -82,52 +83,49 @@ cloneOrPullGit() {
|
||||||
mkdir -p ${root}/${group}
|
mkdir -p ${root}/${group}
|
||||||
|
|
||||||
checkGit ${source}
|
checkGit ${source}
|
||||||
if [[ "${YES}" == "$?" ]]; then
|
if [[ "${ENV_YES}" == "$?" ]]; then
|
||||||
# 如果 ${source} 是 git 项目,执行 pull 操作
|
cd ${source} || return ${ENV_FAILED}
|
||||||
cd ${source} || return ${FAILED}
|
|
||||||
|
|
||||||
|
git fetch --all
|
||||||
git checkout -f ${branch}
|
git checkout -f ${branch}
|
||||||
if [[ "${SUCCEED}" != "$?" ]]; then
|
if [[ "${ENV_SUCCEED}" != "$?" ]]; then
|
||||||
logError "<<<< git checkout ${branch} failed."
|
logError "<<<< git checkout ${branch} failed."
|
||||||
return ${FAILED}
|
return ${ENV_FAILED}
|
||||||
fi
|
fi
|
||||||
logInfo "git checkout ${branch} succeed."
|
logInfo "git checkout ${branch} succeed."
|
||||||
|
|
||||||
getGitOriginBranch
|
getGitOriginBranch
|
||||||
git fetch --all
|
|
||||||
git reset --hard ${GIT_ORIGIN_BRANCH}
|
git reset --hard ${GIT_ORIGIN_BRANCH}
|
||||||
if [[ "${SUCCEED}" != "$?" ]]; then
|
if [[ "${ENV_SUCCEED}" != "$?" ]]; then
|
||||||
logError "<<<< git reset --hard ${GIT_ORIGIN_BRANCH} failed."
|
logError "<<<< git reset --hard ${GIT_ORIGIN_BRANCH} failed."
|
||||||
return ${FAILED}
|
return ${ENV_FAILED}
|
||||||
fi
|
fi
|
||||||
logInfo "git reset --hard ${GIT_ORIGIN_BRANCH} succeed."
|
logInfo "git reset --hard ${GIT_ORIGIN_BRANCH} succeed."
|
||||||
|
|
||||||
git pull
|
git pull
|
||||||
if [[ "${SUCCEED}" != "$?" ]]; then
|
if [[ "${ENV_SUCCEED}" != "$?" ]]; then
|
||||||
logError "<<<< git pull failed."
|
logError "<<<< git pull failed."
|
||||||
return ${FAILED}
|
return ${ENV_FAILED}
|
||||||
fi
|
fi
|
||||||
logInfo "git pull succeed."
|
logInfo "git pull succeed."
|
||||||
else
|
else
|
||||||
# 如果 ${source} 不是 git 项目,执行 clone 操作
|
|
||||||
|
|
||||||
git clone "${repository}:${group}/${project}.git" ${source}
|
git clone "${repository}:${group}/${project}.git" ${source}
|
||||||
if [[ "${SUCCEED}" != "$?" ]]; then
|
if [[ "${ENV_SUCCEED}" != "$?" ]]; then
|
||||||
logError "<<<< git clone ${project} failed."
|
logError "<<<< git clone ${project} failed."
|
||||||
return ${FAILED}
|
return ${ENV_FAILED}
|
||||||
fi
|
fi
|
||||||
logInfo "git clone ${project} succeed."
|
logInfo "git clone ${project} succeed."
|
||||||
|
|
||||||
cd ${source} || return ${FAILED}
|
cd ${source} || return ${ENV_FAILED}
|
||||||
|
|
||||||
git checkout -f ${branch}
|
git checkout -f ${branch}
|
||||||
if [[ "${SUCCEED}" != "$?" ]]; then
|
if [[ "${ENV_SUCCEED}" != "$?" ]]; then
|
||||||
logError "<<<< git checkout ${branch} failed."
|
logError "<<<< git checkout ${branch} failed."
|
||||||
return ${FAILED}
|
return ${ENV_FAILED}
|
||||||
fi
|
fi
|
||||||
logInfo "git checkout ${branch} succeed."
|
logInfo "git checkout ${branch} succeed."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
logInfo "Clone or pull git project [$2/$3:$4] succeed."
|
logInfo "Clone or pull git project [$2/$3:$4] succeed."
|
||||||
return ${SUCCEED}
|
return ${ENV_SUCCEED}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ startServer() {
|
||||||
|
|
||||||
# >>>> 3. create log dir and console log file
|
# >>>> 3. create log dir and console log file
|
||||||
mkdir -p ${LOG_PATH}
|
mkdir -p ${LOG_PATH}
|
||||||
if [[ ! -f ${CONSOLE_LOG} ]]; then
|
if [[ ! -x ${CONSOLE_LOG} ]]; then
|
||||||
touch ${CONSOLE_LOG}
|
touch ${CONSOLE_LOG}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -1,37 +1,41 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------
|
||||||
# maven 项目操作脚本
|
# maven operation utils
|
||||||
# @author Zhang Peng
|
# @author Zhang Peng
|
||||||
# ------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------ load libs
|
||||||
|
|
||||||
# 装载其它库
|
|
||||||
LINUX_SCRIPTS_LIB_DIR=`dirname ${BASH_SOURCE[0]}`
|
LINUX_SCRIPTS_LIB_DIR=`dirname ${BASH_SOURCE[0]}`
|
||||||
|
|
||||||
if [[ ! -x ${LINUX_SCRIPTS_LIB_DIR}/utils.sh ]]; then
|
if [[ ! -x ${LINUX_SCRIPTS_LIB_DIR}/utils.sh ]]; then
|
||||||
echo "必要脚本库 ${LINUX_SCRIPTS_LIB_DIR}/utils.sh 不存在!"
|
echo "${LINUX_SCRIPTS_LIB_DIR}/utils.sh not exists!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
source ${LINUX_SCRIPTS_LIB_DIR}/utils.sh
|
source ${LINUX_SCRIPTS_LIB_DIR}/utils.sh
|
||||||
|
|
||||||
# 执行 maven 操作
|
|
||||||
# @param $1: 第一个参数为 maven 项目路径
|
# ------------------------------------------------------------------------------ functions
|
||||||
# @param $2: 第二个参数为 maven 操作,如 package、install、deploy
|
|
||||||
# @param $3: 第三个参数为 maven profile 【非必填】
|
# execute maven lifecycle operation
|
||||||
|
# @param $1: maven project path
|
||||||
|
# @param $2: maven lifecycle, eg. package、install、deploy
|
||||||
|
# @param $3: maven profile [optional]
|
||||||
mavenOperation() {
|
mavenOperation() {
|
||||||
local source=$1
|
local source=$1
|
||||||
local lifecycle=$2
|
local lifecycle=$2
|
||||||
local profile=$3
|
local profile=$3
|
||||||
|
|
||||||
mavenCheck ${source}
|
mavenCheck ${source}
|
||||||
if [[ "${SUCCEED}" != "$?" ]]; then
|
if [[ "${ENV_SUCCEED}" != "$?" ]]; then
|
||||||
return ${FAILED}
|
return ${ENV_FAILED}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! "${lifecycle}" ]]; then
|
if [[ ! "${lifecycle}" ]]; then
|
||||||
logError "please input maven lifecycle"
|
logError "please input maven lifecycle"
|
||||||
return ${FAILED}
|
return ${ENV_FAILED}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local mvnCli="mvn clean ${lifecycle} -DskipTests=true -B -U"
|
local mvnCli="mvn clean ${lifecycle} -DskipTests=true -B -U"
|
||||||
|
@ -47,25 +51,25 @@ mavenOperation() {
|
||||||
|
|
||||||
callAndLog "${mvnCli}"
|
callAndLog "${mvnCli}"
|
||||||
cd -
|
cd -
|
||||||
return ${SUCCEED}
|
return ${ENV_SUCCEED}
|
||||||
}
|
}
|
||||||
|
|
||||||
# 判断指定路径下是否为 maven 工程
|
# check specified path is maven project or not
|
||||||
# @param $1: 第一个参数为 maven 项目路径
|
# @param $1: maven project path
|
||||||
mavenCheck() {
|
mavenCheck() {
|
||||||
local source=$1
|
local source=$1
|
||||||
if [[ -d "${source}" ]]; then
|
if [[ -d "${source}" ]]; then
|
||||||
cd ${source}
|
cd ${source}
|
||||||
if [[ -f "${source}/pom.xml" ]]; then
|
if [[ -f "${source}/pom.xml" ]]; then
|
||||||
return ${YES}
|
return ${ENV_YES}
|
||||||
else
|
else
|
||||||
logError "pom.xml is not exists"
|
logError "pom.xml is not exists"
|
||||||
return ${NO}
|
return ${ENV_NO}
|
||||||
fi
|
fi
|
||||||
cd -
|
cd -
|
||||||
return ${YES}
|
return ${ENV_YES}
|
||||||
else
|
else
|
||||||
logError "please input valid maven project path"
|
logError "please input valid maven project path"
|
||||||
return ${NO}
|
return ${ENV_NO}
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------
|
||||||
|
# 数据库操作脚本
|
||||||
|
# @author Zhang Peng
|
||||||
|
# -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------ 1. env
|
||||||
|
|
||||||
|
## 数据库IP
|
||||||
|
#ENV_MYSQL_HOST="127.0.0.1"
|
||||||
|
## 数据库用户名
|
||||||
|
#ENV_MYSQL_USERNAME="root"
|
||||||
|
## 数据密码
|
||||||
|
#ENV_MYSQL_PASSWORD="Tw#123456"
|
||||||
|
if [[ ! ${ENV_MYSQL_HOST} ]] || [[ ! ${ENV_MYSQL_USERNAME} ]] || [[ ! ${ENV_MYSQL_PASSWORD} ]]; then
|
||||||
|
logError "执行本脚本前必须先 export 环境变量: ENV_MYSQL_HOST, ENV_MYSQL_USERNAME, ENV_MYSQL_PASSWORD."
|
||||||
|
exit ${ENV_FAILED}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 备份模式:备份所有数据库(--all-databases)|备份指定数据库列表
|
||||||
|
MYSQL_DATABASES="${ENV_MYSQL_DATABASES:---all-databases}"
|
||||||
|
|
||||||
|
#备份路径
|
||||||
|
MYSQL_BACKUP_DIR="${ENV_MYSQL_BACKUP_DIR:-/var/lib/mysql/backup}"
|
||||||
|
#备份日志路径
|
||||||
|
export ENV_LOG_PATH="${MYSQL_BACKUP_DIR}/mysql-backup.log"
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------ 2. libs
|
||||||
|
|
||||||
|
# 装载其它库
|
||||||
|
LINUX_SCRIPTS_LIB_DIR=`dirname ${BASH_SOURCE[0]}`
|
||||||
|
|
||||||
|
if [[ ! -x ${LINUX_SCRIPTS_LIB_DIR}/utils.sh ]]; then
|
||||||
|
logError "${LINUX_SCRIPTS_LIB_DIR}/utils.sh not exists!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
source ${LINUX_SCRIPTS_LIB_DIR}/utils.sh
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------ 3. global var
|
||||||
|
|
||||||
|
# 备份文件最大数量
|
||||||
|
BACKUP_ARTIFACTS_MAX_NUM=7
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------ 4. functions
|
||||||
|
|
||||||
|
backupAllDatabase() {
|
||||||
|
|
||||||
|
#时间戳
|
||||||
|
local timestamp=$(date +"%Y%m%d")
|
||||||
|
|
||||||
|
#备份所有数据库
|
||||||
|
logInfo "正在备份所有数据库"
|
||||||
|
mysqldump -h ${ENV_MYSQL_HOST} -P${ENV_MYSQL_PORT} -u${ENV_MYSQL_USERNAME} -p${ENV_MYSQL_PASSWORD} --all-databases > "${MYSQL_BACKUP_DIR}/all-${timestamp}.sql" 2>> ${ENV_LOG_PATH};
|
||||||
|
|
||||||
|
#检查备份结果是否成功
|
||||||
|
if [[ "$?" != 0 ]]; then
|
||||||
|
logError "<<<< 备份所有数据库失败"
|
||||||
|
return ${ENV_FAILED}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 压缩备份sql文件,删除旧的备份文件
|
||||||
|
cd "${MYSQL_BACKUP_DIR}"
|
||||||
|
if [[ ! -f "${MYSQL_BACKUP_DIR}/all-${timestamp}.sql" ]]; then
|
||||||
|
logError "备份文件 ${MYSQL_BACKUP_DIR}/all-${timestamp}.sql 不存在"
|
||||||
|
return ${ENV_FAILED}
|
||||||
|
fi
|
||||||
|
#为节约硬盘空间,将数据库压缩
|
||||||
|
sudo tar zcf "all-${timestamp}.tar.gz" "all-${timestamp}.sql" > /dev/null
|
||||||
|
#删除原始文件,只留压缩后文件
|
||||||
|
sudo rm -f "all-${timestamp}.sql"
|
||||||
|
#删除七天前备份,也就是只保存7天内的备份
|
||||||
|
find "${MYSQL_BACKUP_DIR} -name all-*.tar.gz -type f -mtime +${BACKUP_ARTIFACTS_MAX_NUM} -exec rm -rf {} \;" > /dev/null 2>&1
|
||||||
|
|
||||||
|
logInfo "<<<< 备份所有数据库成功"
|
||||||
|
return ${ENV_SUCCEED}
|
||||||
|
}
|
||||||
|
|
||||||
|
backupSelectedDatabase() {
|
||||||
|
|
||||||
|
#时间戳
|
||||||
|
local timestamp=$(date +"%Y%m%d")
|
||||||
|
|
||||||
|
#数据库,如有多个库用空格分开
|
||||||
|
databaseList="${MYSQL_DATABASES}"
|
||||||
|
|
||||||
|
#备份指定数据库列表
|
||||||
|
for database in ${databaseList}; do
|
||||||
|
|
||||||
|
logInfo "正在备份数据库:${database}"
|
||||||
|
mysqldump -h ${ENV_MYSQL_HOST} -P${ENV_MYSQL_PORT} -u${ENV_MYSQL_USERNAME} -p${ENV_MYSQL_PASSWORD} "${database}" > "${MYSQL_BACKUP_DIR}/${database}-${timestamp}.sql" 2>> ${ENV_LOG_PATH};
|
||||||
|
if [[ "$?" != 0 ]]; then
|
||||||
|
logError "<<<< 备份 ${database} 失败"
|
||||||
|
return ${ENV_FAILED}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 压缩备份sql文件,删除旧的备份文件
|
||||||
|
cd "${MYSQL_BACKUP_DIR}"
|
||||||
|
if [[ ! -f "${MYSQL_BACKUP_DIR}/${database}-${timestamp}.sql" ]]; then
|
||||||
|
logError "备份文件 ${MYSQL_BACKUP_DIR}/${database}-${timestamp}.sql 不存在"
|
||||||
|
return ${ENV_FAILED}
|
||||||
|
fi
|
||||||
|
#为节约硬盘空间,将数据库压缩
|
||||||
|
sudo tar zcf "${database}-${timestamp}.tar.gz" "${database}-${timestamp}.sql" > /dev/null
|
||||||
|
#删除原始文件,只留压缩后文件
|
||||||
|
sudo rm -f "${database}-${timestamp}.sql"
|
||||||
|
#删除七天前备份,也就是只保存7天内的备份
|
||||||
|
find "${MYSQL_BACKUP_DIR} -name ${database}-*.tar.gz -type f -mtime +${BACKUP_ARTIFACTS_MAX_NUM} -exec rm -rf {} \;" > /dev/null 2>&1
|
||||||
|
done
|
||||||
|
|
||||||
|
logInfo "<<<< 备份数据库 ${MYSQL_DATABASES} 成功"
|
||||||
|
return ${ENV_SUCCEED}
|
||||||
|
}
|
||||||
|
|
||||||
|
backupMysql() {
|
||||||
|
|
||||||
|
#日志记录头部
|
||||||
|
sudo mkdir -p ${MYSQL_BACKUP_DIR}
|
||||||
|
touch ${ENV_LOG_PATH}
|
||||||
|
|
||||||
|
logInfo "------------------------------------------------------------------"
|
||||||
|
logInfo ">>>> 备份数据库开始"
|
||||||
|
|
||||||
|
#正式备份数据库
|
||||||
|
if [[ ${MYSQL_DATABASES} == "--all-databases" ]]; then
|
||||||
|
backupAllDatabase
|
||||||
|
else
|
||||||
|
backupSelectedDatabase
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
recoveryMysql() {
|
||||||
|
|
||||||
|
logInfo "------------------------------------------------------------------"
|
||||||
|
logInfo ">>>> 恢复数据库开始"
|
||||||
|
|
||||||
|
if [[ ! -f ${ENV_SQL_FILE_PATH} ]]; then
|
||||||
|
logError "sql 文件 ${ENV_SQL_FILE_PATH} 不存在"
|
||||||
|
return ${ENV_FAILED}
|
||||||
|
fi
|
||||||
|
|
||||||
|
mysql -h ${ENV_MYSQL_HOST} -P${ENV_MYSQL_PORT} -u${ENV_MYSQL_USERNAME} -p${ENV_MYSQL_PASSWORD} < ${ENV_SQL_FILE_PATH}
|
||||||
|
if [[ "$?" != 0 ]]; then
|
||||||
|
logError "<<<< 恢复数据库失败"
|
||||||
|
return ${ENV_FAILED}
|
||||||
|
fi
|
||||||
|
|
||||||
|
logInfo "<<<< 恢复数据库成功"
|
||||||
|
return ${ENV_SUCCEED}
|
||||||
|
}
|
|
@ -1,118 +1,113 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------
|
||||||
# Shell Utils
|
# Shell Utils
|
||||||
# @author Zhang Peng
|
# @author Zhang Peng
|
||||||
# ------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------ 颜色状态
|
# ------------------------------------------------------------------------------ env
|
||||||
|
|
||||||
# Regular Color
|
# Regular Color
|
||||||
export C_BLACK="\033[0;30m"
|
export ENV_COLOR_BLACK="\033[0;30m"
|
||||||
export C_RED="\033[0;31m"
|
export ENV_COLOR_RED="\033[0;31m"
|
||||||
export C_GREEN="\033[0;32m"
|
export ENV_COLOR_GREEN="\033[0;32m"
|
||||||
export C_YELLOW="\033[0;33m"
|
export ENV_COLOR_YELLOW="\033[0;33m"
|
||||||
export C_BLUE="\033[0;34m"
|
export ENV_COLOR_BLUE="\033[0;34m"
|
||||||
export C_MAGENTA="\033[0;35m"
|
export ENV_COLOR_MAGENTA="\033[0;35m"
|
||||||
export C_CYAN="\033[0;36m"
|
export ENV_COLOR_CYAN="\033[0;36m"
|
||||||
export C_WHITE="\033[0;37m"
|
export ENV_COLOR_WHITE="\033[0;37m"
|
||||||
|
|
||||||
# Bold Color
|
# Bold Color
|
||||||
export C_B_BLACK="\033[1;30m"
|
export ENV_COLOR_B_BLACK="\033[1;30m"
|
||||||
export C_B_RED="\033[1;31m"
|
export ENV_COLOR_B_RED="\033[1;31m"
|
||||||
export C_B_GREEN="\033[1;32m"
|
export ENV_COLOR_B_GREEN="\033[1;32m"
|
||||||
export C_B_YELLOW="\033[1;33m"
|
export ENV_COLOR_B_YELLOW="\033[1;33m"
|
||||||
export C_B_BLUE="\033[1;34m"
|
export ENV_COLOR_B_BLUE="\033[1;34m"
|
||||||
export C_B_MAGENTA="\033[1;35m"
|
export ENV_COLOR_B_MAGENTA="\033[1;35m"
|
||||||
export C_B_CYAN="\033[1;36m"
|
export ENV_COLOR_B_CYAN="\033[1;36m"
|
||||||
export C_B_WHITE="\033[1;37m"
|
export ENV_COLOR_B_WHITE="\033[1;37m"
|
||||||
|
|
||||||
# Underline Color
|
# Underline Color
|
||||||
export C_U_BLACK="\033[4;30m"
|
export ENV_COLOR_U_BLACK="\033[4;30m"
|
||||||
export C_U_RED="\033[4;31m"
|
export ENV_COLOR_U_RED="\033[4;31m"
|
||||||
export C_U_GREEN="\033[4;32m"
|
export ENV_COLOR_U_GREEN="\033[4;32m"
|
||||||
export C_U_YELLOW="\033[4;33m"
|
export ENV_COLOR_U_YELLOW="\033[4;33m"
|
||||||
export C_U_BLUE="\033[4;34m"
|
export ENV_COLOR_U_BLUE="\033[4;34m"
|
||||||
export C_U_MAGENTA="\033[4;35m"
|
export ENV_COLOR_U_MAGENTA="\033[4;35m"
|
||||||
export C_U_CYAN="\033[4;36m"
|
export ENV_COLOR_U_CYAN="\033[4;36m"
|
||||||
export C_U_WHITE="\033[4;37m"
|
export ENV_COLOR_U_WHITE="\033[4;37m"
|
||||||
|
|
||||||
# Background Color
|
# Background Color
|
||||||
export C_BG_BLACK="\033[40m"
|
export ENV_COLOR_BG_BLACK="\033[40m"
|
||||||
export C_BG_RED="\033[41m"
|
export ENV_COLOR_BG_RED="\033[41m"
|
||||||
export C_BG_GREEN="\033[42m"
|
export ENV_COLOR_BG_GREEN="\033[42m"
|
||||||
export C_BG_YELLOW="\033[43m"
|
export ENV_COLOR_BG_YELLOW="\033[43m"
|
||||||
export C_BG_BLUE="\033[44m"
|
export ENV_COLOR_BG_BLUE="\033[44m"
|
||||||
export C_BG_MAGENTA="\033[45m"
|
export ENV_COLOR_BG_MAGENTA="\033[45m"
|
||||||
export C_BG_CYAN="\033[46m"
|
export ENV_COLOR_BG_CYAN="\033[46m"
|
||||||
export C_BG_WHITE="\033[47m"
|
export ENV_COLOR_BG_WHITE="\033[47m"
|
||||||
|
|
||||||
# Reset Color
|
# Reset Color
|
||||||
export C_RESET="$(tput sgr0)"
|
export ENV_COLOR_RESET="$(tput sgr0)"
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------ 常用状态值
|
# status
|
||||||
|
export ENV_YES=0
|
||||||
|
export ENV_NO=1
|
||||||
|
export ENV_SUCCEED=0
|
||||||
|
export ENV_FAILED=1
|
||||||
|
|
||||||
export YES=0
|
|
||||||
export NO=1
|
|
||||||
export SUCCEED=0
|
|
||||||
export FAILED=1
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------ 常用状态值
|
# ------------------------------------------------------------------------------ functions
|
||||||
|
|
||||||
# 显示打印日志的时间
|
# 显示打印日志的时间
|
||||||
DATE=$(date "+%Y-%m-%d %H:%M:%S")
|
SHELL_LOG_TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
|
||||||
# 那个用户在操作
|
# 那个用户在操作
|
||||||
USER=$(whoami)
|
USER=$(whoami)
|
||||||
# 日志路径
|
# 日志路径
|
||||||
LOG_DIR=/var/log/dunwu
|
LOG_PATH=${ENV_LOG_PATH:-/var/log/shell.log}
|
||||||
LOG_PATH=${LOG_DIR}/shell.log
|
# 日志目录
|
||||||
|
LOG_DIR=${LOG_PATH%/*}
|
||||||
|
|
||||||
createLogFileIfNotExists() {
|
createLogFileIfNotExists() {
|
||||||
if [[ ! -f "${LOG_PATH}" ]]; then
|
if [[ ! -x "${LOG_PATH}" ]]; then
|
||||||
sudo mkdir -p "${LOG_DIR}"
|
mkdir -p "${LOG_DIR}"
|
||||||
touch "${LOG_PATH}"
|
touch "${LOG_PATH}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
logInfo() {
|
logInfo() {
|
||||||
echo -e "${C_B_GREEN}[INFO] $@${C_RESET}"
|
echo -e "${ENV_COLOR_B_GREEN}[INFO] $@${ENV_COLOR_RESET}"
|
||||||
createLogFileIfNotExists
|
createLogFileIfNotExists
|
||||||
echo "[${DATE}] [${USER}] [INFO] [$0] [$@] execute succeed." >> "${LOG_PATH}"
|
echo "[${SHELL_LOG_TIMESTAMP}] [${USER}] [INFO] [$0] $@" >> "${LOG_PATH}"
|
||||||
}
|
}
|
||||||
|
|
||||||
logWarn() {
|
logWarn() {
|
||||||
echo -e "${C_B_YELLOW}[WARN] $@${C_RESET}"
|
echo -e "${ENV_COLOR_B_YELLOW}[WARN] $@${ENV_COLOR_RESET}"
|
||||||
createLogFileIfNotExists
|
createLogFileIfNotExists
|
||||||
echo "[${DATE}] [${USER}] [WARN] [$0] [$@] execute succeed." >> "${LOG_PATH}"
|
echo "[${SHELL_LOG_TIMESTAMP}] [${USER}] [WARN] [$0] $@" >> "${LOG_PATH}"
|
||||||
}
|
}
|
||||||
|
|
||||||
logError() {
|
logError() {
|
||||||
echo -e "${C_B_RED}[ERROR] $@${C_RESET}"
|
echo -e "${ENV_COLOR_B_RED}[ERROR] $@${ENV_COLOR_RESET}"
|
||||||
createLogFileIfNotExists
|
createLogFileIfNotExists
|
||||||
echo "[${DATE}] [${USER}] [ERROR] [$0] [$@] execute failed." >> "${LOG_PATH}"
|
echo "[${SHELL_LOG_TIMESTAMP}] [${USER}] [ERROR] [$0] $@" >> "${LOG_PATH}"
|
||||||
}
|
}
|
||||||
|
|
||||||
printInfo() {
|
printInfo() {
|
||||||
echo -e "${C_B_GREEN}[INFO] $@${C_RESET}"
|
echo -e "${ENV_COLOR_B_GREEN}[INFO] $@${ENV_COLOR_RESET}"
|
||||||
}
|
}
|
||||||
|
|
||||||
printWarn() {
|
printWarn() {
|
||||||
echo -e "${C_B_YELLOW}[WARN] $@${C_RESET}"
|
echo -e "${ENV_COLOR_B_YELLOW}[WARN] $@${ENV_COLOR_RESET}"
|
||||||
}
|
}
|
||||||
|
|
||||||
printError() {
|
printError() {
|
||||||
echo -e "${C_B_RED}[ERROR] $@${C_RESET}"
|
echo -e "${ENV_COLOR_B_RED}[ERROR] $@${ENV_COLOR_RESET}"
|
||||||
}
|
}
|
||||||
|
|
||||||
callAndLog () {
|
callAndLog () {
|
||||||
$*
|
$*
|
||||||
if [[ $? -eq ${SUCCEED} ]]; then
|
if [[ $? -eq ${ENV_SUCCEED} ]]; then
|
||||||
logInfo "$@ succeed"
|
logInfo "$@"
|
||||||
echo -e "${C_B_GREEN}[INFO] [$0] [$@] execute succeed.${C_RESET}"
|
return ${ENV_SUCCEED}
|
||||||
return ${SUCCEED}
|
|
||||||
else
|
else
|
||||||
logError "$@ failed"
|
logError "$@ EXECUTE FAILED"
|
||||||
echo -e "${C_B_RED}[ERROR] [$0] [$@] execute failed.${C_RESET}"
|
return ${ENV_FAILED}
|
||||||
return ${FAILED}
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
path=/dir1/dir2/dir3/test.txt
|
||||||
|
echo ${path##*/} 获取文件名 test.txt
|
||||||
|
echo ${path##*.} 获取后缀 txt
|
||||||
|
|
||||||
|
#不带后缀的文件名
|
||||||
|
temp=${path##*/}
|
||||||
|
echo ${temp%.*} test
|
||||||
|
|
||||||
|
#获取目录
|
||||||
|
echo ${path%/*} /dir1/dir2/dir3
|
|
@ -30,7 +30,7 @@ module.exports = {
|
||||||
}, {
|
}, {
|
||||||
text: "Docker 教程", link: "/docker/",
|
text: "Docker 教程", link: "/docker/",
|
||||||
}, {
|
}, {
|
||||||
text: "博客", link: "https://github.com/dunwu/blog", target: "_blank", rel: ""
|
text: "🎯 博客", link: "https://github.com/dunwu/blog", target: "_blank", rel: ""
|
||||||
}], sidebar: "auto", sidebarDepth: 2
|
}], sidebar: "auto", sidebarDepth: 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,31 +19,31 @@ footer: CC-BY-SA-4.0 Licensed | Copyright © 2018-Now Dunwu
|
||||||
|
|
||||||
### Linux 命令
|
### Linux 命令
|
||||||
|
|
||||||
> 学习 Linux 的第一步:当然是从 [Linux 命令](docs/linux/cli/README.md) 入手了。
|
> 学习 Linux 的第一步:当然是从 [Linux 命令](linux/cli/README.md) 入手了。
|
||||||
|
|
||||||
- [查看 Linux 命令帮助信息](docs/linux/cli/linux-cli-help.md) - 关键词:`help`, `whatis`, `info`, `which`, `whereis`, `man`
|
- [查看 Linux 命令帮助信息](linux/cli/linux-cli-help.md) - 关键词:`help`, `whatis`, `info`, `which`, `whereis`, `man`
|
||||||
- [Linux 文件目录管理](docs/linux/cli/linux-cli-dir.md) - 关键词:`cd`, `ls`, `pwd`, `mkdir`, `rmdir`, `tree`, `touch`, `ln`, `rename`, `stat`, `file`, `chmod`, `chown`, `locate`, `find`, `cp`, `mv`, `rm`
|
- [Linux 文件目录管理](linux/cli/linux-cli-dir.md) - 关键词:`cd`, `ls`, `pwd`, `mkdir`, `rmdir`, `tree`, `touch`, `ln`, `rename`, `stat`, `file`, `chmod`, `chown`, `locate`, `find`, `cp`, `mv`, `rm`
|
||||||
- [Linux 文件内容查看命令](docs/linux/cli/linux-cli-file.md) - 关键词:`cat`, `head`, `tail`, `more`, `less`, `sed`, `vi`, `grep`
|
- [Linux 文件内容查看命令](linux/cli/linux-cli-file.md) - 关键词:`cat`, `head`, `tail`, `more`, `less`, `sed`, `vi`, `grep`
|
||||||
- [Linux 文件压缩和解压](docs/linux/cli/linux-cli-file-compress.md) - 关键词:`tar`, `gzip`, `zip`, `unzip`
|
- [Linux 文件压缩和解压](linux/cli/linux-cli-file-compress.md) - 关键词:`tar`, `gzip`, `zip`, `unzip`
|
||||||
- [Linux 用户管理](docs/linux/cli/linux-cli-user.md) - 关键词:`groupadd`, `groupdel`, `groupmod`, `useradd`, `userdel`, `usermod`, `passwd`, `su`, `sudo`
|
- [Linux 用户管理](linux/cli/linux-cli-user.md) - 关键词:`groupadd`, `groupdel`, `groupmod`, `useradd`, `userdel`, `usermod`, `passwd`, `su`, `sudo`
|
||||||
- [Linux 系统管理](docs/linux/cli/linux-cli-system.md) - 关键词:`reboot`, `exit`, `shutdown`, `date`, `mount`, `umount`, `ps`, `kill`, `systemctl`, `service`, `crontab`
|
- [Linux 系统管理](linux/cli/linux-cli-system.md) - 关键词:`reboot`, `exit`, `shutdown`, `date`, `mount`, `umount`, `ps`, `kill`, `systemctl`, `service`, `crontab`
|
||||||
- [Linux 网络管理](docs/linux/cli/linux-cli-net.md) - 关键词:关键词:`curl`, `wget`, `telnet`, `ip`, `hostname`, `ifconfig`, `route`, `ssh`, `ssh-keygen`, `firewalld`, `iptables`, `host`, `nslookup`, `nc`/`netcat`, `ping`, `traceroute`, `netstat`
|
- [Linux 网络管理](linux/cli/linux-cli-net.md) - 关键词:关键词:`curl`, `wget`, `telnet`, `ip`, `hostname`, `ifconfig`, `route`, `ssh`, `ssh-keygen`, `firewalld`, `iptables`, `host`, `nslookup`, `nc`/`netcat`, `ping`, `traceroute`, `netstat`
|
||||||
- [Linux 硬件管理](docs/linux/cli/linux-cli-hardware.md) - 关键词:`df`, `du`, `top`, `free`, `iotop`
|
- [Linux 硬件管理](linux/cli/linux-cli-hardware.md) - 关键词:`df`, `du`, `top`, `free`, `iotop`
|
||||||
- [Linux 软件管理](docs/linux/cli/linux-cli-software.md) - 关键词:`rpm`, `yum`, `apt-get`
|
- [Linux 软件管理](linux/cli/linux-cli-software.md) - 关键词:`rpm`, `yum`, `apt-get`
|
||||||
|
|
||||||
### Linux 运维
|
### Linux 运维
|
||||||
|
|
||||||
> Linux 系统的常见运维工作。
|
> Linux 系统的常见运维工作。
|
||||||
|
|
||||||
- [网络运维](docs/linux/ops/network-ops.md)
|
- [网络运维](linux/ops/network-ops.md)
|
||||||
- [Samba](docs/linux/ops/samba.md)
|
- [Samba](linux/ops/samba.md)
|
||||||
- [NTP](docs/linux/ops/ntp.md)
|
- [NTP](linux/ops/ntp.md)
|
||||||
- [Firewalld](docs/linux/ops/firewalld.md)
|
- [Firewalld](linux/ops/firewalld.md)
|
||||||
- [Crontab](docs/linux/ops/crontab.md)
|
- [Crontab](linux/ops/crontab.md)
|
||||||
- [Systemd](docs/linux/ops/systemd.md)
|
- [Systemd](linux/ops/systemd.md)
|
||||||
- [Vim](docs/linux/ops/vim.md)
|
- [Vim](linux/ops/vim.md)
|
||||||
- [Iptables](docs/linux/ops/iptables.md)
|
- [Iptables](linux/ops/iptables.md)
|
||||||
- [oh-my-zsh](docs/linux/ops/zsh.md)
|
- [oh-my-zsh](linux/ops/zsh.md)
|
||||||
|
|
||||||
### 软件运维
|
### 软件运维
|
||||||
|
|
||||||
|
@ -52,34 +52,34 @@ footer: CC-BY-SA-4.0 Licensed | Copyright © 2018-Now Dunwu
|
||||||
> 配套安装脚本:⌨ [软件运维配置脚本集合](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/soft)
|
> 配套安装脚本:⌨ [软件运维配置脚本集合](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/soft)
|
||||||
|
|
||||||
- 开发环境
|
- 开发环境
|
||||||
- [JDK 安装](docs/linux/soft/jdk-install.md)
|
- [JDK 安装](linux/soft/jdk-install.md)
|
||||||
- [Maven 安装](docs/linux/soft/maven-install.md)
|
- [Maven 安装](linux/soft/maven-install.md)
|
||||||
- [Nodejs 安装](docs/linux/soft/nodejs-install.md)
|
- [Nodejs 安装](linux/soft/nodejs-install.md)
|
||||||
- 开发工具
|
- 开发工具
|
||||||
- [Nexus 运维](docs/linux/soft/nexus-ops.md)
|
- [Nexus 运维](linux/soft/nexus-ops.md)
|
||||||
- [Gitlab 运维](docs/linux/soft/kafka-install.md)
|
- [Gitlab 运维](linux/soft/kafka-install.md)
|
||||||
- [Jenkins 运维](docs/linux/soft/jenkins.md)
|
- [Jenkins 运维](linux/soft/jenkins.md)
|
||||||
- [Svn 运维](docs/linux/soft/svn-ops.md)
|
- [Svn 运维](linux/soft/svn-ops.md)
|
||||||
- [YApi 运维](docs/linux/soft/yapi-ops.md)
|
- [YApi 运维](linux/soft/yapi-ops.md)
|
||||||
- 中间件服务
|
- 中间件服务
|
||||||
- [Elastic 运维](docs/linux/soft/elastic)
|
- [Elastic 运维](linux/soft/elastic)
|
||||||
- [Kafka 运维](docs/linux/soft/kafka-install.md)
|
- [Kafka 运维](linux/soft/kafka-install.md)
|
||||||
- [RocketMQ 运维](docs/linux/soft/rocketmq-install.md)
|
- [RocketMQ 运维](linux/soft/rocketmq-install.md)
|
||||||
- [Zookeeper 运维](https://github.com/dunwu/javatech/blob/master/docs/technology/monitor/zookeeper-ops.md)
|
- [Zookeeper 运维](https://github.com/dunwu/javatech/blob/master/docs/technology/monitor/zookeeper-ops.md)
|
||||||
- [Nacos 运维](docs/linux/soft/nacos-install.md)
|
- [Nacos 运维](linux/soft/nacos-install.md)
|
||||||
- 服务器
|
- 服务器
|
||||||
- [Nginx 教程](https://github.com/dunwu/nginx-tutorial) 📚
|
- [Nginx 教程](https://github.com/dunwu/nginx-tutorial) 📚
|
||||||
- [Tomcat 运维](docs/linux/soft/tomcat-install.md)
|
- [Tomcat 运维](linux/soft/tomcat-install.md)
|
||||||
- [数据库](https://github.com/dunwu/db-tutorial) 📚
|
- [数据库](https://github.com/dunwu/db-tutorial) 📚
|
||||||
- [Mysql 运维](https://github.com/dunwu/db-tutorial/blob/master/docs/sql/mysql/mysql-ops.md)
|
- [Mysql 运维](https://github.com/dunwu/db-tutorial/blob/master/docs/sql/mysql/mysql-ops.md)
|
||||||
- [Redis 运维](https://github.com/dunwu/db-tutorial/blob/master/docs/nosql/redis/redis-ops.md)
|
- [Redis 运维](https://github.com/dunwu/db-tutorial/blob/master/docs/nosql/redis/redis-ops.md)
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
|
||||||
- [Docker 快速入门](docs/docker/docker-quickstart.md)
|
- [Docker 快速入门](docker/docker-quickstart.md)
|
||||||
- [Dockerfile 最佳实践](docs/docker/docker-dockerfile.md)
|
- [Dockerfile 最佳实践](docker/docker-dockerfile.md)
|
||||||
- [Docker Cheat Sheet](docs/docker/docker-cheat-sheet.md)
|
- [Docker Cheat Sheet](docker/docker-cheat-sheet.md)
|
||||||
- [Kubernetes 应用指南](docs/docker/kubernetes.md)
|
- [Kubernetes 应用指南](docker/kubernetes.md)
|
||||||
|
|
||||||
### 其他
|
### 其他
|
||||||
|
|
||||||
|
@ -103,4 +103,4 @@ footer: CC-BY-SA-4.0 Licensed | Copyright © 2018-Now Dunwu
|
||||||
|
|
||||||
## 🚪 传送门
|
## 🚪 传送门
|
||||||
|
|
||||||
◾ 🏠 [DB-TUTORIAL 首页](https://github.com/dunwu/linux-tutorial) ◾ 🎯 [我的博客](https://github.com/dunwu/blog) ◾
|
◾ 🏠 [LINUX-TUTORIAL 首页](https://github.com/dunwu/linux-tutorial) ◾ 🎯 [我的博客](https://github.com/dunwu/blog) ◾
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
# free
|
||||||
|
|
||||||
|
显示内存的使用情况
|
||||||
|
|
||||||
|
## 补充说明
|
||||||
|
|
||||||
|
**free 命令** 可以显示当前系统未使用的和已使用的内存数目,还可以显示被内核使用的内存缓冲区。
|
||||||
|
|
||||||
|
### 语法
|
||||||
|
|
||||||
|
```shell
|
||||||
|
free(选项)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
```shell
|
||||||
|
-b # 以Byte为单位显示内存使用情况;
|
||||||
|
-k # 以KB为单位显示内存使用情况;
|
||||||
|
-m # 以MB为单位显示内存使用情况;
|
||||||
|
-g # 以GB为单位显示内存使用情况。
|
||||||
|
-o # 不显示缓冲区调节列;
|
||||||
|
-s<间隔秒数> # 持续观察内存使用状况;
|
||||||
|
-t # 显示内存总和列;
|
||||||
|
-V # 显示版本信息。
|
||||||
|
```
|
||||||
|
|
||||||
|
### 实例
|
||||||
|
|
||||||
|
```shell
|
||||||
|
free -t # 以总和的形式显示内存的使用信息
|
||||||
|
free -s 10 # 周期性的查询内存使用信息,每10s 执行一次命令
|
||||||
|
```
|
||||||
|
|
||||||
|
显示内存使用情况
|
||||||
|
|
||||||
|
```shell
|
||||||
|
free -m
|
||||||
|
total used free shared buffers cached
|
||||||
|
Mem: 2016 1973 42 0 163 1497
|
||||||
|
-/+ buffers/cache: 312 1703
|
||||||
|
Swap: 4094 0 4094
|
||||||
|
```
|
||||||
|
|
||||||
|
**第一部分 Mem 行解释:**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
total:内存总数;
|
||||||
|
used:已经使用的内存数;
|
||||||
|
free:空闲的内存数;
|
||||||
|
shared:当前已经废弃不用;
|
||||||
|
buffers Buffer:缓存内存数;
|
||||||
|
cached Page:缓存内存数。
|
||||||
|
```
|
||||||
|
|
||||||
|
关系:total = used + free
|
||||||
|
|
||||||
|
**第二部分(-/+ buffers/cache)解释:**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
(-buffers/cache) used内存数:第一部分Mem行中的 used – buffers – cached
|
||||||
|
(+buffers/cache) free内存数: 第一部分Mem行中的 free + buffers + cached
|
||||||
|
```
|
||||||
|
|
||||||
|
可见-buffers/cache 反映的是被程序实实在在吃掉的内存,而+buffers/cache 反映的是可以挪用的内存总数。
|
||||||
|
|
||||||
|
第三部分是指交换分区。
|
||||||
|
|
||||||
|
输出结果的第四行是交换分区 SWAP 的,也就是我们通常所说的虚拟内存。
|
||||||
|
区别:第二行(mem)的 used/free 与第三行(-/+ buffers/cache) used/free 的区别。 这两个的区别在于使用的角度来看,第一行是从 OS 的角度来看,因为对于 OS,buffers/cached 都是属于被使用,所以他的可用内存是 2098428KB,已用内存是 30841684KB,其中包括,内核(OS)使用+Application(X, oracle,etc)使用的+buffers+cached.
|
||||||
|
|
||||||
|
第三行所指的是从应用程序角度来看,对于应用程序来说,buffers/cached 是等于可用的,因为 buffer/cached 是为了提高文件读取的性能,当应用程序需在用到内存的时候,buffer/cached 会很快地被回收。
|
||||||
|
|
||||||
|
所以从应用程序的角度来说,可用内存=系统 free memory+buffers+cached。
|
||||||
|
如本机情况的可用内存为:
|
||||||
|
|
||||||
|
18007156=2098428KB+4545340KB+11363424KB
|
||||||
|
|
||||||
|
接下来解释什么时候内存会被交换,以及按什么方交换。
|
||||||
|
|
||||||
|
当可用内存少于额定值的时候,就会开会进行交换。如何看额定值:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cat /proc/meminfo
|
||||||
|
|
||||||
|
MemTotal: 16140816 kB
|
||||||
|
MemFree: 816004 kB
|
||||||
|
MemAvailable: 2913824 kB
|
||||||
|
Buffers: 17912 kB
|
||||||
|
Cached: 2239076 kB
|
||||||
|
SwapCached: 0 kB
|
||||||
|
Active: 12774804 kB
|
||||||
|
Inactive: 1594328 kB
|
||||||
|
Active(anon): 12085544 kB
|
||||||
|
Inactive(anon): 94572 kB
|
||||||
|
Active(file): 689260 kB
|
||||||
|
Inactive(file): 1499756 kB
|
||||||
|
Unevictable: 116888 kB
|
||||||
|
Mlocked: 116888 kB
|
||||||
|
SwapTotal: 8191996 kB
|
||||||
|
SwapFree: 8191996 kB
|
||||||
|
Dirty: 56 kB
|
||||||
|
Writeback: 0 kB
|
||||||
|
AnonPages: 12229228 kB
|
||||||
|
Mapped: 117136 kB
|
||||||
|
Shmem: 58736 kB
|
||||||
|
Slab: 395568 kB
|
||||||
|
SReclaimable: 246700 kB
|
||||||
|
SUnreclaim: 148868 kB
|
||||||
|
KernelStack: 30496 kB
|
||||||
|
PageTables: 165104 kB
|
||||||
|
NFS_Unstable: 0 kB
|
||||||
|
Bounce: 0 kB
|
||||||
|
WritebackTmp: 0 kB
|
||||||
|
CommitLimit: 16262404 kB
|
||||||
|
Committed_AS: 27698600 kB
|
||||||
|
VmallocTotal: 34359738367 kB
|
||||||
|
VmallocUsed: 311072 kB
|
||||||
|
VmallocChunk: 34350899200 kB
|
||||||
|
HardwareCorrupted: 0 kB
|
||||||
|
AnonHugePages: 3104768 kB
|
||||||
|
HugePages_Total: 0
|
||||||
|
HugePages_Free: 0
|
||||||
|
HugePages_Rsvd: 0
|
||||||
|
HugePages_Surp: 0
|
||||||
|
Hugepagesize: 2048 kB
|
||||||
|
DirectMap4k: 225536 kB
|
||||||
|
DirectMap2M: 13279232 kB
|
||||||
|
DirectMap1G: 5242880 kB
|
||||||
|
```
|
||||||
|
|
||||||
|
交换将通过三个途径来减少系统中使用的物理页面的个数:
|
||||||
|
|
||||||
|
1. 减少缓冲与页面 cache 的大小,
|
||||||
|
2. 将系统 V 类型的内存页面交换出去,
|
||||||
|
3. 换出或者丢弃页面。(Application 占用的内存页,也就是物理内存不足)。
|
||||||
|
|
||||||
|
事实上,少量地使用 swap 是不是影响到系统性能的。
|
||||||
|
|
||||||
|
那 buffers 和 cached 都是缓存,两者有什么区别呢?
|
||||||
|
|
||||||
|
为了提高磁盘存取效率, Linux 做了一些精心的设计, 除了对 dentry 进行缓存(用于 VFS,加速文件路径名到 inode 的转换), 还采取了两种主要 Cache 方式:
|
||||||
|
|
||||||
|
Buffer Cache 和 Page Cache。前者针对磁盘块的读写,后者针对文件 inode 的读写。这些 Cache 有效缩短了 I/O 系统调用(比如 read,write,getdents)的时间。
|
||||||
|
磁盘的操作有逻辑级(文件系统)和物理级(磁盘块),这两种 Cache 就是分别缓存逻辑和物理级数据的。
|
||||||
|
|
||||||
|
Page cache 实际上是针对文件系统的,是文件的缓存,在文件层面上的数据会缓存到 page cache。文件的逻辑层需要映射到实际的物理磁盘,这种映射关系由文件系统来完成。当 page cache 的数据需要刷新时,page cache 中的数据交给 buffer cache,因为 Buffer Cache 就是缓存磁盘块的。但是这种处理在 2.6 版本的内核之后就变的很简单了,没有真正意义上的 cache 操作。
|
||||||
|
|
||||||
|
Buffer cache 是针对磁盘块的缓存,也就是在没有文件系统的情况下,直接对磁盘进行操作的数据会缓存到 buffer cache 中,例如,文件系统的元数据都会缓存到 buffer cache 中。
|
||||||
|
|
||||||
|
简单说来,page cache 用来缓存文件数据,buffer cache 用来缓存磁盘数据。在有文件系统的情况下,对文件操作,那么数据会缓存到 page cache,如果直接采用 dd 等工具对磁盘进行读写,那么数据会缓存到 buffer cache。
|
||||||
|
|
||||||
|
所以我们看 linux,只要不用 swap 的交换空间,就不用担心自己的内存太少.如果常常 swap 用很多,可能你就要考虑加物理内存了.这也是 linux 看内存是否够用的标准.
|
||||||
|
|
||||||
|
如果是应用服务器的话,一般只看第二行,+buffers/cache,即对应用程序来说 free 的内存太少了,也是该考虑优化程序或加内存了。
|
|
@ -0,0 +1,245 @@
|
||||||
|
# grep
|
||||||
|
|
||||||
|
强大的文本搜索工具
|
||||||
|
|
||||||
|
## 补充说明
|
||||||
|
|
||||||
|
**grep** (global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。用于过滤/搜索的特定字符。可使用正则表达式能多种命令配合使用,使用上十分灵活。
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
```shell
|
||||||
|
-a --text # 不要忽略二进制数据。
|
||||||
|
-A <显示行数> --after-context=<显示行数> # 除了显示符合范本样式的那一行之外,并显示该行之后的内容。
|
||||||
|
-b --byte-offset # 在显示符合范本样式的那一行之外,并显示该行之前的内容。
|
||||||
|
-B<显示行数> --before-context=<显示行数> # 除了显示符合样式的那一行之外,并显示该行之前的内容。
|
||||||
|
-c --count # 计算符合范本样式的列数。
|
||||||
|
-C<显示行数> --context=<显示行数>或-<显示行数> # 除了显示符合范本样式的那一列之外,并显示该列之前后的内容。
|
||||||
|
-d<进行动作> --directories=<动作> # 当指定要查找的是目录而非文件时,必须使用这项参数,否则grep命令将回报信息并停止动作。
|
||||||
|
-e<范本样式> --regexp=<范本样式> # 指定字符串作为查找文件内容的范本样式。
|
||||||
|
-E --extended-regexp # 将范本样式为延伸的普通表示法来使用,意味着使用能使用扩展正则表达式。
|
||||||
|
-f<范本文件> --file=<规则文件> # 指定范本文件,其内容有一个或多个范本样式,让grep查找符合范本条件的文件内容,格式为每一列的范本样式。
|
||||||
|
-F --fixed-regexp # 将范本样式视为固定字符串的列表。
|
||||||
|
-G --basic-regexp # 将范本样式视为普通的表示法来使用。
|
||||||
|
-h --no-filename # 在显示符合范本样式的那一列之前,不标示该列所属的文件名称。
|
||||||
|
-H --with-filename # 在显示符合范本样式的那一列之前,标示该列的文件名称。
|
||||||
|
-i --ignore-case # 忽略字符大小写的差别。
|
||||||
|
-l --file-with-matches # 列出文件内容符合指定的范本样式的文件名称。
|
||||||
|
-L --files-without-match # 列出文件内容不符合指定的范本样式的文件名称。
|
||||||
|
-n --line-number # 在显示符合范本样式的那一列之前,标示出该列的编号。
|
||||||
|
-P --perl-regexp # PATTERN 是一个 Perl 正则表达式
|
||||||
|
-q --quiet或--silent # 不显示任何信息。
|
||||||
|
-R/-r --recursive # 此参数的效果和指定“-d recurse”参数相同。
|
||||||
|
-s --no-messages # 不显示错误信息。
|
||||||
|
-v --revert-match # 反转查找。
|
||||||
|
-V --version # 显示版本信息。
|
||||||
|
-w --word-regexp # 只显示全字符合的列。
|
||||||
|
-x --line-regexp # 只显示全列符合的列。
|
||||||
|
-y # 此参数效果跟“-i”相同。
|
||||||
|
-o # 只输出文件中匹配到的部分。
|
||||||
|
-m <num> --max-count=<num> # 找到num行结果后停止查找,用来限制匹配行数
|
||||||
|
```
|
||||||
|
|
||||||
|
### 规则表达式
|
||||||
|
|
||||||
|
```shell
|
||||||
|
^ # 锚定行的开始 如:'^grep'匹配所有以grep开头的行。
|
||||||
|
$ # 锚定行的结束 如:'grep$' 匹配所有以grep结尾的行。
|
||||||
|
. # 匹配一个非换行符的字符 如:'gr.p'匹配gr后接一个任意字符,然后是p。
|
||||||
|
* # 匹配零个或多个先前字符 如:'*grep'匹配所有一个或多个空格后紧跟grep的行。
|
||||||
|
.* # 一起用代表任意字符。
|
||||||
|
[] # 匹配一个指定范围内的字符,如'[Gg]rep'匹配Grep和grep。
|
||||||
|
[^] # 匹配一个不在指定范围内的字符,如:'[^A-FH-Z]rep'匹配不包含A-R和T-Z的一个字母开头,紧跟rep的行。
|
||||||
|
\(..\) # 标记匹配字符,如'\(love\)',love被标记为1。
|
||||||
|
\< # 锚定单词的开始,如:'\<grep'匹配包含以grep开头的单词的行。
|
||||||
|
\> # 锚定单词的结束,如'grep\>'匹配包含以grep结尾的单词的行。
|
||||||
|
x\{m\} # 重复字符x,m次,如:'0\{5\}'匹配包含5个o的行。
|
||||||
|
x\{m,\} # 重复字符x,至少m次,如:'o\{5,\}'匹配至少有5个o的行。
|
||||||
|
x\{m,n\} # 重复字符x,至少m次,不多于n次,如:'o\{5,10\}'匹配5--10个o的行。
|
||||||
|
\w # 匹配文字和数字字符,也就是[A-Za-z0-9],如:'G\w*p'匹配以G后跟零个或多个文字或数字字符,然后是p。
|
||||||
|
\W # \w的反置形式,匹配一个或多个非单词字符,如点号句号等。
|
||||||
|
\b # 单词锁定符,如: '\bgrep\b'只匹配grep。
|
||||||
|
```
|
||||||
|
|
||||||
|
## grep 命令常见用法
|
||||||
|
|
||||||
|
在文件中搜索一个单词,命令会返回一个包含 **“match_pattern”** 的文本行:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
grep match_pattern file_name
|
||||||
|
grep "match_pattern" file_name
|
||||||
|
```
|
||||||
|
|
||||||
|
在多个文件中查找:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
grep "match_pattern" file_1 file_2 file_3 ...
|
||||||
|
```
|
||||||
|
|
||||||
|
输出除之外的所有行 **-v** 选项:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
grep -v "match_pattern" file_name
|
||||||
|
```
|
||||||
|
|
||||||
|
标记匹配颜色 **--color=auto** 选项:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
grep "match_pattern" file_name --color=auto
|
||||||
|
```
|
||||||
|
|
||||||
|
使用正则表达式 **-E** 选项:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
grep -E "[1-9]+"
|
||||||
|
# 或
|
||||||
|
egrep "[1-9]+"
|
||||||
|
```
|
||||||
|
|
||||||
|
使用正则表达式 **-P** 选项:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
grep -P "(\d{3}\-){2}\d{4}" file_name
|
||||||
|
```
|
||||||
|
|
||||||
|
只输出文件中匹配到的部分 **-o** 选项:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
echo this is a test line. | grep -o -E "[a-z]+\."
|
||||||
|
line.
|
||||||
|
|
||||||
|
echo this is a test line. | egrep -o "[a-z]+\."
|
||||||
|
line.
|
||||||
|
```
|
||||||
|
|
||||||
|
统计文件或者文本中包含匹配字符串的行数 **-c** 选项:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
grep -c "text" file_name
|
||||||
|
```
|
||||||
|
|
||||||
|
输出包含匹配字符串的行数 **-n** 选项:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
grep "text" -n file_name
|
||||||
|
# 或
|
||||||
|
cat file_name | grep "text" -n
|
||||||
|
|
||||||
|
#多个文件
|
||||||
|
grep "text" -n file_1 file_2
|
||||||
|
```
|
||||||
|
|
||||||
|
打印样式匹配所位于的字符或字节偏移:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
echo gun is not unix | grep -b -o "not"
|
||||||
|
7:not
|
||||||
|
#一行中字符串的字符便宜是从该行的第一个字符开始计算,起始值为0。选项 **-b -o** 一般总是配合使用。
|
||||||
|
```
|
||||||
|
|
||||||
|
搜索多个文件并查找匹配文本在哪些文件中:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
grep -l "text" file1 file2 file3...
|
||||||
|
```
|
||||||
|
|
||||||
|
### grep 递归搜索文件
|
||||||
|
|
||||||
|
在多级目录中对文本进行递归搜索:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
grep "text" . -r -n
|
||||||
|
# .表示当前目录。
|
||||||
|
```
|
||||||
|
|
||||||
|
忽略匹配样式中的字符大小写:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
echo "hello world" | grep -i "HELLO"
|
||||||
|
# hello
|
||||||
|
```
|
||||||
|
|
||||||
|
选项 **-e** 制动多个匹配样式:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
echo this is a text line | grep -e "is" -e "line" -o
|
||||||
|
is
|
||||||
|
line
|
||||||
|
|
||||||
|
#也可以使用 **-f** 选项来匹配多个样式,在样式文件中逐行写出需要匹配的字符。
|
||||||
|
cat patfile
|
||||||
|
aaa
|
||||||
|
bbb
|
||||||
|
|
||||||
|
echo aaa bbb ccc ddd eee | grep -f patfile -o
|
||||||
|
```
|
||||||
|
|
||||||
|
在 grep 搜索结果中包括或者排除指定文件:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# 只在目录中所有的.php和.html文件中递归搜索字符"main()"
|
||||||
|
grep "main()" . -r --include *.{php,html}
|
||||||
|
|
||||||
|
# 在搜索结果中排除所有README文件
|
||||||
|
grep "main()" . -r --exclude "README"
|
||||||
|
|
||||||
|
# 在搜索结果中排除filelist文件列表里的文件
|
||||||
|
grep "main()" . -r --exclude-from filelist
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
使用 0 值字节后缀的 grep 与 xargs:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# 测试文件:
|
||||||
|
echo "aaa" > file1
|
||||||
|
echo "bbb" > file2
|
||||||
|
echo "aaa" > file3
|
||||||
|
|
||||||
|
grep "aaa" file* -lZ | xargs -0 rm
|
||||||
|
|
||||||
|
# 执行后会删除file1和file3,grep输出用-Z选项来指定以0值字节作为终结符文件名(\0),xargs -0 读取输入并用0值字节终结符分隔文件名,然后删除匹配文件,-Z通常和-l结合使用。
|
||||||
|
```
|
||||||
|
|
||||||
|
grep 静默输出:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
grep -q "test" filename
|
||||||
|
# 不会输出任何信息,如果命令运行成功返回0,失败则返回非0值。一般用于条件测试。
|
||||||
|
```
|
||||||
|
|
||||||
|
打印出匹配文本之前或者之后的行:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# 显示匹配某个结果之后的3行,使用 -A 选项:
|
||||||
|
seq 10 | grep "5" -A 3
|
||||||
|
5
|
||||||
|
6
|
||||||
|
7
|
||||||
|
8
|
||||||
|
|
||||||
|
# 显示匹配某个结果之前的3行,使用 -B 选项:
|
||||||
|
seq 10 | grep "5" -B 3
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
|
||||||
|
# 显示匹配某个结果的前三行和后三行,使用 -C 选项:
|
||||||
|
seq 10 | grep "5" -C 3
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
6
|
||||||
|
7
|
||||||
|
8
|
||||||
|
|
||||||
|
# 如果匹配结果有多个,会用“--”作为各匹配结果之间的分隔符:
|
||||||
|
echo -e "a\nb\nc\na\nb\nc" | grep a -A 1
|
||||||
|
a
|
||||||
|
b
|
||||||
|
--
|
||||||
|
a
|
||||||
|
b
|
||||||
|
```
|
|
@ -0,0 +1,70 @@
|
||||||
|
# iostat
|
||||||
|
|
||||||
|
监视系统输入输出设备和 CPU 的使用情况
|
||||||
|
|
||||||
|
## 补充说明
|
||||||
|
|
||||||
|
**iostat 命令** 被用于监视系统输入输出设备和 CPU 的使用情况。它的特点是汇报磁盘活动统计情况,同时也会汇报出 CPU 使用情况。同 vmstat 一样,iostat 也有一个弱点,就是它不能对某个进程进行深入分析,仅对系统的整体情况进行分析。
|
||||||
|
|
||||||
|
### 语法
|
||||||
|
|
||||||
|
```shell
|
||||||
|
iostat(选项)(参数)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
```shell
|
||||||
|
-c:仅显示CPU使用情况;
|
||||||
|
-d:仅显示设备利用率;
|
||||||
|
-k:显示状态以千字节每秒为单位,而不使用块每秒;
|
||||||
|
-m:显示状态以兆字节每秒为单位;
|
||||||
|
-p:仅显示块设备和所有被使用的其他分区的状态;
|
||||||
|
-t:显示每个报告产生时的时间;
|
||||||
|
-V:显示版号并退出;
|
||||||
|
-x:显示扩展状态。
|
||||||
|
```
|
||||||
|
|
||||||
|
### 参数
|
||||||
|
|
||||||
|
- 间隔时间:每次报告的间隔时间(秒);
|
||||||
|
- 次数:显示报告的次数。
|
||||||
|
|
||||||
|
### 实例
|
||||||
|
|
||||||
|
用`iostat -x /dev/sda1`来观看磁盘 I/O 的详细情况:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
iostat -x /dev/sda1
|
||||||
|
Linux 2.6.18-164.el5xen (localhost.localdomain)
|
||||||
|
2010年03月26日
|
||||||
|
|
||||||
|
avg-cpu: %user %nice %system %iowait
|
||||||
|
%steal %idle
|
||||||
|
0.11 0.02 0.18 0.35
|
||||||
|
0.03 99.31
|
||||||
|
|
||||||
|
Device: tps Blk_read/s Blk_wrtn/s
|
||||||
|
Blk_read Blk_wrtn
|
||||||
|
sda1 0.02 0.08
|
||||||
|
0.00 2014 4
|
||||||
|
```
|
||||||
|
|
||||||
|
详细说明:第二行是系统信息和监测时间,第三行和第四行显示 CPU 使用情况(具体内容和 mpstat 命令相同)。这里主要关注后面 I/O 输出的信息,如下所示:
|
||||||
|
|
||||||
|
| 标示 | 说明 |
|
||||||
|
| -------- | ----------------------------------- |
|
||||||
|
| Device | 监测设备名称 |
|
||||||
|
| rrqm/s | 每秒需要读取需求的数量 |
|
||||||
|
| wrqm/s | 每秒需要写入需求的数量 |
|
||||||
|
| r/s | 每秒实际读取需求的数量 |
|
||||||
|
| w/s | 每秒实际写入需求的数量 |
|
||||||
|
| rsec/s | 每秒读取区段的数量 |
|
||||||
|
| wsec/s | 每秒写入区段的数量 |
|
||||||
|
| rkB/s | 每秒实际读取的大小,单位为 KB |
|
||||||
|
| wkB/s | 每秒实际写入的大小,单位为 KB |
|
||||||
|
| avgrq-sz | 需求的平均大小区段 |
|
||||||
|
| avgqu-sz | 需求的平均队列长度 |
|
||||||
|
| await | 等待 I/O 平均的时间(milliseconds) |
|
||||||
|
| svctm | I/O 需求完成的平均时间 |
|
||||||
|
| %util | 被 I/O 需求消耗的 CPU 百分比 |
|
|
@ -0,0 +1,79 @@
|
||||||
|
# iotop
|
||||||
|
|
||||||
|
用来监视磁盘 I/O 使用状况的工具
|
||||||
|
|
||||||
|
## 补充说明
|
||||||
|
|
||||||
|
**iotop 命令** 是一个用来监视磁盘 I/O 使用状况的 top 类工具。iotop 具有与 top 相似的 UI,其中包括 PID、用户、I/O、进程等相关信息。Linux 下的 IO 统计工具如 iostat,nmon 等大多数是只能统计到 per 设备的读写情况,如果你想知道每个进程是如何使用 IO 的就比较麻烦,使用 iotop 命令可以很方便的查看。
|
||||||
|
|
||||||
|
iotop 使用 Python 语言编写而成,要求 Python2.5(及以上版本)和 Linux kernel2.6.20(及以上版本)。iotop 提供有源代码及 rpm 包,可从其官方主页下载。
|
||||||
|
|
||||||
|
### 安装
|
||||||
|
|
||||||
|
**Ubuntu**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
apt-get install iotop
|
||||||
|
```
|
||||||
|
|
||||||
|
**CentOS**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
yum install iotop
|
||||||
|
```
|
||||||
|
|
||||||
|
**编译安装**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
wget http://guichaz.free.fr/iotop/files/iotop-0.4.4.tar.gz
|
||||||
|
tar zxf iotop-0.4.4.tar.gz
|
||||||
|
python setup.py build
|
||||||
|
python setup.py install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 语法
|
||||||
|
|
||||||
|
```shell
|
||||||
|
iotop(选项)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
```shell
|
||||||
|
-o:只显示有io操作的进程
|
||||||
|
-b:批量显示,无交互,主要用作记录到文件。
|
||||||
|
-n NUM:显示NUM次,主要用于非交互式模式。
|
||||||
|
-d SEC:间隔SEC秒显示一次。
|
||||||
|
-p PID:监控的进程pid。
|
||||||
|
-u USER:监控的进程用户。
|
||||||
|
```
|
||||||
|
|
||||||
|
**iotop 常用快捷键:**
|
||||||
|
|
||||||
|
1. 左右箭头:改变排序方式,默认是按 IO 排序。
|
||||||
|
2. r:改变排序顺序。
|
||||||
|
3. o:只显示有 IO 输出的进程。
|
||||||
|
4. p:进程/线程的显示方式的切换。
|
||||||
|
5. a:显示累积使用量。
|
||||||
|
6. q:退出。
|
||||||
|
|
||||||
|
### 实例
|
||||||
|
|
||||||
|
直接执行 iotop 就可以看到效果了:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
Total DISK read: 0.00 B/s | Total DISK write: 0.00 B/s
|
||||||
|
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> command
|
||||||
|
1 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % init [3]
|
||||||
|
2 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [kthreadd]
|
||||||
|
3 rt/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [migration/0]
|
||||||
|
4 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [ksoftirqd/0]
|
||||||
|
5 rt/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [watchdog/0]
|
||||||
|
6 rt/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [migration/1]
|
||||||
|
7 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [ksoftirqd/1]
|
||||||
|
8 rt/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [watchdog/1]
|
||||||
|
9 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [events/0]
|
||||||
|
10 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [events/1]
|
||||||
|
11 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [khelper]
|
||||||
|
2572 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [bluetooth]
|
||||||
|
```
|
|
@ -0,0 +1,83 @@
|
||||||
|
# scp
|
||||||
|
|
||||||
|
加密的方式在本地主机和远程主机之间复制文件
|
||||||
|
|
||||||
|
## 补充说明
|
||||||
|
|
||||||
|
**scp 命令** 用于在 Linux 下进行远程拷贝文件的命令,和它类似的命令有 cp,不过 cp 只是在本机进行拷贝不能跨服务器,而且 scp 传输是加密的。可能会稍微影响一下速度。当你服务器硬盘变为只读 read only system 时,用 scp 可以帮你把文件移出来。另外,scp 还非常不占资源,不会提高多少系统负荷,在这一点上,rsync 就远远不及它了。虽然 rsync 比 scp 会快一点,但当小文件众多的情况下,rsync 会导致硬盘 I/O 非常高,而 scp 基本不影响系统正常使用。
|
||||||
|
|
||||||
|
### 语法
|
||||||
|
|
||||||
|
```shell
|
||||||
|
scp(选项)(参数)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
```shell
|
||||||
|
-1:使用ssh协议版本1;
|
||||||
|
-2:使用ssh协议版本2;
|
||||||
|
-4:使用ipv4;
|
||||||
|
-6:使用ipv6;
|
||||||
|
-B:以批处理模式运行;
|
||||||
|
-C:使用压缩;
|
||||||
|
-F:指定ssh配置文件;
|
||||||
|
-i:identity_file 从指定文件中读取传输时使用的密钥文件(例如亚马逊云pem),此参数直接传递给ssh;
|
||||||
|
-l:指定宽带限制;
|
||||||
|
-o:指定使用的ssh选项;
|
||||||
|
-P:指定远程主机的端口号;
|
||||||
|
-p:保留文件的最后修改时间,最后访问时间和权限模式;
|
||||||
|
-q:不显示复制进度;
|
||||||
|
-r:以递归方式复制。
|
||||||
|
```
|
||||||
|
|
||||||
|
### 参数
|
||||||
|
|
||||||
|
- 源文件:指定要复制的源文件。
|
||||||
|
- 目标文件:目标文件。格式为`user@host:filename`(文件名为目标文件的名称)。
|
||||||
|
|
||||||
|
### 实例
|
||||||
|
|
||||||
|
从远程复制到本地的 scp 命令与上面的命令雷同,只要将从本地复制到远程的命令后面 2 个参数互换顺序就行了。
|
||||||
|
|
||||||
|
**从远处复制文件到本地目录**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
scp root@10.10.10.10:/opt/soft/nginx-0.5.38.tar.gz /opt/soft/
|
||||||
|
```
|
||||||
|
|
||||||
|
从 10.10.10.10 机器上的`/opt/soft/`的目录中下载 nginx-0.5.38.tar.gz 文件到本地`/opt/soft/`目录中。
|
||||||
|
|
||||||
|
**从亚马逊云复制 OpenVPN 到本地目录**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
scp -i amazon.pem ubuntu@10.10.10.10:/usr/local/openvpn_as/etc/exe/openvpn-connect-2.1.3.110.dmg openvpn-connect-2.1.3.110.dmg
|
||||||
|
```
|
||||||
|
|
||||||
|
从 10.10.10.10 机器上下载 openvpn 安装文件到本地当前目录来。
|
||||||
|
|
||||||
|
**从远处复制到本地**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
scp -r root@10.10.10.10:/opt/soft/mongodb /opt/soft/
|
||||||
|
```
|
||||||
|
|
||||||
|
从 10.10.10.10 机器上的`/opt/soft/`中下载 mongodb 目录到本地的`/opt/soft/`目录来。
|
||||||
|
|
||||||
|
**上传本地文件到远程机器指定目录**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
scp /opt/soft/nginx-0.5.38.tar.gz root@10.10.10.10:/opt/soft/scptest
|
||||||
|
# 指定端口 2222
|
||||||
|
scp -rp -P 2222 /opt/soft/nginx-0.5.38.tar.gz root@10.10.10.10:/opt/soft/scptest
|
||||||
|
```
|
||||||
|
|
||||||
|
复制本地`/opt/soft/`目录下的文件 nginx-0.5.38.tar.gz 到远程机器 10.10.10.10 的`opt/soft/scptest`目录。
|
||||||
|
|
||||||
|
**上传本地目录到远程机器指定目录**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
scp -r /opt/soft/mongodb root@10.10.10.10:/opt/soft/scptest
|
||||||
|
```
|
||||||
|
|
||||||
|
上传本地目录`/opt/soft/mongodb`到远程机器 10.10.10.10 上`/opt/soft/scptest`的目录中去。
|
|
@ -0,0 +1,88 @@
|
||||||
|
# top
|
||||||
|
|
||||||
|
显示或管理执行中的程序
|
||||||
|
|
||||||
|
## 补充说明
|
||||||
|
|
||||||
|
**top 命令** 可以实时动态地查看系统的整体运行情况,是一个综合了多方信息监测系统性能和运行信息的实用工具。通过 top 命令所提供的互动式界面,用热键可以管理。
|
||||||
|
|
||||||
|
### 语法
|
||||||
|
|
||||||
|
```shell
|
||||||
|
top(选项)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
```shell
|
||||||
|
-b:以批处理模式操作;
|
||||||
|
-c:显示完整的治命令;
|
||||||
|
-d:屏幕刷新间隔时间;
|
||||||
|
-I:忽略失效过程;
|
||||||
|
-s:保密模式;
|
||||||
|
-S:累积模式;
|
||||||
|
-i<时间>:设置间隔时间;
|
||||||
|
-u<用户名>:指定用户名;
|
||||||
|
-p<进程号>:指定进程;
|
||||||
|
-n<次数>:循环显示的次数。
|
||||||
|
```
|
||||||
|
|
||||||
|
### top 交互命令
|
||||||
|
|
||||||
|
在 top 命令执行过程中可以使用的一些交互命令。这些命令都是单字母的,如果在命令行中使用了-s 选项, 其中一些命令可能会被屏蔽。
|
||||||
|
|
||||||
|
```shell
|
||||||
|
h:显示帮助画面,给出一些简短的命令总结说明;
|
||||||
|
k:终止一个进程;
|
||||||
|
i:忽略闲置和僵死进程,这是一个开关式命令;
|
||||||
|
q:退出程序;
|
||||||
|
r:重新安排一个进程的优先级别;
|
||||||
|
S:切换到累计模式;
|
||||||
|
s:改变两次刷新之间的延迟时间(单位为s),如果有小数,就换算成ms。输入0值则系统将不断刷新,默认值是5s;
|
||||||
|
f或者F:从当前显示中添加或者删除项目;
|
||||||
|
o或者O:改变显示项目的顺序;
|
||||||
|
l:切换显示平均负载和启动时间信息;
|
||||||
|
m:切换显示内存信息;
|
||||||
|
t:切换显示进程和CPU状态信息;
|
||||||
|
c:切换显示命令名称和完整命令行;
|
||||||
|
M:根据驻留内存大小进行排序;
|
||||||
|
P:根据CPU使用百分比大小进行排序;
|
||||||
|
T:根据时间/累计时间进行排序;
|
||||||
|
w:将当前设置写入~/.toprc文件中。
|
||||||
|
```
|
||||||
|
|
||||||
|
### 实例
|
||||||
|
|
||||||
|
```shell
|
||||||
|
top - 09:44:56 up 16 days, 21:23, 1 user, load average: 9.59, 4.75, 1.92
|
||||||
|
Tasks: 145 total, 2 running, 143 sleeping, 0 stopped, 0 zombie
|
||||||
|
Cpu(s): 99.8%us, 0.1%sy, 0.0%ni, 0.2%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
|
||||||
|
Mem: 4147888k total, 2493092k used, 1654796k free, 158188k buffers
|
||||||
|
Swap: 5144568k total, 56k used, 5144512k free, 2013180k cached
|
||||||
|
```
|
||||||
|
|
||||||
|
**解释:**
|
||||||
|
|
||||||
|
- top - 09:44:56[当前系统时间],
|
||||||
|
- 16 days[系统已经运行了 16 天],
|
||||||
|
- 1 user[个用户当前登录],
|
||||||
|
- load average: 9.59, 4.75, 1.92[系统负载,即任务队列的平均长度]
|
||||||
|
- Tasks: 145 total[总进程数],
|
||||||
|
- 2 running[正在运行的进程数],
|
||||||
|
- 143 sleeping[睡眠的进程数],
|
||||||
|
- 0 stopped[停止的进程数],
|
||||||
|
- 0 zombie[冻结进程数],
|
||||||
|
- Cpu(s): 99.8%us[用户空间占用 CPU 百分比],
|
||||||
|
- 0.1%sy[内核空间占用 CPU 百分比],
|
||||||
|
- 0.0%ni[用户进程空间内改变过优先级的进程占用 CPU 百分比],
|
||||||
|
- 0.2%id[空闲 CPU 百分比], 0.0%wa[等待输入输出的 CPU 时间百分比],
|
||||||
|
- 0.0%hi[],
|
||||||
|
- 0.0%st[],
|
||||||
|
- Mem: 4147888k total[物理内存总量],
|
||||||
|
- 2493092k used[使用的物理内存总量],
|
||||||
|
- 1654796k free[空闲内存总量],
|
||||||
|
- 158188k buffers[用作内核缓存的内存量]
|
||||||
|
- Swap: 5144568k total[交换区总量],
|
||||||
|
- 56k used[使用的交换区总量],
|
||||||
|
- 5144512k free[空闲交换区总量],
|
||||||
|
- 2013180k cached[缓冲的交换区总量],
|
|
@ -0,0 +1,95 @@
|
||||||
|
# vmstat
|
||||||
|
|
||||||
|
显示虚拟内存状态
|
||||||
|
|
||||||
|
## 补充说明
|
||||||
|
|
||||||
|
**vmstat 命令** 的含义为显示虚拟内存状态(“Viryual Memor Statics”),但是它可以报告关于进程、内存、I/O 等系统整体运行状态。
|
||||||
|
|
||||||
|
### 语法
|
||||||
|
|
||||||
|
```shell
|
||||||
|
vmstat(选项)(参数)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
```shell
|
||||||
|
-a:显示活动内页;
|
||||||
|
-f:显示启动后创建的进程总数;
|
||||||
|
-m:显示slab信息;
|
||||||
|
-n:头信息仅显示一次;
|
||||||
|
-s:以表格方式显示事件计数器和内存状态;
|
||||||
|
-d:报告磁盘状态;
|
||||||
|
-p:显示指定的硬盘分区状态;
|
||||||
|
-S:输出信息的单位。
|
||||||
|
```
|
||||||
|
|
||||||
|
### 参数
|
||||||
|
|
||||||
|
- 事件间隔:状态信息刷新的时间间隔;
|
||||||
|
- 次数:显示报告的次数。
|
||||||
|
|
||||||
|
### 实例
|
||||||
|
|
||||||
|
```shell
|
||||||
|
vmstat 3
|
||||||
|
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
|
||||||
|
r b swpd free buff cache si so bi bo in cs us sy id wa st
|
||||||
|
0 0 320 42188 167332 1534368 0 0 4 7 1 0 0 0 99 0 0
|
||||||
|
0 0 320 42188 167332 1534392 0 0 0 0 1002 39 0 0 100 0 0
|
||||||
|
0 0 320 42188 167336 1534392 0 0 0 19 1002 44 0 0 100 0 0
|
||||||
|
0 0 320 42188 167336 1534392 0 0 0 0 1002 41 0 0 100 0 0
|
||||||
|
0 0 320 42188 167336 1534392 0 0 0 0 1002 41 0 0 100 0 0
|
||||||
|
```
|
||||||
|
|
||||||
|
**字段说明:**
|
||||||
|
|
||||||
|
Procs(进程)
|
||||||
|
|
||||||
|
- r: 运行队列中进程数量,这个值也可以判断是否需要增加 CPU。(长期大于 1)
|
||||||
|
- b: 等待 IO 的进程数量。
|
||||||
|
|
||||||
|
Memory(内存)
|
||||||
|
|
||||||
|
- swpd: 使用虚拟内存大小,如果 swpd 的值不为 0,但是 SI,SO 的值长期为 0,这种情况不会影响系统性能。
|
||||||
|
- free: 空闲物理内存大小。
|
||||||
|
- buff: 用作缓冲的内存大小。
|
||||||
|
- cache: 用作缓存的内存大小,如果 cache 的值大的时候,说明 cache 处的文件数多,如果频繁访问到的文件都能被 cache 处,那么磁盘的读 IO bi 会非常小。
|
||||||
|
|
||||||
|
Swap
|
||||||
|
|
||||||
|
- si: 每秒从交换区写到内存的大小,由磁盘调入内存。
|
||||||
|
- so: 每秒写入交换区的内存大小,由内存调入磁盘。
|
||||||
|
|
||||||
|
注意:内存够用的时候,这 2 个值都是 0,如果这 2 个值长期大于 0 时,系统性能会受到影响,磁盘 IO 和 CPU 资源都会被消耗。有些朋友看到空闲内存(free)很少的或接近于 0 时,就认为内存不够用了,不能光看这一点,还要结合 si 和 so,如果 free 很少,但是 si 和 so 也很少(大多时候是 0),那么不用担心,系统性能这时不会受到影响的。
|
||||||
|
|
||||||
|
IO(现在的 Linux 版本块的大小为 1kb)
|
||||||
|
|
||||||
|
- bi: 每秒读取的块数
|
||||||
|
- bo: 每秒写入的块数
|
||||||
|
|
||||||
|
注意:随机磁盘读写的时候,这 2 个值越大(如超出 1024k),能看到 CPU 在 IO 等待的值也会越大。
|
||||||
|
|
||||||
|
system(系统)
|
||||||
|
|
||||||
|
- in: 每秒中断数,包括时钟中断。
|
||||||
|
- cs: 每秒上下文切换数。
|
||||||
|
|
||||||
|
注意:上面 2 个值越大,会看到由内核消耗的 CPU 时间会越大。
|
||||||
|
|
||||||
|
CPU(以百分比表示)
|
||||||
|
|
||||||
|
- us: 用户进程执行时间百分比(user time)
|
||||||
|
|
||||||
|
us 的值比较高时,说明用户进程消耗的 CPU 时间多,但是如果长期超 50%的使用,那么我们就该考虑优化程序算法或者进行加速。
|
||||||
|
|
||||||
|
- sy: 内核系统进程执行时间百分比(system time)
|
||||||
|
|
||||||
|
sy 的值高时,说明系统内核消耗的 CPU 资源多,这并不是良性表现,我们应该检查原因。
|
||||||
|
|
||||||
|
- wa: IO 等待时间百分比
|
||||||
|
|
||||||
|
wa 的值高时,说明 IO 等待比较严重,这可能由于磁盘大量作随机访问造成,也有可能磁盘出现瓶颈(块操作)。
|
||||||
|
|
||||||
|
- id: 空闲时间百分比
|
|
@ -0,0 +1,180 @@
|
||||||
|
# expect shell 脚本
|
||||||
|
|
||||||
|
## expect 简介
|
||||||
|
|
||||||
|
`expect` 是一个自动化交互套件,主要应用于执行命令和程序时,系统以交互形式要求输入指定字符串,实现交互通信。
|
||||||
|
|
||||||
|
在实际工作中,我们运行命令、脚本或程序时,这些命令、脚本或程序都需要从终端输入某些继续运行的指令,而这些输入都需要人为的手工进行。而利用 `expect`,则可以根据程序的提示,模拟标准输入提供给程序,从而实现自动化交互执行。这就是 `expect` 。
|
||||||
|
|
||||||
|
expect 自动交互流程:
|
||||||
|
|
||||||
|
1. spawn 启动指定进程
|
||||||
|
2. expect 获取指定关键字
|
||||||
|
3. send 向指定程序发送指定字符
|
||||||
|
4. 执行完成退出
|
||||||
|
|
||||||
|
## expect 安装
|
||||||
|
|
||||||
|
### yum 安装
|
||||||
|
|
||||||
|
执行命令:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
yum -y install expect
|
||||||
|
```
|
||||||
|
|
||||||
|
### 手动安装
|
||||||
|
|
||||||
|
expect 依赖 tcl,所以需要先安装 tcl:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
wget https://nchc.dl.sourceforge.net/project/tcl/Tcl/8.6.9/tcl8.6.9-src.tar.gz
|
||||||
|
tar xf tcl8.6.9-src.tar.gz
|
||||||
|
cd tcl8.6.9/unix/
|
||||||
|
./configure && make && sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
再安装 expect:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
wget https://nchc.dl.sourceforge.net/project/expect/Expect/5.45.4/expect5.45.4.tar.gz
|
||||||
|
tar xf expect5.45.4.tar.gz
|
||||||
|
cd ./expect5.45.4
|
||||||
|
./configure && make && sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
## expect 参数
|
||||||
|
|
||||||
|
启用选项:
|
||||||
|
|
||||||
|
- `-c` - 执行脚本前先执行的命令,可多次使用。
|
||||||
|
- `-d` - debug 模式,可以在运行时输出一些诊断信息,与在脚本开始处使用 `exp_internal 1` 相似。
|
||||||
|
- `-D` - 启用交换调式器,可设一整数参数。
|
||||||
|
- `-f` - 从文件读取命令,仅用于使用 `#!` 时。如果文件名为 `-`,则从 stdin 读取(使用 `./-` 从文件名为-的文件读取)。
|
||||||
|
- `-i` - 交互式输入命令,使用 `exit` 或 `EOF` 退出输入状态。
|
||||||
|
- `--` - 标示选项结束(如果你需要传递与 `expect` 选项相似的参数给脚本时),可放到 `#!` 行: `#!/usr/bin/expect --` 。
|
||||||
|
- `-v` - 显示 `expect` 版本信息。
|
||||||
|
|
||||||
|
## expect 命令
|
||||||
|
|
||||||
|
- `spawn` - 命令用来启动新的进程,`spawn`后的`send`和`expect`命令都是和使用`spawn`打开的进程进行交互。
|
||||||
|
- `expect` - 获取匹配信息,匹配成功则执行 `expect` 后面的程序动作。
|
||||||
|
- `exp_continue` - 在 `expect` 中多次匹配就需要用到。
|
||||||
|
- `send` - 命令接收一个字符串参数,并将该参数发送到进程。
|
||||||
|
- `send exp_send` - 用于发送指定的字符串信息。
|
||||||
|
- `interact` - 命令用的其实不是很多,一般情况下使用`spawn`、`send`和`expect`命令就可以很好的完成我们的任务;但在一些特殊场合下还是需要使用`interact`命令的,`interact`命令主要用于退出自动化,进入人工交互。比如我们使用`spawn`、`send`和`expect`命令完成了 ftp 登陆主机,执行下载文件任务,但是我们希望在文件下载结束以后,仍然可以停留在 ftp 命令行状态,以便手动的执行后续命令,此时使用`interact`命令就可以很好的完成这个任务。
|
||||||
|
- `send_user` - 用来打印输出 相当于 shell 中的 echo
|
||||||
|
- `set` - 定义变量。
|
||||||
|
- `set timeout` - 设置超时时间。
|
||||||
|
- `puts` - 输出变量。
|
||||||
|
- `exit` - 退出 expect 脚本
|
||||||
|
- `eof` - expect 执行结束,退出。
|
||||||
|
|
||||||
|
## 示例场景
|
||||||
|
|
||||||
|
远程登录
|
||||||
|
|
||||||
|
(1)ssh 登录远程主机执行命令,执行方法 `expect 1.sh` 或者 `source 1.sh`
|
||||||
|
|
||||||
|
```shell
|
||||||
|
#!/usr/bin/expect
|
||||||
|
|
||||||
|
spawn ssh saneri@192.168.56.103 df -Th
|
||||||
|
expect "*password"
|
||||||
|
send "123456\n"
|
||||||
|
expect eof
|
||||||
|
```
|
||||||
|
|
||||||
|
(2)ssh 远程登录主机执行命令,在 shell 脚本中执行 expect 命令,执行方法 sh 2.sh、bash 2.sh 或./2.sh 都可以执行.
|
||||||
|
|
||||||
|
```
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
passwd='123456'
|
||||||
|
|
||||||
|
/usr/bin/expect <<-EOF
|
||||||
|
|
||||||
|
set time 30
|
||||||
|
spawn ssh saneri@192.168.56.103 df -Th
|
||||||
|
expect {
|
||||||
|
"*yes/no" { send "yes\r"; exp_continue }
|
||||||
|
"*password:" { send "$passwd\r" }
|
||||||
|
}
|
||||||
|
expect eof
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
(3)expect 执行多条命令
|
||||||
|
|
||||||
|
```
|
||||||
|
#!/usr/bin/expect -f
|
||||||
|
|
||||||
|
set timeout 10
|
||||||
|
|
||||||
|
spawn sudo su - root
|
||||||
|
expect "*password*"
|
||||||
|
send "123456\r"
|
||||||
|
expect "#*"
|
||||||
|
send "ls\r"
|
||||||
|
expect "#*"
|
||||||
|
send "df -Th\r"
|
||||||
|
send "exit\r"
|
||||||
|
expect eof
|
||||||
|
```
|
||||||
|
|
||||||
|
(4)创建 ssh key,将 id_rsa 和 id_rsa.pub 文件分发到各台主机上面。
|
||||||
|
|
||||||
|
```shell
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 判断id_rsa密钥文件是否存在
|
||||||
|
if [ ! -f ~/.ssh/id_rsa ];then
|
||||||
|
ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa
|
||||||
|
else
|
||||||
|
echo "id_rsa has created ..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
#分发到各个节点,这里分发到host文件中的主机中.
|
||||||
|
while read line
|
||||||
|
do
|
||||||
|
user=`echo $line | cut -d " " -f 2`
|
||||||
|
ip=`echo $line | cut -d " " -f 1`
|
||||||
|
passwd=`echo $line | cut -d " " -f 3`
|
||||||
|
|
||||||
|
expect <<EOF
|
||||||
|
set timeout 10
|
||||||
|
spawn ssh-copy-id $user@$ip
|
||||||
|
expect {
|
||||||
|
"yes/no" { send "yes\n";exp_continue }
|
||||||
|
"password" { send "$passwd\n" }
|
||||||
|
}
|
||||||
|
expect "password" { send "$passwd\n" }
|
||||||
|
EOF
|
||||||
|
done < hosts
|
||||||
|
```
|
||||||
|
|
||||||
|
(5)shell 调用 expect 执行多行命令.
|
||||||
|
|
||||||
|
```
|
||||||
|
#!/bin/bash
|
||||||
|
ip=$1
|
||||||
|
user=$2
|
||||||
|
password=$3
|
||||||
|
|
||||||
|
expect <<EOF
|
||||||
|
set timeout 10
|
||||||
|
spawn ssh $user@$ip
|
||||||
|
expect {
|
||||||
|
"yes/no" { send "yes\n";exp_continue }
|
||||||
|
"password" { send "$password\n" }
|
||||||
|
}
|
||||||
|
expect "]#" { send "useradd hehe\n" }
|
||||||
|
expect "]#" { send "touch /tmp/test.txt\n" }
|
||||||
|
expect "]#" { send "exit\n" } expect eof
|
||||||
|
EOF
|
||||||
|
#./ssh5.sh 192.168.1.10 root 123456
|
||||||
|
```
|
||||||
|
|
||||||
|
## 参考资料
|
||||||
|
|
||||||
|
- [linux expect 自动交互脚本用法](https://blog.csdn.net/u010820857/article/details/89925274)
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
### 1.1. Zsh 是什么
|
### 1.1. Zsh 是什么
|
||||||
|
|
||||||
使用 Linux 的人都知道:**_Shell_ 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。_Shell_ 既是一种命令语言,又是一种程序设计语言**。
|
使用 Linux 的人都知道:***Shell_ 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。_Shell_ 既是一种命令语言,又是一种程序设计语言**。
|
||||||
|
|
||||||
Shell 的类型有很多种,linux 下默认的是 bash,虽然 bash 的功能已经很强大,但对于以懒惰为美德的程序员来说,bash 的提示功能不够强大,界面也不够炫,并非理想工具。
|
Shell 的类型有很多种,linux 下默认的是 bash,虽然 bash 的功能已经很强大,但对于以懒惰为美德的程序员来说,bash 的提示功能不够强大,界面也不够炫,并非理想工具。
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,362 @@
|
||||||
|
# Jenkins 运维
|
||||||
|
|
||||||
|
> 环境要求
|
||||||
|
>
|
||||||
|
> - JDK:JDK7+,官网推荐是 JDK 8
|
||||||
|
> - Jenkins:2.190.1
|
||||||
|
|
||||||
|
## Jenkins 简介
|
||||||
|
|
||||||
|
### Jenkins 是什么
|
||||||
|
|
||||||
|
Jenkins 是一款开源 CI&CD 软件,用于自动化各种任务,包括构建、测试和部署软件。
|
||||||
|
|
||||||
|
Jenkins 支持各种运行方式,可通过系统包、Docker 或者通过一个独立的 Java 程序。
|
||||||
|
|
||||||
|
### CI/CD 是什么
|
||||||
|
|
||||||
|
CI(Continuous integration,中文意思是持续集成)是一种软件开发时间。持续集成强调开发人员提交了新代码之后,立刻进行构建、(单元)测试。根据测试结果,我们可以确定新代码和原有代码能否正确地集成在一起。借用网络图片对 CI 加以理解。
|
||||||
|
|
||||||
|
![img](http://dunwu.test.upcdn.net/snap/20200310174528.png)
|
||||||
|
|
||||||
|
CD(Continuous Delivery, 中文意思持续交付)是在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境(类生产环境)中。比如,我们完成单元测试后,可以把代码部署到连接数据库的 Staging 环境中更多的测试。如果代码没有问题,可以继续手动部署到生产环境。下图反应的是 CI/CD 的大概工作模式。
|
||||||
|
|
||||||
|
![img](http://dunwu.test.upcdn.net/snap/20200310174544.png)
|
||||||
|
|
||||||
|
## Jenkins 安装
|
||||||
|
|
||||||
|
> 更详细内容请参考:[Jenkins 官方安装文档](https://jenkins.io/zh/doc/book/installing/)
|
||||||
|
|
||||||
|
### War 包部署
|
||||||
|
|
||||||
|
安装步骤如下:
|
||||||
|
|
||||||
|
(1)下载并解压到本地
|
||||||
|
|
||||||
|
进入[官网下载地址](https://jenkins.io/zh/download/),选择合适的版本下载。
|
||||||
|
|
||||||
|
我选择的是最新稳定 war 版本 2.89.4:http://mirrors.jenkins.io/war-stable/latest/jenkins.war
|
||||||
|
|
||||||
|
我个人喜欢存放在:`/opt/software/jenkins`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p /opt/software/jenkins
|
||||||
|
wget -O /opt/software/jenkins/jenkins.war http://mirrors.jenkins.io/war-stable/latest/jenkins.wa
|
||||||
|
```
|
||||||
|
|
||||||
|
(2)启动
|
||||||
|
|
||||||
|
如果你和我一样,选择 war 版本,那么你可以将 war 移到 Tomcat 的 webapps 目录下,通过 Tomcat 来启动。
|
||||||
|
|
||||||
|
当然,也可以通过 `java -jar` 方式来启动。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/software/jenkins
|
||||||
|
nohup java -jar jenkins.war --httpPort=8080 >> nohup.out 2>&1 &
|
||||||
|
```
|
||||||
|
|
||||||
|
### rpm 包部署
|
||||||
|
|
||||||
|
(1)下载安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
|
||||||
|
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
|
||||||
|
yum install jenkins
|
||||||
|
```
|
||||||
|
|
||||||
|
(2)启动
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl start jenkins
|
||||||
|
```
|
||||||
|
|
||||||
|
### 访问
|
||||||
|
|
||||||
|
1. 打开浏览器进入链接 `http://localhost:8080`.
|
||||||
|
2. 按照说明完成安装.
|
||||||
|
|
||||||
|
## Jenkins 基本使用
|
||||||
|
|
||||||
|
Jenkins 是一个强大的 CI 工具,虽然本身使用 Java 开发,但也能用来做其他语言开发的项目 CI。下面讲解如何使用 Jenkins 创建一个构建任务。
|
||||||
|
|
||||||
|
登录 Jenkins, 点击左侧的新建,创建新的构建任务。
|
||||||
|
|
||||||
|
![img](https:////upload-images.jianshu.io/upload_images/6464255-22b3c49af599565d.png?imageMogr2/auto-orient/strip|imageView2/2/w/374/format/webp)
|
||||||
|
|
||||||
|
跳转到如下界面。任务名称可以自行设定,但需要全局唯一。输入名称后选择构建一个自由风格的软件项目(其他选项不作介绍)。并点击下方的确定按钮即创建了一个构建任务。之后会自动跳转到该 job 的配置页面。
|
||||||
|
|
||||||
|
![img](https:////upload-images.jianshu.io/upload_images/6464255-0febc0bc4ca3cadd.png?imageMogr2/auto-orient/strip|imageView2/2/w/1044/format/webp)
|
||||||
|
|
||||||
|
新建自由风格的软件项目
|
||||||
|
|
||||||
|
下图是构建任务设置界面,可以看到上方的几个选项**"General", "源码管理", "构建触发器","构建环境", "构建", "构建后操作"**。下面逐一介绍。
|
||||||
|
|
||||||
|
![img](https:////upload-images.jianshu.io/upload_images/6464255-77998a3e6a70b83f.png?imageMogr2/auto-orient/strip|imageView2/2/w/1032/format/webp)
|
||||||
|
|
||||||
|
### General
|
||||||
|
|
||||||
|
General 是构建任务的一些基本配置。名称,描述之类的。
|
||||||
|
|
||||||
|
![](http://dunwu.test.upcdn.net/snap/20200310221814.png)
|
||||||
|
|
||||||
|
重要配置项:
|
||||||
|
|
||||||
|
- **Description**:对构建任务的描述。
|
||||||
|
- **Discard old builds**:服务器资源是有限的,有时候保存了太多的历史构建,会导致 Jenkins 速度变慢,并且服务器硬盘资源也会被占满。当然下方的"保持构建天数" 和 保持构建的最大个数是可以自定义的,需要根据实际情况确定一个合理的值。
|
||||||
|
|
||||||
|
点击右方的问号图标可以查看帮助信息。
|
||||||
|
|
||||||
|
### Source Code Management
|
||||||
|
|
||||||
|
**Source Code Management**,即源码管理,就是配置你代码的存放位置。
|
||||||
|
|
||||||
|
![](http://dunwu.test.upcdn.net/snap/20200310222110.png)
|
||||||
|
|
||||||
|
- **Git:** 支持主流的 Github 和 Gitlab 代码仓库。因我们的研发团队使用的是 gitlab,所以下面我只会对该项进行介绍。
|
||||||
|
- **Repository URL**:仓库地址。
|
||||||
|
- **Credentials**:凭证。可以使用 HTTP 方式的用户名密码,也可以是 RSA 文件。 但要通过后面的"ADD"按钮添加凭证。
|
||||||
|
- **Branches to build**:构建的分支。`*/master` 表示 master 分支,也可以设置为其他分支。
|
||||||
|
- **Repository browser**:你所使用的代码仓库管理工具,如 Github、Gitlab.
|
||||||
|
- **Subversion**:即 SVN,这里不作介绍。
|
||||||
|
|
||||||
|
### Build Triggers
|
||||||
|
|
||||||
|
**Build Triggers**,即构建触发器,用于构建任务的触发器。
|
||||||
|
|
||||||
|
![](http://dunwu.test.upcdn.net/snap/20200310222608.png)
|
||||||
|
|
||||||
|
配置说明:
|
||||||
|
|
||||||
|
- **Trigger builds remotely (e.g., from scripts)**:触发远程构建(例如,使用脚本)。该选项会提供一个接口,可以用来在代码层面触发构建。
|
||||||
|
- **Build after other projects are built**:该选项意思是"在其他项目构建后再构建"。
|
||||||
|
- **Build periodically**:周期性的构建。就是每隔一段时间进行构建。日程表类似 linux crontab 书写格式。如:`H/30 * * * *`,表示每隔 30 分钟进行一次构建。
|
||||||
|
- **Build when a change is pushed to GitLab:**当有 git push 到 Gitlab 仓库,即触发构建。后面会有一个触发构建的地址,一般被称为 webhooks。需要将这个地址配置到 gitlab 中,webhooks 如何配置后面介绍。这个是常用的构建触发器。
|
||||||
|
- **Poll SCM:**该选项是配合上面这个选项使用的。当代码仓库发生改动,jenkins 并不知道。需要配置这个选项,周期性的去检查代码仓库是否发生改动。
|
||||||
|
|
||||||
|
### Build Environment
|
||||||
|
|
||||||
|
**Build Environment**,即构建环境,配置构建前的一些准备工作,如指定构建工具。
|
||||||
|
|
||||||
|
![](http://dunwu.test.upcdn.net/snap/20200310223004.png)
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
Build,即构建。
|
||||||
|
|
||||||
|
点击下图中的 Add build step 按钮,会弹出一个构建任务菜单,可以根据实际需要来选择。
|
||||||
|
|
||||||
|
![](http://dunwu.test.upcdn.net/snap/20200310223241.png)
|
||||||
|
|
||||||
|
【说明】
|
||||||
|
|
||||||
|
- **Copy artifacts from another project**:从其他项目获取构建。一般当本任务有上游任务,需要获取上游任务的构件时使用。比如:有个 Java Web 项目,需要依赖于上一个前端构建任务输出的静态文件压缩包。
|
||||||
|
- Eexcute NodeJS script:执行 Nodejs 脚本。默认支持 nodejs、npm 命令。
|
||||||
|
- **Eexcute shell**: 执行 shell 脚本。用于 Linux 环境。
|
||||||
|
- **Execute Windows batch command**:执行 batch 脚本。用于 Windows 环境。
|
||||||
|
- **Invoke Ant**:Ant 是一款 java 项目构建工具。
|
||||||
|
- **Invoke Gradle script**:Gradle 构建项目。
|
||||||
|
- **Invoke top-level Maven targets**:Maven 构建项目。
|
||||||
|
|
||||||
|
### Post-build Actions
|
||||||
|
|
||||||
|
**Post-build Actions**,即构建后操作,用于构建完本项目的一些后续操作,比如生成相应的代码测试报告。
|
||||||
|
|
||||||
|
![](http://dunwu.test.upcdn.net/snap/20200310224106.png)
|
||||||
|
|
||||||
|
![](http://dunwu.test.upcdn.net/snap/20200310224254.png)
|
||||||
|
|
||||||
|
![](http://dunwu.test.upcdn.net/snap/20200310224331.png)
|
||||||
|
|
||||||
|
个人较常用的配置:
|
||||||
|
|
||||||
|
- **Archive the artifacts**:归档构件。
|
||||||
|
- **Build other projects**:构建其他项目。
|
||||||
|
- **Trigger parameterized build on other projects**:构建其他项目,并传输构建参数。
|
||||||
|
- **Publish JUnit test result report**:发布 Junit 测试报告。
|
||||||
|
- **E-mail Notification**:邮件通知,构建完成后发邮件到指定的邮箱。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**以上配置完成后,点击保存即可。**
|
||||||
|
|
||||||
|
### 开始构建
|
||||||
|
|
||||||
|
![](http://dunwu.test.upcdn.net/snap/20200310224927.png)
|
||||||
|
|
||||||
|
如上图所示,一切配置好后,即可点击 **Build Now** 开始构建。
|
||||||
|
|
||||||
|
### 构建结果
|
||||||
|
|
||||||
|
![](http://dunwu.test.upcdn.net/snap/20200310225234.png)
|
||||||
|
|
||||||
|
- **构建状态**
|
||||||
|
- **Successful 蓝色**:构建完成,并且被认为是稳定的。
|
||||||
|
- **Unstable 黄色**:构建完成,但被认为是不稳定的。
|
||||||
|
- **Failed 红色**:构建失败。
|
||||||
|
- **Disable 灰色**:构建已禁用
|
||||||
|
- **构建稳定性**
|
||||||
|
- 构建稳定性用天气表示:**晴、晴转多云、多云、小雨、雷阵雨**。天气越好表示构建越稳定,反之亦然。
|
||||||
|
- 构建历史界面
|
||||||
|
- **console output**:输出构建的日志信息
|
||||||
|
|
||||||
|
## 其他相关配置
|
||||||
|
|
||||||
|
### SSH Server 配置
|
||||||
|
|
||||||
|
登录 jenkins -> 系统管理 -> 系统设置
|
||||||
|
|
||||||
|
配置请看下图:
|
||||||
|
|
||||||
|
![img](https:////upload-images.jianshu.io/upload_images/6464255-15476f9e273daa58.png?imageMogr2/auto-orient/strip|imageView2/2/w/1108/format/webp)
|
||||||
|
|
||||||
|
重要配置:
|
||||||
|
|
||||||
|
- **SSH Servers:** 由于 jenkins 服务器公钥文件我已经配置好,所以之后新增 SSH Servers 只需要配置这一项即可。
|
||||||
|
- **Name:** 自定义,需要全局唯一。
|
||||||
|
|
||||||
|
- **HostName:** 主机名,直接用 ip 地址即可。
|
||||||
|
|
||||||
|
- **Username:** 新增 Server 的用户名,这里配置的是 root。
|
||||||
|
|
||||||
|
- **Remote Directory:** 远程目录。jenkins 服务器发送文件给新增的 server 默认是在这个目录。
|
||||||
|
|
||||||
|
### 配置 Gitlab webhooks
|
||||||
|
|
||||||
|
在 gitlab 的 project 页面 打开**settings**,再打开 **web hooks** 。点击**"ADD WEB HOOK"** 添加 webhook。把之前 jenkins 配置中的那个 url 添加到这里,添加完成后,点击**"TEST HOOK"**进行测试,如果显示 SUCCESS 则表示添加成功。
|
||||||
|
|
||||||
|
![img](https:////upload-images.jianshu.io/upload_images/6464255-9f8d04a1400556f9.png?imageMogr2/auto-orient/strip|imageView2/2/w/246/format/webp)
|
||||||
|
|
||||||
|
![img](https:////upload-images.jianshu.io/upload_images/6464255-154a62db330c819b.png?imageMogr2/auto-orient/strip|imageView2/2/w/240/format/webp)
|
||||||
|
|
||||||
|
![img](https:////upload-images.jianshu.io/upload_images/6464255-e4d1ea1e1dbde812.png?imageMogr2/auto-orient/strip|imageView2/2/w/1036/format/webp)
|
||||||
|
|
||||||
|
![img](https:////upload-images.jianshu.io/upload_images/6464255-c7a687207b2c26fc.png?imageMogr2/auto-orient/strip|imageView2/2/w/1106/format/webp)
|
||||||
|
|
||||||
|
![img](https:////upload-images.jianshu.io/upload_images/6464255-ce8ae810bc2cb0d4.png?imageMogr2/auto-orient/strip|imageView2/2/w/1154/format/webp)
|
||||||
|
|
||||||
|
配置 phpunit.xml
|
||||||
|
|
||||||
|
phpunit.xml 是 phpunit 这个工具用来单元测试所需要的配置文件。这个文件的名称同样也是可以自定义的,但是要在"build.xml"中配置好名字就行。默认情况下,用"phpunit.xml", 则不需要在"build.xml"中配置文件名。
|
||||||
|
|
||||||
|
![img](https:////upload-images.jianshu.io/upload_images/6464255-aa212d3b3eaff548.png?imageMogr2/auto-orient/strip|imageView2/2/w/798/format/webp)
|
||||||
|
|
||||||
|
build.xml 中 phpunit 配置
|
||||||
|
|
||||||
|
fileset dir 指定单元测试文件所在路径,include 指定包含哪些文件,支持通配符匹配。当然也可以用 exclude 关键字指定不包含的文件。
|
||||||
|
|
||||||
|
![img](https:////upload-images.jianshu.io/upload_images/6464255-dbc0084f6d50a240.png?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp)
|
||||||
|
|
||||||
|
### jenkins 权限管理
|
||||||
|
|
||||||
|
由于 jenkins 默认的权限管理体系不支持用户组或角色的配置,因此需要安装第三发插件来支持角色的配置,本文将使用 Role Strategy Plugin。基于这个插件的权限管理设置请参考这篇文章:[http://blog.csdn.net/russ44/article/details/52276222](https://link.jianshu.com?t=http%3A%2F%2Fblog.csdn.net%2Fruss44%2Farticle%2Fdetails%2F52276222),这里不作详细介绍。
|
||||||
|
|
||||||
|
至此,就可以用 jenkins 周而复始的进行 CI 了,当然 jenkins 是一个强大的工具,功能绝不仅仅是以上这些,其他方面要是以后用到,我会更新到这篇文章中。有疑问欢迎在下方留言。
|
||||||
|
|
||||||
|
## Jenkins FAQ
|
||||||
|
|
||||||
|
### 登录密码
|
||||||
|
|
||||||
|
如果不知道初始登录密码,可以通过以下方式查看:
|
||||||
|
|
||||||
|
执行命令 `cat /root/.jenkins/secrets/initialAdminPassword`,打印出来的即是初始登录密码。
|
||||||
|
|
||||||
|
### 忘记密码
|
||||||
|
|
||||||
|
1.执行 `vim /root/.jenkins/config.xml` ,删除以下内容
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<useSecurity>true</useSecurity>
|
||||||
|
<authorizationStrategy class="hudson.security.FullControlOnceLoggedInAuthorizationStrategy">
|
||||||
|
<denyAnonymousReadAccess>true</denyAnonymousReadAccess>
|
||||||
|
</authorizationStrategy>
|
||||||
|
<securityRealm class="hudson.security.HudsonPrivateSecurityRealm">
|
||||||
|
<disableSignup>true</disableSignup>
|
||||||
|
<enableCaptcha>false</enableCaptcha>
|
||||||
|
</securityRealm>
|
||||||
|
```
|
||||||
|
|
||||||
|
2.重启 Jenkins 服务;
|
||||||
|
|
||||||
|
3.进入首页>“系统管理”>“Configure Global Security”;
|
||||||
|
|
||||||
|
4.勾选“启用安全”;
|
||||||
|
|
||||||
|
5.点选“Jenkins 专有用户数据库”,并点击“保存”;
|
||||||
|
|
||||||
|
6.重新点击首页>“系统管理”,发现此时出现“管理用户”;
|
||||||
|
|
||||||
|
7.点击进入展示“用户列表”;
|
||||||
|
|
||||||
|
8.点击右侧进入修改密码页面,修改后即可重新登录。
|
||||||
|
|
||||||
|
### 卡在 check 页面
|
||||||
|
|
||||||
|
**现象**:输入密码后,卡在 check 页面
|
||||||
|
|
||||||
|
**原因**:jenkins 在安装插件前总是尝试连接 www.google.com,来判断网络是否连通。谷歌的网站在大陆是连不上的,所以会出现这个问题。
|
||||||
|
|
||||||
|
**解决方案**:执行`vim /root/.jenkins/updates/default.json`,将 `connectionCheckUrl` 后的 `www.google.com` 改为 `www.baidu.com` 。然后重启即可。
|
||||||
|
|
||||||
|
或者直接执行命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sed -i 's/www.google.com/www.baidu.com/g' /root/.jenkins/updates/default.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### 卡在 getting startted 页面
|
||||||
|
|
||||||
|
**现象**:卡在 getting startted 页面
|
||||||
|
|
||||||
|
**原因**:jenkins 默认的插件下载服务器地址在国外,如果不翻墙下载不了。
|
||||||
|
|
||||||
|
**解决方案**:执行`vim /root/.jenkins/hudson.model.UpdateCenter.xml`,将 `<url>` 改为 `http://mirror.xmission.com/jenkins/updates/update-center.json` 。然后重启即可。
|
||||||
|
|
||||||
|
或者直接执行命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sed -i '/^<url>/s/.*/<url>http:\/\/mirror.xmission.com\/jenkins\/updates\/update-center.json<\/url>/g' /root/.jenkins/hudson.model.UpdateCenter.xml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 以 root 用户运行
|
||||||
|
|
||||||
|
(1)修改 jenkins 用户
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vim /etc/sysconfig/jenkins
|
||||||
|
```
|
||||||
|
|
||||||
|
修改用户
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$JENKINS_USER="root"
|
||||||
|
```
|
||||||
|
|
||||||
|
(2)修改 `Jenkins` 相关文件夹用户权限
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chown -R root:root /var/lib/jenkins
|
||||||
|
chown -R root:root /var/cache/jenkins
|
||||||
|
chown -R root:root /var/log/jenkins
|
||||||
|
```
|
||||||
|
|
||||||
|
(3)重启 Jenkins
|
||||||
|
|
||||||
|
```
|
||||||
|
systemctl restart jenkins
|
||||||
|
```
|
||||||
|
|
||||||
|
## 参考资料
|
||||||
|
|
||||||
|
- **官方**
|
||||||
|
|
||||||
|
- [Jenkins 官网](https://jenkins.io/zh/)
|
||||||
|
- [Jenkins 中文文档](https://jenkins.io/zh/doc/tutorials/)
|
||||||
|
|
||||||
|
- **引申**
|
||||||
|
- [操作系统、运维部署总结系列](https://github.com/dunwu/OS)
|
||||||
|
- **文章**
|
||||||
|
- https://jenkins.io/doc/pipeline/tour/getting-started/
|
||||||
|
- https://www.cnblogs.com/austinspark-jessylu/p/6894944.html
|
||||||
|
- http://blog.csdn.net/jlminghui/article/details/54952148
|
||||||
|
- [Jenkins 详细教程](https://www.jianshu.com/p/5f671aca2b5a)
|
|
@ -1,165 +0,0 @@
|
||||||
# Jenkins 安装
|
|
||||||
|
|
||||||
> 环境要求
|
|
||||||
>
|
|
||||||
> - JDK:JDK7+,官网推荐是 JDK 8
|
|
||||||
|
|
||||||
## 部署
|
|
||||||
|
|
||||||
> 参考:[官方安装文档](https://jenkins.io/zh/doc/book/installing/)
|
|
||||||
|
|
||||||
### War 包部署
|
|
||||||
|
|
||||||
安装步骤如下:
|
|
||||||
|
|
||||||
(1)下载并解压到本地
|
|
||||||
|
|
||||||
进入[官网下载地址](https://jenkins.io/zh/download/),选择合适的版本下载。
|
|
||||||
|
|
||||||
我选择的是最新稳定 war 版本 2.89.4:http://mirrors.jenkins.io/war-stable/latest/jenkins.war
|
|
||||||
|
|
||||||
我个人喜欢存放在:`/opt/software/jenkins`
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mkdir -p /opt/software/jenkins
|
|
||||||
wget -O /opt/software/jenkins/jenkins.war http://mirrors.jenkins.io/war-stable/latest/jenkins.wa
|
|
||||||
```
|
|
||||||
|
|
||||||
(2)启动
|
|
||||||
|
|
||||||
如果你和我一样,选择 war 版本,那么你可以将 war 移到 Tomcat 的 webapps 目录下,通过 Tomcat 来启动。
|
|
||||||
|
|
||||||
当然,也可以通过 `java -jar` 方式来启动。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /opt/software/jenkins
|
|
||||||
nohup java -jar jenkins.war --httpPort=8080 >> nohup.out 2>&1 &
|
|
||||||
```
|
|
||||||
|
|
||||||
### rpm 包部署
|
|
||||||
|
|
||||||
(1)下载安装
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
|
|
||||||
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
|
|
||||||
yum install jenkins
|
|
||||||
```
|
|
||||||
|
|
||||||
(2)启动
|
|
||||||
|
|
||||||
```bash
|
|
||||||
systemctl start jenkins
|
|
||||||
```
|
|
||||||
|
|
||||||
### 访问
|
|
||||||
|
|
||||||
1. 打开浏览器进入链接 `http://localhost:8080`.
|
|
||||||
2. 按照说明完成安装.
|
|
||||||
|
|
||||||
## 系统配置
|
|
||||||
|
|
||||||
## FAQ
|
|
||||||
|
|
||||||
### 登录密码
|
|
||||||
|
|
||||||
如果不知道初始登录密码,可以通过以下方式查看:
|
|
||||||
|
|
||||||
执行命令 `cat /root/.jenkins/secrets/initialAdminPassword`,打印出来的即是初始登录密码。
|
|
||||||
|
|
||||||
### 忘记密码
|
|
||||||
|
|
||||||
1.执行 `vim /root/.jenkins/config.xml` ,删除以下内容
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<useSecurity>true</useSecurity>
|
|
||||||
<authorizationStrategy class="hudson.security.FullControlOnceLoggedInAuthorizationStrategy">
|
|
||||||
<denyAnonymousReadAccess>true</denyAnonymousReadAccess>
|
|
||||||
</authorizationStrategy>
|
|
||||||
<securityRealm class="hudson.security.HudsonPrivateSecurityRealm">
|
|
||||||
<disableSignup>true</disableSignup>
|
|
||||||
<enableCaptcha>false</enableCaptcha>
|
|
||||||
</securityRealm>
|
|
||||||
```
|
|
||||||
|
|
||||||
2.重启 Jenkins 服务;
|
|
||||||
|
|
||||||
3.进入首页>“系统管理”>“Configure Global Security”;
|
|
||||||
|
|
||||||
4.勾选“启用安全”;
|
|
||||||
|
|
||||||
5.点选“Jenkins 专有用户数据库”,并点击“保存”;
|
|
||||||
|
|
||||||
6.重新点击首页>“系统管理”,发现此时出现“管理用户”;
|
|
||||||
|
|
||||||
7.点击进入展示“用户列表”;
|
|
||||||
|
|
||||||
8.点击右侧进入修改密码页面,修改后即可重新登录。
|
|
||||||
|
|
||||||
### 卡在 check 页面
|
|
||||||
|
|
||||||
**现象**:输入密码后,卡在 check 页面
|
|
||||||
|
|
||||||
**原因**:jenkins 在安装插件前总是尝试连接 www.google.com,来判断网络是否连通。谷歌的网站在大陆是连不上的,所以会出现这个问题。
|
|
||||||
|
|
||||||
**解决方案**:执行`vim /root/.jenkins/updates/default.json`,将 `connectionCheckUrl` 后的 `www.google.com` 改为 `www.baidu.com` 。然后重启即可。
|
|
||||||
|
|
||||||
或者直接执行命令:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sed -i 's/www.google.com/www.baidu.com/g' /root/.jenkins/updates/default.json
|
|
||||||
```
|
|
||||||
|
|
||||||
### 卡在 getting startted 页面
|
|
||||||
|
|
||||||
**现象**:卡在 getting startted 页面
|
|
||||||
|
|
||||||
**原因**:jenkins 默认的插件下载服务器地址在国外,如果不翻墙下载不了。
|
|
||||||
|
|
||||||
**解决方案**:执行`vim /root/.jenkins/hudson.model.UpdateCenter.xml`,将 `<url>` 改为 `http://mirror.xmission.com/jenkins/updates/update-center.json` 。然后重启即可。
|
|
||||||
|
|
||||||
或者直接执行命令:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sed -i '/^<url>/s/.*/<url>http:\/\/mirror.xmission.com\/jenkins\/updates\/update-center.json<\/url>/g' /root/.jenkins/hudson.model.UpdateCenter.xml
|
|
||||||
```
|
|
||||||
|
|
||||||
### 以 root 用户运行
|
|
||||||
|
|
||||||
(1)修改 jenkins 用户
|
|
||||||
|
|
||||||
```bash
|
|
||||||
vim /etc/sysconfig/jenkins
|
|
||||||
```
|
|
||||||
|
|
||||||
修改用户
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$JENKINS_USER="root"
|
|
||||||
```
|
|
||||||
|
|
||||||
(2)修改 `Jenkins` 相关文件夹用户权限
|
|
||||||
|
|
||||||
```bash
|
|
||||||
chown -R root:root /var/lib/jenkins
|
|
||||||
chown -R root:root /var/cache/jenkins
|
|
||||||
chown -R root:root /var/log/jenkins
|
|
||||||
```
|
|
||||||
|
|
||||||
(3)重启 Jenkins
|
|
||||||
|
|
||||||
```
|
|
||||||
systemctl restart jenkins
|
|
||||||
```
|
|
||||||
|
|
||||||
## 参考资料
|
|
||||||
|
|
||||||
- **官方**
|
|
||||||
- [Jenkins 官网](https://jenkins.io/zh/)
|
|
||||||
|
|
||||||
- **引申**
|
|
||||||
- [操作系统、运维部署总结系列](https://github.com/dunwu/OS)
|
|
||||||
- **引用**
|
|
||||||
- https://jenkins.io/doc/pipeline/tour/getting-started/
|
|
||||||
- https://www.cnblogs.com/austinspark-jessylu/p/6894944.html
|
|
||||||
- http://blog.csdn.net/jlminghui/article/details/54952148
|
|
Loading…
Reference in New Issue