Shell基础学习
文章目录
一、脚本的概念
- 什么是脚本: 可以执行的一个文件,实现某种功能。
例如:
创建用户,其命令为:tom = useradd tom
将我们所学习的命令,按照顺序写入文本文件,赋予文本文件执行权限,如此便是一个可以执行的脚本文件了。
- 编写第一个脚本
编写一个面世问候 /root/hello.sh 脚本
显示出一段话 Hello World
[root@server0 ~]# vim /root/hello.sh
echo hello world
[root@server0 ~]# chmod +x /root/hello.sh #赋予执行权限
[root@server0 ~]# /root/hello.sh #绝对路径运行
-
脚本的组成
-
#! 环境声明,以下所有代码由那个程序进行翻译执行
-
#注释文本
-
可执行代码
-
-
编写一个输出当前红帽系统的版本信息、内核版本、主机名的脚本文件
[root@server0 ~]# vim /root/hello.sh
#!/bin/bash
echo hello world
cat /etc/redhat-release
uname -r
hostname
ifconfig | head -2
[root@server0 ~]# chmod +x /root/hello.sh
[root@server0 ~]# /root/hello.sh
二、重定向输出
- 只收集前面命令的正确输出
- 2>: 只收集前面命令的错误输出
- &>: 收集前面命令的正确与错误输出
代码示例:
[root@server0 ~]# echo 123 > /opt/1.txt
[root@server0 ~]# cat /opt/1.txt
[root@server0 ~]# cat /a
[root@server0 ~]# cat /opt/1.txt /a
[root@server0 ~]# cat /opt/1.txt /a > /opt/2.txt
[root@server0 ~]# cat /opt/2.txt
[root@server0 ~]# cat /opt/1.txt /a 2> /opt/2.txt
[root@server0 ~]# cat /opt/2.txt
[root@server0 ~]# cat /opt/1.txt /a &> /opt/2.txt
[root@server0 ~]# cat /opt/2.txt
三、特殊字符的作用
- 单引号 ’ ’ : 取消所有特殊字符意义
- 反撇号" `"与 $( ) : 将命令的输出,当做参数直接参与下一个命令的运行
单引号代码示例:
[root@server0 ~]# echo '*'
[root@server0 ~]# echo '* ? {} [] |'
[root@server0 ~]# echo '*********************'
[root@server0 ~]# echo '*******欢迎*******'
反撇号代码示例:
每一天在/opt/目录下创建一个以 年-月-日 结尾的目录
[root@server0 ~]# date +%F
[root@server0 ~]# cd /opt
[root@server0 opt]# mkdir nsd-`date +%F`
[root@server0 opt]# ls
[root@server0 opt]# mkdir abc-$(date +%F)
[root@server0 opt]# ls
[root@server0 opt]# mkdir $(hostname)-$(date +%F)
[root@server0 opt]# ls
[root@server0 ~]# date --help
四、案列:书写创建用户设置密码的脚本
重点注意: 黑洞设备:/dev/null
代码示例:
[root@server0 /]# vim /root/user.sh
#!/bin/bash
a=harry
useradd $a &> /dev/null
echo 用户$a创建成功
echo 123 | passwd --stdin $a &> /dev/null
echo 用户$a密码设置成功
[root@server0 /]# chmod +x /root/user.sh
[root@server0 /]# /root/user.sh
这种方式效率不高可以使用变量来增加效率。
变量的简单介绍:
- 变量:为了适应多变的环境需求
- 变量:会变化的量 以不变的名称存储可以变化的值 类似容器
- 变量名=存储的值
- 使用变量储存的值: $变量名
read命令简介:
- 为了用户的体验,降低脚本的使用难度,产生交互向脚本中传递命令行参
- read -p ‘屏幕输出信息’ 变量 这样就有了交互,人就知道要输入信息给变量了。
- read命令作用
- 1.产生交互
- 2.记录用户在键盘输入
- 3.将记录的信息,赋值给一个变量储存
优化后的代码:
[root@server0 /]# cat /root/user.sh
#!/bin/bash
read -p '请输入您要创建的用户名:' a
useradd $a &> /dev/null
echo 用户$a创建成功
echo 123 | passwd --stdin $a &> /dev/null
echo 用户$a密码设置成功
五、变量
变量的分类:
- 环境变量 变量名一般都大写,用来设置用户/系统环境
- 位置变量 bash内置,存储执行脚本时提供的命令行参数
- 预定义变量 bash内置,可直接调用的特殊值,不能直接修改
- 自定义变量 用户自主设置、修改及使用
1. 环境变量:由系统定义并且赋值完成,一般变量名为大写
代码示例:
USER=当前登录的用户名
[root@server0 /]# echo $USER
root
[root@server0 /]# su - nsd01
[nsd01@server0 ~]$ echo $USER
nsd01
[nsd01@server0 ~]$ exit
logout
[root@server0 /]# su - tom
[tom@server0 ~]$ echo $USER
tom
[tom@server0 ~]$ exit
logout
[root@server0 /]#
2. 位置变量: 由系统定义完成
- 在执行脚本时提供的命令行参数
- 表示为 $n,n为序号
- $1…到10的时候要带上{},如:刀了{10}
代码示例:
[root@server0 /]# vim /root/user.sh
#!/bin/bash
#read -p '请输入您要创建的用户名:' a
useradd $1 &> /dev/null (注:将脚本文件后的第一个参数给$1变量,第二个参数给$2变量。以此类推。)
echo 用户$1创建成功
echo 123 | passwd --stdin $1 &> /dev/null
echo 用户$1密码设置成功
[root@server0 /]# vim /root/1.sh
#!/bin/bash
echo $1
echo $2
echo $3
[root@server0 /]# vim /root/2.sh
#!/bin/bash
cat -n $1 | head -$2
echo 显示文件$1内容的前$2行
[root@server0 /]# /root/2.sh /etc/passwd 4
3. 预定义变量
- 用来保存脚本程序的执行信息
- 直接使用这些变量
- 不能直接为这些变量赋值
$# 已加载的位置变量的个数
$? 程序退出后的状态值,0表示正常,其他值异常
代码示例:
[root@server0 /]# vim /root/1.sh
#!/bin/bash
echo $1
echo $2
echo $3
echo $#
[root@server0 /]# /root/1.sh dc tc
[root@server0 /]# /root/1.sh a b c d
判断用户是否输入参数?
当$#的值为0的时候,说明用户没有输入参数
六、测试操作
格式:
[ 测试表达式 ]
选项:
- 检查文件状态
- -e:文档存在才为真
- -d:文档存在,且必须为目录才为真
- -f:文档存在,且必须为文件才为真
- 比较整数大小
- -gt:大于
- -ge:大于等于
- -eq:等于
- -ne:不等于
- -lt:小于
- -le:小于等于
- 字符串比对
- !=:不一致为真
- ==:一致为真
代码示例:
检查文件状态
[root@server0 /]# [ -e /etc/haha ]
[root@server0 /]# echo $?
[root@server0 /]# [ -f /etc ]
[root@server0 /]# echo $?
[root@server0 /]# [ -f /etc/passwd ]
[root@server0 /]# echo $?
[root@server0 /]# [ -d /etc ]
[root@server0 /]# echo $?
比较整数大小
[root@server0 /]# [ 10 -le 11 ]
[root@server0 /]# echo $?
字符串比对
[root@server0 /]# [ haha == xixi ]
[root@server0 /]# echo $?
1
[root@server0 /]# [ $USER == root ]
[root@server0 /]# echo $?
0
[root@server0 /]# [ haha != xixi ]
[root@server0 /]# echo $?
0
七、if双分支处理
格式:
if [条件测试];then
命令序列xx
else
命令序列yy
fi
代码示例:
[root@server0 /]# vim /root/if01.sh
#!/bin/bash
if [ $1 -eq 1 ];then
echo hello
else
echo hi
fi
[root@server0 /]# /root/if01.sh 1
[root@server0 /]# /root/if01.sh 2
案例编写:
案例1:用户是否输入参数的脚本
[root@server0 /]# vim /root/if02.sh
#!/bin/bash
if [ $# -eq 0 ];then
echo 您没有输入参数
else
echo 您输入了参数
fi
[root@server0 /]# /root/if02.sh haha
[root@server0 /]# /root/if02.sh
案例2:
利用read获取用户输入的用户名
进行判断:
如果输入的用户存在,则输出 用户已存在
如果输入的用户不存在,则输出 用户不存在
[root@server0 /]# cat /root/if03.sh
#!/bin/bash
read -p '请输入您要测试的用户名:' a
id $a &> /dev/null
if [ $? -eq 0 ];then
echo $a存在
else
echo $a不存在
fi
八、if多分支处理
格式:
if [条件测试1];then
命令序列xx
elif [条件测试2];then
命令序列yy
else
命令序列zz
fi
代码示例:
案例:成绩查询脚本
利用read获取用户输入的成绩
进行判断:
如果大于等于90,则输出 优秀
如果大于等于80,则输出 良好
如果大于等于70,则输出 一般
如果大于等于60,则输出 合格
以上条件均不满足则输出 一首凉凉送给你
#!/bin/bash
[root@server0 /]# cat /root/if04.sh
read -p '请输入您的成绩:' num
if [ $num -ge 90 ];then
echo 优秀
elif [ $num -ge 80 ];then
echo 良好
elif [ $num -ge 70 ];then
echo 一般
elif [ $num -ge 60 ];then
echo 合格
else
echo '一首凉凉送给你!'
fi
九、列表式循环场景
定义:给定一批对象,反复执行类似的操作
for循环处理:
根据变量的不同取值,重复执行xx处理
for循环格式:
for 变量名 in 值列表
do
命令序列
done可以用抽血这个操作来类比学习循环:
for 献血车 in dc tc zhangsan dcc
do
抽血
done
代码示例:
[root@server0 /]# vim /root/for01.sh
#!/bin/bash
for a in zhangsan lisi dc tc nsd15
do
useradd $a &> /dev/null
echo $a创建成功
done
循环的列表值,可以不参与循环执行的重复操作
[root@server0 /]# vim /root/for02.sh
#!/bin/bash
for a in {1..5}
do
echo hello world
done
[root@server0 /]# /root/for02.sh
造数工具:{起始值..结束值}
{1..20}:制造1到20连续数字
十、编写一个判断脚本
案例:编写一个判断脚本
在 server0 上创建 /root/foo.sh 脚本
1)当运行/root/foo.sh redhat,输出为fedora
2)当运行/root/foo.sh fedora,输出为redhat
3)当没有任何参数或者参数不是 redhat 或者
fedora时,其错误输出产生以下信息:
/root/foo.sh redhat|fedora
代码示例:
[root@server0 /]# cat /root/foo.sh
#!/bin/bash
# [ $# -eq 0 ] 判断用户是否输入参数
# >&2 将echo后的信息修改为错误输出
# exit 退出返回脚本状态值
if [ $# -eq 0 ];then
echo '/root/foo.sh redhat|fedora' >&2 #>&2这三个符号连用,就是把echo前面单引号中的信息变为错误输出。) (注:单引号会让特殊字符失去作用,单引号括起来的东西,会原样输出到屏幕上。
exit 3 #exit可以修改程序退出时的状态,如果exit后面什么都不写,默认是0。
elif [ $1 == redhat ];then
echo fedora
elif [ $1 == fedora ];then
echo redhat
else
echo '/root/foo.sh redhat|fedora' >&2
exit 4
fi
t@server0 /]# cat /root/foo.sh
#!/bin/bash
[ $# -eq 0 ] 判断用户是否输入参数
>&2 将echo后的信息修改为错误输出
exit 退出返回脚本状态值
if [ $# -eq 0 ];then
echo ‘/root/foo.sh redhat|fedora’ >&2 #>&2这三个符号连用,就是把echo前面单引号中的信息变为错误输出。) (注:单引号会让特殊字符失去作用,单引号括起来的东西,会原样输出到屏幕上。
exit 3 #exit可以修改程序退出时的状态,如果exit后面什么都不写,默认是0。
elif [ $1 == redhat ];then
echo fedora
elif [ $1 == fedora ];then
echo redhat
else
echo ‘/root/foo.sh redhat|fedora’ >&2
exit 4
fi