【Linux后端服务器开发】shell脚本

目录

一、变量

1. 普通变量

2. 环境变量

3. 位置变量

4. 特殊变量

二、输入输出

1. read命令接收输入

2. echo命令输出字符串

三、表达式

1. 算术表达式

2. 逻辑表达式

四、分支控制

1. if 分支

2. case 分支

五、循环控制

1. for 循环

2. while 循环

3. until 循环

4. select 循环

六、函数

1. 函数的格式

2. 函数的返回值

3. 函数参数

4. 库函数


一、变量

shell脚本只有一种数据类型,就是string字符串类型。

变量名必须是字母开头,可以包含数字、下划线等,不能有空格,不能使用关键字。

1. 普通变量

变量取值,可以与其他字符串构成新的字符串

变量赋值,用“=”赋值两端无空格

2. 环境变量

环境变量的级别:

  • 系统级:System env-var
  • 用户级:User login env-var
  • 脚本级:Script env-var

查看系统的环境变量:

  • echo:显示某个环境变量,如 echo $PATH

  • export:设置一个新环境变量,export PATH=&PATH:/...要添加的路径.../

  • env:显示所有环境变量

  • unset:清除环境变量

  • set:显示本地定义的shell变量和环境变量

查看环境变量

#include <stdio.h>

int main(int argc, char* argv[], char* env[]) {
    for (int i = 0; env[i]; ++i) {
        printf("env[%d]: %s\n", i, env[i]);
    }
}

通过环境变量区分root用户和普通用户

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main() {
    char* who = getenv("USER");
    if (strcmp(who, "root") == 0) {
        printf("user: %s\n", who);
    }
    else {
        printf("user: %s, 权限不够\n", who);
    }
}

自定义环境变量

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define MY_ENV "myenv"
 
int main() {
    char* myenv = getenv(MY_ENV);
    if (myenv == NULL) {
        printf("%s, not found\n", MY_ENV);
    }
    else {
        printf("%s = %s\n", MY_ENV, myenv);
    }
    return 0;
}

3. 位置变量

#!/bin/bash

echo $0
echo $1
echo $2
echo $3
echo $4
echo $5
echo $6
echo $7
echo $8
echo $9

 打印命令行指令参数选项

        命令行指令通过不同的参数执行不同的任务

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
int main(int argc, char* argv[], char* env[]) {
    if (argc != 2) {
        printf("usage: \n\t%s [-a/-b/-c/-ab/-ac/-bc/-abc]\n", argv[0]);
        return 1;
    }
    if (strcmp("-a", argv[1]) == 0) {
        printf("功能%s\n", argv[1]);
    }
    else if (strcmp("-b", argv[1]) == 0) {
        printf("功能%s\n", argv[1]);
    }
    else if (strcmp("-ab", argv[1]) == 0) {
        printf("功能%s\n", argv[1]);
    }
    else if (strcmp("-abc", argv[1]) == 0) {
        printf("功能%s\n", argv[1]);
    }
    //...
}

4. 特殊变量

  • 最后一条命令状态:$?  (0成功,1失败,2错误)
  • 传递给script的参数的个数:$#
  • 将命令行所有的参数作为一个整体的字符串:$*
  • 查看进程的PID:$$
#!/bin/bash

echo $#
echo $*

 

二、输入输出

1. read命令接收输入

  • 接收标准输入(键盘)的输入
  • 接收其他文件的输入
  • 得到输入后,将输入放入一个变量中
  • read命令可以结合echo命令进行输入提示,也可用 -p 选项做输入提示
  • read命令会一直阻塞等待用户输入,可以通过 -t 选项设置等待秒速
  • read命令可以通过 -n 选项限制输入的字符数
  • read命令可以通过 -s 选项进行静默输入,不显示输入内容,如密码的输入

2. echo命令输出字符串

echo命令加上 -n 选项,输出不换号

 

echo命令加上 -e 选项,支持转义字符

  • \b:向前回退一个
  • \c:在字符串输入末尾不换号
  • \n:回车换行
  • \r:回车
  • \v:换行
  • \t:水平方向跳Tab制表符距离

 

echo的引用与转义

  • " ":可取值输出
  • ' ':将单引号内的值原样输出
  • ` `:将反撇号的内容当作命令取执行
  • \:转义字符

三、表达式

1. 算术表达式

expr命令:+    -    *    /    %         (乘法运算符必须加上"",其他运算符可加可不加)

 

let命令:可赋值和计算

 

算术扩展格式:双小括号

bc工具:yum install -y bc

 

2. 逻辑表达式

通过 test命令 进行逻辑判断:

  • 执行状态为0表示true,执行状态为1表示false,如果变量可能为空,需要加双引号
  • -n 选项:变量非空则命令成功
  • -z 选项:变量为空则命令成功
  • -eq 是按照数值比较,= 是按照字符进行比较

复合条件判断:

  • -gt ,greater than ,大于
  • -lt ,less than,小于
  • -ge,greter or equal,大于等于
  • -le,less or equal,小于等于
  • -eq,数值等于
  • -a ,and,与运算,可以用 && 替换
  • -o,or,或运算,可以用 || 替换

test命令可用 [  ] 中括号等价替换,注意 "[ " 和 " ]",前后中括号之间都要有空格

文件或目录属性判断:

  • -e:判断文件或目录是否存在
  • -d:判断是否为目录以及是否存在
  • -f:判断是否为文件以及是否存在
  • -r-w-x:判断权限

四、分支控制

1. if 分支

if 分支的结构

# 格式1:if 条件; then 执行; fi

#! /bin/bash
a=5
if [ $a -gt 3 ]
then
   echo "OK"
fi


# 格式2:if 条件1; then 执行1; else 执行2; fi

#! /bin/bash
a=1
if [ $a -gt 3 ]; then
   echo "OK"
else
   echo "error"
fi


# 格式3:if 条件1; then 执行1; elif 条件2; then 执行2; else 执行3; fi

#! /bin/bash
a=5
if [ $a -gt 8 ]; then
   echo ">8"
elif [ $a -gt 3 ]; then
   echo ">3"
else
   echo "<3"
fi

2. case 分支

case 变量值 in
模式 1)
	命令序列1;;
模式 2)
	命令序列2;;
	.......
*)
	默认命令序列;;
esac

case值得注意的特点

  • case行尾必须为单词"in",每一模式必须以右括号“)”结束
  • 双分号";;"表示命令序列结束
  • 模式字符串中,可以用方括号表示一个连续的范围,如"[0-9]";还可以用管道符号" | “表示或,如"A|B”.
  • 最后的 " *) " 表示默认模式,其中的 星号 相当于通配符
#!/bin/bash

read read -p "请输入一个字符,并按Enter键确定:" KEY
case "$KEY" in
    [a-z]|[A-Z]) echo "您输入的是字母!";;
    [0-9]) echo "您输入的是数字!";;
    *)	echo "您输入的是空格,功能键或其他控制字符。";;
esac

五、循环控制

1. for 循环

for val in valuelist...
do
    commands
done

for((exp1;exp2;exp3))
do
    commands
done

# exp1 初始化
# exp2 变量取值范围
# exp3 变量增量

 

2. while 循环

while command
do
    command
    ...
done

# while后面的命令执行成功则循环,否则跳出循环

while 简单循环

通过while脚本实现给文件内容加行号

3. until 循环

until command
do
    commands
done

# until后面的命令成功的时候结束循环,失败的时候进入循环

通过until脚本监控某用户是否登录

#!/bin/bash

until who | grep "$1" >/dev/null 2>&1
do
    sleep 3
done
echo "Be careaful, $1 is online now!"

# 2>&1 是把标准错误输出重定向
# /dev/null 是系统垃圾堆,将所有接收到的数据都丢失

# 若该用户未登录则命令指令不成功,即循环等待
# 当用户登录,until突出循环

 

4. select 循环

select var in menu...
do
    commands
done

# select 后面跟的是菜单
# in 关键字后面是菜单取值列表
# 这些值以空格隔开
# 用户选择数字对应菜单值
# 变量var获取值后执行循环一次
#!/bin/bash

PS3="Please Select[1-4]:"
select m in new insert modify delete exit;
do
    if [ $m = exit ]; then
        break
    fi
    echo $m;
done

# PS3是一个环境变量,它是selet的提示符

六、函数

1. 函数的格式

#shell中的函数定义
#其中function为关键字,FUNCTION_NAME为函数名
function FUNCTION_NAME(){
       command1 #函数体中可以有多个语句,不允许有空语句
       command2
       ...
}
#省略关键字function,效果一致
FUNCTION_NAME(){
       command1
       command2
       ...
}

# 函数名后的小括号中没有参数
# 函数function关键字可以不写
# 函数必须遵循先定义再定义原则

2. 函数的返回值

#!/bin/bash

echo -n "请输入文件名:"
read FILE
function checkFileExist(){
        if [ -f $FILE ]; then
                return 0
        else
                return 1
        fi
}

echo "call function checkFileExist"
checkFileExist
if [ $? -eq 0 ]; then
        echo "$FILE exist"
else
        echo "$FILE not exist"
fi

3. 函数参数

#!/bin/bash

function checkFileExist(){
		if [ -f $1 ]; then
				return 0
		else
				return 1
		fi
}

echo "Call function countLine"
checkFileExist $1       # 函数调用
if [ $? -eq 0 ]; then
		echo "$1 exist"
else
		echo "$1 not exist"
fi

#执行脚本时,通过直接向脚本传递文件全路径的方式传递参数
#可以看到这种方式不会因为测试文件的不一样而修改脚本本身的内容,非常简单

4. 库函数

由于Shell是一门面向过程的脚本型语言,而且用户主要是Linux系统管理人员,所以并没有非常活跃的社区,这也造成了Shell缺乏第三方函数库,所以在很多时候需要系统管理人员根据实际工作的需要自行开发函数库。下面建立一个叫 funclib 的函数库,该函数库目前只有一个函数,用于判断文件是否存在。

_checkFileExists(){
      if [ -f $1 ]; then
             echo "File:$1 exists"
      else
             echo "File:$1 not exist"
      fi
}

​其他脚本在希望直接调用_checkFileExists函数时,可以通过直接加载 funclib 函数库的方式实现。加载方式有如下两种:

#使用“点”命令
$ . /PATH/TO/LIB
#使用source命令
$ source /PATH/TO/LIB

假设现在有个脚本想要直接调用_checkFileExists函数,可以通过加载 funclib 函数库来实现。

 

可以通过 set 和 unset 命令查看当期那内存中已经定义和载入的函数,使用 unset 清除函数,函数修改后必须重新载入。

 

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AllinTome

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值