shell简介
Shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行。
实际上Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核。不仅如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序。Shell编程语言具有普通编程语言的很多特点,比如它也有循环结构和分支、控制结构等,用这种编程语言编写的Shell程序与其他应用程序具有同样的效果。
Shell类型 | 易学性 | 可移至性 | 编辑性 | 快捷性 |
Bourne shell(sh) | 容易 | 好 | 较差 | 较差 |
Bourne Again shell(bash) | 难 | 较好 | 好 | 好 |
C shell(csh) | 较难 | 差 | 较好 | 较好 |
TC shell(tcsh) | 难 | 差 | 好 | 好 |
查询Linux中支持的shell类型:
[root@localhost ~]# cat /etc/shells /bin/sh /bin/bash /usr/bin/sh /usr/bin/bash /bin/tcsh /bin/csh 查看默认shell [root@localhost ~]# echo $SHELL /bin/bash |
1、echo命令
命令格式:echo 选项 输出内容 子选项: -n 取消输出后行末的换行符号,即内容输出后不换行 -e 支持反斜线控制的字符转换,根据需求进行输出内容格 式调整,进行内容排版布局 控制字符: \\ 输出\本身 \a 输出警告音 \b 退格键,向左删除 \c 取消输出行末的换行符 \e ESCAPE键,向右删除 \f 换页符 \n 换行符 \r 回车键 \t 制表符(TAB键) \v 垂直制表符 \0nnn 按照八进制的ASCII码表输出字符,0为数字,nnn为三位八进制 \xhh 按照十六进制ASCII码表输出字符,hh为两位十六进制数 颜色输出:echo -e "\e[1;31m ab \e[0m" #输出红色的ab(\e[1代表颜色输出开始,\e[0m代表颜色输出结束) 30=黑色,31=红色,32=绿色,33=黄色,34=蓝色,35=紫色,36=天蓝,37=白色,39=结束 底纹颜色: 40=黑色,41=红色,42=绿色,43=黄色,44=蓝色,45=紫色,46=天蓝,47=白色,49=结束 特殊的显示: \e[0m 关闭所有属性 \e[1m 设置高亮度 \e[4m 下划线 \e[5m 闪烁 \e[7m 反显 \e[8m 消隐 注意:多个条件之间用分号(;)分割开,同时生效。 |
2、shell脚本的执行方式
shell脚本的后缀名:.sh 执行方式: 1)添加x权限,用路径执行 chomod +x 脚本.sh 绝对路径执行(文件需有执行权限,在子shell中执行) 相对路径执行(文件需有执行权限,在子shell中执行) bash 路径/文件名(在子shell中执行) 2)用 bash命令,调用脚本文件 |
3、EOF脚本的使用方式
#!/bin/bash #定义了shell类型,EOF脚本一定要写这一行,且必须正确; 感叹号是调用
cat << EOF #显示EOF之后的内容;efo,eof都可以,但必须前后对应;
显示内容
EOF #表示结束,必须与开头对应。
4、bash的功能
1)history:历史命令功能;单用history是命令的历史缓存 [root@localhost ~]# echo $HISTSIZE #存放历史命令的条目(数量) 1000 [root@localhost ~]# echo $HISTFILE #存放用户执行的历史命令,写入文件 /root/.bash_history 子选项: -c 清空历史命令 -r 恢复历史命令 -w 把缓存中的历史命令写入历史命令的保存文件中。如果不指定历史命令保存文件,则放入默认文件中~/.bash_history 历史命令调用方法 !行号 #根据行号调用历史命令 !字符串 #根据关键词在历史命令中调用执行 !! #执行上次的命令,以及上下左右寻找 2)补全功能:TAB键补全文件或命令 注意:补齐功能有时候会将目录结尾处自动补上/符号,导致系统识别出现问题,从而报错。 软链接目录后不能加/,会使软链接信息显示原文件信息;xfsdump 目标文件后也不能加/ Linux支持对目录创建软链接,因为存在. ..目录,所以关闭了功能(. 当前目录 .. 返回上级目录,因为两个目录的存在,会使系统崩溃) sudo -i 开启新的shell 3)别名功能:alias 命令:alias 别名=’原命令 [选项]’ alias ld=’ls -ld’ #输入ld 效果等同于 ls -ld; unalias 命令1 #关闭命令1的别名; unalias -a #关闭所有别名 不同类型的命令执行顺序: 第一顺位:用绝对路径或相对路径执行的命令; 第二顺位:执行别名;(hash表优先于别名) 第三顺位:执行bash的内部命令; 第四顺位:执行按照$PATH环境变量定义的目录查找顺序找到的第一个命令。 补充:$PATH #输出此环境变量保存的所有路径。如果把脚本放在其中任何一个路径下,既可以不输入路径,直接输入命令来执行。 cp、mv、rm执行时有提示,因为有-i选项 取消提示可以加-f或者转义符\ ln -sf 执行后如果存在软链接会覆盖 别名相关配置文件(永久保存别名) 单个用户生效:~/.bashrc 或 ~/.bash_profile 所有用户生效:/etc/bashrc 或 /etc/profile 注:别名命令的优先级更高,如:执行ls,优先执行的ls的别名 source 配置文件 或 . 配置文件 #刷新配置文件内容,使新设置的选项生效 |
umask值: 普通用户:0002 超级用户:0022 当普通用户的用户名和组名相同时,并且用户的UID号大于199,用户的umask值为002 当普通用户的用户名和组名不相同时,但用户的UID号大于199,用户的umask值为022 #此处为临时解释,不作为最终真实含义,后续纠正!!! |
实验:用别名实现批量远程登录处理
#别名配置永久文件:/etc/bashrc ;/etc/profile 1、打开vim,在/etc/bashrc新建别名 [root@localhost ~]# vim /etc/bashrc 2、新建ip.txt文件,将主机ip写入 [root@localhost ~]# vim ip.txt 192.168.26.129 192.168.26.130 3、分别手动接收公钥文件(129、130),当ssh远程时,会强制接收对方的公钥文件 2、创建钥匙对(使用秘钥对实现主机之间的免密登录) 公钥: 锁 私(密)钥: 钥匙 ssh-keygen -t rsa -b 2048 #ras 加密算法 #-b 2048 加密的长度 3、切换到隐藏目录 .ssh/ 4、将公钥文件上传到指定服务器的指定位置,并查看 ssh-copy-id 192.168.26.129 5、此时,登录客户端不需要密码 6、激活别名 [root@localhost ~]# source /etc/bashrc #激活别名 7、用户别名批量执行命令(修改ip列表和执行命令来实现批量管理) [root@localhost ~]# tb 'yum -y installee';done 完整for循环代码 for i in $(cat /root/ip.txt) do ssh $i 'yum -y install tree' done
#终端同步 8、查看客户端命令是否安装成功 |
5、bash常用快捷键
快捷键 | 作用 |
ctrl+a | 把光标移动到命令行开头;Home |
ctrl+e | 把光标移动到行尾;End |
ctrl+c | 强制终止当前命令 |
ctrl+l | 清屏,相当于clear |
ctrl+u | 删除或剪切光标之前的内容 |
ctrl+k | 删除或剪切光标之后的内容 |
ctrl+y | 粘贴剪切的内容 |
ctrl+r | 在历史命令中搜索(输入搜索内容,→确认选择) |
ctrl+d | 退出当前终端 |
ctrl+z | 暂停并放入后台;命令 &将终端放入后台 |
ctrl+s | 暂停屏幕输出 |
ctrl+q | 恢复屏幕输出 |
#首次登录必须修改密码
chage -d o zhangsan # -d 修改密码过期时间
6、输入输出重定向
bash的标准输入输出:
设备 | 设备文件名 | 文件描述符 | 类型 |
键盘 | /dev/stdin | 0 | 标准输入 |
显示器 | /dev/stdout | 1 | 标准输出 |
显示器 | /dev/stderr | 2 | 标准错误输出 |
输出重定向:
类型 | 符号 | 作用 |
标准输出重定向 | 命令 > 文件 | 以覆盖的方式,把命令的正确输出输出到指定文件或设备中 |
命令 >> 文件 | 追加的方式 | |
标准错误输出重定向 | 错误命令 2> 文件 | 以覆盖的方式,把命令的错误输出输出到指定的文件或设备中 |
错误命令 2>> 文件 | 追加 | |
正确和错误输出同时保存 | 命令 &> 文件 | 以覆盖的方式把正确的和错误的输出都保存在同一文件中 |
命令 &>> 文件 | 追加 | |
命令 >> 文件1 2 >> 文件2 | 把正确的输出追加到文件1中,把错误的输出追加到文件2中 |
命令 1>>ok.txt 2>>error.txt
#在无法保证命令是否能执行成功的情况下,可以使用上述方法分开保存命令执行结果。
rpm包从Linux导入到windows中被识别为压缩包,可以看到.cpio结尾的压缩包,解压后的目录结构和yum安装后的目录结构一样。 cipo用绝对路径打包,恢复也是按照绝对路径恢复 用cpio命令将分散在不同目录打包成一个包,再用rpm封装为软件包,同时写软件包的描述信息和依赖关系,最终rpm包产生。用yum去安装,展开rpm包,展开cpio包,复制粘贴到目录下。 |
输入重定向:
wc 选项 文件名
#统计文件中的行数,单词数,字数并将统计结果显示输出;
选项: -c 统计字数(字符)
-w 统计单词数(字符串,由空白,跳格或换行字符分隔的字符串)
-l 统计行数
> >> #输出重定向
< #输入重定向
命令 &> file.txt
#正确或错误输出都重定向到file.txt中
7、多命令顺序执行
多命令执行符 | 格式 | 作 用 |
; | 命令1;命令2 | 多个命令顺序执行,命令之间没有任何逻辑联系 |
&& | 命令1 &&命令2 | 当命令1正确执行($?=0),则命令2才会执行 当命令1执行不正确($?≠0),则命令2不会执行 |
|| | 命令1||命令2 | 当命令1执行不正确($?≠0),则命令2才会执行 当命令1正确执行($?=0),则命令2不会执行 |
8、grep 命令
命令:grep [选项] “关键词” 文件名 #行提取命令
-A 数字:列出符合条件的行,并将连续列出后续n行
-B 数字:列出符合条件的行,并将连续列出前面n行
-c :统计包含字符串的行一共几行!
-i :忽略大小写
-n :输出行号
-v :反向查找(取反)
--color=auto:搜索出的关键词高亮显示(默认别名)
9、通配符功能介绍
10、test命令:用来测试
test 33 -gt 23 && echo yes || echo no 当test 33 -gt 23执行成功,echo yes执行成功,echo no不会执行 test 13 -gt 23 && echo yes || echo no 当test 13 -gt 23执行失败,echo yes不会执行。echo no判断test命令执行结果而不是&& test判断文件类型 test -文件类型 test -f a.txt && echo yes || echo no #判断是否为普通文件 test判断权限 test -权限 test -r a.txt && echo yes || echo no #判断是否有读权限 |
11、grep 和 find
查询文件在Linux中所在目录的命令 find #遍历式查询 优点:准 缺点:慢 locate #数据库查询 优点:快 缺点:需要依赖数据库的更新频率 find #查询系统中是否存在某文件 默认是精准匹配,支持使用通用匹配符号(通配符)模糊匹配 * #匹配任意数量的任意字符 grep #查询指定文件中是否包含关键词 默认就是模糊匹配,需要使用正则表达式进行精准匹配 * #代表匹配对象的数量(任意数量) a* #匹配a出现0次或任意次数 grep -v ^$ /bash/test.sh #显示非空白行内容 # ^代表行首 $代表行尾 |
12、bash中的特殊符号
符号 | 作用 | |
‘’ | 单引号。在单引号中所有的特殊符号都没有特殊含义,用于单个字符 | |
“” | 双引号。在双引号中的特殊符号都没有特殊含义($ \ ! `` 例外);常用于表示整体。 | |
`` | 反引号。反引号括起来的是系统命令,在bash中会先执行它 (将命令结果调取出来,一般用在给变量赋值的方式上)
| |
$() | 和反引号作用相同,用于引用系统命令
| |
() | 用于一串命令执行时,()中的命令会在子shell中运行 (在小括号内执行的命令,使用的是一个临时的新的bash解析器,当小括号内命令执行结束后,该解析器自动销毁。作用:变量的替换或测试)
| |
{} | 用于一串命令执行时,{}中的命令会会在当前shell中执行。也可以用于变量变形与替换。(在大括号内执行的命令,就是在当前bash解析器执行,和不加大括号效果一样,{和一个命令中间要空格,命令结尾要加;号) | |
[] | 用于变量测试(条件判断式,功能和test一样)
| |
# | 在shell脚本中,#开头的行代表注释 注释符还有 ; // /**/ <!--内容--> | |
$ | 用于调用变量的值 | |
\ | 转义符,跟在\之后的特殊符号将变为普通字符 | |
$[] $(( )) | 用来进行整数型数值运算的运算器,括号内写运算式 |
13、bash的变量
变量叠加: 例如: echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin PATH=$PATH:/bash #保证变量原有值存在的情况下,增加新值。 会随着环境变化(登录用户的身份),而动态调整变量中值的变量叫环境变量。 if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then umask 002 export UMASK=002 else umask 022 export UMASK=022 fi 双分支条件判断式 声明环境变量的要求: 1. 必须使用export命令声明 2. 环境变量尽量使用大写字母表示 3. 查看环境变量有一个专属命令env env 只能查看环境变量,即只能查看export声明的变量 set 可以查看所有变量 脚本随机生成一个数字,直到符合条件的数字被随机出来后,脚本才停止 echo $RANDOM #生成随机数字 echo $(($RANDOM%100)) #取余(%)对象就是取值的数量 #!/bin/bash for ((;;)) #无限循环 do sj=$(($RANDOM%100)) if [ $sj -eq 88 ] then echo "终于随机到88了" exit else echo $sj fi done |
14、定义变量的规则:
格式: 变量名=值
注意:给已声明的变量赋值,会覆盖原值。每次执行一次bash命令,就会开启一个新的bash解析器,相应的就会有父shell和子shell
①变量名称可以由字母,数字和下划线组成,但不能以数字开头;
②在bash中,变量的默认类型都是字符串型,如果要进行数值运算,则必须修改指定变量类型为数值型。
③变量用等号连接值,等号左右两边不能有空格;
④变量的值如果有空格,需要使用单引号或双引号包括(双引号括起来的内容都有特殊含义,单引号括起来的内容都是普通字符);
⑤变量的值中,可以使用\转义符;
⑥如果需要增加变量的值,那么可以进行变量值的叠加,不过变量需要用双引号包含“$变量名”或${变量名}包含变量名;
⑦如果把命令的结果作为变量赋予变量,则需要使用反引号或$()包含命令。
⑧在字符串中调用变量的值,需要加花括号;
⑨变量名建议大写,便于区分。
声明变量的方式
当变量名和后续字符串在一起的时候,需要使用大括号划定范围
file=a.txt
${file}dir
read #在脚本内声明变量,将脚本外的值调给脚本内,赋值给指定变量
选项 -p 添加注释信息
在脚本中实现计算机的功能 vim js.sh |
15、变量的分类
用户自定义变量:由用户自由定义变量命名和变量的值;
环境变量:在bash中预设了很多环境变量,在工作中我们可以直接调用这些变量。Linux系统是通过PATH变量来搜索命令的,系统会按照PATH变量里目录的顺序查找该命令,如果所有目录都没找到命令,则提示命令未找到。
位置参数变量:向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的;
预定义变量:bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。
16、变量查看set:
set -u #调用未声明的变量时会有提示(-u开启,+u关闭); set -x #在命令执行之前,会把命令先输出一次(-x开启,+x关闭); unset 变量名 #删除变量 补充:set命令可以查看所有变量。(已生效的变量) # -x 一般用来进行脚本的debug(调试) 格式: bash -x 脚本.sh |
17、环境变量
环境变量设置与删除
age=18 #定义变量名和赋值; export age #声明age变量为环境变量(export age=18 #声明并赋值); env #查看环境变量; 补充:env只能查看环境变量; 环境变量会在开启子shell时传递给子shell,但是子shell不会把自己设置的环境变量传递给父进程。 |
18、PS1变量:命令提示符设置(不属于环境变量)
格式:[\u@\h \W]\$
# [用户名@主机名 所在位置]$或#
19、LANG语系变量(属于环境变量)
LANG变量定义了Linux系统的主语系环境,这个变量的默认值是: zh_CN.UTF-8 #图形化界面 en_US.UTF-8 #字符界面 LANG=zh_CN.UTF-8 #将zh_CN.UTF-8设为当前的语系变量 查看语系变量: localectl status 列出所有语系变量: localectl list-locales 永久配置文件: /etc/locale.conf 设置语系变量的方法: localectl set-locale LANG=zh_CN-utf8 #该命令直接修改配置文件
|
20、位置参数变量
shell中的内置变量(不需要管理员进行声明,有特殊含义,并且不能改变其含义)
作用:用来将脚本外的值传入脚本内
let命令 和$((运算式))、$[ 运算式 ] 功能一样,区别是let命令调用变量不需要$符号
位置参数变量 | 作用 |
$n | n为数字,$0代表命令本身,$1-9代表第一到第九个参数,十以上的参数要用大括号包含 ${10} |
$* | 这个变量代表命令行中所有的参数,$*把所有的参数看成一个整体 |
$@ | 代表命令行中所有参数,不过$@把每个参数区分对待 |
$# | 代表命令行中所有参数的个数 |
21、预定义变量
预定义变量 | 作用 |
$? | 最后一次执行命令的返回状态。返回0表示命令执行正确,返回非0表示命令执行错误 |
$$ | 当前进程的进程号(PID);常用于脚本中输出重定向 echo $$ >> 文件名.pid |
$! | 后台运行的最后一个进程的进程号(PID) |
exit 数字 #退出脚本
#就是$?的返回值,用来进行脚本故障点的快速定位
22、read 接收键盘输入,完成交互式操作
命令格式:read 选项 变量名 选项: -p “提示信息”:等待read输入时,输出提示信息; -t 秒数:read命令会一直等待用户输入,使用此选项可以指定等待时间; -n 字符数:read命令只接收指定的字符数量,然后就会 执行; -s 隐藏输入内容,适用于机密信息的输入。 read变量名定义:
|
23、shell的运算符
1)数值运算的方法
格式:declare [+/-] [子选项] 变量名
子选项:
- 给变量设定类型属性
+ 取消变量的类型属性
-a 将变量声明为数组型
-i 将变量声明为整数型
-r 将变量声明为只读变量(只读变量无法更改值,无法被删除和取消属性)
-x 将变量声明为环境变量
-p 显示指定变量的被声明类型
2)数组变量类型
把有限个类型相同的变量用一个名字命名,然后用编号区分他们的变量集合。变量名称为数组,编号称为下标。
例:name[0]=”aa” name[1]=”bb” name[2]=”cc”
echo $name 输出aa
echo $name[1] 输出bb
echo $name[*] 输出aa bb cc
注:数组的下标从0开始,调用数组的元素时要使用${数组[下标]}的格式
数组声明:
变量=(值1 值2 值3 值...)
#小括号,值之间有空格
declare -a name[0]=zhangsan
declare -a name[1]=lisi
#数组变量,下标变量
数组变量叠加:
[root@localhost ~]# echo ${name[@]}
zhangsan lisi laowang
[root@localhost ~]# name=(${name[@]} laosong)
[root@localhost ~]#
[root@localhost ~]# name=(zhangsan lisi laowang laosong)
3)使用expr 或 let 进行数值运算
这两个是直接声明运算过程是数值运算,而不是通过声明变量的类型,所以相对简单,但是要注意格式:
[root@localhost sh]# x=1000
[root@localhost sh]# y=2000
[root@localhost sh]# expr $x + $y
3000
expr 使用时需要注意的是,在运算符两边要有空格,否则不会正常运算。
let 则相对简单易用,原理相同,格式略微变化:调用变量可以不写$符号 let s=x+y
[root@localhost sh]# x=1000
[root@localhost sh]# y=2000
[root@localhost sh]# let s=$x+$y
[root@localhost sh]# echo $s
3000
let 还能进行自增增减,或者指定增加量或减少量。
自增&自减
不管是expr 还是 let 都能实现数值运算,看个人使用习惯。
24、shell 常用运算符
优先级 | 运算符 | 功能描述 |
1 | + - | 正、负 |
2 | * / % | 乘、除、取余 |
3 | + - | 加、减 |
4 | += -= … | 自增、自减 … |
扩展知识点:
其他语言中除了取余运算之外,还有一种类似于取余的运算,叫做取模运算。看区别:
1.求整数商: c = a/b
2.计算模或者余数: r = a-c*b
注意:当a和b符号一致时,求模运算和求余运算所得的c的值一致,因此结果一致。但是当符号不一致的时候,结果不一样。具体来说,求模运算结果的符号和b一致,求余运算结果的符号和a一致。
25、环境变量配置文件
1)source 环境变量配置文件 在配置文件中写入新的规则之后,执行次命令即可刷新此文件使规则生效。 # 例:source ./bashrc 或 . ./bashrc 2)配置文件 全局配置文件: /etc/profile 和 /etc/bashrc 局部配置文件: ~/.bashrc 和 ~/.bash_profile 相同的变量赋值,局部配置文件生效晚于全局配置文件。因此局部配置文件的赋值会覆盖全局配置文件的赋值。 注销时生效的变量配置文件:~/.bash_logout 3)文件调用的顺序是 a.先调用/etc/profile文件在这个环境变量配置文件中会定义这些默认环境变量 USER变量:根据登录的用户,给这个变量赋值(就是让USER变量的值保存当前用户名)。 LOGNAME变量:根据USER变量的值,给这个变量赋值。 MAIL变量:根据登录的用户,定义用户的邮箱为/var/spool/mail/用户名。 PATH变量:根据登录用户的身份,决定PATH变量是否包含专属目录(/root/sh)。 HOSTNAME变量:更改主机名,给这个变量赋值。 HISTSIZE变量:定义历史命令的保存条数。 b. ~/.bash_profile文件就没有那么复杂了,这个文件主要实现了两个功能 调用了~/.bashrc文件。 在PATH变量后面加入了“:$HOME/bin”这个目录。那也就是说,如果我们在自己的家目录中建立bin目录,然后把自己的脚本放入“~/bin”目录,就可以直接执行脚本,而不用通过目录执行了。 c.在~/.bashrc文件中主要实现了 定义默认别名,所以我们把自己定义的别名也放入了这个文件。 调用/etc/bashrc d. 在/etc/bashrc文件中主要定义了这些内容 PS1变量:也就是用户的提示符,如果我们想要永久修改提示符,就要在这个文件中修改 umask:定义umask默认权限。这个文件中定义的umask是针对“没有登录过程(也就是不需要输入用户名和密码时,比如从一个终端切换到另一个终端,或进入子Shell)”时生效的。如果是“有用户登录过程”,则是/etc/profile文件中的umask生效。 PATH变量:会给PATH变量追加值,当然也是在“没有登录过程”时才生效。 调用/etc/profile.d/*.sh文件 4)shell登录信息 a.本地终端登录时的提示信息配置文件:/etc/issue(登录前显示) 远程终端登录时的提示信息配置文件:/etc/issue.net(登录前显示) /etc/issue.net修改方法: vim /etc/issue.net 将要提示的信息写入(不能使用特殊符号,需要手动输入); vim /etc/ssh/sshd_config # 在#Banner none下一行写入Banner /etc/issue.net systemctl restart sshd 查询组合作用可用man agetty \d :显示当前系统日期 \s :显示操作系统名称 \l :显示登录的终端号 \m :显示硬件体系结构 \n :显示主机名 \o :显示域名 \r :显示内核版本 \t :显示当前系统时间 \u :显示当前登录用户的序列号 CentOS 7 主机名的生效逻辑
b.本地和远程登录提示信息配置文件:/etc/motd(登录后提示) /etc/motd文件中是显示欢迎信息的,这个文件是在用户输入用户名和密码,正确登录之后显示欢迎信息。在/etc/motd文件中的欢迎信息,不论是本地登录,还是远程登录都可以显示。我们一般在这个文件里写一写登录警告信息,告诉用户登录后需要注意哪些事情。 c.查询bash的快捷键 stty -a 修改快捷键 stty 关键词 快捷键 |