初识shell
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
文章目录
一、shell基本知识
1.1为什么学习和使用Shell编程
对于一个合格的系统管理员来说学习和掌握Shell编程是非常重要的。通过编程可以在很大程度上简化日常的维护工作使得管理员从简单的重复劳动中解脱出来。
shell程序的特点:
- 简单易学
- 解释性语言不需要编译即可执行
1.2 什么是Shell
在学习Shell编程之前必须弄清楚什么是Shell。为了能够使读者在学习具体的Shell编程之前对Shell有个基本的了解本节将对Shell进行概括性的介绍包括Shell的起源和功能。
1.2.1 shell的起源
-
1964年美国AT&T公司的贝尔实验室、麻省理工学院及美国通用电气公司共同参与开始研发一套可以安装在大型主机上的多用户、多任务的操作系统该操作系统的名称为Multics。
-
1970年丹尼斯•里奇和汤普逊启动了另外一个新的多用户、多任务的操作系统的项目他们把这个项目称之为UNICS。
-
1973年使用C语言重新编写了Unix。通过这次编写使得Unix得以移植到其他的小型机上面。
-
1979年第一个重要的标准UNIX Shell在Unix的第7版中推出并以作者史蒂夫•伯恩StephenBourne的名字命名叫做Bourne
Shell简称为sh。 -
20世纪70年代末C Shell作为2BSD UNIX的一部分发布简称csh。
-
之后又出现了许多其他的Shell程序主要包括Tenex C Shelltcsh、Korn Shellksh以及GNUBourne-Again shellbash。
1.2.2 shell的功能
Shell又称命令解释器它能识别用户输入的各种命令并传递给操作系统。它的作用类似于Windows操作系统中的命令行但是Shell的功能远比命令行强大的多在UNIX或者localhost中Shell既是用户交互的界面也是控制系统的脚本语言。
1.3 shell的分类
- Bourne Shell标识为sh该Shell由SteveBourne在贝尔实验室时编写。在许多Unix系统中该Shell是root用户的默认的Shell。
- Bourne-Again Shell标识为bash该Shell由Brian
Fox在1987年编写是绝大多数localhost发行版的默认的Shell。 - Korn Shell标识为ksh该Shell由贝尔实验室的David Korn在二十世纪八十年代早期编写。它完全向上兼容 BourneShell 并包含了C Shell 的很多特性。
- C Shell标识为csh该Shell由Bill Joy在BSD系统上开发。由于其语法类似于C语言因此称为CShell。
如何查看当前系统支持的shell
[root@localhost ~]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
如何查看当前系统默认shell
[root@localhost ~]# echo $SHELL
/bin/bash
1.4 作为程序设计的语言——shell
Shell不仅仅是充当用户与UNIX或者localhost交互的角色还可以作为一种程序设计语言来使用。通过Shell编程可以实现许多非常实用的功能提高系统管理的自动化水平。
如果有一系列经常需要使用的命令把它存储在一个文件里shell可以读取这个文件并顺序执行其中的命令我们把这样的文件就叫shell脚本。shell脚本按行解释文件里的命令。
1.5 如何学好shell
学好shell编程基础知识
- 熟练使用vivim编辑器
- 熟练掌握Linux基本命令
- 熟练掌握文本三剑客工具grep、sed、awk
- 熟悉常用服务器部署、优化、日志及排错
如何学好shell编程
- 掌握Shell脚本基本语法
- 形成自己的脚本开发风格
- 从简单做起简单判断简单循环
- 多模仿多参考资料练习多思考
- 学会分析问题逐渐形成编程思维
- 编程变量名字要规范采用驼峰语法表示
什么是驼峰语法
骆驼式命名法就是当变量名或函数名是由一个或多个单词连结在一起而构成的唯一识别字时第一个单词以小写字母开始从第二个单词开始以后的每个单词的首字母都采用大写字母例如
myFirstName、myLastName这样的变量名看上去就像骆驼峰一样此起彼伏故得名。
除了驼峰命名法另外还有匈牙利命名法。基本原则是变量名=属性+类型+对象描述。匈牙利命名法关键是标识符的名字以一个或者多个小写字母开头作为前缀前缀之后的是首字母大写的一个单词或多个单词组合该单词要指明变量的用途。比如m_lpszStr, 表示指向一个以0字符结尾的字符串的长指针成员变量。
还有下划线命名法比如file_name。
1.6 shell脚本的基本元素
对于一个基本的Shell程序来说应该拥有以下基本元素
- 声明声明用哪个命令解释器来解释并执行当前脚本文件中的语句一般写的解释器为
#!/bin/bash 。
-
命令可执行语句实现程序的功能。
-
注释说明某些代码的功能通过在代码中增加注释可以提高程序的可读性。
-
1单行注释#开头的一整行都是注释例如
#comment1 #comment2 #comment3 ……
-
2多行注释使用冒号
“:”
配合here document可实现多行注释例如:<<BLOCK ……注释内容 BLOCK
-
-
赋予rx的权限
1.7 shell脚本编写规范
1脚本文件名应见名知意例如backup_mysql.sh
2文件开头指定脚本解释器 #!/bin/sh 或 #!/bin/bash
3开头加版本特权等信息
# Date:创建日期
# Author:作者
# Mail:联系方式
# Function:功能
# Version:版本
4脚本中尽量不要用中文
- 注释别吝啬添加注释必要的注释方便自己别人理解脚本逻辑和功能
- 尽量用英文注释防止本机或切换系统环境后中文乱码的困扰
- 单行注释可以放在代码行的尾部或代码行的上部
- 多行注释用于注解复杂的功能说明可以放在程序体中也可以放在代码块的开始部分。
5多使用内部命令
常用的内部命令有echo、eval、exec、export、read、shift、exit
-
echo可在屏幕上输出信息
示例[root@localhost ~]# echo -n i have a cat i have a cat[root@localhost ~]# [root@localhost ~]# echo i\thave\ta\tcat ithavetatcat [root@localhost ~]# echo -e i\thave\ta\tcat ithavetatcat [root@localhost ~]# echo -e "i\thave\ta\tcat" i have a cat
-
eval
- 命令格式
eval args
功能当shell程序执行到eval语句时shell读入参数args并将它们组合成一个新的命令然后执行。[root@localhost test]# a='shuju;head -1 /etc/passwd' [root@localhost test]# echo $a shuju;head -1 /etc/passwd [root@localhost test]# eval echo $a shuju root:x:0:0:root:/root:/bin/bash
- 命令格式
-
exec命令能够在不创建新的子进程的前提下转去执行指定的命令当指定的命令执行完毕后该进程就终止了。
-
export设置或者显示环境变量
-
read命令可从标准输入读取字符串等信息传给shell程序内部定义的变量。
-p prompt设置提示信息
-t timeout设置输入等待时间单位默认为秒
[root@localhost test]# read -t 10 -p "please input your name:" name
please input your name:xiaoming
[root@localhost test]# echo $name
xiaoming
[root@localhost test]# echo -n "please input your name:";read name1 name2
#读取两个输入以空格隔开分别赋值给name1和name2
please input your name:xiaoming xiaohong
[root@localhost test]# echo $name1
xiaoming
[root@localhost test]# echo $name2
xiaohong
- shift在程序中每使用一次shift语句都会使所有的位置参数依次向左移动一个位置并使位置参数$#减1直到减到0为止。
- exit退出shell程序。在exit之后可以有选择地指定一个数作为返回状态
6没有必要使用cat命令
egcat /etc/passwd | grep guru
使用以下方式即可
eggrep guru /etc/passwd
7代码缩进
示例
#!/bin/bash
i=1
while [ $i -le 10 ]
do
if [ $i -le 9 ]
then
username=user0$i
else
username=user$i
fi
! id $username &>/dev/null && {
useradd $username
echo $username | passwd --stdin $username &>/dev/null
}
let i++
done
8仔细阅读出错信息
有时候我们修改了某个错误并再次运行后系统依旧会报错。然后我们再次修改但系统再次报错。这可能会持续很长时间。但实际上旧的错误可能已经被纠正只是由于出现了其它一些新错误才导致系统再次报错。
如何快速生成脚本开头的版本版权注释信息
[root@localhost ~]# vim ~/.vimrc //进入vimrc配置
autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()"
func SetTitle()
if expand("%:e") == 'sh'
call setline(1,"#!/bin/bash")
call setline(2,"#########################")
call setline(3,"#File name:".expand("%"))
call setline(4,"#Version:v1.0")
call setline(5,"#Email:admin@test.com")
call setline(6,"#Created time:".strftime("%F %T"))
call setline(7,"#Description:")
call setline(8,"#########################")
call setline(9,"")
endif
endfunc
1.8shell脚本的执行方式
1交互式执行 //人工输入一句机器执行一句
[root@localhost ~]# for filename in `ls /etc`
> do
> if echo "$filename" | grep "passwd"
> then
> echo "$filename"
> fi
> done
2作为程序文件执行常用
对于一组需要经常重复执行的Shell语句来说将它们保存在一个文件中来执行。我们通常称这种包含多个Shell语句的文件为Shell脚本或者Shell脚本文件。脚本文件是普通的文本文件可使用任何的文本编辑器查看或修改Shell脚本
[root@localhost ~]# mkdir /test
[root@localhost ~]# cd /test
[root@localhost test]# vim test1.sh
#!/bin/bash
for filename in `ls /etc`
do
if echo "$filename" | grep "passwd"
then
echo "$filename"
fi
done
1.9 执行脚本的方法
1bash ./filename.sh产生子进程再运行使用当前指定的bash shell去运行
2./filename.sh产生子进程再运行使用脚本里面指定的shell去运行。使用该种方式执行需要x权限
3source ./filename.shsource命令是一个shell内部命令其功能是读取指定的shell程序文件并且依次执行其中的所有的语句并没有创建新的子shell进程所以脚本里面所有创建的变量都会保存到当前的shell里面
4. filename.sh和source一样也是使用当前进程执行
示例一
[root@localhost test]# vim test2.sh
#!/bin/bash
cd /tmp
pwd
[root@localhost test]# ls -l test2.sh
-rw-r--r--. 1 root root 24 Apr 30 20:09 test2.sh
(1)[root@localhost test]# bash test2.sh
/tmp
(2)[root@localhost test]# ./test2.sh
-bash: ./test2.sh: Permission denied
[root@localhost test]# chmod a+rx test2.sh
[root@localhost test]# ./test2.sh
/tmp
(3)[root@localhost test]# source test2.sh
/tmp
[root@localhost tmp]#
(4)[root@localhost test]# . test2.sh
/tmp
[root@localhost tmp]#
执行shell脚本时如果使用1和2这种方式执行会在当前的进程下产生一个新的bash子进程所以子进程切换到了/tmp目录当脚本结束子进程也就结束了所以当前进程的目录不会发生变化3和4方式执行时不会产生新的进程所以脚本执行结束后当前的目录会变成/tmp。
示例二
[root@localhost test]# echo 'userdir=`pwd`' > test3.sh
[root@localhost test]# cat test3.sh
userdir=`pwd`
(1)[root@localhost test]# bash test3.sh
[root@localhost test]# echo $userdir
[root@localhost test]#
(2)[root@localhost test]# chmod a+rx test3.sh
[root@localhost test]# ./test3.sh
[root@localhost test]# echo $userdir
[root@localhost test]#
(3)[root@localhost test]# source test3.sh
[root@localhost test]# echo $userdir
/test
(4)[root@localhost test]# . test3.sh
[root@localhost test]# echo $userdir
/test
1.10 shell脚本的退出状态
在UNIX或者Linux中每个命令都会返回一个退出状态码。退出状态码是一个整数其有效范围为0~255。通常情况下成功的命令返回0而不成功的命令返回非0值。非0值通常都被解释成一个错误码。行为良好的UNIX命令程序和工具都会返回0作为退出码来表示成功。
Shell脚本中的函数和脚本本身也会返回退出状态码。在脚本或者是脚本函数中执行的最后的命令会决定退出状态码。另外用户也可以在脚本中使用exit语句将指定的退出状态码传递给Shell。