Linux Shell 语句&脚本编写

1、shell变量

  变量赋值需注意一点等号两边不允许空格;在使用变量时,需在变量前加“$变量”符号或“${变量}(可选)”;

#例如一个for循环
for skill in Ada Coffe Action Java; do
    echo "I am good at ${skill}Script"
done
#字符串变量,"" or ''
my_string='Hello, World!'
my_string="Hello, World!"
#整数变量,可以使用 declare 或 typeset 命令来声明整数变量
declare -i my_integer=42
#数组变量
my_array=(1 2 3 4 5)
#环境变量
echo $PATH
#特殊变量
$0 表示脚本的名称
$1, $2, 等表示脚本的参数
$# 表示传递给脚本的参数数量
$? 表示上一个命令的退出状态
$- 显示Shell使用的当前选项
$$ 脚本运行的当前进程ID

2、传递参数

  在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为 $n,n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数。

[root@localhost ~]# cat test.sh
#!/bin/bash
echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";
[root@localhost ~]# ls -l test.sh
-rw-r--r--  1 root root 23735 Feb 11 11:24 test.sh
[root@localhost ~]# chmod 775 test.sh
[root@localhost ~]# ./test.sh 1 2 3
Shell 传递参数实例!
执行的文件名:./test.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3

3、数组

  数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组);与大部分编程语言类似,数组元素的下标由 0 开始。Shell 数组用括号来表示,元素用"空格"符号分割开。

array_name=(value1 value2 ... valuen)

#!/bin/bash

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

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

4、运算符

4.1、算术运算符

  注意:条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。

#!/bin/bash
a=10
b=20
# 加
val=`expr $a + $b`
# 减
val=`expr $a - $b`
# 乘
val=`expr $a \* $b`
# 除
val=`expr $b / $a`
# 取余
val=`expr $b % $a`

if [ $a == $b ] # 相等
then
   echo "a 等于 b"
fi
if [ $a != $b ] # 不等
then
   echo "a 不等于 b"
fi

4.2、关系运算符

  关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

#!/bin/bash

if [ $a -eq $b ]
then
   echo "$a -eq $b : a 等于 b"
fi
if [ $a -ne $b ]
then
   echo "$a -ne $b: a 不等于 b"
fi
if [ $a -gt $b ]
then
   echo "$a -gt $b: a 大于 b"
fi
if [ $a -lt $b ]
then
   echo "$a -lt $b: a 小于 b"
fi
if [ $a -ge $b ]
then
   echo "$a -ge $b: a 大于或等于 b"
fi
if [ $a -le $b ]
then
   echo "$a -le $b: a 小于或等于 b"
fi

4.3、布尔运算符

运算符 说明 举例
! [ ! false ] 返回 true
-o [ $a -lt 20 -o $b -gt 100 ] 返回 true
-a [ $a -lt 20 -a $b -gt 100 ] 返回 false

4.4、逻辑运算符

&&:逻辑的与
||:逻辑的或

#!/bin/bash

a=10
b=20

if [[ $a -lt 100 && $b -gt 100 ]]
then
   echo "返回 true"
else
   echo "返回 false"
fi

if [[ $a -lt 100 || $b -gt 100 ]]
then
   echo "返回 true"
else
   echo "返回 false"
fi

4.5、字符串运算符

字符串比较 释义
If [ a = b ] 如果string1等于string2,则为真
if [ string1 != string2 ] 如果string1不等于string2,则为真
if [ -n $string ] 如果string 非空(非0),返回0(true)
if [ -z $string ] 如果string 为空,则为真
if [ $sting ] 如果string 非空,返回0 (和-n类似)

4.6、文件测试运算符

表达式 表达式释义
-e Filename 如果Filename存在,则为真
-r Filename 如果Filename可读,则为真
-w Filename 如果Filename可写,则为真
-x Filename 如果Filename可执行,则为真
-d Filename 如果Filename为目录,则为真
-f Filename 如果Filename为常规文件,则为真
-L Filename 如果Filename为符号链接,则为真
-s Filename 如果文件长度不为0,则为真
-h Filename 如果文件是软连接,则为真
Filename1 -nt Filename2 如果Filename1比Filename2新,则为真
Filename1 -ot Filename2 如果Filename1比Filename2旧,则为真

4.7、自增自减操作符

#!/bin/bash

# 自增
let num++

# 自减
let num--

# 使用 $(( ))
num=$((num + 1))
num=$((num - 1))

# 使用 expr
num=$(expr $num + 1)
num=$(expr $num - 1)

# 使用 (( ))
((num++))
((num--))

5、流程控制

  在流程控制中有时候需要在未达到循环结束条件时强制跳出循环,Shell 使用两个命令来实现该功能:break 和 continue;

5.1、Linux下使用for循环的几种使用格式

1、for((i=1;i<10;i++)); do #常用
   ~
   done
2、for i in $(seq 1 10); do
   ~
   done
3、for i in {1..10}; do
    ~
    done
# 无限循环
4、for (( ; ; )); do
    ~
    done
#awk应用
5、awk 'BEGIN{for(i=1;i<10;i++) print i}
     

5.2、Linux下使用if判断的格式

#文件存在且变量不为零,逻辑与
[ -e $load/fiotesf.log -a $loops -eq 0 ]
[[ -e $load/fiotesf.log && $loops -eq 0 ]]
[[ -eq $load/fiotesf.log ]] &&[[ $loops -eq 0 ]]
[ -eq $load/fiotesf.log ]&&[ $loops -eq 0 ]
#if语句格式
if condition; then
    commands;
elif condition; then
    commands;
else
    commands;
fi
#使用&&和 ||也可以达到if else效果
[ condition ] && commands || commands
例:a等于8,则打印True,否则Failed
[root@localhost #] a=8;[ a -eq 8 ] && echo Ture || echo Failed
True

5.3、Linux下使用while语句的格式

while condition
do
    command
done
# 无限循环
while : or while true
do
    command
done

5.4、Linux下使用until语句的格式

  执行一系列命令直至条件为 true 时停止

#!/bin/bash
a=0

until [ ! $a -lt 10 ]
do
   echo $a
   a=`expr $a + 1`
done

5.5、Linux下使用case语句的格式

  case ... esac 为多选择语句,与其他语言中的 switch ... case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case ... esac 语句,esac(就是 case 反过来)作为结束标记

case 值 in
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac
# 示例
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
    1)  echo '你选择了 1'
    ;;
    2)  echo '你选择了 2'
    ;;
    3)  echo '你选择了 3'
    ;;
    4)  echo '你选择了 4'
    ;;
    *)  echo '你没有输入 1 到 4 之间的数字'
    ;;
esac

6、函数

  可以带 function fun() 定义,也可以直接 fun() 定义,不带任何参数。
  参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return 后跟数值 n(0-255).
  注意:所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。
  注意: return 语句只能返回一个介于 0 到 255 之间的整数,而两个输入数字的和可能超过这个范围。

[ function ] funname [()]

{

    action;

    [return int;]

}

7、输入输出重定向

表达式 表达式释义
command > file 将输出重定向到 file
command < file 将输入重定向到 file
command >> file 将输出以追加的方式重定向到 file
n > file 将文件描述符为 n 的文件重定向到 file
n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file
n >& m 将输出文件 m 和 n 合并
n <& m 将输入文件 m 和 n 合并
<< tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入

注意:0 是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。这里的 2 和 > 之间不可以有空格,2> 是一体的时候才表示错误输出。
例:command > /dev/null 2>&1

8、shell脚本

#! /usr/bin/bash

data=`date +"%Y-%m-%d_%H-%M-%S"`

TEMP_DIR='/backup'
MESSAGE_DIR='/var/log/message'


if [[ ! -d $TEMP_DIR ]]; then
    echo "临时目录 $TEMP_DIR 不存在,正在创建 ..."
    mkdir -p $TEMP_DIR
fi

function GetParameter(){
    while getopts "s:d:n:" opt; do
        case $opt in
            s)
                SOURCE_DIR="$OPTARG"
                ;;
            d)
                TARGET_DIR="$OPTARG"
                ;;
            n)
                BACKUP_NAME="$OPTARG"
                ;;
            *)
                echo "用法: $0 -s 原备份文件 -d 目标目录 -n 备份文件名"
                exit 1
                ;;
        esac
    done

    if [[ -z "$SOURCE_DIR" || -z "$TARGET_DIR" || -z "$BACKUP_NAME" ]]; then
        echo "错误:缺少必填参数!"
        echo "用法: ./clearlog.sh -s 源目录 -d 目标目录 -n 备份文件名"
        exit 1
    fi

}

function BackUpLog(){
  
    local target_dir=$1
    local bakup_name=$2
    local source_dir=$3
    local backup_file="$target_dir/$bakup_name-$data.tar.xz"
    if [[ ! -d $target_dir ]]; then
        echo "目标目录 $target_dir 不存在,正在创建 ..."
        mkdir -p $target_dir
    fi

    echo "正在备份 $source_dir 到 $target_dir ..."
    if [[ -z $MESSAGE_DIR ]];then
        echo "备份message ..."
        cp -rv $MESSAGE_DIR $TEMP_DIR
    fi
    
    echo "备份dmesg ..."
    dmesg -T > $TEMP_DIR/dmesg
 
    echo "备份$source_dir ..."
    cp -rv $source_dir $TEMP_DIR
    
    echo "正在压缩文件 ..."
    tar -cJvf $backup_file -P $TEMP_DIR

    if [[ $? -eq 0 ]]; then
        echo "备份成功!备份文件保存在 $backup_file"
    else
        echo "备份失败!请检查错误信息。"
        exit 1
    fi


}

function ClearSourPathLog(){
    local message=$1
    local source_dir=$2
    local temp_dir=$3
    echo "正在清除文件 ..."
    echo "" > $message
    rm -rf $source_dir
    rm -rf $temp_dir
    dmesg -C

}


function main(){
    echo "                  开始执行                  "
    echo "============================================"
    echo "获取传入的源路径、目标路径"
    GetParameter "$@"
    echo "开始进行备份,备份到:$TARGET_DIR"
    BackUpLog $TARGET_DIR $BACKUP_NAME $SOURCE_DIR
    echo "============================================"
    echo "开始清理log,清理路径:$SOURCE_DIR"
    ClearSourPathLog $MESSAGE_DIR $SOURCE_DIR $TEMP_DIR
    echo "============================================"
    unset TARGET_DIR SOURCE_DIR BACKUP_FILE BACKUP_NAME MESSAGE_DIR TEMP_DIR
    echo "执行结束!!!"

}

main "$@"


~文章已经结束了~
声明:本人所写的只是本人在使用中遇到的问题做个记录总结,很多内容也是百度,或者查阅官方文档,若与他人有重复;若需按照本文配置,请认真确认是否适合你的情况,造成一切损失;本人概不负责。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。