shell 基本语法注意点

本文深入探讨Shell脚本中的高级技巧,包括参数引用的区别、数组操作、运算符使用、字符串处理、文件操作、函数参数传递、重定向输入输出、文件包含及复杂的任务管理脚本示例。特别聚焦于如何确保服务的连续运行,通过检查进程状态和PID文件来自动重启失败的服务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. $ *和$ @区别

相同点:都是引用所有参数。

不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数1,2,3 ,,则“*”等价于“1 2 3”(传递了一个参数),而“@” “等价于”1“”2“”3“(传递了三个参数)。

#!/bin/bash
for i in "$*"
do
    echo "$i"
done

foo i in "$@"
do
    echo "$i"
done

123

1

2

3

2.数组

2.1数组的下标从0开始

my_array=(A B "C" D)

echo "第一个元素为: ${my_array[0]}"
echo "第二个元素为: ${my_array[1]}"
echo "第三个元素为: ${my_array[2]}"
echo "第四个元素为: ${my_array[3]}"




res:
第一个元素为: A
第二个元素为: B
第三个元素为: C
第四个元素为: D

2.2获取数组中的所有元素

my_array[0]=A
my_array[1]=B
my_array[2]=C
my_array[3]=D

echo "数组的元素为: ${my_array[*]}"
echo "数组的元素为: ${my_array[@]}"


res:
数组的元素为: A B C D
数组的元素为: A B C D

2.3获取数组的长度(和字符串长度求取一致)

my_array[1]=B
my_array[2]=C
my_array[3]=D

echo "数组元素个数为: ${#my_array[*]}"
echo "数组元素个数为: ${#my_array[@]}"

res:
数组元素个数为: 4
数组元素个数为: 4

3.运算符操作

+ - *,/%完整的表达式要被“包含,且变量之间需要加空格,乘号(*)前边必须加反斜杠(\)才能实现乘法运算;

a=10
b=20

val=`expr $a + $b`
val=`expr $a \* $b`

4.字符串运算

5.文件操作

 

6.函数参数

 

7.重定向输入输出

0标准输入

1标准输出

2错误输出

将正确输出错误输出都丢弃:sh test.sh> / dev / null 2>&1等同于sh test.sh&> / dev / null

8.文件包含

. filename   # 注意点号(.)和文件名中间有一空格

或

source filename

 

shell脚本示例:

#!/bin/bash
#######################################################
#检查任务执行脚本是否在运行,没有则拉起
#######################################################
# 定时脚本,启动保证其单例运行 1min执行一次同步任务
# softdog: appname=${p_name},state=2语句中 state=0表示appname存在不需要重启,state=1表示appname不存在需要重启,state=2表示appname存在但运行不正常需要重启
LOG_PATH="/var/log/rlog1.txt"
MAX_LOGNUM=1000

LOG()
{
        if [ -f $LOG_PATH ]; then
                touch $LOG_PATH
        fi

        line_num=$(awk 'END{print NR}' $LOG_PATH)
        if [ $line_num -ge $MAX_LOGNUM ]; then
                sed -i '1d' $LOG_PATH
        fi

        echo `date` $1 >> $LOG_PATH
}
proclist=$(ps -Ao 'comm' | sort | uniq)
if [ "$proclist" == "" ]; then
    LOG "softdog: softdog get program list failed!"
    exit
fi

pidfilelist=$(ls /var/run/*.pid)
if [ "$pidfilelist" == "" ]; then
        LOG "softdog: softdog get pid file list failed!"
        exit
fi

IsRunning()
{
    for prog in $proclist
    do
        if [ "$prog" == "$1" ]; then
            return 0
        fi
    done
    return 1
}
IsPidfileExist()
{
        for pidfile in $pidfilelist
        do
                if [ "$pidfile" == "$1" ]; then
                        return 0
                fi
        done
        return 1
}

# Usage: DogRun $program $pidfile
# program: 程序名
# pidfile: 程序的pid文件
# pid文件存在才去拉程序, 针对程序异常退出,
# 若正常退出一般会删除pid文件, 所以就不会去拉程序
DaemonRun()
{
        local program=$1
        servicepid="/var/run/"${program}.pid
        IsPidfileExist "$servicepid"
        if [ $? -eq 0 ]; then
                #pidof ${program} 2>/dev/null >/dev/null
        IsRunning "${program}" &>/dev/null
                if [ $? -ne 0 ]; then
                        LOG "softdog: softdog restart ${program} ..."
                        /etc/init.d/${program} restart
                        LOG "softdog: appname=${program},state=1"
                        exit
                fi
                LOG "softdog: appname=${program},state=0"
        fi
}

#判断某进程是否运行正常,命令IsAlive 进程名 超时时间,return:1 正常,0 进程异常
#超时时间单位为秒
IsAlive()
{
        local program=$1
        servicealive="/var/run/"${program}.alive
        lasttime=$(stat -c %Y $servicealive)
        now=$(date +%s)
        if [ $[ $now - $lasttime ] -gt $2 ];then
                return 0
        fi
        return 1
}

#通过ps命令判断某脚本是否在运行 在运行 返回1 
IsScriptRun()
{
    ret=$(ps -ef|grep "$1"|grep -v grep|wc -l)
    if [ $ret -gt 0 ];then
        return 1
    fi
    return 0
}
#脚本程序的保活 进程名 重启脚本路径 超时时间单位为秒
AppRun()
{
    local p_name=$1
    pid_file="/var/run/"${p_name}.pid
    alive_name="/var/run/"${p_name}.alive
    if [ ! -f $pid_file ];then
        exit
    fi
    script_name=${p_name}.py
    IsScriptRun $script_name
    if [ $? -eq 0 ]; then
            sh $2 &>/dev/null &
            LOG "softdog: program not in running.softdog restart ${p_name} ..."
            LOG "softdog: appname=${p_name},state=1"
            exit
    fi
    if [ ! -f $alive_name ];then
            exit
    fi
    IsAlive $1 $3
    if [ $? -eq 0 ]; then
            pid=$(ps -ef|grep $script_name|grep -v grep|awk '{print $2}')
            kill -9 $pid
            LOG "softdog: softdog kill overtime program: ${p_name} ..."
            sh $2 &>/dev/null &
            LOG "softdog: softdog restart ${p_name} ..."
            LOG "softdog: appname=${p_name},state=2"
            exit
    fi
    LOG "softdog: appname=${p_name},state=0"   
}
#第三方服务进程保活 服务名 重启脚本路径 pid文件路径
OtherServiceRunByPid()
{
    service_name=$1
    restart_path=$2
    service_pid=$3
    if [ -f $service_pid ];then
        IsRunning $service_name
        if [ $? -eq 1 ];then
            sh $restart_path
            LOG "softdog: softdog restart ${service_name} ..."
            LOG "softdog: appname=${service_name},state=1"
            exit
        fi
        LOG "softdog: appname=${service_name},state=0"
    fi
}
#其他类型服务 MongoDB
OtherServiceRunByConfg()
{
    service_cmd=$1
    restart_path=$2
    pid_file=$3
    if [ -f $pid_file ];then
        pid=$(pgrep -f "$service_cmd")
        if [ "$pid" != "" ];then
            LOG "softdog: appname=${service_cmd},state=0"
            exit
        else
            sh $restart_path
            LOG "softdog: appname=${service_cmd},state=1"
        fi
    fi   
}

#脚本程序的保活 进程名 重启脚本路径 超时时间单位为秒
AppRunByCmd()
{
    local p_name=$1
    pid_file="/var/run/"${p_name}.pid
    alive_name="/var/run/"${p_name}.alive
    if [ ! -f $pid_file ];then
        exit
    fi
    app_cmd="$4"
    IsScriptRun "$app_cmd"
    if [ $? -eq 0 ]; then
            sh $2 &>/dev/null &
            LOG "softdog: program not in running.softdog restart ${p_name} ..."
            LOG "softdog: appname=${p_name},state=1"
            exit
    fi
    if [ ! -f $alive_name ];then
            exit
    fi
    IsAlive $1 $3
    if [ $? -eq 0 ]; then
            pid=$(ps -ef|grep "$app_cmd"|grep -v grep|awk '{print $2}')
            kill -9 $pid
            LOG "softdog: softdog kill overtime program: ${p_name} ..."
            sh $2 &>/dev/null &
            LOG "softdog: softdog restart ${p_name} ..."
            LOG "softdog: appname=${p_name},state=2"
            exit
    fi
    LOG "softdog: appname=${p_name},state=0"
        
}
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值