文章目录
前言
在UNIX和类UNIX操作系统中,Shell是一个非常重要的组件,为用户提供了操作系统的各种功能和命令,如文件管理、进程管理、网络管理等等。与其他编程语言不同,Shell语言具有解释性,其脚本作为文本文件存储,可以直接运行,也可以用来编写脚本程序。
一.shell 概述
Shell是一种命令行解释器,可以理解为一种软件程序,它接收用户输入的命令并将其转换为操作系统内核能够理解的指令,然后将结果返回给用户。 Shell通常运行在操作系统的用户空间中,作为操作系统和用户之间的接口。
常见的Shell包括Bash、Korn Shell、C Shell等,其中Bash在大多数Linux发行版中被广泛使用。由于Shell的灵活性和易用性,它被广泛用于自动化脚本编写、系统管理、软件配置等领域。
- Shell(外壳):是一种命令解释器程序,它能识别用户输入的各种命令,并传递给操作系统
- 结构图
#查看 shell 命令解释器的路径
[root@localhost ~]# cat /etc/shells
#查看 默认的命令解释器
[root@localhost ~]# echo $SHELL # $ 用于提取变量值
如何编写shell脚本
脚本开头
#创建脚本文件
[root@localhost ~]# vim test1.sh #.sh扩展名不能更改
#编辑文件 ~/.vimrc 自动化生成脚本抬头信息
#写入以下内容
#第一行为文件检索的识别功能:给以.py .cc .sh .java 结尾的文件自动添加抬头信息
autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()"
func SetTitle() #添加一个名为SetTitle的函数
if expand("%:e") == 'sh' #如果调用的文件扩展名是.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
脚本内容
脚本中尽量不用中文注释
多使用内部命令
- 无论碰到哪种情况,请尽量考虑使用内部命令而不是外部命令
- 内部命令执行的效率高,性能好
没有必要使用cat命令
- 这是我们经常在论坛里讨论的话题之一。没有必要使用cat命令指的是在有些时候,我们会发现根本没有必 要使用cat命令。使用了多余的cat命令会让你的代码看起来很丑陋,而且还会带来性能上的问题,增加查询时间,降低查询效率。
- 以下两条命令结果一样
[root@server ~]# cat /etc/passwd | grep root
[root@server ~]# grep root /etc/passwd
仔细阅读出错信息
文件名以sh结尾
- shell脚本文件名应见名知义 ,扩展名位sh,如:backup_mysql.sh
代码缩进:
- shell没有强制要求,但建议缩进,这样可以提高阅读性,程序更有层次感。
for ((i=1;i<10;i++))
do
echo -ne "$i\t" # /t 会被解释为一个制表符,用于在文本中对齐或缩进内容。
done # -ne 代表取echo 默认换行
echo #后面没有内容的 echo 代表换行
for ((i=1;i<70;i++))
do
echo -n "@"
done
echo
for ((i=1;i<10;i++))
do
for ((j=1;j<=i;j++))
do
echo -en "$i*$j=$[i*j]\t"
done
echo
done
执行脚本
[root@timeserver ~]# bash test2.sh
[root@timeserver ~]# /root/test2.sh #需要增加文件权限 X
#bash 时无需增加权限,bash命令自带执行权限,会将/root/test2.sh当作参数执行
[root@timeserver ~]# bash /root/test2.sh
bash shell 基本命令
打印命令
- 格式:echo -参数 内容
- 参数
-n :取消输出后行末的换行符号
-e :启用转义字符
- 可以输出带颜色的字体:
格式:echo -e "\e[字体控制;字体颜色或背景色 字符串内容 \e[0m"
\e[表示控制开始,\e[0m表示控制结束
字体控制选项:1表示高亮,4表示下划线,5颜色闪烁
颜色如下:字颜色:30-37 , 背景色:40-47
[root@server ~]# vim color.sh
echo -e "\e[30m 黑色字\e[0m"
echo -e "\e[1;31m 紅色字\e[0m"
echo -e "\e[32m 綠色字\e[0m"
echo -e "\e[33m 黃色字\e[0m"
echo -e "\e[34m 藍色字\e[0m"
echo -e "\e[35m 紫色字\e[0m"
echo -e "\e[36m 天藍字\e[0m"
echo -e "\e[37m 白色字\e[0m"
echo -e "\e[40;37m 黑底白字\e[0m"
echo -e "\e[41;37m 紅底白字\e[0m"
echo -e "\e[42;37m 綠底白字\e[0m"
echo -e "\e[43;37m 黃底白字\e[0m"
echo -e "\e[44;37m 藍底白字\e[0m"
echo -e "\e[45;37m 紫底白字\e[0m"
echo -e "\e[46;37m 天藍底白字\e[0m"
echo -e "\e[47;30m 白底黑字\e[0m"
[root@server ~]# bash color.sh
printf 命令
默认 printf 不会像 echo 自动添加换行符,我们可以手动添加 /n
格式:printf 格式控制字符串 参数列表
[root@server ~]# echo "Hello, Shell"
[root@server ~]# printf "Hello, Shell\n"
[root@server ~]# printf "%d %s\n" 1 "abc"
[root@server ~]# printf '%d %s\n' 1 "abc" # 单引号双引号效果一样
[root@server ~]# printf %s abcdef # 没有双引号也可输出,没有\n会续连下一个提示符
[root@server ~]# printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
# %s %c %d %f 都是格式替代符,%s 输出一个字符串,%d 整型输出,%c 输出一个字符,%f 输出实
数,以小数形式输出。
# %-10s 指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),任何字符都会被显示在 10 个字符
宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
[root@server ~]# printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
# %-4.2f 指格式化为小数,其中 .2 指保留2位小数
历史命令
history命令用于显示当前用户执行过的命令列表。当在Shell中执行命令时,Shell会将命令记录在历史列表中,以便后续使用。
格式:history [参数] [历史命令保存文件]
参数:-c :清空历史命令记录
-w:把缓存中的历史命令写入历史命令保存文件。如果不手工指定历史命令保存文件,则放 入默认 历史命令保存文件~/.bash_history 中
修改默认记录历史命令条数:
[root@server ~]# vim /etc/profile
#找到如下内容,一般在49行 修改历史列表中命令记录的上限数
HISTSIZE=1000
命令别名
alias 命令允许你为经常使用的命令设置简短的别名。这样你就可以使用更短的命令来调用常用的命令,提高工作效率。
格式:alias 别名=原命令
[root@server ~]# alias ll='ls -l'
#这样,每次你输入 ll 命令时,实际上会被替换为 ls -l 命令。
#为了让这个别名在当前账户下永久生效,可以把别名写入环境变量配置文件“~/.bashrc”。
[root@server ~]# cat ~/.bashrc # 在最下面增加、
##为了让别名不受限于账户永久生效,可以把别名写入/etc/bashrc
#使用以下命令使配置永久生效
[root@server ~]# source /etc/bashrc
命令连接字符
- 顺序执行: ;(分号)
- 用于连接两个命令
[root@server ~]# date ; ls -l /etc/passwd
2023年 10月 23日 星期一 16:40:23 CST
-rw-r--r--. 1 root root 2181 10月 7 15:03 /etc/passwd
- 并且 字符: &&
- 前面命令执行不成功,后面的命令不执行
[root@timeserver ~]# [root@server ~]# mkdir /mnt/iso && mount /dev/sr0 /mnt/iso
bash: [root@server: command not found...
- 或 字符 :||
- 前面命令执行不成功,后面的命令执行
[root@timeserver ~]# [root@server ~]# mkdir tt || ls /
bash: [root@server: command not found...
afs bin boot dev etc home lib lib64 media mnt opt proc root run sbin shell srv sys tmp usr var www
案列1:
# 若账户fox10不存在,则添加账户
[root@server ~]# id fox10 &> /dev/null &&
echo "fox10已存在" || useradd fox10
# &> /dev/null 表示将左侧命令执行的正确和错误输出
到“黑洞”即不显示到屏幕
案列 2:判断当前已登录账户数,若超过5个则输出“Too many”
[root@server ~]# num=$(who | cut -d " " -f1
| sort -u | wc -l)
[root@server ~]# [ $num -gt 5 ] && echo "Too many" || echo "已登录账户数:$num"
已登录账户数:1
# who : 查看当前已登录的账户信息
# cut -d " " -f1 :以空格为列向分割符,截取第1部分
# sort -u :去重后排序
案列 3: 编写脚本temp2.sh ,程序从键盘读入一个目录名, 判断该命令是否存在,若不存在则创建,并显示目录信息
[root@server ~]# vim temp2.sh
#!/bin/bash
cd /
ls
read -p "请输入一个目录名:" dir
test -d $dir && ls -l $dir || (echo "目录不存在,开始新建..." ; mkdir $dir ; ls -l $dir)
案列 4: 编写temp5.sh脚本显示所有用户,选择一个用户输 入,判断是root账户还是系统账户还是普通账户
[root@server ~]# vim temp5.sh
#!/bin/bash
cat /etc/passwd | cut -d ":" -f1 | sort -u
read -p "请输入一个账户名:" us
us_num=$(id -u $us)
if (($us_num==0))
then
echo "此用户为管理员账户"
else
if (($us_num>=1 && $us_num<=999))
then
echo "此账户为系统账户"
else
echo "普通账户"
fi
fi
管道符
管道符
|
是 Linux/Unix 系统中使用的一个特殊符号,用于连接两个命令并将前一个命令的输出作为后一个命令的输入。
[root@timeserver ~]# echo 1 > tt | cat tt
1
例:检索本机IP地址和子网掩码
#截取 IP 地址
[root@timeserver ~]# ip a | grep ens160 | grep inet | tr -s " " | cut -d " " -f3
192.168.186.100/24
192.168.186.200/24
#截取子网掩码
[root@timeserver ~]# ip a | grep ens160 | grep inet | tr -s " " | cut -d " " -f3 | cut -d "/" -f2
24
24
#tr -s " " :将多个空格替换为一个空格
#cut -d " " -f3 :-d 指定列之间的分隔符 #以空格为分隔符号截取第三列
常见状态码
0----------------命令运行成功
1----------------通知未知错误
2----------------误用shell命令
126-------------命令不可执行
127-------------没有找到命令
128-------------无效退出参数
128+x-----------linux信号x的严重错误
130--------------命令通过Ctrl+C终止
255--------------退出状态码越界
不同情况下,程序返回的状态码
[root@server ~]# echo "china"
china
[root@server ~]# echo $?
0
[root@server ~]# ehco "china"
bash: ehco: command not found...
Similar command is: 'echo'
[root@server ~]# echo $?
127