什么是shell
shell是linux的命令解释器
它向用户提供了一个向linux内核发送请求以便运行程序
shell处在内核与外层应用程序之间
在用户与系统之间进行交互的作用
与windows的鼠标点击软件后
就能运行软件的功能类似
如windows下创建一个文件夹
我们先决定去哪里新建即进入该路径
再右键选择新建文件夹即可
在linux当中也是通过类似的方法
不过完全使用命令行罢了
这就是shell
能够在用户与系统间进行交互实现相应的功能
shell是一个强大的编程语言
与一般的编程语言不同的是
它可以直接使用系统命令
这可以大大的减小linux管理员的工作量
只需会写shell脚本即可自动化管理linux
shell的类型
hell有很多的类型
现在一般是使用bash
cat /etc/shells
可以查看当前linux支持的shell类型
系统默认的Shell解析器bash
echo $SHELL
简单例子
第一行#!/bin/bash
标称以下写的脚本使用的是bash
像c语言的 #include<stdio.h> 一样
除了第一行的#!/bin/bash
其他以#开头的都是注释
其他即为程序的主体
可以调用系统命令
#表示注释
创建第一个Shell脚本
touch HelloWorld.sh
vim HelloWorld.sh
写入
#!/bin/bash
echo "Hello World!"
执行脚本
[root@localhost yuan]# ll
总用量 32
-rw-r--r--. 1 root root 15 12月 20 15:55 1.txt
-rw-r--r--. 1 root root 22 12月 20 15:55 2.txt
-rw-r--r--. 1 root root 33 12月 20 22:59 HelloWorld.sh
-rw-r--r--. 1 root root 3573 12月 20 16:30 ShellCode.cpp
-rw-r--r--. 1 root root 10240 12月 20 22:27 test.tar
-rw-r--r--. 1 root root 154 12月 20 16:29 ???乥??.txt
[root@localhost yuan]# sh HelloWorld.sh
Hello World!
[root@localhost yuan]# bash HelloWorld.sh
Hello World!
[root@localhost yuan]# ./HelloWorld.sh
-bash: ./HelloWorld.sh: 权限不够
[root@localhost yuan]#
bash 文件
sh 文件
都是bash去读取里面的命令然后执行HelloWorld.sh本身不需要执行权限
[root@localhost yuan]# chmod 777 HelloWorld.sh
[root@localhost yuan]# ./HelloWorld.sh
Hello World!
[root@localhost yuan]#
创建文本文件并写入内容
#!/bin/bash
cd /home/yuan
touch test.txt
echo "I love cls" >> test.txt
历史命令
history [选项] [历史命令保存文件]
选项:
-c :清空历史命令
-w :把缓存中的历史命令写入历史命令保存文件。如果不手工指定历史命令保存文件,则放入默认历史命令保存文件 ~/.bash_history 中
我们使用 history 命令查看历史命令和 ~/.bash_history 文件中保存的历史命令是不同的。那是因为当前登录操作的命令并没有直接写入 ~/.bash_history 文件,而是保存在缓存中。需要等当前用户注销之后,缓存中的命令才会写入 ~/.bash_history 文件。如果我们需要把内存中的命令直接写入 ~/.bash_history 文件,而不等用户注销才写入,可以使用 history -w 命令
输入输出重定向
Bash 的标准输入输出
设备设备文件名文件描述符类型键盘/dev/stdin0标准输入显示器/dev/stdout1标准输出显示器/dev/stderr2标准错误输出
输出重定向
解释下什么叫输出重定向:
命令的输出本身是应该输出给标准输出设备的,也就是输出到显示器上,重定向就是把它的输出方向改变,让它不在输出到显示器上,而是让它输出到文件中,这就是输出重定向。
标准输出重定向:
ll > abc
标准错误输出重定向
lljfkdf 2>abc
多命令顺序执行x
[root@hepingfly 桌面]# ll;date;cd /home/ 这三条命令会按照顺序执行,不管前面命令执行成功还是失败,后面的命令都会照常执行
[root@hepingfly home]# ls && echo yes 如果第一个命令正确执行了,我就输出一个 yes。如果第一个命令报错,第二个命令是不会执行的。
[root@hepingfly home]# lsfaa || echo no 如果第一个命令没有正确执行,我就输出一个 no。如果第一个命令正确执行,第二个命令是不会执行的
[root@hepingfly home]# ll && echo yes || echo no 这条命令的意思是,如果第一个命令正确执行,则输出 yes,否则输出 no
shell 特殊符号
[root@hepingfly home]# a=$(date) 系统命令的执行结果赋值给变量
[root@hepingfly home]# echo $a
2019年 05月 04日 星期六 21:18:46 CST
[root@hepingfly home]# b=$(ll /home/) 理论上只要命令有输出,就可以赋值给变量
[root@hepingfly home]# echo $b
变量
变量有哪些类型:
用户自定义变量 2.环境变量 3.位置参数变量 4.预定义变量
常用的系统变量
$HOME, $PWD, $SHELL, $USER, $PATH等
[root@localhost yuan]# echo $HOME
/root
[root@localhost yuan]# echo $HOME
/root
[root@localhost yuan]# echo $PWD
/home/yuan
[root@localhost yuan]# echo $SHELL
/bin/bash
[root@localhost yuan]# echo $USER
root
自定义变量
语法
变量 = 值
中间不要加空格
[root@localhost yuan]# A=1
[root@localhost yuan]# echo $A
1
撤销变量
unset 变量
[root@localhost yuan]# unset A
[root@localhost yuan]# echo $A
声明静态变量
readonly变量,注意:不能unset
readonly B=3
变量命名规则
- 变量名称可以由字母、数字、下划线组成,但是不能以数字开头
- 在 Bash 中,变量的默认类型都是字符串型,如果要进行数值运算,则必须指定变量类型为数值型
- 变量用等号连接值,等号左右两侧不能有空格,比如你在 shell 中定义一个变量,可以这么写: name=shp 但是不能这么写: name = shp 这种写法是错误的 因为在 linux 中命令的格式是: 命令 空格 选项 空格 参数 你定义变量的时候加空格,它会把你的变量当成 linux 命令去解析,这样显然有问题
- 变量的值如果有空格,需要使用单引号或者双引号扩起来。
- 如果是要把命令的结果作为变量值赋予变量,则需要使用反引号或者 $() 把命令包起来
[root@hepingfly home]# test=$(date) 把 date 命令的执行结果赋值给变量
[root@hepingfly home]# echo $test
2019年 05月 05日 星期日 21:14:28 CST - 环境变量名建议大写,用于区分
环境变量
可以把变量提升为全局变量,可供其他Shell程序使用
export 变量名
export 变量名=变量值
特殊变量 $n
count.sh 脚本:
#!/bin/bash
a=$1 # 这里拿到命令行中第一个参数
b=$2 # 这里拿到命令行中的第二个参数
sum=$(($a+$b)) # 在 shell 当中如果想要进行数值运算,需要使用 $(()) 把你要运算的算式给括起来,它才知道这是数值运算, $() 是用来括系统命令的,你括起来之后它才知道这是系统命令,然后执行,把结果赋值给变量
echo $sum
echo $0 # 这个就是输出命令行本身
#结果
[root@hepingfly hepingfly]# ./count.sh 22 11
33
./count.sh
param.sh 脚本:
#!/bin/bash
for i in "$*" # $* 是把所有参数当成一个整体
do
echo $i # 这里我有多少个参数,就会一把输出出来
done
echo "============"
for y in "$@" # $@ 是把参数区别对待
do
echo $y # 有多少个参数,循环多少次,依次输出出来
done
echo "============"
echo "$#" # 这里会输出所有参数的个数
结果
[root@localhost yuan]# ./param.sh 1 2 3 4 5
1 2 3 4 5
===========
1
2
3
4
5
===========
5
预定义变量
[root@hepingfly 桌面]# fdfda 随便乱输入一个命令
bash: fdfda: command not found
[root@hepingfly 桌面]# echo $? 输出最后一次命令执行状态
127 # 非 0 表示命令未正确执行
[root@hepingfly 桌面]# ll
总用量 28
-rw-r--r--. 1 root root 25872 3月 28 22:28 mysql80-community-release-el6-2.noarch.rpm
[root@hepingfly 桌面]# echo $?
0
PATH 变量
系统查找命令的路径
[root@hepingfly bin]# echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:/root/bin
PATH 变量的值是用 『:』分割的路径,这些路径就是系统查找命令的路径。也就是说当我们输入一个程序名,如果没有写入路径,系统就会到 PATH 变量定义的路径去找是否有可以执行的程序。如果找到则执行,否则会报 “命令没有发现的错误”。
现在假如说我们有一个自己的脚本,我不想输入路径就直接运行,有什么方法?
方法一:
把你自己写的脚本放到环境变量的路径下,这样就可以直接执行了。例如,把脚本放到 /bin 目录下
方法二:
利用变量叠加去修改环境变量的值
PATH="$PATH":/home/hepingfly/
declare 声明变量类型
linux 中所有变量的默认类型都是字符串类型,我们需要把变量声明为整数类型才可以进行运算。使用 declare 命令就可以实现声明变量的类型。
declare [+/-] [选项] 变量名
选项:
- :给变量设定类型属性
+ :取消变量的类型属性
-a :将变量设定为数组类型
-i :将变量声明为整数类型
-r :将变量声明为只读变量。注意:一旦设定为只读变量,既不能修改变量的值,也不能删除变量,设置不能通过 +r 取消只读属性。
-x :将变量声明为环境变量
-p :显示指定变量的被声明的类型
变量设定为整数类型:
[root@hepingfly hepingfly]# a=1
[root@hepingfly hepingfly]# b=2
[root@hepingfly hepingfly]# c=$a+$b 直接相加是两个字符串做拼接操作
[root@hepingfly hepingfly]# echo $c
1+2
[root@hepingfly hepingfly]# declare -i c=$a+$b 声明变量 c 为数值类型
[root@hepingfly hepingfly]# echo $c
3
数值运算
在 shell 中你如果要进行数值运算,推荐使用
(
(
运
算
式
)
)
方
式
运
算
或
者
((运算式)) 方式运算 或者
((运算式))方式运算或者[运算式]
或者expr命令
expr命令是一个手工命令行计数器,用于在UNIX/LINUX下求表达式变量的值,一般用于整数值,也可用于字符串
计算字串长度
expr length “this is a test”
> expr 14 % 9
5
> expr 10 + 10
20
> expr 1000 + 900
1900
> expr 30 / 3 / 2
5
> expr 30 \* 3 (使用乘号时,必须用反斜线屏蔽其特定含义。因为shell可能会误解显示星号的意义)
90
> expr 30 * 3
expr: Syntax error
$((运算式))
[root@localhost yuan]# c=$((1+2))
[root@localhost yuan]# echo $c
3
关系运算符
流程控制
if 判断
if [ 条件判断式 ];then
程序
fi
# 或者(推荐)
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
fi
实例
#!/bin/bash
if [ $1 -ge 60 ]
then
echo 及格
elif [ $1 -lt 60 ]
then
echo "不及格"
fi
case 分支
case $变量名 in
"值1")
如果变量值等于值1,则执行此处程序1
;;
"值2")
如果变量值等于值2,则执行此处程序2
;;
...省略其它分支...
*)
如果变量值不等于以上列出的值,则执行此处程序
;;
esac
实例
当命令行参数为1时输出“周一”,2时输出“周二”,其他情况输出“其它”
case $1 in
"1")
echo 周一
;;
"2")
echo 周二
;;
*)
echo 其它
;;
esac
for 循环
# 语法1
for 变量名 in 值1 值2 值3...
do
程序
done
# 语法2
for ((初始值;循环控制条件;变量变化))
do
程序
done
实例
输出从1加到100的值。
#!/bin/bash
SUM=0
for ((i=1;i<=100;i++))
do
SUM=$[$SUM+$i]
done
echo $SUM
while 循环
while [ 条件判断式 ]
do
程序
done
实例
输出从1加到100的值。
#!/bin/bash
SUM=0
i=0
while [ $i -le $1 ]
do
SUM=$[$SUM+$i]
i=$[$i+1]
done
echo $SUM
关系运算符只支持数字,不支持字符串,除非字符串的值是数字。关系运算符判断两个数字之间的大小,并返回true(1)或者false(0)。True和false可以参与后面的布尔运算。
#!/bin/sh
a=10
b=20
if [ $a -eq $b ]
then
echo "$a -eq $b : a is equal to b"
else
echo "$a -eq $b: a is not equal to b"
fi
if [ $a -ne $b ]
then
echo "$a -ne $b: a is not equal to b"
else
echo "$a -ne $b : a is equal to b"
fi
if [ $a -gt $b ]
then
echo "$a -gt $b: a is greater than b"
else
echo "$a -gt $b: a is not greater than b"
fi
if [ $a -lt $b ]
then
echo "$a -lt $b: a is less than b"
else
echo "$a -lt $b: a is not less than b"
fi
if [ $a -ge $b ]
then
echo "$a -ge $b: a is greater or equal to b"
else
echo "$a -ge $b: a is not greater or equal to b"
fi
if [ $a -le $b ]
then
echo "$a -le $b: a is less or equal to b"
else
echo "$a -le $b: a is not less or equal to b"
fi
布尔运算符
在 Bash 里有这样的常量,即 true 和 false,表示真,表示假。对它们可以进行与、或、非运算等常规的逻辑运算。
#!/bin/sh
a=10
b=20
if [ $a != $b ]
then
echo "$a != $b : a is not equal to b"
else
echo "$a != $b: a is equal to b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
echo "$a -lt 100 -a $b -gt 15 : returns true"
else
echo "$a -lt 100 -a $b -gt 15 : returns false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
echo "$a -lt 100 -o $b -gt 100 : returns true"
else
echo "$a -lt 100 -o $b -gt 100 : returns false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
echo "$a -lt 100 -o $b -gt 100 : returns true"
else
echo "$a -lt 100 -o $b -gt 100 : returns false"
fi
字符串运算符
字符有可能是数字、字母、空格、其他特殊字符,而字符串有可能是它们中的一种或者多种的组合。
#!/bin/bash
a="abc"
b="efg"
if [ $a = $b ]
then
echo "$a = $b : a is equal to b"
else
echo "$a = $b: a is not equal to b"
fi
if [ $a != $b ]
then
echo "$a != $b : a is not equal to b"
else
echo "$a != $b: a is equal to b"
fi
if [ -z $a ]
then
echo "-z $a : length is 0"
else
echo "-z $a : length is not 0"
fi
if [ -n "$a" ]
then
echo "-n $a : length is not 0"
else
echo "-n $a : length is 0"
fi
if [ $a ]
then
echo "$a : string is not null"
else
echo "$a : string is null"
fi
文件测试运算符
文件测试运算符用于检测 Unix 文件的各种属性。
例如,变量 file 表示文件“~/test.sh”,它的大小为100字节,具有 rwx 权限。下面的代码,将检测该文件的各种属性
if [ -x $file ]
then
echo "File has execute permission"
else
echo "File does not have execute permission"
fi
if [ -f $file ]
then
echo "File is an ordinary file"
else
echo "This is sepcial file"
fi
if [ -d $file ]
then
echo "File is a directory"
else
echo "This is not a directory"
fi
if [ -s $file ]
then
echo "File size is zero"
else
echo "File size is not zero"
fi
if [ -e $file ]
then
echo "File exists"
else
echo "File does not exist"
fi
字符串操作
获取字符串长度
string="abcd"
echo ${#string} #输出 4
提取子字符串
string="alibaba is a great company"
echo ${string:1:4} #输出liba
查找子字符串
string="alibaba is a great company"
echo `expr index "$string" is`
数组
定义数组
array_name=(value1 … valuen)
例如
array_name=(value0 value1 value2 value3)
#或者
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
访问元素
${array_name[index]}
#!/bin/sh
NAME[0]="Zara"
NAME[1]="Qadir"
NAME[2]="Mahnaz"
NAME[3]="Ayan"
NAME[4]="Daisy"
echo "First Index: ${NAME[0]}"
echo "Second Index: ${NAME[1]}"
获取数组的长度
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}
函数
自定义函数
[ function ] funname[()]
{
Action;
[return int;]
}
# 调用
funname 参数1 参数2...
实例
实例
计算输入两个参数的和
#!/bin/bash
function getSum(){
SUM=$[$n1+$n2]
echo "sum=$SUM"
}
read -p "请输入第一个参数n1:" n1
read -p "请输入第二个参数n2:" n2
# 调用 getSum 函数
getSum $n1 $n2
实用参考Demo
判断运行脚本时是否输入了指定个数的参数
#!/bin/sh
if [ $# != 2 ];then
#参数不等于2个时提示 参数不正确
echo "Parameter incorect."
exit 1
fi
自己设置环境变量
#!/bin/bash
#执行/etc/profile这个文件里的shell指令
source /etc/profile
#重新定义全局变量PATH
export PATH="/usr/local/bin:/usr/bin"