shell编程_第一篇_基础

 

shell基础

一 编程与编程语言

Shell是一门编程语言,作为学习shell的开始,需要事先搞明白:编程的目的是什么?什么是编程语言?什么是编程?

  1、编程的目的:

    计算机的发明,是为了用机器取代/解放人力,而编程的目的则是将人类的思想流程按照某种能够被计算机识别的表达方式传递给计算机,从而达到让计算机能够像人脑/电脑一样自动执行的效果。    

 

 

  2、什么是编程语言?

    上面提及的能够被计算机所识别的表达方式即编程语言,语言是沟通的介质,而编程语言是程序员与计算机沟通的介质。在编程的世界里,计算机更像是人的奴隶,人类编程的目的就命令奴隶去工作。

 

 

  3、什么是编程?

    编程即程序员根据需求把自己的思想流程按照某种编程语言的语法风格编写下来,产出的结果就是包含一堆字符的文件。​

    强调:程序在未运行前跟普通文件无异,只有程序在运行时,文件内所写的字符才有特定的语法意义   

 

 

  4、什么是程序

     编程的结果就是程序,更准确点说,程序就是一系列代码文件

 

 

  5、什么是进程

     程序运行的过程就是进程,或者说是操作系统干活的过程,即操作系统拿着硬件去运行程序的过程

 

 

  6、编程的步骤?

    1、先把自己想让计算机做事的步骤想清楚
    2、再用一种计算机可以听懂的语言把做事的步骤翻译下来

 

  7、所以我有话对大家说

  shell是语言,而学习语言的套路都是一样的,以英语学习为例,你需要学单词,然后学语法,最后写作文。
     英语的单词---------->shell中的关键字
     英语的语法---------->shell的语法
     英语的作文---------->用shell语言写的程序
​
     此时你心里应该有数了,学shell其实很简单,全都是在记忆一些固定的套路而已,那为何有的人会觉得shell难呢?来看一个普遍的问题,问题中包含答案。。。。。。
​
​

二 编程语言分类

  1、编程的语言的发展经历了

     # 机器语言:站在计算机(奴隶)的角度,说计算机能听懂的语言,那就是直接用二进制编程,直接操作硬件;
     #         优点:执行效率最高
     #         缺点:1、二进制指令难以记忆,开发时极容易出错
     #             2、开发程序的复杂度高:即便是完成一个简单的功能,需要用到的二进制指令的条数都会非常多
​
    # 汇编语言:站在计算机(奴隶)的角度,简写的英文标识符取代二进制指令去编写程序,本质仍然是直接操作硬件;
     #         优点:解决了机器语言的二进制指令难以记忆的问题,执行效率还是高
    #         缺点:开发程序的复杂度依然很高:因为汇编语言就是用英文标签对应原来的二进制指令,好记归好记,开发
    #             的复杂度却没有降低
​
  ps:因为上述两类语言都是在直接与计算机硬件打交道,离计算机硬件比较近,所以又统称为低级语言
​
     # 高级语言:站在人(奴隶主)的角度,说人话,即用人类的字符去编写程序,屏蔽了硬件操作
     #         优点:开发复杂度地,即开发效率高
     #         缺点:速度肯定是不如低级语言,一直到今天,对速度要求极高的场景还会用到低级语言,比如操作系统的
    #             调度程序

  2、高级语言更贴近人类语言,因而造成了:它必须被翻译成计算机能读懂二进制后,才能被执行,按照翻译方式分为

    # 1. 编译型(需要编译器,相当于用谷歌翻译):如C,执行速度快,调试麻烦
​
    # 2. 解释型(需要解释器,相当于同声传译):如python,执行速度慢,调试方便

 

三 计算机完整体系结构图

       了解玩编程语言后,我们得知我们使用编程语言的目的在于与计算机对话,准确地说是命令计算机帮我们做事情,但编程语言又分类很多种,不同种类有不同的特点和难度,这对于学习者有不同的要求,比如对机器语言,要求学习者必须具备非常深厚的计算机硬件知识才可以使用它编写程序,一般等级比较低的人是没办法学会机器语言的!但我们大家伙虽然比较low,但我们也都想用一下计算机硬件,家里摆着一台机器能够帮我们做事情,就跟家里养了一个奴隶一样,谁不想呢?

所以,为了方便不同的人群都能够操作计算机硬件,有了一层一层封装的概念,如下图所示

 

 

 

 

四 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

通常用户登录成功后执行的shell程序为:/bin/bash

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

 

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

 

 

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 软件)等。

五 第一个shell程序

5.1 编写shell程序的两种环境

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

# 1、交互式环境
调试方便,无法永久保存代码
​
​
# 2、写到文件中
我们采用解释型语言编写的代码文件通常都会被称之为脚本程序(使用nodpad++演示):可以永久保存代码

5.2 编写shell脚本程序

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

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

 

  [root@xiaowu ~]# vim 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!");
​
}

5.3 运行shell脚本程序

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

  • 方式一:绝对路径,此时采用的是文件头指定的解释器来解释执行文件内代码

    # 权限:
    # 1、对沿途文件夹有x权限
    # 2、对目标文件有r和x权限
    ​
    # 例
    [root@xiaowu ~]# ll -d /a
    d--------x. 3 root root 15 11月 15 11:05 /a
    [root@xiaowu ~]# ll -d /a/b
    d--------x. 2 root root 18 11月 15 11:06 /a/b
    [root@xiaowu ~]# ll /a/b/hello.sh
    -rw-r--r-x. 1 root root 10 11月 15 11:06 /a/b/hello.sh
    [root@xiaowu ~]# su - xiaowu
    [xiaowu@xiaowu ~]$ /a/b/hello.sh
    hello world!

  • 方式二:相对路径,需要加./作为前缀,此时采用的仍是文件头指定的解释器来解释执行文件内代码

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

    # 权限:
    # 1、对沿途文件夹有x权限
    # 2、对目标文件有r权限即可
    因为我们执行的是解释器,当前用户对解释有执行权限就可以了,这个权限默认就有,而解释器需要读文件内容来执行,所以需要对目标文件有r权限
    ​
    # 例
    [root@xiaowu ~]# chmod -R o=x /a
    [root@xiaowu ~]# chmod o=r /a/b/hello.sh
    [root@xiaowu ~]# su - egon
    [xiaowu@xiaowu ~]$ cd /a
    [xiaowu@xiaowu /a]$ bash b/hello.sh
    hello world!

  • 方式四:上述三种方式都是在子shell进程中执行程序,而方式四则是在当前shell进程中执行

    # 权限:
    # 1、对沿途文件夹有x权限
    # 2、对目标文件有r权限即可
    ​
    上述三种方式都是在当前shell环境下开启了一个新的shell解释器环境/子shell来执行程序,脚本程序在子shell中运行完毕后,子shell环境随即关闭,然后返回到父级shell即当前shell环境中,如果就想在当前shell环境中执行,需要这么做
    # 例如
    [xiaowu@localhost shell]$ cd /home/egon/shell/
    [xiaowu@localhost shell]$ ll hello.sh # 当前用户xiaowu对该文件没有执行权限
    -rw-r--r--. 1 root root 60 8月  14 18:33 hello.sh
       
    # 下面两种方式都一样
    [root@xiaowu ~]# chmod -R o=x /a
    [root@xiaowu ~]# chmod o=r /a/b/hello.sh
    [root@xiaowu ~]# su - egon
    [xiaowu@xiaowu ~]$ . /a/b/hello.sh  # . 后跟空格,然后再跟绝对路径
    hello world!
    [xiaowu@xiaowu ~]$ cd /a/b/
    [xiaowu@xiaowu /a/b/a/b]$ . hello.sh # . 后跟空格,然后再跟相对路径
    hello world!
    [xiaowu@xiaowu /a/b/a/b]$ source hello.sh  # 跟上述方式一样
    hello world!

    在当前shell解释器进程中执行脚本与在子shell进程中执行脚本的区别在于作用域,后续我们会详细介绍

    # 一个shell环境就是一个单独的全局作用域,不同的shell环境,无法访问彼此shell环境中的变量
    [root@xiaowu ~]# su - egon
    [xiaowu@localhost ~]$ x=111
    [xiaowu@localhost ~]$ cat /a/b/hello.sh
    #!/bin/bash
    ​
    echo "hello world!"  
    echo $x  # 我们在这里访问一下全局变量x
    ​
    [xiaowu@localhost ~]$ source /a/b/hello.sh  # 在当前shell环境执行,可以访问到x
    hello world!
    111         # 取到了x的值
    [xiaowu@localhost ~]$ bash /a/b/hello.sh  # 在子shell环境执行,不能访问到x
    hello world!
               # 此处打印空

5.3 调试shell程序

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

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

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

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

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

[root@xiaowu 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

5.4 注释是代码之母

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

  • 1、注释掉暂时不想运行的代码

  • 2、为关键代码添加注解说明,增强程序的可读性和可维护性

    1. 可以加在被注释代码的正上方单独一行,或者被注释代码的正后方,例如
    # 注释。。。
    echo "hello"  # 注释。。。
    ​
    2. 不用全部加注释,只需要在自己觉得重要或不好理解的部分加注释即可
    ​
    3. 注释可以用中文或英文,但不要用拼音

六 shell编写规范与建议

一 脚本编写规范

  • 1、脚本存放目录需要统一

  • 2、shell脚本的结尾以.sh

  • 3、脚本开头要有解释器如#!/bin/bash 或者 #!/usr/bin/env bash

  • 4、脚本开头注意加时间、作者、联系邮箱、脚本作用等信息

    使用vimrc文件,可以快速的生成我们所需注释信息。

    配置vimrc步骤:
    挑选心仪模板文件(文章最后添加上了)
    上传模板文件到~目录下(cd ~ 拖拽文件到shell)
    修改模板注释信息(vim .vimrc)
    call setline(5, "# Author: oldboy")
    call setline(6, "# Organization: www.oldboyedu.com")
    重新加载环境变量生效配置(断开shell连接 重新连接)

    验证生效(任意编辑一个***.sh文件,查看开头有无注释信息)
 

    [root@xiaowu ~]# vim 123r21g4gh.sh
    #!/bin/bash
    ##############################################################
    # File Name: 123r21g4gh.sh
    # Version: V1.0
    # Author: xiaowu
    # Organization: https://www.cnblogs.com/pmstaw/
    ##############################################################

  • 5、关键代码应该用#号加上注释

二 代码编写好习惯

  • 1、成对的符号尽量一次性写出来,防止遗漏

    例如大括号{},中括号[],小括号(),单引号’’,双引号””,反引号``等
  • 2、括号的保留空格习惯

    中括号[ ]两端需要留有空格,不然会报错。书写时即可留出空格然后书写内容。
    如果不知道大括号{},中括号[],小括号(),到底哪种括号需要两端留空格,可以在书写这些括号的时候两端都保留空格来进行书写,这样可以有效避免因空格导致的各种错误。
  • 3、流程控制语句一次性书写完再添加内容

    例1:if语句格式一次书写完成
    ​
    if 条件内容
    then
     条件成立后执行的代码
    fi

    ​
    例2:for循环格式一次书写完成
    ​
    for条件内容
      do
        条件成立后执行的代码
      done
    提示:while、until、case等语句也是一样
  • 4、代码缩进提高可读性

  • 5、 常用脚本执行方法:sh source

      sh 与 source 执行脚本的区别

      sh 新建一个子shell执行脚本
      source 在当前shell执行脚本

 

面试题:已知:test.sh脚本内容(如下所示),请问在用sh执行脚本后echo $a返回结果是___空___?
#!/bin/bash
a=1
echo $a

 

 

 

 

 

vimrc内容

[root@xiaowu ~]# cat .vimrc
set nocompatible
set history=100
filetype on
filetype plugin on
filetype indent on
set autoread
set mouse=c
syntax enable
set cursorline
hi cursorline guibg=#00ff00
hi CursorColumn guibg=#00ff00
set foldenable
set foldmethod=manual
set foldcolumn=0
setlocal foldlevel=3
set foldclose=all
nnoremap <space> @=((foldclosed(line('.')) < 0) ? 'zc' : 'zo')<CR>
set expandtab
set tabstop=4
set shiftwidth=4
set softtabstop=4
set smarttab
set ai
set si
set wrap
set sw=4
set wildmenu
set ruler
set cmdheight=1
set lz
set backspace=eol,start,indent
set whichwrap+=<,>,h,l
set magic
set noerrorbells
set novisualbell
set showmatch
set mat=4
set hlsearch
set ignorecase
set encoding=utf-8
set fileencodings=utf-8
set termencoding=utf-8
set smartindent
set cin
set showmatch
set guioptions-=T
set guioptions-=m
set vb t_vb=
set laststatus=4
set pastetoggle=<F9>
set background=dark
highlight Search ctermbg=black ctermfg=white guifg=white guibg=black
autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()"
func SetTitle()
if expand("%:e") == 'sh'
call setline(1, "#!/bin/bash")
call setline(2, "##############################################################")
call setline(3, "# File Name: ".expand("%"))
call setline(4, "# Version: V1.0")
call setline(5, "# Author: xiaowu")
call setline(6, "# Organization: https://www.cnblogs.com/pmstaw/")
call setline(7, "##############################################################")
endif
endfunc

 

posted @ 2021-01-11 10:24  啵啾の园子  阅读(161)  评论(0)    收藏  举报