Linux Shell基础

[TOC]

走进shell

在Linux早起,还没有出现图形化,超哥和其他系统管理员都只能坐在电脑前,输入shell命令,查看控制台的文本输出。
在大多数Linux发行版里,例如centos,可以简单的用组合键来访问Linux控制台,也就是ctrl+F1~F7。
现在更多的使用xshell这样的控制终端,来连接管理我们的Linux机器。
以centos为例,默认的shell都是GNU bash shell,支持一些特性,例如

  • man手册
  • tab补全
  • shell指令

GNU bash shell是在系统普通用户登陆时,作为普通程序运行,这个规则是/etc/passwd中指定的条目

  1. [root@chaogelinux ~]# tail -1 /etc/passwd
  2. susu:x:2009:2010::/home/susu:/bin/bash

bash会在用户登录时候自动启动,如果是虚拟控制台终端登录,`命令行界面(英語:Command-Line Interface,缩写:CLI)提示符会自动出现,此时可以输入shell命令。
或者是通过图形化桌面登录Linux系统,你就需要启动GNOME这样的图形化终端仿真器来访问shell CLI。

什么是shell

image.png
shell的作用是

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

image.png
shell是一块包裹着系统核心的壳,处于操作系统的最外层,与用户直接对话,把用户的输入,解释给操作系统,然后处理操作系统的输出结果,输出到屏幕给与用户看到结果。
image.png
从我们登录Linux,输入账号密码到进入Linux交互式界面,所有的操作,都是交给shell解释并执行
image.png
我们想要获取计算机的数据,不可能每次都编写程序,编译后,再运行,再得到我们想要的,例如你想找到一个文件,可以先写一段C语言的代码,然后调用系统函数,通过gcc编译后,运行程序才能找到文件。。。
因此有大牛开发出了shell解释器,能够让我们方便的使用Linux,例如只要敲下ls -lh这样的字符串,shell解释器就会针对这句话翻译,解释成ls -l -h 然后执行,通过终端输出结果,无论是图形化或是命令行界面。
即使我们用的图形化,点点点的动作,区别也只是

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

image.png

shell和运维

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

什么是shell脚本

当命令或者程序语句写在文件中,我们执行文件,读取其中的代码,这个程序文件就称之为shell脚本。
在shell脚本里定义多条Linux命令以及循环控制语句,然后将这些Linux命令一次性执行完毕,执行脚本文件的方式称之为,非交互式方式。

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

image.png
shell脚本规则
在Linux系统中,shell脚本或者称之为(bash shell程序)通常都是vim编辑,由Linux命令、bash shell指令、逻辑控制语句和注释信息组成。

Shebang

计算机程序中,shebang指的是出现在文本文件的第一行前两个字符#!
在Unix系统中,程序会分析shebang后面的内容,作为解释器的指令,例如

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

注意事项:

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

脚本案例

[root@chaogelinux data]# cat test.sh
#!/bin/bash
echo "超哥强呀,奥力给"
#!/bin/bash 这里就是注释的作用了

系统自带的bash脚本,开机启动脚本

[root@chaogelinux data]# head -1 /etc/rc.d/init.d/network
#! /bin/bash

脚本注释,脚本开发规范

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

    ! /bin/bash

Date : 2019-11-28 14:59:18

Author:created by chaoge

Blog:www.cnblogs.com/pyyu

![image.png](https://cdn.nlark.com/yuque/0/2022/png/12538678/1654484504150-a0a610be-4de7-4a39-a164-4de49853362b.png#clientId=uf579ecd1-2ca8-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ufd614213&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1184&originWidth=1350&originalType=url&ratio=1&rotation=0&showTitle=false&size=267339&status=done&style=none&taskId=u17841bea-5302-4ab5-823e-a1b7cd9348c&title=)
<a name="uDZQR"></a>
### 执行shell脚本的方式

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

[root@chaogelinux data]# cat test.sh

!/bin/bash

echo “超哥强呀,奥力给”

!/bin/bash 这里就是注释的作用了

[root@chaogelinux data]# [root@chaogelinux data]# [root@chaogelinux data]# sh < test.sh 超哥强呀,奥力给 [root@chaogelinux data]# sh test.sh 超哥强呀,奥力给 [root@chaogelinux data]# bash test.sh 超哥强呀,奥力给 [root@chaogelinux data]# source test.sh 超哥强呀,奥力给 [root@chaogelinux data]# . /data/test.sh 超哥强呀,奥力给

权限不足 [root@chaogelinux data]# ./test.sh -bash: ./test.sh: 权限不够 [root@chaogelinux data]# chmod +x test.sh [root@chaogelinux data]# ./test.sh 超哥强呀,奥力给

<a name="sllE2"></a>
## 脚本语言
shell脚本语言属于一种弱类型语言无需声明变量类型,直接定义使用<br />强类型语言,必须先定义变量类型,确定是数字、字符串等,之后再赋予同类型的值<br />centos7系统中支持的shell情况,有如下种类

[root@chaogelinux ~]# cat /etc/shells
/bin/sh /bin/bash /sbin/nologin /usr/bin/sh /usr/bin/bash /usr/sbin/nologin /bin/tcsh /bin/csh

默认的sh解释器

[root@chaogelinux ~]# ll /usr/bin/sh lrwxrwxrwx 1 root root 4 11月 16 10:48 /usr/bin/sh -> bash

<a name="TTXOj"></a>
### 其他脚本语言
![image.png](https://cdn.nlark.com/yuque/0/2022/png/12538678/1654484509069-f29b5d3f-40c0-46ad-82ac-83c7006b6f74.png#clientId=uf579ecd1-2ca8-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u5537e17c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=576&originWidth=1348&originalType=url&ratio=1&rotation=0&showTitle=false&size=880106&status=done&style=none&taskId=ubbbb7545-c8c9-4b37-9867-debc6889421&title=)

- PHP是网页程序语言,专注于Web页面开发,诸多开源产品,wordpress、discuz开源产品都是PHP开发
- Perl语言,擅长支持强大的正则表达式,以及运维工具的开发
- Python语言,明星语言,不仅适用于脚本程序开发,也擅长Web页面开发,如(系统后台,资产管理平台),爬虫程序开发,大量Linux运维工具也由python开发,甚至于游戏开发也使用
<a name="w1t5j"></a>
### shell的优势
虽然有诸多脚本编程语言,但是对于Linux操作系统内部应用而言,shell是最好的工具,Linux底层命令都支持shell语句,以及结合三剑客(grep、sed、awk)进行高级用法。

- 擅长系统管理脚本开发,如软件启停脚本、监控报警脚本、日志分析脚本

每个语言都有自己擅长的地方,扬长避短,达到高效运维的目的是最合适的。

Linux默认shell

[root@chaogelinux ~]# echo $SHELL /bin/bash

<a name="Kecoh"></a>
## bash基础特性
![image.png](https://cdn.nlark.com/yuque/0/2022/png/12538678/1654484510086-05b31c8f-72cc-42bf-a3f8-5fdaa457a8ca.png#clientId=uf579ecd1-2ca8-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u8e2d627f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1022&originWidth=1584&originalType=url&ratio=1&rotation=0&showTitle=false&size=1367792&status=done&style=none&taskId=uda1d6555-2727-43d9-8d9b-7f2bbe4bec4&title=)<br />bash有诸多方便的功能,有助于运维人员提升工作效率<br />**命令历史**<br />**Shell会保留其会话中用户提交执行的命令**

history #命令,查看历史命令记录,注意【包含文件中和内存中的历史记录】

[root@chaogelinux ~]# echo $HISTSIZE #shell进程可保留的命令历史的条数 3000

[root@chaogelinux ~]# echo $HISTFILE #存放历史命令的文件,用户退出登录后,持久化命令个数 /root/.bash_history

存放历史命令的文件

[root@chaogelinux ~]# ls -a ~/.bash_history /root/.bash_history

history命令

history #命令 以及参数 -c: 清空内存中命令历史; -r:从文件中恢复历史命令 数字 :显示最近n条命令 history 10

调用历史命令

!n #执行历史记录中的某n条命令 !! #执行上一次的命令,或者向上箭头 !string #执行名字以string开头的最近一次的命令

调用上一次命令的最后一个参数

ESC . #快捷键 !$

控制历史命令的环境变量

变量名:HISTCONTROL ignoredups:忽略重复的命令; ignorespace:忽略以空白字符开头的命令; ignoreboth:以上两者同时生效;

[root@chaogelinux ~]# HISTCONTROL=ignoreboth [root@chaogelinux ~]# echo $HISTCONTROL ignoreboth

[root@chaogelinux ~]# history

<a name="OZ18l"></a>
### bash特性汇总

- 文件路径tab键补全
- 命令补全
- 快捷键ctrl + a,e,u,k,l
- 通配符
- 命令历史
- 命令别名
- 命令行展开
<a name="gDBRq"></a>
### 变量含义
学生时代所学的数学方程式,如x=1,y=2,那会称之为x,y是未知数<br />对于计算机角度,x=1,y=2等于定义了两个变量,名字分别是x,y,且赋值了1和2<br />**变量是暂时存储数据的地方,是一种数据标记(房间号,标记了客人所在的位置),数据存储在内容空间,通过调用正确的变量名字,即可取出对应的值。**<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/12538678/1654484505620-7b683b81-dce1-4076-b0f9-fb1ef1a99f67.png#clientId=uf579ecd1-2ca8-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u2ef08e12&margin=%5Bobject%20Object%5D&name=image.png&originHeight=880&originWidth=1024&originalType=url&ratio=1&rotation=0&showTitle=false&size=79812&status=done&style=none&taskId=u00587f8d-a482-47a4-838c-e32e56f8e3d&title=)<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/12538678/1654484507722-4da71fab-1340-49ed-bf6a-0217a4e0d90d.png#clientId=uf579ecd1-2ca8-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u12f884ad&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1158&originWidth=990&originalType=url&ratio=1&rotation=0&showTitle=false&size=266699&status=done&style=none&taskId=uc33311cd-a6ee-4e2d-bdb9-88395340bbe&title=)
<a name="k18AC"></a>
### shell变量

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

name=”超哥”

变量名 变量类型,bash默认把所有变量都认为是字符串

bash变量是弱类型,无需事先声明类型,是将声明和赋值同时进行


- 变量替换/引用

[root@chaogelinux ~]# name=”超哥带你学bash” [root@chaogelinux ~]# echo ${name} 超哥带你学bash [root@chaogelinux ~]# echo $name #可以省略花括号 超哥带你学bash


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

有效的变量名: NAME_CHAOGE _chaoge chaoge1 chaogE1 Chao2_ge

无效的变量名: ?chaoge chao*ge chao+ge


- 变量的作用域pstree检查进程树 ![image.png](https://cdn.nlark.com/yuque/0/2022/png/12538678/1654484509604-0c13c66f-be6b-41d7-aa26-225534bceb6f.png#clientId=uf579ecd1-2ca8-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=uad0ee7ba&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1344&originWidth=2304&originalType=url&ratio=1&rotation=0&showTitle=false&size=666283&status=done&style=none&taskId=uc761e0a9-5795-486b-9549-1af9e2d9cd6&title=)![image.png](https://cdn.nlark.com/yuque/0/2022/png/12538678/1654484507774-a0d639e9-cfae-46b2-bab8-1037dd1ee59c.png#clientId=uf579ecd1-2ca8-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ub7440984&margin=%5Bobject%20Object%5D&name=image.png&originHeight=226&originWidth=644&originalType=url&ratio=1&rotation=0&showTitle=false&size=39916&status=done&style=none&taskId=u9c59b823-dbed-4482-b628-e20780999e6&title=)
   - 本地变量,只针对当前的shell进程
   - 环境变量,也称为全局变量,针对当前shell以及其任意子进程,环境变量也分自定义、内置两种环境变量
   - 局部变量,针对在shell函数或是shell脚本中定义
- 位置参数变量:用于shell脚本中传递的参数
- 特殊变量:shell内置的特殊功效变量
   - $?
      - 0:成功
      - 1-255:错误码
- 自定义变量
   - 变量赋值:varName=value
   - 变量引用:${varName}、$varName[root@chaogelinux ~]# n1=1 [root@chaogelinux ~]# n2=2 [root@chaogelinux ~]# [root@chaogelinux ~]# n3="$n1" [root@chaogelinux ~]# echo $n3 1 [root@chaogelinux ~]# n4='$n2' [root@chaogelinux ~]# echo $n4 $n2
      - 双引号,变量名会替换为变量值
      - 单引号,识别为普通字符串
<a name="x4VAb"></a>
### 不同的执行方式,不同的shell环境

[root@chaogelinux data]# echo user1=’超哥’ > testsource.sh [root@chaogelinux data]# echo $user1

[root@chaogelinux data]# sh testsource.sh [root@chaogelinux data]# echo $user1

[root@chaogelinux data]# source testsource.sh [root@chaogelinux data]# echo $user1 超哥

![image.png](https://cdn.nlark.com/yuque/0/2022/png/12538678/1654484509255-31214ed4-6a8c-4341-9cb3-a9f732b62c31.png#clientId=uf579ecd1-2ca8-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=uf62316ad&margin=%5Bobject%20Object%5D&name=image.png&originHeight=516&originWidth=1592&originalType=url&ratio=1&rotation=0&showTitle=false&size=152724&status=done&style=none&taskId=u53b33be7-3fa6-42f9-997e-37fa543c973&title=)<br />解答:<br />1.每次调用bash都会开启一个子shell,因此不保留当前的shell变量,通过pstree命令检查进程树<br />2.调用source或者.  是在当前shell环境加载脚本,因此保留变量
<a name="ObsaV"></a>
#### shell变量面试题
问,如下输入什么内容

[root@chaogelinux data]# cat test.sh user1=whoami [root@chaogelinux data]# sh test.sh [root@chaogelinux data]# echo $user1

A.当前用户 B.超哥 C.空

<a name="gJobW"></a>
## 父子shell
![image.png](https://cdn.nlark.com/yuque/0/2022/png/12538678/1654866225687-37d16a4b-f3b6-485c-a981-54b40921adfc.png#clientId=u2d0abddd-373c-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=594&id=ub9041c11&margin=%5Bobject%20Object%5D&name=image.png&originHeight=594&originWidth=953&originalType=binary&ratio=1&rotation=0&showTitle=false&size=256506&status=done&style=none&taskId=u18c69368-9e5d-4b27-97e0-53629acaf1a&title=&width=953)

<a name="kvHNC"></a>
## 环境变量设置
环境变量一般指的是用export内置命令导出的变量,用于定义shell的运行环境、保证shell命令的正确执行。<br />shell通过环境变量确定登录的用户名、PATH路径、文件系统等各种应用。<br />环境变量可以在命令行中临时创建,但是用户退出shell终端,变量即丢失,如要永久生效,需要修改环境变量配置文件

- 用户个人配置文件~/.bash_profile、~/.bashrc 远程登录用户特有文件,优先加载变量读取
- 全局配置文件/etc/profile、/etc/bashrc,且系统建议最好创建在/etc/profile.d/,而非直接修改主文件,修改全局配置文件,影响所有登录系统的用户

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

- set,输出所有变量,包括全局变量、局部变量
- env,只显示全局变量
- declare,输出所有的变量,如同set
- export,显示和设置环境变量值

**撤销环境变量**

- unset 变量名,删除变量或函数。

**设置只读变量**

- readonly ,只有shell结束,只读变量失效

直接readonly 显示当前系统只读变量 [root@chaogelinux ~]# readonly name=”超哥” [root@chaogelinux ~]# name=”chaochao” -bash: name: 只读变量

**系统保留环境变量关键字**<br />bash内嵌了诸多环境变量,用于定义bash的工作环境

[root@chaogelinux ~]# export |awk -F ‘[ :=]’ ‘{print $3}’

<a name="HmoLm"></a>
### bash多命令执行

[root@chaogelinux home]# ls /data/;cd /tmp/;cd /home;cd /data ```

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

image.png