shell-服务启动(基础部分:变量、数组、分支、循环、函数、命令替换、字符串、$取值)

shell基础部分学习
环境与插件
vscode编辑器 + 插件(shellman, bash debug ,shell format,shell check ,shell script IDE,shell script snippets)

参考书籍:
《Linux命令行与shell脚本编程大全(第3版)》
《Linux Shell核心编程指南》

vscode配置bash shell 调试 launch.json

{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
    	// javascirpt调试
    	// 这个不用管
        {
            "name": "Launch Program",
            "program": "${fileDirname}/${fileBasename}",
            "request": "launch",
            "skipFiles": [
                "<node_internals>/**"
            ],
            "type": "node"
        },
        // shell调试
        {
            "type": "bashdb",
            "request": "launch",
            "name": "Bash-Debug (simplest configuration)",
            "program": "${fileDirname}/${fileBasename}"
        }
    ]
}

1、变量、数组、分支、循环、函数

(1)、变量

定义: variable = value , 如REDIS_BIN=/usr/local/bin
取值:$variable, 如echo “$REDIS_BIN”

(2)、数组

定义、修改元素,取元素,取数组长度,取单个元素长度、
取数组所有值、数组拼接、删除数组、删除元素、遍历元素
定义关联数组、遍历关联数组值、遍历关联数组key等

#!/bin/bash

#服务列表名称,数组定义 array_name=(value1,value2,...,valueN)
serverList=(
  "redis-server"
  "mysql"
  "nginx"
  "xxl-job-admin"
  "fdfs_trackerd"
  "fdfs_storaged"
  "mongod"
)

# 取数组下标为0的值 ${array_name[index]}
echo "${serverList[0]}"
# 修改特定元素的值 array_name[index]=value
serverList[0]="test"
# 取数组下标为0的值  ${array_name[index]}
echo "${serverList[0]}"
# 取数组长度 $#表示参数个数  假设echo "${serverList[#]}",不行!!!
echo "${#serverList[@]}";
echo "${#serverList[*]}"
# 获取单个元素的长度
echo "${#serverList[1]}"
# 取数组所有值,并以空格隔开,效果:redis-server mysql nginx xxl-job-admin fdfs_trackerd fdfs_storaged mongod
echo "${serverList[@]}"
echo "${serverList[*]}"
# 数组拼接,就是形成(value1 value2 ... valueN)  
# 那么按照上边的说法array_new=(${array1[@]} ${array2[@]})
# 玩积木---层层叠加

# 删除数组元素 unset array_name[index]    unset array_name
unset "serverList[0]"
if [[ "${serverList[0]}" == "" ]]; then
    echo "删除成功"
fi
echo "${serverList[0]}"
unset serverList
if [[ "${serverList[*]}" == "" ]]; then
    echo "删除成功"
fi

# 循环遍历数组
for serverItem in "${serverList[@]}"; 
do
  echo "$serverItem"  
done

# 形如map的关联数组
declare -A array_name
array_name["lch"]=999
array_name["lx"]=0

# 遍历关联数组值
for arrayItem in "${array_name[@]}"; 
do
  echo "$arrayItem"  
done

# 遍历关联数组键,在${array_name[@]}基础之上加个 ! 形成 ${!array_name[@]}
for arrayKey in "${!array_name[@]}"; 
do
  echo "$arrayKey"  
done

(3)、分支

if分支定义:

if condition; then
     # if body
     commands
elif condition; then
     # else if body
     commands
else
     # else body
     commands
fi
condition: 条件
commands:0个或多个命令

根据条件执行命令。

如果condition为零,则执行`then commands'列表。
否则按顺序执行每个 `elif condition'列表,并且如果它的退出状态为零,
则执行对应的 `then commands' 列表并且 if 命令终止。
否则如果存在的情况下,执行 `else commands'列表。
整个结构的退出状态是最后一个执行的命令的状态,或者如果没有条件测试为真的话,为零。
退出状态:
返回最后一个执行的命令的状态。
    
注:
1、一般的命令其成功返回值为0,这里的if分支,其实是condition为0,则执行then语句。
2、condition可以是命令,也可以是数值判断
3、condition为零,具体含义为执行命令/判断之后,$?的值为0
比如:
(( 2 == 3))
echo "$?"   # 2 3不相等,$?值为 1 
(( 2 == 2))
echo "$?"  # 2  3相等,$?值为 0 
# 那么,下边就会打印相等
if (( 2 == 2));
then 
    echo "相等"
fi

case 分支:

case 词 in [模式 [| 模式]...) 命令 ;;]... esac

基于模式匹配来执行命令。

基于 PATTERN 模式匹配的词 WORD,有选择的执行 COMMANDS 命令。
`|' 用于分隔多个模式。

退出状态:
返回最后一个执行的命令的状态。

case "${item}" in
    1)
        echo "item = 1"
    ;;
    2|3)
        echo "item = 2 or item = 3"
    ;;
    *)
        echo "default (none of above)"
    ;;
esac

(4)、循环

for循环

for 名称 [in 词语 ... ] ; do 命令; done
为列表中的每个成员执行命令。

“for”循环为列表中的每个成员执行一系列的命令。如果没有
“in <词语> ...;”则假定使用“in "$@"”。对于 <词语> 中的每
 个元素,<名称> 变量被设定为该元素后执行 <命令>。

退出状态:
返回最后执行的命令的状态。

比如:
#!/bin/bash
serverList=("redis-server" "mysql" "nginx" "xxl-job-admin" "fdfs_trackerd" "fdfs_storaged" "mongod")
#服务启动核心逻辑
for serverItem in "${serverList[@]}"; 
do
	echo "$serverItem"
done

while循环:

while condition; do commands done
只要测试成功即执行命令。

只要在 condition 为0,则展开并执行 commands 命令。

退出状态:
返回最后一个执行的命令的状态。

比如:
# 打印0-9
index=0
while (( index < 10 )); do
    # body
    echo "$index"
    (( index++ ))
done

注:
1、这里的condition跟if分支condition一样

(5)、函数

抽离重复代码,将代码封装到函数以便其他模块调用。

1、创建函数
function name{
	commands
}
2、使用函数
function name   参数
如:
# $@ $* :  所有参数
# $0 1 2 ... : 参数0 1 ...  $0为执行程序  $1 .. 为参数
# $? 程序返回值
# $# 参数个数
# $variable  取变量值
function  printAge{
	echo "age: $1"
	return 0
}
printAge 20

3、函数返回跟默认退出状态码
函数中变量:
局部变量与全局变量冲突,默认为局部变量。

函数返回值(最好为0)
return value

取函数返回值
$?
若没有return,默认为最后一条命令的返回值
若函数为空,默认返回 0

正确使用函数输出
#!/bin/bash
# using the echo to return a value
function dbl {
 read -p "Enter a value: " value
 echo $[ $value * 2 ]
}
result=$(dbl)
echo "The new value is $result"

通过这种技术,你还可以返回浮点值和字符串值。这使它成为一种获取函数返回值的强
大方法。

2、命令替换与匹配

#!/bin/bash
#           left    right
#  最小匹配   #         %    
#  最大匹配   ##        %%   
#  例子:假设 path=/etc/sysconfig/network
#  ${path#*/}     //去掉path变量左边 第一次出现 */  子串    *代表匹配任意0或0个以上字符
#  ${path#tc}     //像这样是匹配不成功的,第一个字符‘t’ 与 左边第一个字符‘/’没匹配上,直接就结束了
#  ${path##*/}    //最大匹配
#  ${path%/*}     //去掉path变量右边匹配的子串
#  ${字符串/变量:开始位置:长度}                  ${path:0:5}   
#  字符替换 ${字符串/变量//要查找的值/替换值}      ${path//lc/ym}
#  $((算术表达式))
#  命令替换:可在shell语句里边执行命令      ``或$()
CURRENT_SCRIPT_DIR=$(cd "$(dirname "$0")" || exit; pwd;)
echo "$CURRENT_SCRIPT_DIR"
paramNumber=$#
if (( paramNumber != 1 )); then
    echo "没有输入主目录"
    return 1;
fi
HOME=$1
# HOME=/home/lch/learn/shell
COMMON_CONFIG_PATH=$HOME"/config/config.ini"
LOG_CONFIG_PATH=$HOME"/config/log.conf"
echo "$COMMON_CONFIG_PATH"
echo "$LOG_CONFIG_PATH"
# sed 's/\/sbin\/nologin/\/bin\/sh/' /tmp/passwd  使用转义替换
# sed 's#/sbin/nologin#/bin/sh#' /tmp/passwd      井号作为替换符
# sed 's,/sbin/nologin,/bin/sh,' /tmp/passwd      逗号作为替换符
sed -i "s#\${[a-zA-Z_]\+}#$HOME#" "$COMMON_CONFIG_PATH"
sed -i "s#\${[a-zA-Z_]\+}#$HOME#" "$LOG_CONFIG_PATH"

3、$取值

#!/bin/bash
export COMMAND_HOME=/home/lch/learn/shell
bash ./config.sh $COMMAND_HOME
result=$?
if (( result != 0 )); then
    return 1;
fi
# export COMMAND_HOME=/home/lch/os_code/command/build/command
# $@ $* :  所有参数
# $0 1 2 ... : 参数0 1 ...  $0为执行程序  $1 .. 为参数
# $? 程序返回值
# $# 参数个数
# $variable  取变量值
paramNumber=$#
#./client -e "ls -l"
if (( paramNumber != 2 )); then
    echo "参数数量错误"
    return 1;
fi
echo "./client $1 \"$2\""

3、服务启动停止

#!/bin/bash
#开启管理员
#sudo -i
#开启ssh连接
#service ssh start
if [ -f /etc/profile ]
then
    source /etc/profile
    result=$? 
    # -lt -le -eq -ge -gt -ne
    if [[ $result != 0 ]]
    then 
        exit 1
    fi
else
    exit 1
fi

#启动参数,可修改
#redis
REDIS_BIN=/usr/local/bin
REDIS_CONF=/usr/local/redis/redis.conf
#nginx
NGINX_BIN=/opt/apps/nginx/sbin
NGINX_CONF=/opt/apps/nginx/conf/nginx.conf
#mysql
MYSQL_START_HOME=/usr/local/mysql/support-files
#xxl-job-admin
XXLJOBBIN=/usr/local
#code_id
CODEIDBIN=/usr/local
#code_websocket
CODEWEBSOCKETTESTBIN=/usr/local
#fdfs_tracker
TRACKER_CONF=/etc/fdfs/tracker.conf
#fdfs_storage
STORAGE_CONF=/etc/fdfs/storage.conf
#mongod
MONGODB_BIN=/usr/local/mongodb/bin
MONGODB_CONF=/usr/local/mongodb/mongodb.conf


#函数定义
function startServer() {
  serverName=$1
  result=0
  echo "$serverName"
  case "${serverName}" in
    redis-server)
      startRedis
    ;;
    mysql)
      startMysql
    ;;
    xxl-job-admin)
      startXxlJobAdmin
    ;;
    nginx)
      startNginx
    ;;
    fdfs_trackerd)
      startFdfsTrackerd
    ;;
    fdfs_storaged)
      startFdfsStoraged
    ;;
    mongod)
      startMongod
    ;;
    code_id)
      startCodeId
    ;;
    code_websocket_test)
      startCodeWebsocket
    ;;
    *)
      echo "default (none of above)"
      return 1
    ;;
  esac
}
#redis 启动逻辑
function startRedis() {
  cd $REDIS_BIN || exit
  ./redis-server $REDIS_CONF
}
#mysql 启动逻辑
function startMysql() {
  cd $MYSQL_START_HOME || exit
  ./mysql.server start
}
#xxl-job-admin 启动逻辑
function startXxlJobAdmin() {
  cd $XXLJOBBIN || exit
	./xxlJob.sh
}
#nginx 启动逻辑
function startNginx() {
  cd $NGINX_BIN || exit
  ./nginx  -c  $NGINX_CONF
}
#fdfs_trackerd 启动逻辑
function startFdfsTrackerd() {
  fdfs_trackerd $TRACKER_CONF
  sleep 2
}
#fdfs_storaged 启动逻辑
function startFdfsStoraged() {
  # netstat -tulnp
  fdfs_storaged $STORAGE_CONF
  sleep 2
}
#mongod 启动逻辑
function startMongod() {
  cd $MONGODB_BIN || exit
  nohup mongod --fork --config $MONGODB_CONF > /dev/null 2>&1
}
#CodeId 启动逻辑 code_id
function startCodeId() {
  cd $CODEIDBIN || exit
  ./codeId.sh
}
#CodeWebsocket 启动逻辑
function startCodeWebsocket() {
  #code_websocket_test
  cd $CODEWEBSOCKETTESTBIN || exit
  ./code_websocket_test.sh
}

#服务列表名称
serverList=(
  "redis-server"
  "mysql"
  "nginx"
  "xxl-job-admin"
  "fdfs_trackerd"
  "fdfs_storaged"
  "mongod"
)

#服务启动核心逻辑
for serverItem in "${serverList[@]}"; 
do
  sleep 1
  #$(ps -ef | grep "mysql" | grep -c -v grep )
  runFlag=$(pgrep "${serverItem}" | grep -c -v grep )
  if [ "$runFlag" -lt 1 ];
  then
    echo "$serverItem 服务未启动, 正在启动该服务......"
  else
    echo "$serverItem 服务已启动, 正在停止该服务......"
    #$( ps -ef | grep "redis-server" | grep -v grep |awk '{print $2}')
    oldServerIds=$( pgrep "${serverItem}" )
    for oldServerPid in $oldServerIds; 
    do
      if [ -n "$oldServerPid" ];
      then
        echo "kill $serverItem server id: $oldServerPid"
        kill -9 "$oldServerPid"
      fi
    done
    echo "$serverItem 服务已停止, 正在启动该服务......"
  fi
  sleep 1
  startServer "$serverItem"
  #判断服务是否启动成功
  runFlag=$(pgrep "${serverItem}" | grep -c -v grep )
  if [ "$runFlag" -lt 1 ];
  then
    echo "$serverItem 服务启动失败"
  else
    echo "$serverItem 服务启动成功"
  fi
done
exit 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值