走进shell

什么是shell

shell的作用是:

  • 解释执行用户输入的命令或程序等
  • 用户输入一条命令,shell就解释一条
  • 键盘输入命令,Linux给与响应的方式,称之为交互式式

image-20230707114012121

shell是一块包裹这系统核心的壳,处于操作系统的最外层,与用户直接对话,把用户的输入,解释给操作系统,然后处理操作系统的输出结果,输出到屏幕给与用户看到结果

从我们登入Linux,输入账号密码到进去Linux交互式界面,所有的操作都是交给shell解释并执行

shell运行的一个流程

1.1

我们想要获取计算就的数据,不可能每次都编写程序,编译后,再运行,再得到我们想要的,例如你想找到一个文件,可以先写一段c语言的代码。然后调用系统函数,通过gcc编译后,运行程序才能找到文件。。。

因此有大牛开发出了shell解释器,能够让我们方便的使用Linux,例如只要敲下ls -l这样的字符串,shell解释器就会针对这句话翻译,解释成ls -l -h 然后执行,通过终端输出结果,无论是图形化还是命令行界面

即使我们用的图形化,点点点的动作,区别也只是

  • 命令行操作,shell解释执行后,输出结果到黑屏命令行界面
  • 图形化操作,shell接受点击动作,输出图案数据

shell和运维

shell脚本语言很适合处理纯文本类型数据,且Linux的哲学思想就是一切皆文件,如日志丶配置文件丶文本丶网页文件丶,大多数都是纯文本类型的,因此shell可以进行方便的文本处理,好比强大的Linux三剑客(awk sed grep )

什么是shell脚本

当命令或者程序语句写在文件中,我们执行文件,读取其中的代码,这个程序文件就称之为shell脚本

在sehll脚本里重定义多条Linux命令以及循环控制语句,然后将这些Linux命令一次性执行完毕,执行脚本文件的方式称之为,非交互式方式

  • windowsh中存在*.bat 批处理脚本
  • LInux中常用*.sh 脚本文件

shell脚本规则:shell脚本或者称之为(bash shell程序)通常都是vim编辑,由Linux命令丶bash shell指令丶 逻辑控制语句和注释信息组成

shell语言定义的变量,数据类型默认都是字符串类型

int 数字数据类型

shebang

计算机程序中,shabang指的是出现在文本文件的第一行两个字符#!

在Unix系统中,程序会分析shabang后面的内容,作为解释器的命令,例如:

  • #!/bin/sh开头的文件,程序在执行的时候会调用/bin/sh,也就是 bash解释器
  • #!/usr/bin/python开头的文件,代表指定python解释器取执行
  • #!/usr/bin/env [解释器名称],是一种在不同平台上都能正确找到解释器的办法

注意:

  • 如果脚本未指定shabang,脚本执行的时候,默认用当前shell去解释脚本,既$SHELL
  • 如果shabang指定了可执行的解释器,如 /bin/bash /usr/bin/python ,脚本在执行时,文件名会作为参数传递给解释器
  • 如果#!指定的解释器没有可执行权限,则会报错“bad inteerpreter:Permission denied”
  • 如果#!指定的解释程序不是一个可执行文件,那么指定的解释程序会被忽略,转而交给当前的SHELL去执行这个脚本
  • 如果#!指定的解释程序不存在,那么会报错“bad inteerpreter:No such file or direc'tory”
  • #!之后的解释程序,需要写绝对路径(如#!/bin/bash),它是不会自动到$PATH中寻找解释器的
  • 如果你使用“bash test.sh”这样的命令来执行脚本,那么#!这一行将会被忽略掉,解释器当然是用命令行中显示指定的bash。

脚本案列:

脚本注释,脚本开发规范

  • 在shell脚本中,#后面的内容代表注释掉的内容,提供给开发者和使用者观看,系统就会忽略这行
  • 注释可以单独写一行,也可以跟在命令后面
  • 尽量保持爱写注释的习惯,便于以后回顾代码的含义,尽量使用英文而非中文

执行shell脚本的方式

  • bash scripts.shsh scripts.sh,文件本身没执行权限,没x权限则使用的方法,或脚本未指定shabang,重点推荐的方式
  • 使用绝对/相对路径执行脚本,需要文件含义x权限
  • source scripts.sh或者. scripts.sh,代表执行的含义,source等于.(点)
  • 少见的用法,sh < scripts.sh

脚本语言

shell脚本语言属于一种弱类型语言,无需声明变量类型,直接定义使用

强类型语言,必须定义变量类型,确定是数字丶字符串等。之后在赋予同类型的值

centos7系统中支持的shell情况,有如下种类:

默认的sh解释器

其他脚本语言

  • PHP是网页程序语言,专注于web页面开发,诸多开源产品,wordpress丶discuz开源产品都是PHP开发
  • perl语言,擅长支持强大的正则表达式,以及运维工具开发
  • Python语言,明星语言,不仅适用于脚本程序开发,如(系统后台,资产管理平台),爬虫程序开发,大量Linux运维工具也有Python开发,甚至于游戏开发使用

shell的优势

虽然有诸多的脚本编程语言,但是对于Linux操作系统内部应用而言,shell是最好的工具,Linux底层命令都支持shell语句,以及结合三剑客(awk sed grep )进行高级用法

  • 擅长系统管理脚本开发,如软件启停脚本丶监控报警脚本丶日志分析脚本,每个语言都有自己擅长的地方,扬长避短,达到高效运维的目的是最合适的

bash基础特性

bash是什么

  • bash是一个命令处理器,运行在文本窗口中,并能执行用户直接输入的命令
  • bash还能从文件中读取linux命令,称之为脚本
  • bash支持通配符丶管道丶命令替换丶条件判断等逻辑控制语句

bash有诸多方便的功能,有助于运维人员提升工作效率

命令历史

shell会保留其会话中用户提交执行的命令

bash特性汇总

  • 文件路径tab键补全
  • 命令补全
  • 快捷键ctrl+a,e,u,k,l
  • 通配符
  • 命令历史
  • 命令别名
  • 命令行展开

变量含义

学生时代所学的数学方程式,如x=1,y=2,那会称之为x,y为未知数

对于计算就而已,x=1,y=2等于定义了两个变量,名字分别是x,y。且赋值了1和2

**变量是暂时存储数据的地方,是一种数据标记(房间号,标记了客人所在的位置),数据存储在内容空间,通过调用正确的变量名字,即可取出对应的值。

shell的变量

  • 变量定义与赋值,注意变量与值之间不得有空格

  • 变量替换/引用

  • 变量名规则
    • 名称定义要做到见明知意,且按照规则来,切不得引用保留关键字(help检查保留字)
    • 只能包含数字丶字母丶下划线
    • 不能以数字开头i
    • 不能用标点符号
    • 变量名严格区分大小写

  • 变量的作用域
    • 本地变量,只针对当前的sehll进程

父,子shell的不同作用域:

image-20230328103628571

pstree检查进程树

  • 本地变量,当前的shell
单引号变量,不识别特殊语法
双引号变量,识别特殊语法

  • 环境变量,也称全局变量,针对当前shell以及其任意子进程,环境变量也分自定义丶内置两种环境变量
  • 局部变量,针对在shell函数或是shell脚本中定义
  • 位置参数变量:用于shell脚本中传递的参数
  • 特殊变量:shell内置的特殊功效变量
    • $?
    • 0:成功
    • 1-255:错误码
  • 自定义变量
    • 变量赋值:varName=value
    • 变量引用: ${varName} 丶$varName
    • 双引号,变量名会替换为变量值
    • 单引号,识别为普通字符串

不同的执行方式,不同的shell环境

不同环境的区别:

#注意 :
每次调用bash/sh都会开启一个子shell,因此不保留当前的shell变量,通过pstree命令查看进程树
调用source实在当前shell环境加载变量,因此保留变量

shell变量面试题

问,如下输出什么内容

#注:
`linux命令`
在linux中反引号中的命令执行结果会被保留下来

例:

答:c

因为whoami加的是反引号,所以输出结果应是root
但是,因为是用sh运行的脚本,开启了一个子shell
所以echo输出结果为空
如果,用source运行,则输出root

环境变量设置

环境变量一般指的是用export内置命令导出的变量,用于定义shell的运行环境,保证shell命令的正确执行。shell通过环境变量确定登录的用户名丶PATH路径丶文件系统等各种应用

环境变量可以在命令行中临时创建,但是用户退出shell终端,变量即丢失,如要永久生效,需要修改环境变量设置

用户个人配置文件**~/.bash_profile丶~/.bashrc**远程登录用户特有文件
全局配置文件**/etc/profile丶/etc/bashrc,**且系统建议最好创键在**/etc/profile.d/,**而非直接修改主文件,修改全局配置文件,影响所以登录的用户

检查系统环境变量的命令:

set:输出所有变量,包括全局变量丶局部变量(指sh脚本文件中定义的变量)
env:只显示全局变量
declare:输出所有变量,如同‘set’
export:显示和设置环境变量值

撤销环境变量:

语法:unset 变量名,删除变量名或函数

设置只读变量:

  • readonly,只有shell结束,只读变量失效
[root@hadoop102 ~]# readonly name=jiujiu
[root@hadoop102 ~]# echo $name
jiujiu
[root@hadoop102 ~]# name=like
-bash: name: readonly variable
[root@hadoop102 ~]# unset name
-bash: unset: name: cannot unset: readonly variable

试题:

过滤出,格式化所有的linux环境变量
[root@hadoop102 ~]# export | awk -F '[ =]' '{print $3}'
HISTCONTROL
HISTSIZE
HOME
HOSTNAME
LANG
LESSOPEN
LOGNAME
LS_COLORS
MAIL
OLDPWD
PATH
PWD
SELINUX_LEVEL_REQUESTED
SELINUX_ROLE_REQUESTED
SELINUX_USE_CURRENT_RANGE
SHELL
SHLVL
SSH_CLIENT
SSH_CONNECTION
SSH_TTY
TERM
USER
XDG_RUNTIME_DIR
XDG_SESSION_ID

bash多命令执行

[root@hadoop102 ~]# ll jiujiu/;ll dir1/;cd jiujiu
total 0
-rw-r--r--. 1 root root 0 Mar 28 11:43 like
total 0
-rw-r--r--. 1 root root 0 Mar 27 18:14 file1
-rw-r--r--. 1 root root 0 Mar 27 18:14 file10
-rw-r--r--. 1 root root 0 Mar 27 18:14 file2
-rw-r--r--. 1 root root 0 Mar 27 18:14 file3
-rw-r--r--. 1 root root 0 Mar 27 18:14 file4
-rw-r--r--. 1 root root 0 Mar 27 18:14 file5
-rw-r--r--. 1 root root 0 Mar 27 18:14 file6
-rw-r--r--. 1 root root 0 Mar 27 18:14 file7
-rw-r--r--. 1 root root 0 Mar 27 18:14 file8
-rw-r--r--. 1 root root 0 Mar 27 18:14 file9
[root@hadoop102 jiujiu]# 
#命令之间用分号相隔

环境变量初始化与加载顺序

image-20230328114820870

shell变量

本地变量

  • 定义shell变量,变量名不需要加美元符$
  • 本地变量只在用户当前shell生存期中生效,如:
[root@hadoop102 ~]# name="jiujiu"
[root@hadoop102 ~]# echo $name
jiujiu
[root@hadoop102 ~]# bash   (开启子shell)
[root@hadoop102 ~]# echo $name

[root@hadoop102 ~]# exit
exit
[root@hadoop102 ~]# echo $name
jiujiu
[root@hadoop102 ~]# 

变量定义

变量名要求:字母丶数字丶下划线组成,可以是字母或是下划线开头,如:

  • jiujiu
  • jiujiu_123
  • _jiujiu123

变量名严格区分大小写:

  • jiujiu_123
  • Jiujiu_123
#变量名的大小写会影响到想要的的变量结果
  • 1.赋值不加引号

  • [root@hadoop102 ~]# name=jiujiu
  • 2.赋值加单引号

    • [root@hadoop102 ~]# name='jiujiu'
  • 3.赋值加双引号

    • [root@hadoop102 ~]# name="jiujiu"

取出变量值

  • 单引号:所见即所得,强引用
  • 双引号:输出引号里所有内容,识别特殊符号,弱引用
  • 无引号:连续的符号可以不加引号,有空格则有歧义,最好使用双引号
  • 反引号:引用命令执行结果,等于$()用法

特殊变量

shell的特殊变量,用在如脚本,函数传递参数调用,有如下特殊的,位置参数变量

$0 :获取shell脚本文件名,以及脚本路径
$n :获取shell脚本的第n个参数,n在1~9之间,如$1,$2..$9. 大于9则需要写成${10},参数空格隔开 
$# :获取执行的shell脚本后面的参数总个数
$* :获取shell脚本所有参数,不加引号等同于$@的作用,加上引号“$*”的作用是 接收所有参数为单个字符,如“$1 $2.....”
$@ :不加引号,效果同上,加引号,是接收所有参数为独立字符串,如“$1” “$2” “$3” ...,空格保留

脚本实践:

[root@hadoop102 ~]# vim like.sh
[root@hadoop102 ~]# bash like.sh jiujiu 185 120 200 500
like.sh: line 1: !#/bin/bash: No such file or directory
特殊变量$0 $1 $2 ..的实践
结果:  like.sh jiujiu 185
-------------------------------
特殊变量$#获取参数总个数
‘结果: ’ 5
--------------------------------
特殊变量$* 实践
结果:  jiujiu 185 120 200 500
---------------------------
特殊变量$@ 实践
结果:  jiujiu 185 120 200 500

面试题例:

问:$*和$@的区别你了解吗?

答:
$*和$@都表示传递给函数或脚本的所有参数
当$*和$@不被双引号" "包围时,它们之间没有任何区别,都是将接收到的每一个参数看做一份数据,彼此之间以空格分割

但是当它们被双引号" "包含时,就会有区别了:
"$*"会将所有的参数从整体上看做一份数据,而不是把每个参数都看作数据
"$@"仍然将每个参数都看作一份数据,彼此之间是独立的

比如传递了5个参数,那么对于"$*"来说,这5个参数会合并到一起形成一份数据,它们之间是无法分割的;而对于"$@"来说,这5个参数是相互独立的,它们是5份数据

如果使用echo直接输出"$*"和"$@"做对比,是看不区别的;但如果使用for循环来逐个输出数据,立即就能看出区别来

实践区别:

[root@hadoop102 ~]# vim jiujiu.sh
[root@hadoop102 ~]# cat jiujiu.sh 
!#/bin/bash
echo "print each param from \"\$*\""
for var in "$*"
do
    echo "$var"
done

echo "print each param from \"\$@\""
for var in "$@"
do
    echo "$var"
done
[root@hadoop102 ~]# bash jiujiu.sh like 185 120 500
jiujiu.sh: line 1: !#/bin/bash: No such file or directory
print each param from "$*"
like 185 120 500
print each param from "$@"
like
185
120
500
0