Linux之Shell脚本自动化编程一(shell脚本的用处和不同语言的代码的执行方式)

前面已经有了一些linux的基础知识,但是shell脚本这里我们还是缺失的,那么这个系列就来补上这一块。废话不多说,开始学习shell编程吧。

先来学shell脚本能干什么?

shell scripts 的用处

 

这里面需要了解的:

 

 

 

 

 

 

 

 

 

通常的代理服务器,只用于代理内部网络对Internet的连接请求,客户机必须指定代理服务器,并将本来要直接发送到Web服务器上的http请求发送到代理服务器中。由于外部网络上的主机并不会配置并使用这个代理服务器,普通代理服务器也被设计为在Internet上搜寻多个不确定的服务器,而不是针对Internet上多个客户机的请求访问某一个固定的服务器,因此普通的Web代理服务器不支持外部对内部网络的访问请求。当一个代理服务器能够代理外部网络上的主机,访问内部网络时,这种代理服务的方式称为反向代理服务。此时代理服务器对外就表现为一个Web服务器,外部网络就可以简单把它当作一个标准的Web服务器而不需要特定的配置。不同之处在于,这个服务器没有保存任何网页的真实数据,所有的静态网页或者CGI程序,都保存在内部的Web服务器上。因此对反向代理服务器的攻击并不会使得网页信息遭到破坏,这样就增强了Web服务器的安全性。反向代理方式和包过滤方式或普通代理方式并无冲突,因此可以在防火墙设备中同时使用这两种方式,其中反向代理用于外部网络访问内部网络时使用,正向代理或包过滤方式用于拒绝其他外部访问方式并提供内部网络对外部网络的访问能力。因此可以结合这些方式提供最佳的安全访问方式。

下面是kvm管理一个shell脚本运行的例子:

 

LVSLinux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统。

PV(page view)即页面浏览量,通常是衡量一个网络新闻频道或网站甚至一条网络新闻的主要指标。网页浏览数是评价网站流量最常用的指标之一,简称为PV。监测网站PV的变化趋势和分析其变化原因是很多站长定期要做的工作。 Page Views中的Page一般是指普通的html网页,也包含php、jsp等动态产生的html内容。来自浏览器的一次html内容请求会被看作一个PV,逐渐累计成为PV总数。

 

网络地址转换(NAT,Network Address Translation)属接入广域网(WAN)技术,是一种将私有(保留)地址转化为合法IP地址的转换技术,它被广泛应用于各种类型Internet接入方式和各种类型的网络中。原因很简单,NAT不仅完美地解决了lP地址不足的问题,而且还能够有效地避免来自网络外部的攻击,隐藏并保护网络内部的计算机。基本网络地址转换(Basic NAT)是一种将一组 IP地址映射到另一组 IP 地址的技术,这对终端用户来说是透明的。网络地址端口转换(NAPT)是一种将群体网络地址及其对应 TCP/UDP 端口翻译成单个网络地址及其对应TCP/UDP端口的方法。这两种操作,即传统 NAT 提供了一种机制,将只有私有地址的内部领域连接到有全球唯一注册地址的外部领域。

 

 

 

亚马逊弹性计算云(EC2,Elastic Compute Cloud)是一个让使用者可以租用云端电脑运行所需应用的系统。EC2借由提供Web服务的方式让使用者可以弹性地运行自己的Amazon机器映像档,使用者将可以在这个虚拟机器上运行任何自己想要的软件或应用程式。提供可调整的云计算能力。它旨在使开发者的网络规模计算变得更为容易。

阿里的云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。

不同语言的代码的执行方式

以前就讲过,我们用的那个黑乎乎的shell叫做bash shell,里面执行bash脚本没有问题,但是很多时候我们可能有其它编程语言的需求,比如python等,这时候我们安装一个python的解释器,也是可以在bash shell里面执行python的脚本的,不过需要指定解释器,而bash脚本不需要指定解释器,因为本身就是在bash shell里面。

bash shell脚本的执行方式

bash脚本也是一门语言了。在bash shell里bash脚本我总结了以下几种执行方式:

第一种,用bash或者sh直接指定解释器执行。

我先来解释以下我后面命令的意思。ping -c1 baidu.com && echo the url is up || echo the url is down

-c1是ping一次的意思,不指定次数会无限ping,除非用ctrl+c打断。&&就是逻辑与的意思,在c语言,MATLAB里都是这意思,||就是逻辑或了。首先要说明一件事,bash shell里每一个命令都是会有返回值的,如果命令执行过程种没有问题,则返回0,否则,返回非0值。我们是用echo $?来获取上一条命令的返回值并打印出来的。

 

date执行没有任何问题,返回值是0,ping一次百度也没有问题,返回值也是0。接着我们ping了一个乱七八糟的域名,DNS一看应该是没有解析的结果(因为是0 received,没有数据返回),这时候我们这条命令的结果是1,注意这里并不是ping -c1这个命令本身打错了,这个命令还是执行了的,要不然我们也看不到ping的过程,而是你输入的域名有问题,最后导致这个命令执行的结果可以说不是预期的吧,那么返回值也不是0。然后我们ls一个不存在的文件,结果返回值是2,然后输入一个根本不存在的命令,返回值是127,由此可见,其实命令的返回值是和命令执行过程中出问题的种类其实也是有关系的,不同的种类会有不同的返回值,不过我们现在只需要知道它们这些命令执行结果出问题的返回值都是非0的。

 

&&在上面代码中的意思是如果前面的命令执行过程中没有什么问题,那么就执行后面的命令,如果有问题,就执行||后的命令。所以ping -c1 baidu.com && echo the url is up || echo the url is down的意思就是如果ping baidu.com一次并且成功了,那么就打印the url is up,如果不成功就打印the url is down。不过我其实我还有一种理解方式,不过正好是把&&和||的含义反过来了。我的理解是基于逻辑短路,学过c语言的都应该知道什么叫逻辑短路,我还是简单再说一遍,就是a && b,a的值或者返回值是0的话,b就不会执行,因为任何数和0与都是0,这个表达式的结果已经确定了,这在数字电路中其实也叫与门被锁上了,如果a的值或者返回值非0,那么b可以执行以确定整个表达式的值。那么a || b的话,正好相反,如果a的值或者返回值是1,那么b就不会执行,因为1和任何数或都是1,反之,b会被执行以确定表达式的值。上面的解释是基于c语言的,但是在bash shell里,&&和||的含义似乎反过来了。看下面的图中的例子,lklklkl这个命令是没有的,返回值是127,按理说 相与的话echo 0应该被执行的,但是却没有。而相或的时候,echo 0被执行了,echo $?也是0,echo $?返回的是上一条被执行的命令的返回值而不是代码的,它只针对命令,因为上一条执行的命令是echo 0。

 

date && dsadasdasdasd,date的返回值是0,那么后面应该不会被执行才对,但是事实就是正好相反。如果把&&和||的c语言含义反过来,ping -c1 baidu.com && echo the url is up || echo the url is down我的理解是,ping百度一次成功的话,打印the url is up,而且因为前面

ping -c1 baidu.com && echo the url is up的结果已经是0了,||又是逻辑与,后面的自然不会被执行。而ping百度没有成功的话,返回值是1,或就会造成逻辑短路,前面ping -c1 baidu.com && echo the url is up的结果就是1,然后与不会短路,后面打印the url is down的还会执行。

用上面我的理论再来解释下面的例子。

 

ping百度是没有问题的,返回0,或没有短路,执行后面的e the url is up,这个命令不存在,返回值是非0,前面综合一下返回值是非0(非0就是二进制正逻辑的1),然后与没有短路,执行打印the url is down。看到的结果也正是如此,ping的过程下面是e的报错信息,然后最后的down也打印了,最后执行的命令是打印down的,返回值0。然后ping这个不存在的域名,返回值是非0,或造成逻辑短路,并没有e的报错信息,前面综合一下是1,与没有导致短路,后面还是打印了down。我觉得我的理解更好一点,但是缺点就是需要把&&是看成逻辑或,||看成逻辑与,和其它编程语言规定的不一样,有点奇葩。

 

 

下面正式来看bash脚本的第一种执行方式(说明一点,一般我们命名脚本的时候还是要规范一点比较好,bash脚本后面加上.sh,当然可以不加,不过这算是一种规范):

 

b是没有执行权限的,但是我们仍然可以通过人工执行解释器来执行,怎么指定呢?bash和sh都行。其实sh最后还是指向了bash。

 

这种方式没有执行权限的,直接输入绝对路径是没有办法执行的。

第二种方式,给脚本加执行权限执行。由于就是在bash shell里,执行bash脚本是可以不指定解释器的,自动会用bash解释器。

 

这次输入从根开始的完整路径就可以了。./b就相当于/root/b这个绝对路径。直接输相对路径b还是不行。

 

当然我们不想在终端上显示ping的过程只想要结果的话也可以,用混合输出重定向把ping的输出输出到/dev/null。其实解释器还可以在脚本第一行指定。格式其实我们以前见过的#!加解释器路径。#!这个东西官方的叫法叫做shebang。不过这种也需要文件有执行权限。

 

即使bash脚本第一行指定了用python解释,./b最后还是用了bash解析,因为优先使用在命令行中的解释器,后面还有这样的例子。

 

指定python解释器就会报错了。

第三种是直接执行,具体实现方式就是把脚本放到环境变量里面。那么就明显有两种想法了,一种是把当前目录加到环境变量里面,但是不建议修改环境变量,不过可以看看https://www.cnblogs.com/aaronLinux/p/5837702.html;另一种想法就是把脚本加到环境变量里面。

 

我们直接输脚本的名字就可以执行脚本。虽然这个脚本只有一行,我们在手动打也可以,但是如果我是一个数据库备份的很长的脚本呢?每天3点增量备份数据库一次(全量备份是备份所有,增量只备份前一次备份过后增加的数据),而且代码很长,你作为程序员会每天3点去打一段很长的代码?我们把它写成脚本做成计划任务多方便啊。

python脚本执行方式

第一种还是在输命令时直接加上解释器,也是不需要文件有执行权限的。不过解释器一定要是python。

 

第二种也是给文件加执行权限,不过对于python脚本,还必须做的是要在脚本第一行指定解释器,因为是在bash shell下嘛。

 

只有写在第一行的解释器才有用,而且命令指定的解释器优先级高于脚本。

 

下面是一个bash脚本,还是说明解释器必须定义在第一行,如果定义在第二行,第一行是空格也不行。

 

注意对比上下图的cat b,第二次cat b第一行是空的,所以相当于没有指定解释器,所以./b就用bash shell默认的bash解释器解释。

 

 

 

这个python脚本也是,#!必须在第一行。

第三种也是移到环境变量的目录里面。

 

也是必须要执行权限的。

在学习c语言的程序执行方式之前,我们先了解有关几种常见编程语言的一些知识。首先c语言写的程序不能叫做脚本。脚本(script)是使用一种特定的描述性语言,依据一定的格式编写的可执行文件,又称作宏或批处理文件。脚本简单地说就是一条条的文字命令,这些文字命令是可以看到的(如可以用记事本打开查看、编辑),脚本程序在执行时,是由系统的一个解释器,将其一条条的翻译成机器可识别的指令,并按程序顺序执行。因为脚本在执行时多了一道翻译的过程,所以它比二进制程序执行效率要稍低一些,而用c语言写成的程序,都必须通过编译链接,生成机器能认识的二进制文件,才能运行,他不是一种解释性的语言。

 

 

 

 

 

 

上面的expect语言至少我是见得比较少的,先大概了解一下:

Expect是一个免费的编程工具语言,用来实现自动和交互式任务进行通信,而无需人的干预。Expect的作者Don Libes在1990年开始编写Expect时对Expect做有如下定义:Expect是一个用来实现自动交互功能的软件套件(Expect [is a] software suite for automating interactive tools)。使用它,系统管理员可以创建脚本来对命令或程序进行输入,而这些命令和程序是期望从终端(terminal)得到输入,一般来说这些输入都需要手工输入进行的。Expect则可以根据程序的提示模拟标准输入提供给程序需要的输入来实现交互程序执行。甚至可以实现简单的BBS聊天机器人。 :)Expect是不断发展的,随着时间的流逝,其功能越来越强大,已经成为系统管理员的的一个强大助手。Expect需要Tcl编程语言的支持,要在系统上运行Expect必须首先安装Tcl。下面来学习一下编译和解释的区别,参考了https://blog.csdn.net/sholck222/article/details/72724377。

 

所以说c语言是上面列出的几种语言里面代码量相同的情况下运行速度最快的。

 

不同的指令集的汇编语言和对应的机器码都是不一样的,x86复杂指令集是一套,arm精简指令集又是另一套,所以需要编译的语言移植性会不太好,但是会有交叉编译可以解决移植性问题。交叉编译这个概念的出现和流行是和嵌入式系统的广泛发展同步的。我们常用的计算机软件,都需要通过编译的方式,把使用高级计算机语言编写的代码(比如C代码)编译(compile)成计算机可以识别和执行的二进制代码。比如,我们在Windows平台上,可使用Visual C++开发环境,编写程序并编译成可执行程序。这种方式下,我们使用PC平台上的Windows工具开发针对Windows本身的可执行程序,这种编译过程称为native compilation,中文可理解为本机编译。然而,在进行嵌入式系统的开发时,运行程序的目标平台通常具有有限的存储空间和运算能力,比如常见的 ARM 平台,其一般的静态存储空间大概是16到32MB,而CPU的主频大概在100MHz到500MHz之间。这种情况下,在ARM平台上进行本机编译就不太可能了,这是因为一般的编译工具链(compilation tool chain)需要很大的存储空间,并需要很强的CPU运算能力。为了解决这个问题,交叉编译工具就应运而生了。通过交叉编译工具,我们就可以在CPU能力很强、存储空间足够的主机平台上(比如PC上)编译出针对其他平台的可执行程序。要进行交叉编译,我们需要在主机平台上安装对应的交叉编译工具链(cross compilation tool chain),然后用这个交叉编译工具链编译我们的源代码,最终生成可在目标平台上运行的代码。常见的交叉编译例子如下:

1、在Windows PC上,利用ADS(ARM 开发环境),使用armcc编译器,则可编译出针对ARM CPU的可执行代码。

2、在Linux PC上,利用arm-linux-gcc编译器,可编译出针对Linux ARM平台的可执行代码。

3、在Windows PC上,利用cygwin环境,运行arm-elf-gcc编译器,可编译出针对ARM CPU的可执行代码。

 

编译是把一个程序文件.c或者.cpp里面的所有代码全部一次性变成二进制,逻辑关系已经包含在二进制里面了,cpu就拿来就用就行了,不需要思考,速度也会很快,而解释是在这句执行的时候才开始转化为机器码,开始去分析逻辑关系,速度会比较慢。解释器的动态性会很好,因为改一个东西不是牵一发而动全身,它本身就是一句一句解释的,而c程序改一个地方就要重新编译一次才行。

 

 

 

java虚拟机,java编译器等其它软件都被整合在一个叫做JDK的软件包里面,windows里下了这个软件包也可以编译java,执行java了。按照上面的知识,python解释执行用得比较多,但是其实它也是可以编译运行的,它也是先编译成字节码,然后由python虚拟机来执行这些字节码,这些python字节码cpu是不认识的,当然java虚拟机也不认识,特定语言的字节码必须在对应的虚拟机上才能正常运行。

 

C语言程序的执行方式

我觉得说到这里有必要来学习一下c语言编译的过程,参考了https://www.cnblogs.com/CarpenterLee/p/5994681.html

 

从c语言程序到可执行文件一共有四步,1.预处理(Preprocessing), 2.编译(Compilation), 3.汇编(Assemble), 4.链接(Linking)。

 

我们来做一个例子,首先我们得有gcc编译器,这个在linux源码包安装的时候其实已经装过了。

 

c语言宏定义不需要等号,我差点忘了。

 

 

看到1.c和1.i差的还是有点多。

 

 

 

当然后面还有好多。

这里面stdio.h里面的内容都写进来了。

 

 

 

发现有warning,我大一学的c语言,就计算机二级用了一下,后面到现在大三中间就没怎么用过c语言,忘了很多了,这里我直接去掉这一行了。

 

1.s里面确实是汇编,不过这和我学过的汇编还不太一样。

 

 

 

这个.o应该就是obj这种类型的。

 

 

 

这个里面是二进制。

 

但是上面只是为了学习编译链接的过程,真正编译链接只需要:

gcc 1.c -o 1c

这一句就都够了,

 

我们可以选择不把它输出的可执行文件放在环境变量的目录里面,用绝对路径执行,也可以放在里面,直接输名字就可以执行了。

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值