Shell基础入门

97 阅读4分钟

一、什么是Shell Shell 是一个命令行解释器,它为用户提供了一个向 Linux 内核发送请求以便运行程序的界面系统级程序,用户可以用 Shell 来启动、挂起、停止甚至是编写一些程序.

#二、Shell脚本的执行方式 #1、脚本格式要求 脚本以 #!/bin/bash 开头 脚本需要有可执行权限 例如

1)新建helloworld.sh 文件,并加入内容

#!/bin/bash echo "hello world!" #在控制台输出 helloworld

#2、脚本的常用执行方式 1)输入脚本的绝对或相对路径

首先要赋予 helloworld.sh 脚本的 +x 权限

修改文件权限为可执行,本组其他用户可执行,其他组用户可执行

chmod 755 helloworld.sh 执行脚本

绝对路径

/root/myshell/helloworld.sh 相对路径

./helloworld.sh 2)sh+脚本(不推荐)

可以不必事先设定shell的执行权限,甚至都不用写shell文件中的第一行(指定bash路径)。因为是将helloworld.sh作为参数传给sh(bash)命令来执行的。这时不是helloworld.sh自己来执行,而是被调用执行,所以可以不要执行权限。

可以不赋予权限

sh helloworld.sh #或者 bash helloworld.sh

#三、Shell变量 #1、简介 Linux Shell 中的变量分为,系统变量和用户自定义变量

系统变量

HOMEHOME、PWD、SHELLSHELL、USER 等 定义变量:变量=值

#!/bin/bash echo "path=PATH"echo"user=PATH" echo "user=USER"

set 显示所有shell变量

#2、变量的定义 定义变量:变量名=值

引用变量: 变量名 ∗ ∗ 或 ∗ ∗ 变量名∗∗或∗∗{变量名}

撤销变量:unset 变量名

声明静态变量(只读):readonly 变量名=值,注意:不能 unset

例1:

定义变量 A=100 撤销变量 A

#!/bin/bash A=100 echo "A=A"unsetAecho"A=A" unset A echo "A=A"

例2:

定义一个静态变量,不可unset

#!/bin/bash readonly A=100 echo "A=$A" unset A

#3、定义变量的规则 变量名称可以由字母、数字和下划线组成,但是不能以数字开头 等号两侧不能有空格 变量名称一般习惯为大写 #4、将命令的返回值赋给变量 A=ls -l /opt 反引号,运行里面的命令,并把结果返回给变量 将opt目录下的内容赋值给变量A NOW_DATE=$(date) 等价于反引号 将date指令输出的日期赋值给NOW_DATE变量

#!/bin/bash A=ls /opt echo Aecho""NOWDATE=A echo "" NOW_DATE=(date) echo $NOW_DATE

#四、设置系统环境变量 基本语法

export 变量名=变量值 (功能描述:将 shell 变量输出为环境变量)

source 配置文件路径 (功能描述:让修改后的配置信息立即生效)

echo $变量名 (功能描述:输出环境变量的值到控制台)

Shell中多行的注释:

:<<! 注释内容 注释内容 ! 例如

1)在 /etc/profile文件中为TOMCAT_HOME添加环境变量

TOMCAT_HOME=/opt/tomcat_7.0 export TOMCAT_HOME 2)让修改的配置文件立即生效

source /etc/profile 3)控制台查看环境变量 TOMCAT_HOME 的值

echo $TOMCAT_HOME

4)在helloworld.sh文件中使用环境变量

#!/bin/bash

:<<! 这是注释的内容 哈哈哈 !

#使用自定义的环境变量 echo "tomcathome=$TOMCAT_HOME" 执行helloword.sh脚本

#五、位置参数变量 当我们执行一个 shell 脚本时,如果希望获取到命令行的参数信息,就可以使用到位置参数变量,比如 : ./myshell.sh 100 200 , 这个就是一个执行 shell 的命令行,可以在 myshell 脚本中获取到参数信息

基本语法

$n

功能描述:n 为数字,0代表命令本身,0 代表命令本身,1-9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如9 代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如 $*

功能描述:这个变量代表命令行中所有的参数,把所有的参数看成一个整体*把所有的参数看成一个整体 @

功能描述:这个变量也代表命令行中所有的参数,不过@把每个参数区分对待@把每个参数区分对待 #

功能描述:这个变量代表命令行中所有参数的个数 例如

1)新建positionPara.sh脚本文件,加入以下内容

#!/bin/bash #获取命令的各个参数 echo "00 1 2"echo"2" echo "*" echo "@"echo"@" echo "#" 2)执行脚本并传入参数 ./positionPara.sh 100 200 300

#六、预定义变量 就是 shell 设计者事先已经定义好的变量,可以直接在 shell 脚本中使用

当前进程的进程号(PID) $! 后台运行的最后一个进程的进程号(PID) $? 最后一次执行的命令的返回状态。如果这个变量的值为 0,证明上一个命令正确执行;如果这个变量的值为非 0(具体是哪个数,由命令自己来决定),则证明上一个命令不正确 例如 1)新建 preVar.sh脚本文件,加入以下内容 #!/bin/bash echo "当前的进程号:$$" #后台运行helloworld.sh脚本 ./hellowrold.sh & echo "最后执行的进程号:$!" echo "最后一次执行的命令的返回状态:$?" 2)执行该脚本 ./preVar.sh #七、运算符 如何在 shell 中进行各种运算操 以下几种操作均可以 ① “$((运算式))” ② “$[运算式]” (常用) ③ `expr m + n** 或 **\expr m - n` (符合:+, -, \*, /, %) ,乘号 * 要用 \ 转义 注意 expr 运算符要有空格 例1: 计算(2+3)*4的值 新建caculate.sh脚本文件,测试以下内容 ①“$((运算式))" RESULT_1="$(((2+3)*4))" echo RESULT_1=$RESULT_1 ②“$[运算式]" (常用) RESULT_2="$[(2+3)*4]" echo RESULT_2=$RESULT_2 ③`expr m + n` TEMP=`expr 2 + 3` RESULT_3=`expr $TEMP \* 4` echo RESULT_3=$RESULT_3 例2: 计算命令行执行输入参数的和 ./caculate.sh 100 200 #!/bin/bash RESULT_4="$[$1+$2]" echo RESULT_4=$RESULT_4 输出结果 #八、判断语句 #1、基本语法 [ condition ] 注意 condition 前后要有空格 非空返回 true,可使用$?验证(0 为 true,>1 为 false) 例如: [ louchen ] 返回true [] 返回false [ condition ] && echo "ok" || echo "notok" [ condition ]为真, 输出 "ok" [] && echo "ok" || echo "notok" [] 为假,输出 "notok" #2、常用条件判断 #1)字符串和整数的比较 以下为字符串比较: = 字符串比较 [ "字符串1" = "字符串2" ] 注意:等号两边需要加空格 以下为整数比较: -lt 小于 [ 整数1 -lt 整数2] -le 小于等于 -eq 等于 -gt 大于 -ge 大于等于 -ne 不等于 #2)按照文件权限进行判断 -r 有读的权限 [ -r 文件路径 ] -w 有写的权限 -x 有执行的权限 #3)按照文件类型进行判断 -f 文件存在并且是一个常规的文件 [ -f 文件路径 ] -e 文件是否存在 -d 文件存在并是一个目录 #3)实例 ①"ok"是否等于"ok" #!/bin/bash if [ "ok" = "ok" ] then echo "等于" fi 其中 fi 代表**finsh **判断结束 ② 23 是否大于等于 22 #!/bin/bash if [ 23 -ge 22 ] then echo "大于或等于" fi ③判断 /root/hello.log 目录中的文件是否存在 在/root/myshell/ 文件夹下新建 hello.log 文件 #!/bin/bash if [ -e /root/myshell/hello.log ] then echo "文件存在" fi #九、流程控制 #1、if判断 第一种方式 if [ 条件判断式 ];then 程序 fi 第二种方式(常用) if [ 条件判断式 ] then 程序 elif [条件判断式] then 程序 fi 注意: [ 条件判断式 ],中括号和条件判断式之间必须有空格 例如: 编写一个 shell脚本,如果输入的参数,大于等于 60,则输出 "及格了",如果小于 60,则输出 "不及格" #!/bin/bash if [ $1 -ge 60 ] then echo "及格了" elif [ $1 -lt 60 ] then echo "不及格" fi #2、case语句 基本语法 case $变量名 in "值1") 如果变量的值等于值 1,则执行程序 1 ;; "值2") 如果变量的值等于值 2,则执行程序 2 ;; *) 如果变量的值都不是以上的值,则执行此程序 ;; esac 例如: 当命令行参数是 1 时,输出 "周一", 是 2 时,就输出"周二",是3时,就输出"周三",其它情况输出 "other" #!/bin/bash case $1 in "1") echo "周一" ;; "2") echo "周二" ;; "3") echo "周三" ;; *) echo "其他" ;; esac #3、for循环 #1、基本语法1 for 变 量 in 值1 值2 值3 do 程序 done *$ ,$@**的区别 $* 代表命令行中所有的参数,$*把所有的参数看成一个整体 $@ 代表命令行中所有的参数,不过$@把每个参数区分对待 例如: 题目:打印命令行输入的参数 ①使用到$* #!/bin/bash for i in "$*" do echo "the num is $i" done 遍历$*中的参数给i,这里$*将参数当做一个整体给i ②使用$@ #!/bin/bash for i in "$@" do echo "the num is $i" done 遍历$@中的参数给i,把每个输入的参数区别对待 #2、基本语法2 for((初始值;循环控制条件;变量变化)) do 程序 done 例如: 题目:从 1 加到 100 的值输出显示 #!/bin/bash SUM=0 for((i=0;i<=100;i++)) do SUM="$[$SUM+$i]" done echo SUM=$SUM #4、while循环 基本语法 while [ 条件判断式 ] do 程序 done 例子: 题目:从命令行输入一个数 n,统计从 1+...+ n 的值是多少? 新建 whilejudge.sh脚本文件,加入以下内容 #!/bin/bash SUM=0 i=0 while [ $i -le $1 ] do SUM=$[$SUM+$i] i=$[$i+1] done echo "SUM=$SUM" #十、read 读取控制台输入 1、基本语法 read [选项] [选项值] [变量] [选项] -p 指定读取值时的提示符(prompt) -t 指定读取值时等待的时间(秒),如果没有在指定的时间内输入,就不再等待了 [变量] 指定赋值的变量名 例子: 读取控制台输入一个 num1 值 读取控制台输入一个 num2 值,在 10 秒内输入。 新建 readtest.sh 脚本文件,并加入以下内容 #!/bin/bash read -p "请输入num1的值:" NUM1 echo "您输入的num1=$NUM1" read -p "等待时间为10s,请输入num2的值:" -t 10 NUM2 echo "您输入的num2=$NUM2" #十一、函数 #1、系统函数 basename [文件路径] 返回完整路径最后 / 的部分,常用于获取文件名,包含后缀 basename [文件路径] [后缀] 返回完整路径最后 / 的部分,常用于获取文件名,不包含后缀 dirname [文件路径] 返回指定路径的文件目录路径,不包含最后的文件名和后缀 #2、自定义函数 基本语法 function 方法名(){ } 例如: 题目:定义一个方法,输入两个参数累加求和 新建 definefun.sh 脚本 #!/bin/bash function add(){ SUM=$[$n1+$n2] echo "n1+n2=$SUM" } read -p "请输入n1的值:" n1 read -p "请输入n2的值:" n2 #调用方法 add $n1 $n2 */2 * * * * /root/vhr/mysql_db_backup.sh #十二、常用案例 #1、MySQL定时备份 1)在/root/vhr/mysql_db_backup.sh脚本文件 #!/bin/bash #备份的路径 BACKUP=/root/vhr/bak/db #当前时间作为文件名 DATETIME=$(date +%Y_%m_%d_%H%M%S) #echo $DATETIME echo "======开始备份======" echo "备份的路径是:$BACKUP/$DATETIME.sql" #主机 HOST=localhost #用户名 DB_USER=root #密码 DB_PWD=xxxxxx #备份的数据库名称 DATABASE=vhr #如果备份的路径文件夹存在,就使用,否则创建 [ ! -d "$BACKUP" ] && mkdir -p "$BACKUP" #执行mysql的备份数据库的指令,这里我们使用docker中的mysql docker exec mysql01 mysqldump -u${DB_USER} -p${DB_PWD} --host=${HOST} $DATABASE > $BACKUP/$DATETIME.sql #这里我们一天一次备份,只保留十天的备份文件 find $BACKUP -mtime +10 -name "*.sql" -exec rm -rf {} \; echo "备份文件成功" 注意 问题:因为我们mysql在docker中,所以使用crontab定时执行的时候,如果在备份脚本中写 docker exec -it mysql01 ,那么备份的文件会mysqldump出来的文件大小始终是0 解决办法:去掉 -it ,即 docker exec mysql01 crontab定时执行的时候dump出来的文件大小始终是0,后来发现去掉-it就可以了 2)编写定时任务 执行 crontab -e 编写定时任务,加入以下内容 30 2 * * * /root/vhr/mysql_db_backup.sh >> /root/vhr/backup.txt 每天 2:30 执行 mysql_db_backup.sh 脚本文件完成数据库备份,并将脚本的执行日志追加到 /root/vhr/ 目录下的backup.txt文件中 crontab -l 查看所有定时任务 crontab -r 删除当前用户所有的crontab任务 systemctl restart crond 重启任务调度器 #2、重新启动Jar包 #!/bin/bash APP_NAME=/opt/motiblog/moti-blog-0.0.1-SNAPSHOT.jar LOG_FILE=/opt/motiblog/moti.log pid=`ps -ef|grep $APP_NAME | grep -v grep | awk '{print $2}'` kill -9 $pid echo "$pid进程终止成功" sleep 2 if test -e $APP_NAME then echo '文件存在,开始启动此程序...' nohup java -jar $APP_NAME > $LOG_FILE 2>&1 & echo "$APP_NAME 启动成功..." else echo "$APP_NAME 文件不存在,请检查" fi