一编程基础
1程序编程风格
程序:指令+数据
程序编程风格:
(1)过程式:以指令为中心,数据服务于指令。
程序员把主要的精力集中在程序指令上,一步步怎么做的。比如C、C++符合人类处理事情的逻辑关系的,不过这适合简单的事情。
对于大型的应用程序的开发这种方法是非常难的,会产生混乱。
(2)对象式:以数据为中心,指令服务于数据。
通过指令处理数据,得到我们关心的结果,程序最重要的功能是在处理数据上。
对于大型的事是采用这种方法。比如盖大楼要雇用一些团队,把大的工作分解成小的工作。设计图纸有专门的设计院来完成,搬砖要有专门的工人。
对于大的项目来说不太关注每个流程了。更多的考虑把任务分包给具体的人,每个团队做自己的事,做完就好,不关心做事的方式。
就像有句话叫做只要白猫黑猫能抓住老鼠的就是好猫。
大项目使用的是面向对象,而小项目是面向过程。我们现在编脚本还是面向过程式的。
2程序的执行方式
(1)计算机:运行二进制指令
计算机只能识别二进制。计算机真的要运行一个程序,要把人类能够理解的东西转化成二进制。
(2)编程语言:
1低级:汇编
汇编语言也是字符串,和机器语言是一一对应的,要把汇编语言转化成机器码进行分析。
2高级:
<1>编译
<1>编译:高级语言-->编译器-->目标代码 比如java,C#
编译型的语言要转化成二进制的内容才会执行,需要有编译器生成二进制的东西。
比如ls命令是一个二进制的东西,是编译完了的最终结果。
我们看里面的东西是乱码的。
[root@centos73 ~]# cat /bin/ls
<2>解释
<2>解释:高级语言-->解释器-->机器代码 比如shell, perl, python
对于解释型语言,在运行的时候,系统后台有一个解释器,自动把文字的东西解释成机器代码。
虽然也是转换成二进制的,但是是放在内存中的,不需要生成文件。
所以感觉好像就是一个文本在运行。
而shell里面的解释器有很多,比如bash shell。
shell程序就是把我们所学的命令按照逻辑关系写到文本中。提供了编程能力,翻译成机器码解释执行。
编译是要人工去做,而解释是系统自动完成的,所以在代码出现问题需要修改编译更麻烦。
Java,C语言事先要进行编译一下,变成了看不懂的二进制的文档,而不是解释执行。
3编程基本概念——编程逻辑处理方式
1顺序执行。就是指令按照顺序执行。
2循环执行。重复的执行某个指令,比如创建100个账号。
3选择执行。当满足某个条件执行一个指令,而当满足另外一个条件的时候执行另外的指令。
shell编程:过程式、解释执行
编程语言的基本结构:各种系统命令的组合,数据存储:变量、数组,表达式: a + b,语句:if。
二shell脚本基础
1shell脚本介绍
规范的shell脚本的语法要求,包含一些命令或声明,并符合一定格式的文本文件格式要求。
格式要求:首行shebang机制
#在英文里面叫做sharp,!叫做bang.#!就是shebang
第一行要告诉shell,使用的是那种shell,对于其他语言写上自己语言的类型即可。
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
2shell脚本的用途
- 自动化常用命令,做事要3次以上建议写脚本。
- 执行系统管理和故障排除
- 创建简单的应用程序
- 处理文本或文件
3shell脚本的执行原理
当执行一个命令的时候,先判断是不是别名,内部命令。如果不是就看是否是外部命令,外部命令是对应PATH变量的路径来找的。
在Linux里面,执行命令是不会寻找当前目录的
而当shell脚本运行时,它会先查找系统环境变量ENV里面的PATH路径。
该变量指定了环境文件(加载顺序一般默认是/etc/profile、.bash profile.、~/.bashrc, /etc/bashrc等),在加载了上述环境变量文件后, shell就开始执行shell脚本中的内容。
shell脚本是从上至下、从左至右依次执行每一行的命令及语句的,即执行完了一个命令后再执行下一个。
如果在shell脚本中遇到子脚本(即脚本嵌套)时,就会先执行子脚本的内容,完成后再返回父脚本继续执行父脚本内后续的命令及语句。
通常情况下,在执行shell脚本时,会向系统内核请求启动一个新的进程,以便在该进程中执行脚本的命令及子shell脚本。
基本流程如图所示:
PATH=/root/shell_scripts:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
注意第1个路径是我后来加的,为了执行方便
[root@centos733 ~]# env XDG_SESSION_ID=1 HOSTNAME=centos733.huawei.com SELINUX_ROLE_REQUESTED= TERM=xterm SHELL=/bin/bash HISTSIZE=1000 SSH_CLIENT=192.168.137.34 58583 22 SELINUX_USE_CURRENT_RANGE= SSH_TTY=/dev/pts/0 USER=root LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36: MAIL=/var/spool/mail/root PATH=/root/shell_scripts:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin PWD=/root |/usr/bin/lesspipe.sh %s XDG_RUNTIME_DIR=/run/user/0 _=/usr/bin/env
4创建shell脚本的步骤
第一步:使用文本编辑器,比如常见的vim来创建文本文件。
第一行必须包括shell声明序列#!/bin/bash
添加注释,注释以#开头
第二步:运行脚本,给予执行权限,在命令行上指定脚本的绝对或相对路径。直接运行解释器,将脚本作为解释器程序的参数运行。
由于系统默认的是使用bash,所以可以省略不写,但是把脚本拷到其他的机器上,不一定使用的是这个bash。为了避免产生BUG建议都要写。
为了让程序更易于维护,要加注释,包括作者,版本号,功能等等。
注意shell本身是开源的,没法加密的。
5shell脚本规范
脚本代码开头约定
1、第一行一般为调用使用的语言
2、程序名,避免更改文件名为无法找到正确的文件
3、版本号
4、更改后时间
5、作者相关信息
6、该程序的作用,及注意事项
7、最后是各版本的更新简要说明
6shell脚本的基本结构
第一行 #!SHEBANG
变量 CONFIGURATION VARIABLES
函数 FUNCTION DEFINITIONS
主要代码 MAIN CODE
7shell脚本执行的方式
Shell脚本的执行通常可以采用以下几种方式
1 bash script-name或sh script-name
这是当脚本文件本身没有可执行权限(即文件权限属性x位为-号)时常使用的方法,或者脚本文件开头没有指定解释器时需要使用的方法。
推荐使用这种方法
2 path/script-name或/script-name
在当前路径下执行脚本(脚本需要有执行权限),需要将脚本文件的权限先改为可执行(即文件权限属性加x位),
具体方法为chmod +x script-name,然后通过脚本绝对路径或相对路径就可以直接执行脚本了。
在企业生产环境中,不少运维人员在写完Shell脚本之后,由于忘记为该脚本设置执行权限,然后就直接应用了,结果导致脚本没有按照自己的意愿手动或定时执行,
对于这一点,避免出现该问题的方法就是用第1种方法替代第2种。
3 source script-name或. script-name
这种方法通常是使用source或"." (点号)读入或加载指定的Shell脚本文件(如san.sh),然后,依次执行指定的Shell脚本文件san.sh中的所有语句。
这些语句将在当前父Shell脚本father.sh进程中运行(其他几种模式都会启动新的进程执行子脚本)。
因此,使用source或“."可以将san.sh自身脚本中的变量值或函数等的返回值传递到当前父Shell脚本father.sh中使用。
这是它和其他几种方法最大的区别。
source或“."命令的功能是:在当前Shell中执行source或“."加载并执行的相关脚本文件中的命令及语句,而不是产生一个子Shell来执行文件中的命令。
注意"."和后面的脚本名之间要有空格。
source或"."相当于PHP开发的include的功能。HTTP服务软件Apache,Nginx等配置文件里都支持这样的用法。
4 sh<script-name或cat scripts-namelsh
同样适用于bash,不过不常见
不用循环语句来实现精简开机自启动服务就是通过将所有字符串拼接为命令的形式,然后经由管道交给bash操作
注意不写路径直接执行脚本,那么就把脚本放到PATH变量里面的路径去,即使是在其他的路径也可以执行。
[root@centos733 shell_scripts]# pwd /root/shell_scripts [root@centos733 shell_scripts]# echo $PATH /root/shell_scripts:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
运行第1个脚本
注意最后找一个集中的目录来存放自己写的脚本,便于查看和备份
#!/bin/bash # Filename: hel1o.sh # Revision: 1.1 # Date: 2018/06/01 #Author: wangm # Description: This is the first script echo "hello world"
1 bash script-name或sh script-name
脚本是在 shell_scripts目录下写的,但是是在root目录下执行
[root@centos733 ~]# ll shell_scripts/ -d drwxr-xr-x. 3 root root 4096 Mar 14 21:50 shell_scripts/ [root@centos733 ~]# ll shell_scripts/hello.sh -rw-r--r--. 1 root root 161 Mar 14 21:50 shell_scripts/hello.sh [root@centos733 ~]# bash hello.sh hello world [root@centos733 ~]# cat shell_scripts/hello.sh #!/bin/bash #Author=wang # Filename: hel1o.sh # Revision: 1.1 # Date: 2018/06/01 #Author: wangm # Description: This is the first script echo "hello world"
2 path/script-name或/script-name
[root@centos733 ~]# ./shell_scripts/hello.sh -bash: ./shell_scripts/hello.sh: Permission denied [root@centos733 ~]# cd shell_scripts/ [root@centos733 shell_scripts]# pwd /root/shell_scripts [root@centos733 shell_scripts]# ./hello.sh -bash: ./hello.sh: Permission denied [root@centos733 shell_scripts]# ll hello.sh -rw-r--r--. 1 root root 161 Mar 14 21:50 hello.sh [root@centos733 shell_scripts]# chmod +x hello.sh [root@centos733 shell_scripts]# ./hello.sh hello world [root@centos733 shell_scripts]# cd [root@centos733 ~]# ./shell_scripts/hello.sh hello world [root@centos733 ~]# ./shell_scripts/hello.sh hello world [root@centos733 ~]# ll shell_scripts/hello.sh -rwxr-xr-x. 1 root root 161 Mar 14 21:50 shell_scripts/hello.sh
3 source script-name或. script-name
和法1一样不需要加执行权限也可以执行
[root@centos733 ~]# . shell_scripts/hello.sh hello world [root@centos733 ~]# source shell_scripts/hello.sh hello world [root@centos733 ~]# chmod -x shell_scripts/hello.sh [root@centos733 ~]# ll shell_scripts/hello.sh -rw-r--r--. 1 root root 161 Mar 14 21:50 shell_scripts/hello.sh [root@centos733 ~]# . shell_scripts/hello.sh hello world [root@centos733 ~]# source shell_scripts/hello.sh hello world
8脚本语法检测和调试
1脚本语法检测
bash -n /path/to/some_script
检测脚本中的语法错误。注意bash -n对于语法错误是可以查出来的,但是对于命令写错是不能查出来的。
2 调试执行
bash -x /path/to/some_script
编写关于显示操作系统各种信息的脚本
[root@centos733 shell_scripts]# cat OS.sh #!/bin/bash #Description: show system info echo "The host is `hostname`" echo "The kernel version is `uname -r`" echo "The CPU is `lscpu | grep "Model name:" | tr -s ' ' | cut -d : -f2`" cat /proc/meminfo | head -n1 echo "The IP is `ifconfig ens33 | grep netmask | tr -s ' ' | cut -d " " -f3`"
1脚本语法检测
[root@centos733 shell_scripts]# pwd /root/shell_scripts [root@centos733 shell_scripts]# bash -n OS.sh
2 调试执行
跟踪每一步的执行结果。可以看出命令是分解执行的,同一行也是这样。
命令嵌套,所以看到是先执行里面的hostname,然后执行外面的echo
[root@centos733 shell_scripts]# bash -x OS.sh ++ hostname + echo 'The host is centos733.huawei.com' The host is centos733.huawei.com ++ uname -r + echo 'The kernel version is 3.10.0-862.el7.x86_64' The kernel version is 3.10.0-862.el7.x86_64 ++ lscpu ++ grep 'Model name:' ++ tr -s ' ' ++ cut -d : -f2 + echo 'The CPU is Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz' The CPU is Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz + cat /proc/meminfo + head -n1 MemTotal: 997980 kB ++ grep netmask ++ cut -d ' ' -f3 ++ tr -s ' ' ++ ifconfig ens33 + echo 'The IP is 192.168.137.73' The IP is 192.168.137.73
因为hostname是一个命令,我们用echo调用他是要加上反引号,为了看起来更清晰,使用单引号引起来。
显示内核版本的命令是uname -r
显示一下CPU的型号
[root@centos73 ~]# lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 1 On-line CPU(s) list: 0 Thread(s) per core: 1 Core(s) per socket: 1 Socket(s): 1 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 142 Model name: Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz
查看内存,使用命令free
显示当前系统的地址,调用命令是要在命令的左右两边加上反单引号。
[root@centos73 ~]# free -h -h, --human show human-readable output total used free shared buff/cache available Mem: 992M 169M 82M 13M 739M 623M Swap: 3.0G 520K 3.0G
[root@centos73 ~]# cat /proc/meminfo MemTotal: 1015828 kB MemFree: 84564 kB MemAvailable: 638036 kB Buffers: 36 kB Cached: 656816 kB SwapCached: 216 kB Active: 333592 kB