- Shell 编程
- 一、 概述
- 1、 shell 名词解释
- 2、 第一个脚本
- 二、基础入门
- 1、变量
- 2、字符串
- 3、数组
- 4、注释
- 5、 参数传递
- 三、 运算符
- 1、 算术运算符
- 2、 关系运算符
- 3、 布尔运算符
- 4、 逻辑运算符
- 5、 字符串运算符
- 6、 文件测试运算符
- 7、 test
- 四、 流程控制
- 1、 分支语句
- 1.1 if
- 1.2 case
- 2、 循环语句
- 2.1 for
- 2.2 while
- 1、 分支语句
- 五、 函数
- 1、 简介
- 2、 定义
- 3、 使用案例
- 六、 其他
- 1、 重定向
- 2、 文件包含
- 七、 系统任务设置
- 1、 系统启动流程
- 2、 系统服务
- 3、 开机自启动
- 3.1 rc.local
- 3.2 chkconfig
- 4、 定时任务
- 一、 概述
kernel
- linux 内核主要为了和硬件打交道
shell
- 命令解释器
- shell 是一个用 C 语言编写的程序,它是用户使用 linux 的桥梁,shell 既是一种命令语言,又是一种程序设计语言
- shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务
Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 Shell。
2、 第一个脚本#!
声明:告诉系统其后路径所指定的程序即是解释此脚本文件的shell程序
#!/usr/bin/bash
echo -e "hello world!\n"
脚本执行:
# 方式一
bash hello.sh
sh hello.sh # sh 是 bash 的软链接
# 方式二
chmod u+x hello.sh # 使文件有执行的权限
./hello.sh # 运行文件
# 方式三
source hello.sh # 加载脚本文件
启动方式的区别:
- 方式一和方式二会新打开一个bash,不同bash中的变量无法共享
- 方式三是在同一个bash里面执行的
export
:可以将当前进程的变量传递给子进程去使用
- 配置
profile
的时候,所有变量前必须加export
定义变量时,变量名不加美元符号
- 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头
- 中间不能有空格,可以使用下划线
- 不能使用标点符号
- 不能使用bash里面的关键字(可用help命令查看保留关键字)
变量的类型
-
局部变量
- 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量
-
环境变量
- 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行
Linux中常见的环境变量有: 1.PATH:指定命令的搜索路径 2.HOME:指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录) 3.HISTSIZE:指保存历史命令记录的条数。 4.LOGNAME:指当前用户的登录名。 5.HOSTNAME:指主机的名称,许多应用程序如果要用到主机名的话,通常是从这个环境变量中来取得的。 6.SHELL:指当前用户用的是哪种Shell。 7.LANG/LANGUGE:和语言相关的环境变量,使用多种语言的用户可以修改此环境变量。 8.MAIL:指当前用户的邮件存放目录。 9.PS1:命令基本提示符,对于root用户是#,对于普通用户是$。 10.PS2:附属提示符,默认是“>”。
-
shell 变量
- shell 变量是由shell程序设置的特殊变量,shell变量中有一部分是环境变量,有一部分是环境变量
#!/bin/bash
name="lihua" # 局部变量
printf "%s\n" ${name} # ${name} = $name,其都为变量的调用
export name_="zhansan" # 环境变量
readonly name # 只读变量
unset name # 删除变量
2、字符串
字符串是shell中最常见最有用的数据类型,字符串可以用单引号,也可以用双引号,也可以不用引号
单引号:
- 单引号里的任何字符串都会原样输出,单引号字符串中的变量是无效的
- 单引号字符串中不能出现单独一个的单引号,但可成对出现,作为字符拼接使用
双引号:
- 双引号可以有变量
- 双引号可以出现转义字符
#!/bin/bash
# 声明字符串
str1='hello'
# 字符串拼接--单引号
pwd='123'
pwd1='hello, '${pwd}'!' # -> hello, 123
pwd2='hello, ${pwd}!' # -> hello, ${pwd}
pwd3="hello, ${pwd}!" # -> hello, 123
# 字符串长度
email="3500515050@qq.com"
echo ${#email} # 返回字符串的长度
echo ${email:1:4} # 字符串的截取
3、数组
bash 支持支持以为数组,不支持多维数组,并且没有限定数组的大小
数组的元素下标由 0 开始编号,获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0
# 定义数组,括号来表示数组,数组元素用空格分割开
数组名=(值1 值2 ... 值n)
#!/usr/bin/bash
names=("lihua", "zhansan", "lishi")
# 读取数据 `$(数组[下标])`
name=${names[0]}
# 使用 @ 符号可以获取数组中的所有元素
echo ${names[@]}
# 获取数组的长度
len1=${#names[@]} # 这两个效果一样
len2=${#names[*]}
echo -e "len1=${len1}"
echo -e "len2=${len2}"
4、注释
以#
开头的行就是注释,会被解释器忽略
通过每一行加一个#
号可以实现多行注释
# 这是一个单行注释后,编译器不会执行这个代码
#多行
#注释
echo "hello world!"
:<<EOF
这也是一个多行注释哦!
EOF
:<<!
这也也也是一个多行注释哦!
!
5、 参数传递
执行 shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n
,n 代表一个数字
$#
传递到脚本的参数表个数
$*
以一个单字符串显示所有向脚本传递的参数
$$
脚本运行的当前进程ID昊
$!
后台运行的最后一个进程ID号
$?
显示最后命令退出状态,0表示没有错误,其他任何值表明有错误
$0
执行的文件名
#!/bin/bash
printf "Shell 传递的参数实例!\n";
printf "执行的文件名:$0\n";
printf "第一个参数为:$1\n";
printf "第二个参数为:$2\n";
三、 运算符
1、 算术运算符
expr $a + $b
结果为 30。
-
减法
expr $a - $b
结果为 -10。
*
乘法
expr $a \* $b
结果为 200。
/
除法
expr $b / $a
结果为 2。
%
取余
expr $b % $a
结果为 0。
=
赋值
a=$b
把变量 b 的值赋给 a。
==
相等。用于比较两个数字,相同则返回 true。
[ $a == $b ]
返回 false。
!=
不相等。用于比较两个数字,不相同则返回 true。
[ $a != $b ]
返回 true。
+ - * / % = == !=
2、 关系运算符
[ $a -eq $b ]
返回 false。
-ne
检测两个数是否不相等,不相等返回 true。
[ $a -ne $b ]
返回 true。
-gt
检测左边的数是否大于右边的,如果是,则返回 true。
[ $a -gt $b ]
返回 false。
-lt
检测左边的数是否小于右边的,如果是,则返回 true。
[ $a -lt $b ]
返回 true。
-ge
检测左边的数是否大于等于右边的,如果是,则返回 true。
[ $a -ge $b ]
返回 false。
-le
检测左边的数是否小于等于右边的,如果是,则返回 true。
[ $a -le $b ]
返回 true。
-eq -> == # equals
-ne -> != # not equals
-gt -> > # great than
-lt -> < # less than
-ge -> >= # great equal
-le -> <= # less equal
3、 布尔运算符
[ $a -lt 20 -o $b -gt 100 ]
返回 true。
-a
与运算,两个表达式都为 true 才返回 true。
[ $a -lt 20 -a $b -gt 100 ]
返回 false。
-a # and 与
-o # or 或
! # not 非
4、 逻辑运算符
[[ $a -lt 100 && $b -gt 100 ]]
返回 false
||
逻辑的 OR
`[[ $a -lt 100
&& # 短路与
|| # 短路或
5、 字符串运算符
#!/bin/bash
a="abc"
b="efg"
if [ $a == $b ] then
echo "$a = $b : a等于b"
else
echo "$a = $b : a不等于b"
fi
if [ $a != $b ] then
echo "$a = $b : a不等于b"
else
echo "$a = $b : a等于b"
fi
if [ -z $a ] then
echo "-z $a : 字符串长度为0"
else
echo "-z $a : 字符串长度不为0"
fi
if [ -n $a ] then
echo "-n $a : 字符串长度不为0"
else
echo "-n $a : 字符串长度为0"
fi
if [ $a ] then
echo "$a : 字符串不为空"
else
echo "$a : 字符串为空"
fi
6、 文件测试运算符
#!/usr/bin/bash
file="/home/kun/a.py"
if [ -r $file ] then
echo "文件可读"
else
echo "文件不可读"
fi
if [ -w $file ] then
echo "文件可写"
else
echo "文件不可写"
fi
if [ -x $file ] then
echo "文件可执行"
else
echo "文件不可执行"
fi
if [ -f $file ] then
echo "文件为普通文件"
else
echo "文件为特殊文件"
fi
if [ -d $file ] then
echo "文件是一个目录"
else
echo "文件不是一个目录"
fi
if [ -s $file ] then
echo "文件不为空"
else
echo "文件为空"
fi
if [ -e $file ] then
echo "文件存在"
else
echo "文件不存在"
fi
7、 test
使用test
来判断条件是否成立
#!/usr/bin/bash
name1="lihua"
name2="lihua"
if test ${name1} == ${name2}
then
echo "两个名字相等"
fi
四、 流程控制
1、 分支语句
1.1 if
if condiction1
then
command1
elif condiction2
then
command2
else
command3
fi
实例:
#!/bin/bash
a=10
b=20
if [ $a == $b ]
then
echo "a = b"
elif test $a -lt $b
then
echo "a < b"
else
echo "a > b"
fi
1.2 case
case expression in
pattern1)
statement1
;;
pattern2)
statement2
;;
pattern3)
statement3
;;
…
*)
statementn
esac
实例:
#!/bin/bash
read -p "Enter a number: " num
case $num in
1) echo "你输入了1"
;;
2) echo "您输入了2"
;;
3|4|5) echo "您输入了3~5"
;;
*) echo "你输入了除了1和2外的其他数字"
;;
esac
2、 循环语句
2.1 for
# 语法1:C语言风格
for((exp1; exp2; exp3))
do
statements
done
# 实例
for ((i=1; i<100; i++))
do
echo $i
done
# 语法2;python风格
for variable in value_list -》 也可以是一个取值范围 {start..end}
do
statements
done
# 示例
for n in 1 2 3 4 5 6
do
echo $n
((sum+=n))
done
echo "The sum is "$sum
使用案例:
#!/bin/bash
for i in `ls /bin/` # 遍历ls返回的结果,使用$(ls)也是一样的
do
echo "The filepath is $i"
done
echo "over"
2.2 while
while 循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件
while condition
do
command
if condition1
then
break # 退出循环
if condition2
then
continue # 中断本次循环
done
五、 函数
1、 简介
shell 可以用户定义函数,然后再shell脚本中可以随便调用
可以function func()
定义,也可以直接func()
定义,不带任何参数
参数返回,可以显示加:return
返回,将以最后一条命令运行结果,作为返回值,return
后跟数值n
func() {
command
return ...
}
func
ret=$? # 使用$?来获取函数的返回值
3、 使用案例
#!/bin/bash
# 函数定义
function firstFunc() {
echo -e "函数开始执行\nhello world!\n函数结束执行"
}
# 有函数返回值
secondFunc() {
echo "这个函数的功能是对输入的两个数字进行相加操作"
read -p "请输入第一个数字:" num1
read -p "请输入第二个数字:" num2
return $(($num1+$num2))
}
# 有参函数的调用
thirdFunc() {
echo -e "--------------------\n有参函数的调用"
echo "函数传入的第一个参数为:$1"
echo "函数传入的第二个参数为:$2"
echo "总共传入的参数有:$#个"
}
# 函数调用
firstFunc
echo -e "开始执行第二个函数\n------------------------------\n"
secondFunc
# 函数调用的返回值在调用函数后通过$?(最近一次返回的结果)来获得
ret=$?
echo "第二个函数相加的结果为$ret"
thirdFunc 第一个参数 第二个参数
六、 其他
1、 重定向
和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。
Shell 文件包含的语法格式如下:
. filename # 注意点号(.)和文件名中间有一空格
或
source filename
七、 系统任务设置 1、 系统启动流程这两个方式效果一样
启动计算机的硬件[BIOS]
- 读取时间
- 选择对应的启动模式
如果是Linux
系统,会去找/boot
目录,引导这个系统启动
计算机系统开始启动,读取初始化配置文件
-
vim /etc/inittab
-
启动时,控制着计算机的运行级别
- 运行级别 0:系统停机状态,系统默认运行级别不要设为 0,否则不能正常启动;
- 运行级别 1:单用户工作状态,具有 root 权限,用于系统维护,禁止远程登陆;
- 运行级别 2:多用户状态 ( 没有NFS,不能联网 );
- 运行级别 3:完全的多用户状态 ( 有 NFS,能联网 ),登陆后进入控制台命令行模式;
- 运行级别 4:系统未使用,保留;
- 运行级别 5:X11 控制台,登陆后进入图形 GUI 模式;
- 运行级别 6:系统正常关闭并重启,默认运行级别不能设为 6,否则不能正常启动;
-
默认为级别3,以级别三启动对应的服务和组件
开始默认引导公共的组件或者服务
vim /etc/rc.d/init.d
- 可以将脚本文件移动到此目录,进行开机自启动
开始加载对应runserver
的服务
vim /etc/rc.d/rc3.d
- K:关机时需要关闭的服务
- S:启动时需要开启的服务
- 数字代表了开启或关闭的顺序
- 所有的文件都是软链接,链接的地址为
/etc/init.d
当启动完毕时,所有的服务也被加载完成
2、 系统服务我们可以使用chkconfig
命令查看当前虚拟机的服务
通过查看可以得知不同的级别对应到每一个服务确定本次开机自启动
开机结束后,我们需要使用systemctl
命令控制服务的开启或关闭
- 首先创建脚本存放的文件夹
mkdir -p /usr/local/scripts
- 在文件夹中创建脚本文件
vim hello.sh
- 给予执行的权限
chmod a+x hello.sh
- 去
/etc/rc.d/rc.local
文件中添加脚本的绝对路径echo "/usr/local/scripts/hello.sh" >> /etc/rc.d/rc.local
chmod a+x /etc/rc.d/rc.local
:给rc.local
添加执行的权限
- 创建开机自启动脚本文件
vim hello.sh
- 给予执行的权限
chmod a+x hello.sh
- 将脚本文件拷贝到
/etc/init.d
目录下cp hello.sh /etc/init.d/
- 添加到服务
chkconfig --add /etc/init.d/hello.sh
- 重启服务器
reboot
-
在系统服务中心,
crond
负责周期任务systemctl status crond.service
-
添加任务,编辑当前用户的任务列表
crontab -e
-
编辑任务
语法:
*/1 * * * * sh /usr/local/scripts/hello.sh 分 时 日 月 周 命令 分:1~59 时:1~23,0表示0点 日:1~31 月:1~12 周:0~6 0表示星期天 命令:表示要运行的命令
*:每使用*或者*/1表示,表示每分钟,每小时
-:表示区间,是一个范围
,:是分割时段,表示间断
/n:表示分割,可以看成除法,*/n表示每n分钟执行一次