Shell学习-Day1

Shell编程

1 Shell简介

1.1 Shell是什么

在计算机语言中,Shell指的是一种命令行解释器,是为用户和操作系统之间通信提供的一种接口,它接受来自用户输入的命令,并将其转换为一系列的系统调用送到内核执行,并将结果输出给用户。Shell在操作系统中的位置如下图:
在这里插入图片描述
Shell分为两大类,一类是图形界面Shell(Graphical User Interface),用户可以在GNOME桌面空白外右键选项中单击Open Terminal,即可唤出Shell;另一类是命令行式Shell(Command Line Interface),即CLI。
Shell除了是一种解释器外,它还是一种编程工具,称为脚本语言,与编译型语言不同,脚本语言经过编写后不需要做任何编译就可以运行,因此被称为解释型语言。

1.2 Shell的功能

当一台系统运行起来时,Kernel会被调入内存中运行,由Kernel执行所有底层的工作,它会将所有Application及用户的操作翻译成CPU的基本指令,并将其送至处理器。整个过程听起来非常复杂,而且确实非常底层和技术化的。为了对用户屏蔽这些复杂的技术细节,同时也是为了保护Kernel不会因用户直接操作而受到损害,有必要在Kernel之上创建一个层,这个层相当于一个“壳”,也就是Shell名称的由来。
Bash Shell有两种工作模式,分别是互动模式和脚本模式。互动模式就是由系统管理人员直接通过键盘输入命令,并等待其执行完毕后再执行下一条命令的模式;脚本模式就是设计出一个脚本文件,将所有需要执行的命令写在该文件中,由Bash Shell读取并执行。后一种工作模式的效率更高且便于自动化,因此我们学习Shell最重要的原因就是将一切工作自动化处理。

2 编写Shell脚本

2.1 第一个Shell脚本

几乎所有编程语言的教程都是从使用著名的“Hello Wrold”开始的,出于对这种传统的尊重,新建第一个脚本,并命名为HelloWorld.sh

#!/bin/bash
#This Line is a comment
echo “Hello World”

解释一下脚本,一个Shell脚本永远是以“#!”开头的,这是一个脚本开始的标记,它是在告诉系统执行这个文件需要使用某个解释器,后面的/bin/bash指明了解释器的具体位置。第二行同样是以“#”开头的,但这行只是一个注解。第三行是一句简单的命令:输出“Hello World”

2.2 运行脚本

运行HelloWorld.sh有三种方式,第一种是在脚本所在的目录中直接bash这个脚本。如果使用这种方式来运行脚本的话,脚本代码的第一行“#!/bin/bash”就可以省去了,因为bash一个文件就相当于指明使用Bash Shell来解释脚本了。

[root@localhost ~]# bash HelloWorld.sh
HelloWorld

第二种方式是给该脚本加上可执行权限,再使用“./”来运行。

[root@localhost ~]# chmod +x HelloWorld.sh
[root@localhost ~]# ./HelloWorld.sh
HelloWorld

第三种方式是将脚本复制到系统变量所包含的目录($PATH)中,同时赋予可执行权限,这样该脚本就成为默认的系统命令。

[root@localhost ~]# chmod +x HelloWorld.sh
[root@localhost ~]# mv HelloWorld.sh /bin/
[root@localhost ~]# HelloWorld.sh
HelloWorld

2.3 Shell脚本的排错

Shell脚本在执行时出错是很常见的,最简单的原因无外乎脚本在编写的过程中出现了语法错误或者不小心输错了命令等。找出脚本中的错误是很重要的能力。假设在上面的脚本中,不小心把echo命令写成ehco,那么执行效果如下:

[root@localhost ~]# bash HelloWorld.sh
HelloWorld.sh: line 2: ehco: command not found

从报错信息很容易了解到,出错的原因是“命令不存在”。重新编辑文件修改正确的命令即可。如果只是语法上的错误或命令错误还是比较容易辨别的,但往往一些逻辑或算法错误不容易发现,因为它的语法正确且本身并不会造成程序运行出错。例如,下面的脚本BadLoop.sh,本来是想连续10次做某些操作的,结果却迟迟没有任何输出。仔细观察就知道,其实是陷入了死循环。

#!/bin/bash
for ((i=10;i>0;i=i+1))
do
		#do something here
done

如果在循环中间的代码块中加入了echo语句,那就容易发现问题了。也就是说,在排查错误时,使用echo命令有助于观察代码执行的情况。假设在上面的脚本中使用echo,再次运行脚本时注意到脚本在不断地打印输出,这样就可以发现异常了。再加上sleep 2命令,就更清楚地观察循环的过程了。

#!/bin/bash
for ((i=10;i>0;i=i+1))
do
		#do something here
		echo "i=$i";
		sleep 2
done

为了更清晰地看到脚本运行的过程,还可以借助-x参数来观察脚本的运行情况。脚本运行到一定程度,输入“Ctrl + c”来停止脚本。

[root@localhost ~]# bash -x BadLoop.sh
+ (( i=10 ))
+ (( i>0 ))
+ echo i=10
i=10
+ sleep 2
+ (( i=i+1 ))
+ (( i>0 ))
+ echo i=11
i=11
+ sleep 2
+ (( i=i+1 ))
+ (( i>0 ))
+ echo i=12
i=12
+ sleep 2

Shell本身并没有提供很好的排错工具,想要尽量减少错误,除了多学习它的语法,多写、多想、多改之外并没有的办法,只有勤加练习才能更快地进步。除此之外,我们还可以借助第三方工具bashdb来调试脚本,具体下载安装自行搜索。

3 Shell的内建命令

1、type:判断一个命令是否内建命令

# cd命令是内建命令
[root@localhost ~]# type cd
cd is a Shell builtin
# ifconfig命令是外部文件
[root@localhost ~]# type ifconfig
ifconfig is /sbin/ifconfig

2、.:点号,执行程序
“.”点号用于执行脚本,甚至脚本没有可执行权限也可以运行,相对的“./”则只能执行具有可执行权限的脚本

[root@localhost ~]# . ./HelloWorld.sh
HelloWorld

与点号类似,source命令也可读取并在当前环境中执行脚本,同时还可以返回脚本中最后一个命令的返回状态;如果没有返回值则返回0,代表执行成功;如果未找到指定的脚本则返回false

[root@localhost ~]# source HelloWorld.sh
HelloWorld

3、alias:别名,用于创建命令的别名
若直接输入alias命令且不带参数,则列出当前用户使用了别名的命令。现在应该理解类似ll命令为什么与ls -l命令的效果一样了吧

[root@localhhost ~]# alias
alias cp='cp -i'
alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias ls='ls --color=tty'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'

4、bg、fg、jobs:任务前后台切换
在运行比较耗时的任务时,在前台执行的话会一直占用当前终端,导致无法执行其他任务,此时就应该将这类任务放置后台

[root@localhost ~]# tar -zcf usr.tgz /usr
tar: Removing leading `/' from member names  # 开始打包
	# 此时用Ctrl + z暂停前台任务
[1]+  Stopped                 tar -zcf usr.tgz /usr
[root@localhost ~]# jobs  # 查看暂停的任务,刚刚的tar任务编号为1
[1]+  Stopped                 tar -zcf usr.tgz /usr
[root@localhost ~]# bg 1  # 把tar任务放置后台继续运行
[1]+ tar -zcf usr.tgz /usr &  # tar任务继续运行
[root@localhost ~]# fg 1  # 使用fg命令把后台任务调至前台执行
tar -zcf usr.tgz /usr

# 如果预知某个任务耗时很久,可以一开始就将命令放入后台
[root@localhost ~]# tar -zcf usr.tgz /usr &

5、cd:改变目录
改变当前目录的命令,应该是使用最频繁的了
6、declare、typeset:声明变量
使用declare命令时,参数-i 声明整型变量,参数-r 声明变量为只读,参数-F、-f显示脚本中定义的函数和函数体
7、echo:打印字符
参数-n 不打印换行符,参数-e 打印转义字符时必需
8、break:跳出循环
9、continue:循环控制
10、eval:将所跟的参数作为Shell的输入,并执行产生的命令

# 用法例一:将字符串解析成命令执行
[root@localhost ~]# cmd='ls -l /etc/passwd'
[root@localhost ~]# eval $cmd
-rw-r--r-- 1 root root 1638 Mar 3 00:43 /etc/passwd

# 用法例二:程序运行中根据某个变量确定实际的变量名
[root@localhost ~]# name1=John
[root@localhost ~]# name2=Lisa
[root@localhost ~]# num=1
[root@localhost ~]# eval echo "$"name$num
John

# 用法例三:将某个变量的值当做另一个变量名并给其赋值
[root@localhost ~]# name1=John
[root@localhost ~]# name2=Lisa
[root@localhost ~]# eval $name1="$name2"
[root@localhost ~]# echo $John
Lisa

11、exec:执行命令来取代当前的Shell
内建命令exec并不启动新的Shell,而是用要被执行的命令替换当前的Shell进程,并且将老进程的环境清理掉,而且exec命令后的其他命令将不再执行。
12、export:使变量能被子Shell识别
13、kill:发送信号给指定PID或进程
首先需要了解Linux操作系统包括3种不同类型的进行:第一种是交互进程,这是由一个Shell启动的进程,既可以在前台运行,也可以在后台运行;第二种是批处理进程,与终端没有联系,是一个进程序列;第三种是监控进程,也称系统守护进程,它们往往系统启动时启动,并保持在后台运行。
而kill命令用于终止进程,其工作原理是向系统的内核发送一个系统操作信号和某个程序的进程标识号,然后系统内核就可以对进程标识号指定的进程进行操作。
14、let:整数运算
这是Shell内建的整数运算命令,它支持类C的计算方式,如自增自减运算
15、pwd:显示当前工作目录
16、local:声明局部变量
17、read:从标准输入读取一行到变量
18、return:定义函数返回值
19、shift:向左移动位置参数
要想搞清楚shift的用法,首先需要了解脚本“位置参数”的概念。假设一个脚本在运行时可以接受参数,那么从左到右第一个参数被记作$1,第二个参数为 2 , 以 此 类 推 , 第 n 个 参 数 为 2,以此类推,第n个参数为 2nN。所有参数记作 @ 或 @或 @*,参数的总个数记作$#, 而脚本本身记作$0

# 通过阅读该脚本了解$0、$1、$2、$3、$@、$#等符号的含义
[root@localhost ~]# cat shift_01.sh
#!/bin/bash
echo "This script's name is:$0"
echo "The First parameter is:$1"
echo "The Second parameter is:$2"
echo "The Third parameter is:$3"
echo "All of the parameter are $@"
echo "Count of parameter is:$#"
# 运行脚本
[root@localhost ~]# bash shift_01.sh 1 2 3
This script's name is:shift_01.gh
The First parameter is:1
The Second parameter is:2
The Third parameter is:3
All of the parameter are 1 2 3
Count of parameter is:3

shift命令可以对脚本的参数做“偏移”操作。假设脚本有A、B、C这3个参数,那么$1为A,$2为B,$3为C;shift一次后,$1为B,$2为C;再次shift后$1为C,如下所示:

# 通过阅读该脚本了解shift命令的作用
[root@localhost ~]# cat shift_02.sh
#!/bin/bash
until [ -z "$1" ]
do
		echo "$@ "
		shift
done
# 运行脚本,使用A B C参数
[root@localhost ~]# bash shift_02.sh A B C
A B C
B C
C

20、ulimit:显示并设置进程资源限度
系统的可用资源是有限的,如果不限制用户和进程对系统资源的使用,则很容易陷入资源耗尽的地步,而使用ulimit命令可以控制进程对可用资源的访问。
21、test:测试表达式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值