本部分讲述shell基础

  • 1、shell介绍(shell语言与shell解释器)
  • 2、安装shell解释器与第一个shell程序


1、介绍shell

# 1、一层指的是shell这门语言,是一种特定的语法风格,规范等

# 2、另外一层指的是专门用于解释执行shell这门语言语法的应用程序,
即shell解释器,我们常用的是bash

linux系统上自带多种shell解释器,无需安装

[root@localhost ~]# chsh -l
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh

通常我们的用户在登陆后,进入的解释器默认为/bin/bash

[root@localhost ~]# head -1 /etc/passwd
root:x:0:0:root:/root:/bin/bash

shell本身就是一门解释型、弱类型、动态语言,与python相对应,Python属于解释型、强类型、动态语言,我们平时登录成功一个用户后进入的就是bash解释器的交互式环境,我们敲的命令其实都属于shell这门语言的语法

shell 语法                      Python语法

bash解释器                   Cpython解释器

操作系统                       操作系统

硬件系统                        硬件系统

2、为何要用shell

那还用说吗,一些日常的运维工作自动化、配合计划任务威力无穷,彻底解放双手,你说它不香吗?例如

  • 自动备份
  • 自动部署
  • 监控脚本

3、Shell VS python

shell语言

Shell 脚本的优势在于处理偏操作系统底层的业务,例如,Linux 内部的很多应用(有的是应用的一部分)都是使用 Shell 脚本开发的,因为有 1000 多个 Linux 系统命令为它作支撑,特别是 Linux 正则表达式以及三剑客 grep、awk、sed 等命令。

对于一些常见的系统脚本,使用 Shell 开发会更简单、更快速,例如,让软件一键自动化安装、优化,监控报警脚本,软件启动脚本,日志分析脚本等,虽然 Python 也能做到这些,但是考虑到掌握难度、开发效率、开发习惯等因素,它们可能就不如 Shell 脚本流行以及有优势了。对于一些常见的业务应用,使用 Shell 更符合 Linux 运维简单、易用、高效的三大原则。

python语言

Python 是近几年非常流行的语言,它不但可以用于脚本程序开发,也可以实现 Web 程序开发(知乎、豆瓣、YouTube、Instagram 都是用 Python 开发),甚至还可以实现软件的开发(大名鼎鼎的 OpenStack、SaltStack 都是 Python 语言开发)、游戏开发、大数据开发、移动端开发。

现在越来越多的公司要求运维人员会 Python 自动化开发,Python 也成了运维人员必备的技能,每一个运维人员在熟悉了 Shell 之后,都应该再学习 Python 语言。

Python 语言的优势在于开发复杂的运维软件、Web 页面的管理工具和 Web 业务的开发(例如 CMDB 自动化运维平台、跳板机、批量管理软件 SaltStack、云计算OpenStack 软件)等。

4、编写shell必知必会

4.1 编写shell程序的两种环境

我们可以在两个地方编写shell程序

# 1、交互式环境
调试方便,无法永久保存代码
ps:
交互式环境,请看附录《shell解释器交互式环境》
https://www.cnblogs.com/linhaifeng/articles/13976243.html


# 2、写到文件中
我们采用解释型语言编写的代码文件通常都会被称之为脚本程序(使用nodpad++演示)
可以永久保存代码

4.2 编写shell脚本程序

其实我们在交互式环境里敲的命令直接放到一个文本文件里,一个简单的shell程序就完成了

强调:shell解释器执行程序是解释执行,即打开文件读内容,因此文件的后缀名没有硬性限制,但通常定义为.sh结尾

[root@egon ~~]# mkdir -p /a/b
[root@egon ~~]# vim /a/b/hello.sh
[root@egon ~~]# cat /a/b/hello.sh
#!/bin/bash

#第一个shell小程序
echo "hello world!"

解释

  • 1、第一行表示我们选择使用的shell解释器是bash,也可以用 :#!/usr/bin/env bash
    shell的第一行比较特殊,一般都会以#!开始来指定使用的shell解释的类型。
    在linux中,除了bash shell以外,还有很多版本的shell, 例如zsh、dash等等...
    不过bash shell还是我们使用最多的。
  • 2、第二行以#符号开始,表示本行是注释,注释是对代码的解释说明,注释的内容不会执行,对关键代码加注释是一种好的编程习惯
  • 3、第三行中的echo是linux中的输出命令,该行的意思很明显的就是输出hello world!


精通各种语言的hello world!看一看还是高级语言的简洁

#C++
#include <iostream>
 int main(void)
 {
  std::cout<<"Hello world";
 }

#C
#include <stdio.h>
int main(void)
{
printf("\nhello world!");
return 0;
}

#JAVA
public class HelloWorld{
  // 程序的入口
  public static void main(String args[]){
    // 向控制台输出信息
    System.out.println("Hello World!");
  }
}

#PHP
<?php  
             echo "hello world!";  
?>

#Ruby
日本人开发的,砸日本车的时候,顺手就把你拖出去打死了,祭天
puts "Hello world."

#GO
package main
import "fmt"
func main(){

    fmt.Printf("Hello World!\n God Bless You!");

}

4.3 运行shell脚本程序

编写好shell脚本之后,运行它有几种方式

  • 方式一:绝对路径,此时采用的是文件头指定的解释器来解释执行文件内代码
    # 权限:
    # 1、对沿途文件夹有x权限
    # 2、对目标文件有r和x权限

    # 例
    [root@egon ~~]# ll -d /a
    d--------x. 3 root root 15 11月 15 11:05 /a
    [root@egon ~~]# ll -d /a/b
    d--------x. 2 root root 18 11月 15 11:06 /a/b
    [root@egon ~~]# ll /a/b/hello.sh
    -rw-r--r-x. 1 root root 10 11月 15 11:06 /a/b/hello.sh
    [root@egon ~~]# su - egon
    [egon@egon ~~]$ /a/b/hello.sh
    hello world!
    [egon@egon ~~]$
  • 方式二:相对路径,需要加./作为前缀,此时采用的仍是文件头指定的解释器来解释执行文件内代码
    # 权限:
    # 1、对沿途文件夹有x权限
    # 2、对目标文件有r和x权限

    # 例
    [root@egon ~~]# ll -d /a
    d--------x. 3 root root 15 11月 15 11:05 /a
    [root@egon ~~]# ll -d /a/b
    d--------x. 2 root root 18 11月 15 11:06 /a/b
    [root@egon ~~]# ll /a/b/hello.sh
    -rw-r--r-x. 1 root root 10 11月 15 11:06 /a/b/hello.sh
    [root@egon ~~]# su - egon
    [egon@egon ~~]$ /a/b/hello.sh # 绝对路径的方式
    hello world!
    [egon@egon ~~]$ cd /a
    [egon@egon /a/a]$ ./b/hello.sh # 相对路径的方式,加./作为前缀
    hello world!
    [egon@egon /a/a]$
  • 方式三:解释器+文件路径(绝对路径或相对路径都可以),此时采用的是我们自己指定的解释器来解释执行文件内代码
    # 权限:
    # 1、对沿途文件夹有x权限
    # 2、对目标文件有r权限即可
    因为我们执行的是解释器,当前用户对解释有执行权限就可以了,这个权限默认就有,而解释器需要读文件内容来执行,所以需要对目标文件有r权限

    # 例
    [root@egon ~~]# chmod -R o=x /a
    [root@egon ~~]# chmod o=r /a/b/hello.sh
    [root@egon ~~]# su - egon
    [egon@egon ~~]$ cd /a
    [egon@egon /a/a]$ bash b/hello.sh
    hello world!
    [egon@egon /a/a]$
  • 方式四:上述三种方式都是在子shell进程中执行程序,而方式四则是在当前shell进程中执行
    # 权限:
    # 1、对沿途文件夹有x权限
    # 2、对目标文件有r权限即可

    上述三种方式都是在当前shell环境下开启了一个新的shell解释器环境/子shell来执行程序,脚本程序在子shell中运行完毕后,子shell环境随即关闭,然后返回到父级shell即当前shell环境中,如果就想在当前shell环境中执行,需要这么做
    # 例如
    [egon@localhost shell]$ cd /home/egon/shell/
    [egon@localhost shell]$ ll hello.sh # 当前用户egon对该文件没有执行权限
    -rw-r--r--. 1 root root 60 8月 14 18:33 hello.sh

    # 下面两种方式都一样
    [root@egon ~~]# chmod -R o=x /a
    [root@egon ~~]# chmod o=r /a/b/hello.sh
    [root@egon ~~]# su - egon
    [egon@egon ~~]$ . /a/b/hello.sh # . 后跟空格,然后再跟绝对路径
    hello world!
    [egon@egon ~~]$ cd /a/b/
    [egon@egon /a/b/a/b]$ . hello.sh # . 后跟空格,然后再跟相对路径
    hello world!
    [egon@egon /a/b/a/b]$ source hello.sh # 跟上述方式一样
    hello world!
    在当前shell解释器进程中执行脚本与在子shell进程中执行脚本的区别在于作用域,后续我们会详细介绍
    # 一个shell环境就是一个单独的全局作用域,不同的shell环境,无法访问彼此shell环境中的变量
    [root@egon ~~]# su - egon
    [egon@localhost ~]$ x=111
    [egon@localhost ~]$ cat /a/b/hello.sh
    #!/bin/bash

    echo "hello world!"
    echo $x # 我们在这里访问一下全局变量x

    [egon@localhost ~]$ source /a/b/hello.sh # 在当前shell环境执行,可以访问到x
    hello world!
    111 # 取到了x的值
    [egon@localhost ~]$ bash /a/b/hello.sh # 在子shell环境执行,不能访问到x
    hello world!
    # 此处打印空
扩展备注:
chmod 修改文件权限主要有两种方式: 字母法与数字法

1、字母法:chmod  (u g o a)   (+ - =)   (r w x)   (文件名)

以上是chmod的用法,每个括号是一个参数, 前三个括号主要放在一起使用即 chmod + 设置模式 + 文件名;下面先介绍这些参数的意义:

[u g o a]	含义
u	user 表示该文件的所有者
g	group 表示与该文件的所有者属于同一组( group )者,即用户组
o	other 表示其它用户组
a	all 表示这三者皆是
[+  -  =]	含义
+	增加权限
-	撤销权限
=	设定权限
[r   w   x]                            含义
r   : read 表示可读取,对于一个目录,如果没有r权限,那么就意味着不能通过ls查看这个目录的内容。
w    :write 表示可写入,对于一个目录,如果没有w权限,那么就意味着不能在目录下创建新的文件。
x   :excute 表示可执行,对于一个目录,如果没有x权限,那么就意味着不能通过cd进入这个目录。

用法:chmod + 设置模式 + 文件名
中间的设置模式,要分别对u(user), g(group), o(other)设置权限。

4.4 调试shell程序

调试方式1:以调试的方式运行

[root@egon test]# sh -vx login.sh  # 不加-v选项,只会显示程序中运行的代码,不会显示注释信息

调试方式2:只调试语法是否有问题,比如if判断少了fi结尾

[root@egon test]# sh -n login.sh

调试方式3:仅调试脚本的一部分,用set -x与set +x包含,运行过程中会只打印(输出执行的语句)它们包含的代码段的运行情况

[root@egon test]# cat login.sh 
#!/usr/bin/env bash
set -x
read -p "请输入您的名字: " name
read -p "请输入您的密码: " pwd
set +x
if [[ "$name" == "egon" && "$pwd" == "123" ]];then
    echo "登录成功"
else
    echo "账号或密码错误"
fi
[root@egon test]# . login.sh

4.5 注释是代码之母

井号#开头的内容不会执行,注释的作用有二

  • 1、注释掉暂时不想运行的代码
  • 2、为关键代码添加注解说明,增强程序的可读性和可维护性
    1. 可以加在被注释代码的正上方单独一行,或者被注释代码的正后方,例如
    # 注释。。。
    echo "hello" # 注释。。。

    2. 不用全部加注释,只需要在自己觉得重要或不好理解的部分加注释即可

    3. 注释可以用中文或英文,但不要用拼音

5 shell编写规范与建议

一 脚本编写规范

  • 1、脚本存放目录需要统一
  • 2、shell脚本的结尾以.sh
  • 3、脚本开头要有解释器如#!/bin/bash 或者 #!/usr/bin/env bash
  • 4、脚本开头注意加时间、作者、联系邮箱、脚本作用等信息
    # Author egon 2020-8-30 version 1 des:xxxxx
  • 5、关键代码应该用#号加上注释

二 代码编写好习惯

  • 1、成对的符号尽量一次性写出来,防止遗漏
    例如大括号{},中括号[],小括号(),单引号’’,双引号””,反引号``等
  • 2、括号的保留空格习惯中括号[ ]两端需要留有空格(shell脚本对空格有严格的规定,赋值语句等号两边不能有空格,而字符串比较,等号两边必须有空格,整数比较中括号两边也必须要有空格),不然会报错。书写时即可留出空格然后书写内容。如果不知道大括号{},中括号[],小括号(),到底哪种括号需要两端留空格,可以在书写这些括号的时候两端都保留空格来进行书写,这样可以有效避免因空格导致的各种错误。
  • 3、流程控制语句一次性书写完再添加内容
    例1:if语句格式一次书写完成

    if 条件内容
    then
    条件成立后执行的代码
    fi
  • 例2:for循环格式一次书写完成

    for条件内容
    do
    条件成立后执行的代码
    done
    提示:while、until、case等语句也是一样
  • 4、代码缩进提高可读性