答:在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认。第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。完成三次握手,客户端与服务器开始传送数据简版:首先A向B发SYN(同步请求),然后B回复SYN+ACK(同步请求应答),最后A回复ACK确认,这样TCP的一次连接(三次握手)的过程就建立了。
这是因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。
但是关闭连接时,当Client端发送FIN报文仅仅表示它不再发送数据了但是还能接收数据,Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
HTTP–Hyper Text Transfer
Protocol,超文本传输协议,是一种建立在TCP上的无状态连接,整个基本的工作流程是客户端发送一个HTTP请求,说明客户端想要访问的资源和请求的动作,服务端收到请求之后,服务端开始处理请求,并根据请求做出相应的动作访问服务器资源,最后通过发送HTTP响应把结果返回给客户端。其中一个请求的开始到一个响应的结束称为事务,当一个事物结束后还会在服务端添加一条日志条目。
HTTP请求是客户端往服务端发送请求动作,告知服务器自己的要求。
HTTP请求由 状态行、请求头、请求 正文三部分组成:
状态行:包括请求方式Method、资源路径URL、协议版本Version;
请求头:包括一些访问的域名、用户代理、Cookie等信息;
请求正文:就是HTTP请求的数据。
备注:请求方式Method一般有GET、POST、PUT、DELETE,含义分别是获取、修改、上传、删除,其中GET方式仅仅为获取服务器资源,方式较为简单,因此在请求方式为GET的HTTP请求数据中,请求正文部分可以省略,直接将想要获取的资源添加到URL中。下图所示就是GET的请求,没有请求正文。详细的说明在下边。
现在大多数协议版本为http/1.1
下图所示为POST请求的格式,有状态行、请求头、请求正文三部分。
服务器收到了客户端发来的HTTP请求后,根据HTTP请求中的动作要求,服务端做出具体的动作,将结果回应给客户端,称为HTTP响应。
HTTP响应由三部分组成: 状态行、响应头、响应正文;
状态行:包括协议版本Version、状态码Status Code、回应短语;
响应头:包括搭建服务器的软件,发送响应的时间,回应数据的格式等信息;
响应正文:就是响应的具体数据。
备注:我们主要关心并且能够在客户端浏览器看得到的是三位数的 状态码,不同的状态码代表不同的含义,其中
1xx | 表示HTTP请求已经接受,继续处理请求 |
2xx | 表示HTTP请求已经处理完成 |
3xx | 表示把请求访问的URL重定向到其他目录 |
4xx | 表示客户端出现错误 |
5xx | 表示服务端出现错误 |
具体HTTP响应实例如下图:
200—OK/请求已经正常处理完毕
301—/请求永久重定向
302—/请求临时重定向
304—/请求被重定向到客户端本地缓存
400—/客户端请求存在语法错误
401—/客户端请求没有经过授权
403—/客户端的请求被服务器拒绝,一般为客户端没有访问权限
404—/客户端请求的URL在服务端不存在
500—/服务端永久错误
503—/服务端发生临时错误
服务器收到HTTP请求之后,会有多种方法响应这个请求,下面是HTTP响应的四种模型:
单进程I/O模型
服务端开启一个进程,一个进程仅能处理一个请求,并且对请求顺序处理;
多进程I/O模型
服务端并行开启多个进程,同样的一个进程只能处理一个请求,这样服务端就可以同时处理多个请求;
复用I/O模型
服务端开启一个进程,但是呢,同时开启多个线程,一个线程响应一个请求,同样可以达到同时处理多个请求,线程间并发执行;
复用多线程I/O模型
服务端并行开启多个进程,同时每个进程开启多个线程,这样服务端可以同时处理进程数M*每个进程的线程数N个请求。
HTTP报文是HTTP应用程序之间传输的数据块,HTTP报文分为HTTP请求报文和HTTP响应报文,但是无论哪种报文,他的整体格式是类似的,大致都是由起始、首部、主体三部分组成,起始说明报文的动作,首部说明报文的属性,主体则是报文的数据。接下来具体说明。
请求报文的起始由请求行构成(有些资料称为状态行,名字不一样而已,都是指的一个东西),用来说明该请求想要做什么,由、、 三个字段组成,注意每个字段之间都有一个空格。
其中字段有不同的值:
GET — 访问服务器的资源
POST — 向服务器发送要修改的数据
HEAD — 获取服务器文档的首部
PUT — 向服务器上传资源
DELETE— 删除服务器的资源
首部部分由多个请求头(也叫首部行)构成,那些首部字段名有如下,不全:
Accept 指定客户端能够接收的内容格式类型
Accept-Language 指定客户端能够接受的语言类型
Accept-Ecoding 指定客户端能够接受的编码类型
User-Agent 用户代理,向服务器说明自己的操作系统、浏览器等信息
Connection 是否开启持久连接(keepalive)
Host 服务器域名
…
主体部分就是报文的具体数据。
响应报文的起始由状态行构成,用来说明服务器做了什么,由、、三个字段组成,同样的每个字段之间留有空格;
首部由多个响应头(也叫首部行)组成, 首部字段名如下,不全:
Server 服务器软件名,Apache/Nginx
Date 服务器发出响应报文的时间
Last-Modified 请求资源的最后的修改时间
…
主体部分是响应报文的具体数据。
小tips:关于更多请求头和响应头(即首部字段名)的说明请参考
HTTP协议的最初版本,功能简陋,仅支持请求方式GET,并且仅能请求访问HTML格式的资源。
在0.9版本上做了进步,增加了请求方式POST和HEAD;不再局限于0.9版本的HTML格式,根据Content-Type可以支持多种数据格式,即MIME多用途互联网邮件扩展,例如text/html、image/jpeg等;同时也开始支持cache,就是当客户端在规定时间内访问统一网站,直接访问cache即可。
但是1.0版本的工作方式是每次TCP连接只能发送一个请求,当服务器响应后就会关闭这次连接,下一个请求需要再次建立TCP连接,就是不支持keepalive。
解决了1.0版本的keepalive问题,1.1版本加入了持久连接,一个TCP连接可以允许多个HTTP请求; 加入了管道机制,一个TCP连接同时允许多个请求同时发送,增加了并发性;新增了请求方式PUT、PATCH、DELETE等。
但是还存在一些问题,服务端是按队列顺序处理请求的,假如一个请求处理时间很长,则会导致后边的请求无法处理,这样就造成了队头阻塞的问题;同时HTTP是无状态的连接,因此每次请求都需要添加重复的字段,降低了带宽的利用率。
为了解决1.1版本利用率不高的问题,提出了HTTP/2.0版本。增加双工模式,即不仅客户端能够同时发送多个请求,服务端也能同时处理多个请求,解决了队头堵塞的问题;HTTP请求和响应中,状态行和请求/响应头都是些信息字段,并没有真正的数据,因此在2.0版本中将所有的信息字段建立一张表,为表中的每个字段建立索引,客户端和服务端共同使用这个表,他们之间就以索引号来表示信息字段,这样就避免了1.0旧版本的重复繁琐的字段,并以压缩的方式传输,提高利用率。
另外也增加服务器推送的功能,即不经请求服务端主动向客户端发送数据。
当前主流的协议版本还是HTTP/1.1版本。
IP IP访问量
相同的公网IP计算一次,就是同一个局域网内的所有用户访问一个网站,但是他们都是借助一个公网IP去访问那个网站的(NAT),因此这也只能算作一个IP访问量。换一次公网IP则会加1。
PV 网页访问量
用户访问的页面数就是PV访问量,同一个局域网的不同用户,而且就算是同一个用户,只要刷新一次网站页面,PV访问量就加1,三个访问量的值往往数PV的值最大。
UV 访客访问量
这里的访客不是用户,而是电脑,一台电脑算一个访客,即使是同一台电脑的不同用户,访问同一个网站UV也只能加1,只有更换电脑才会使UV加1,因为服务端会记录客户端电脑的信息。
解答:
1、在浏览器中输入www.qq.com域名,操作系统会先检查自己本地的hosts文件是否有这个网址映射关系,如果有,就先调用这个IP地址映射,完成域名解析。
2、如果hosts里没有这个域名的映射,则查找本地DNS解析器缓存,是否有这个网址映射关系,如果有,直接返回,完成域名解析。
3、如果hosts与本地DNS解析器缓存都没有相应的网址映射关系,首先会找TCP/IP参数中设置的首选DNS服务器,在此我们叫它本地DNS服务器,此服务器收到查询时,如果要查询的域名,包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性。
4、如果要查询的域名,不由本地DNS服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析,此解析不具有权威性。
5、如果本地DNS服务器本地区域文件与缓存解析都失效,则根据本地DNS服务器的设置(是否设置转发器)进行查询,如果未用转发模式,本地DNS就把请求发至13台根DNS,根DNS服务器收到请求后会判断这个域名(.com)是谁来授权管理,并会返回一个负责该顶级域名服务器的一个IP。本地DNS服务器收到IP信息后,将会联系负责.com域的这台服务器。这台负责.com域的服务器收到请求后,如果自己无法解析,它就会找一个管理.com域的下一级DNS服务器地址(qq.com)给本地DNS服务器。当本地DNS服务器收到这个地址后,就会找qq.com域服务器,重复上面的动作,进行查询,直至找到www.qq.com主机。
6、如果用的是转发模式,此DNS服务器就会把请求转发至上一级DNS服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根DNS或把转请求转至上上级,以此循环。不管是本地DNS服务器用是是转发,还是根提示,最后都是把结果返回给本地DNS服务器,由此DNS服务器再返回给客户机。
从客户端到本地DNS服务器是属于递归查询,而DNS服务器之间就是的交互查询就是迭代查询。
Apache 求职面试提问
在这一节涵盖了25个有趣的Apache工作面试中会提出的问题,并附带有它们的答案,因此你可以方便的理解也许你之前从来没有见到过的一些有关于Apache的新事物.
在你开始阅读这篇文章之前,我们强烈建议你不要去死记硬背,万事首先都要尝试去放在实际场景中理解.
答案: Apache web 服务器 HTTP 是一个非常流行、功能强大并且开源,用于管理web站点并向网络提供web文件服务. 它基于 HTTP 超文本传输协议运行, 这一协议提供了服务器和客户端web浏览器通信的标准. 它支持 SSL, CGI 文件, 虚拟主机还有许多其它的功能特性.
答案: 首先,使用rpm命令来检查Apache是否已经安装. 如果已经安装好了,那就使用httpd -v 命令来姜茶它的版本.
root@centos~]# rpm -qa | grep httpd
httpd-devel-2.2.15-29.el6.centos.i686
httpd-2.2.15-29.el6.centos.i686
httpd-tools-2.2.15-29.el6.centos.i686
[root@centos~]# httpd -v
Server version: Apache/2.2.15 (Unix)
Server built: Aug 13 2013 17:27:11
答案: Apache 以“nobody”用户和httpd守护进程运行. Apache 主要的配置文件在: /etc/httpd/conf/httpd.conf (CentOS/RHEL/Fedora) 还有 /etc/apache2.conf (Ubuntu/Debian).
答案: Apache 默认在80端口侦听http,在443端口侦听https(需要SSL整数). 你也可以使用 netstat 命令 来检查端口.
[root@centos~]# netstat -antp | grep http
tcp 0 0 :::80 :::* LISTEN 1076/httpd
tcp 0 0 :::443 :::* LISTEN 1076/httpd
答案: 很简单, 你可以使用任何诸如(RHEL/CentOS/Fedora)上的yum以及(Debian/Ubuntu)上的apt-get来在你的Linux上安装Apache服务器.
[root@centos~]# yum install httpd
[root@tecmint ~]# apt-get install apache2
答案: Apache默认的配置路径放在: (RHEL/CentOS/Fedora) 中是在 /etc/httpd/ on 而(Debian/Ubuntu) 是在/etc/apache2下 .
[root@tecmint ~]# cd /etc/httpd/
[root@tecmint httpd]# ls -l
total 8
drwxr-xr-x. 2 root root 4096 Dec 24 21:44 conf
drwxr-xr-x. 2 root root 4096 Dec 25 02:09 conf.d
lrwxrwxrwx 1 root root 19 Oct 13 19:06 logs -> ../../var/log/httpd
lrwxrwxrwx 1 root root 27 Oct 13 19:06 modules -> ../../usr/lib/httpd/modules
lrwxrwxrwx 1 root root 19 Oct 13 19:06 run -> ../../var/run/httpd
[root@tecmint ~]# cd /etc/apache2
[root@tecmint apache2]# ls -l
total 84
-rw-r--r-- 1 root root 7113 Jul 24 16:15 apache2.conf
drwxr-xr-x 2 root root 4096 Dec 16 11:48 conf-available
drwxr-xr-x 2 root root 4096 Dec 16 11:45 conf.d
drwxr-xr-x 2 root root 4096 Dec 16 11:48 conf-enabled
-rw-r--r-- 1 root root 1782 Jul 21 02:14 envvars
-rw-r--r-- 1 root root 31063 Jul 21 02:14 magic
drwxr-xr-x 2 root root 12288 Dec 16 11:48 mods-available
drwxr-xr-x 2 root root 4096 Dec 16 11:48 mods-enabled
-rw-r--r-- 1 root root 315 Jul 21 02:14 ports.conf
drwxr-xr-x 2 root root 4096 Dec 16 11:48 sites-available
drwxr-xr-x 2 root root 4096 Dec 6 00:04 sites-enabled
答案: 不可以,它不可以被TCP封装器固定下来,因为它不支持Linux的libwrap.a库.
答案: 在httpd.conf文件中有一个指令“Listen”可以让我们改变默认的Apache端口. 在Listen 指令的帮助下我们可以在不同的端口还有不同的接口进行Apache侦听.
假设你拥有多个IP注册到了你的Linux机器,并且想要Apache在一个特殊的以太网端口或接口接收HTTP请求, 即使是这种要求也可以用Listen指令做到.
为了改变Apache的默认端口,请使用打开你的Apache主配置文件 httpd.conf 或者 apache2.conf .
[root@tecmint ~]# vi /etc/httpd/conf/httpd.conf
[root@tecmint ~]# vi /etc/apache2/apache2.conf
查找”Listen”这个单词, 注释原来的那一行并且在那一行下面写上你自己的指令.
# Listen 80
Listen 8080
OR
Listen 172.16.16.1:8080
保存文件并重启web服务器.
[root@tecmint ~]# service httpd restart
[root@tecmint ~]# service apache2 restart
答案: 可以,我们在一台Linux机器上同时运行两个不同的Apache服务器, 但条件是它们应该在不同的端口上侦听,而我们可以使用Apache的Listen指令来改变端口.
答案: DocumentRoot 的 Apache 意思是服务器上web文件的存储位置, 默认的DocumentRoot是 /var/www/html 或者 /var/www. 这是可以被修改的,只要修改主机中的虚拟主机配置 “DocumentRoot”就行了.
答案: 是的,这可以借助于主Apache配置文件中的Alias指令做到. Alias 指令可以对文件系统中的资源按图索骥, 它使用一个URL 路径,并且使用重定向到系统上的一个文件或目录来替换它.
使用Alias指令,它是Apache的 mod_alias 模块的一部分. Alias指令的默认语法是:
Alias /images /var/data/images/
上面的示例中, 放在/var/data/images 前缀前面的 /images url的意思是客户端请求“http://www.example.com/images/sample-image.png” 会让Apache从服务器上的/var/data/images/sample-image.png 取 “sample-image.png” 文件. 它也被称为URL 映射.
答案 : DirectoryIndex 是当有一个来自主机的请求时Apache首先会去查找的文件. 例如: 客户端发送请求www.example.com, Apache 对此将到站点的文件根目录查找index文件 (首先要展示的文件).
DirectoryIndex 的默认设置是 .html index.html index.php, 如果不是这个名字, 你需要对 httpd.conf 或者 apache2.conf 中的 DirectoryIndex 值做出修改,以将其展示在你的客户端浏览器上.
#
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.
#
# The index.html.var file (a type-map) is used to deliver content-
# negotiated documents. The MultiViews Option can be used for the
# same purpose, but it is much slower.
#
DirectoryIndex index.html index.html.var index.cgi .exe
答案 : 如果站点根目录中的主index文件失效, 那么Apache将会在浏览器上列出所有内容类似的文件,以替换站点主页.
为了关闭Apache目录列表, 你可以在主配置文件中全局的设置,或者在.htaccess文件中部分的设置如下规则.
Options -Indexes
答案 : Apache Web 服务器的默认日志文件是访问日志 “/var/log/httpd/access_log” 和错误日志:/var/log/httpd/error_log”.
答案 : 当服务器正在向请求提供服务时终端用户中断连接, 我们就会在错误日志中看到“connection reset by peer“.
答案 : 虚拟主机部分包含的信息包括站点名称,文档根路径,目录索引,服务器管理员邮箱,错误日志文件路径等等。
你可以随意为你的域添加你需要的指令,但是要运行一个站点,至少要配置量个参数服务器名称和文档根目录。 在Linux机器上,通常我们在httpd.conf文件的末尾来设定我们的虚拟主机部分的相关配置。
虚拟主机示例
ServerAdmin [email protected]
DocumentRoot /www/docs/dummy-host.example.com
ServerName dummy-host.example.com
ErrorLog logs/dummy-host.example.com-error_log
CustomLog logs/dummy-host.example.com-access_log common
答案 :
答案 : Apache虚拟托管是指,在单个web服务器上托管多个web站点。Apache 可以设定两种类型的虚拟主机:基于名称的虚拟托管和基于IP的虚拟主机托管。
更多相关信息,请参阅 如何在Apache中创建基于Name/IP的虚拟主机。
答案 : MPM意思是Multi Processing Modules,实际上是指Apache遵循的一些机制,用来接受和完成对web服务器的请求。
答案 : 它们都是MPM, Worker 和 prefork 有它们各自在Apache上的运行机制. 它们完全依赖于你想要以哪一种模式启动你的Apache.
Worker
和 MPM基本的区别 在于它们产生子进程的处理过程. 在Prefork MPM中,
一个主httpd进行被启动,这个主进程会管理所有其它子进程为客户端请求提供服务. 而在worker
MPM中一个httpd进程被激活,则会使用不同的线程来为客户端请求提供服务.
Prefork
MPM 使用多个子进程,每一个进程带有一个线程而 worker MPM
使用多个子进程,每一个进程带有多个线程.
Prefork MPM中的连接处理,
每一个进程一次处理一个连接而在Worker mpm中每一个线程一次处理一个连接.
内存占用 Prefork MPM 占用庞大的内存, 而Worker占用更小的内存.
答案 : LimitRequestBody 指令被用来在上传大小上做一个限制.
例如: 我想要在 /var/www/html/tecmin/uploads目录中加入 100000 字节的限制. 那么你就需要在Apache配置文件中加入下面的指令.
LimitRequestBody 100000
答案:
mod_perl 是一个随同Apache一起编译的Apache模块,用来做Perl脚本的简单集成并提升其性能.
mod_php 用来做web服务器PHP脚本的简单集成, 它在Apache进程中嵌入了PHP解释器. 它强制Apache子进程使用更多的内存,并且只能在Apache上使用,但是仍然很流行.
答案: 它是一个保护你的web服务器不受像DDOS之类的web攻击的第三方模块,因为它一次只执行一个任务,所有执行得很不错.
更多信心,请阅读这篇文章, 它会指导你 如何在Apache中安装并配置mod_evasive.
答案 : 在Loglevel Debug 选项的帮助下, 我们可以在错误日志中获取或者记录更多的信息,以帮助我们调试问题.
回答: Mod_ssl 是一个Apache模块, 它使Apache可以在一个安全的加密环境中建立连接和传输数据。 使用SSL证书,所有的登录信息和其他重要的保密信息都会以加密的方式在Internet上进行传输,这会防止我们的数据被窃取或IP欺骗。
怎样在Apache中使用SSL
每当https请求到达,Apache都会执行以下三步:
Apache生成它的私钥并且将私钥转换为**.CSR** 文件 (证书签发请求).
然后Apache发送 .csr 文件给 CA (证书管理中心).
CA 收到 .csr 文件 并转换为 .crt (证书) 然后再发回给Apache 来完成https连接请求.
俗话说,站在巨人的肩膀上看世界,一般学习的时候也是先总览一下整体,然后逐个部分个个击破,最后形成思路,了解具体细节,Tomcat的结构很复杂,但是Tomcat 非常的模块化,找到了Tomcat最核心的模块,问题才可以游刃而解,了解了Tomcat的整体架构对以后深入了解Tomcat来说至关重要!
Tomcat中最顶层的容器是Server,代表着整个服务器,从上图中可以看出,一个Server可以包含至少一个Service,用于具体提供服务。
Service主要包含两个部分:Connector和Container。从上图中可以看出 Tomcat 的心脏就是这两个组件,他们的作用如下:
1、Connector用于处理连接相关的事情,并提供Socket与Request和Response相关的转化;
2、Container用于封装和管理Servlet,以及具体处理Request请求;
一个Tomcat中只有一个Server,一个Server可以包含多个Service,一个Service只有一个Container,但是可以有多个Connectors,这是因为一个服务可以有多个连接,如同时提供Http和Https链接,也可以提供向相同协议不同端口的连接,示意图如下(Engine、Host、Context下边会说到):
多个 Connector 和一个 Container 就形成了一个 Service,有了 Service 就可以对外提供服务了,但是 Service 还要一个生存的环境,必须要有人能够给她生命、掌握其生死大权,那就非 Server 莫属了!所以整个 Tomcat 的生命周期由 Server 控制。
另外,上述的包含关系或者说是父子关系,都可以在tomcat的conf目录下的server.xml
配置文件中看出,下图是删除了注释内容之后的一个完整的server.xml
配置文件(Tomcat版本为8.0)
详细的配置文件文件内容可以到Tomcat官网查看:http://tomcat.apache.org/tomcat-8.0-doc/index.html
上边的配置文件,还可以通过下边的一张结构图更清楚的理解:
Server标签设置的端口号为8005,shutdown=”SHUTDOWN” ,表示在8005端口监听“SHUTDOWN”命令,如果接收到了就会关闭Tomcat。一个Server有一个Service,当然还可以进行配置,一个Service有多个,Service左边的内容都属于Container的,Service下边是Connector。
(1)Tomcat中只有一个Server,一个Server可以有多个Service,一个Service可以有多个Connector和一个Container;
(2) Server掌管着整个Tomcat的生死大权;
(4)Service 是对外提供服务的;
(5)Connector用于接受请求并将请求封装成Request和Response来具体处理;
(6)Container用于封装和管理Servlet,以及具体处理request请求;
知道了整个Tomcat顶层的分层架构和各个组件之间的关系以及作用,对于绝大多数的开发人员来说Server和Service对我们来说确实很远,而我们开发中绝大部分进行配置的内容是属于Connector和Container的,所以接下来介绍一下Connector和Container。
由上述内容我们大致可以知道一个请求发送到Tomcat之后,首先经过Service然后会交给我们的Connector,Connector用于接收请求并将接收的请求封装为Request和Response来具体处理,Request和Response封装完之后再交由Container进行处理,Container处理完请求之后再返回给Connector,最后在由Connector通过Socket将处理的结果返回给客户端,这样整个请求的就处理完了!
Connector最底层使用的是Socket来进行连接的,Request和Response是按照HTTP协议来封装的,所以Connector同时需要实现TCP/IP协议和HTTP协议!
Tomcat既然处理请求,那么肯定需要先接收到这个请求,接收请求这个东西我们首先就需要看一下Connector!
Connector用于接受请求并将请求封装成Request和Response,然后交给Container进行处理,Container处理完之后在交给Connector返回给客户端。
因此,我们可以把Connector分为四个方面进行理解:
(1)Connector如何接受请求的?
(2)如何将请求封装成Request和Response的?
(3)封装完之后的Request和Response如何交给Container进行处理的?
(4)Container处理完之后如何交给Connector并返回给客户端的?
首先看一下Connector的结构图(图B),如下所示:
Connector就是使用ProtocolHandler来处理请求的,不同的ProtocolHandler代表不同的连接类型,比如:Http11Protocol使用的是普通Socket来连接的,Http11NioProtocol使用的是NioSocket来连接的。
其中ProtocolHandler由包含了三个部件:Endpoint、Processor、Adapter。
(1)Endpoint用来处理底层Socket的网络连接,Processor用于将Endpoint接收到的Socket封装成Request,Adapter用于将Request交给Container进行具体的处理。
(2)Endpoint由于是处理底层的Socket网络连接,因此Endpoint是用来实现TCP/IP协议的,而Processor用来实现HTTP协议的,Adapter将请求适配到Servlet容器进行具体的处理。
(3)Endpoint的抽象实现AbstractEndpoint里面定义的Acceptor和AsyncTimeout两个内部类和一个Handler接口。Acceptor用于监听请求,AsyncTimeout用于检查异步Request的超时,Handler用于处理接收到的Socket,在内部调用Processor进行处理。
至此,我们应该很轻松的回答(1)(2)(3)的问题了,但是(4)还是不知道,那么我们就来看一下Container是如何进行处理的以及处理完之后是如何将处理完的结果返回给Connector的?
Container用于封装和管理Servlet,以及具体处理Request请求,在Connector内部包含了4个子容器,结构图如下(图C):
4个子容器的作用分别是:
(1)Engine:引擎,用来管理多个站点,一个Service最多只能有一个Engine;
(2)Host:代表一个站点,也可以叫虚拟主机,通过配置Host就可以添加站点;
(3)Context:代表一个应用程序,对应着平时开发的一套程序,或者一个WEB-INF目录以及下面的web.xml文件;
(4)Wrapper:每一Wrapper封装着一个Servlet;
下面找一个Tomcat的文件目录对照一下,如下图所示:
Context和Host的区别是Context表示一个应用,我们的Tomcat中默认的配置下webapps下的每一个文件夹目录都是一个Context,其中ROOT目录中存放着主应用,其他目录存放着子应用,而整个webapps就是一个Host站点。
我们访问应用Context的时候,如果是ROOT下的则直接使用域名就可以访问,例如:www.ledouit.com,如果是Host(webapps)下的其他应用,则可以使用www.ledouit.com/docs进行访问,当然默认指定的根应用(ROOT)是可以进行设定的,只不过Host站点下默认的主营用是ROOT目录下的。
看到这里我们知道Container是什么,但是还是不知道Container是如何进行处理的以及处理完之后是如何将处理完的结果返回给Connector的?别急!下边就开始探讨一下Container是如何进行处理的!
Container处理请求是使用Pipeline-Valve管道来处理的!(Valve是阀门之意)
Pipeline-Valve是责任链模式,责任链模式是指在一个请求处理的过程中有很多处理者依次对请求进行处理,每个处理者负责做自己相应的处理,处理完之后将处理后的请求返回,再让下一个处理着继续处理。
但是!Pipeline-Valve使用的责任链模式和普通的责任链模式有些不同!区别主要有以下两点:
(1)每个Pipeline都有特定的Valve,而且是在管道的最后一个执行,这个Valve叫做BaseValve,BaseValve是不可删除的;
(2)在上层容器的管道的BaseValve中会调用下层容器的管道。
我们知道Container包含四个子容器,而这四个子容器对应的BaseValve分别在:StandardEngineValve、StandardHostValve、StandardContextValve、StandardWrapperValve。
Pipeline的处理流程图如下(图D):
(1)Connector在接收到请求后会首先调用最顶层容器的Pipeline来处理,这里的最顶层容器的Pipeline就是EnginePipeline(Engine的管道);
(2)在Engine的管道中依次会执行EngineValve1、EngineValve2等等,最后会执行StandardEngineValve,在StandardEngineValve中会调用Host管道,然后再依次执行Host的HostValve1、HostValve2等,最后在执行StandardHostValve,然后再依次调用Context的管道和Wrapper的管道,最后执行到StandardWrapperValve。
(3)当执行到StandardWrapperValve的时候,会在StandardWrapperValve中创建FilterChain,并调用其doFilter方法来处理请求,这个FilterChain包含着我们配置的与请求相匹配的Filter和Servlet,其doFilter方法会依次调用所有的Filter的doFilter方法和Servlet的service方法,这样请求就得到了处理!
(4)当所有的Pipeline-Valve都执行完之后,并且处理完了具体的请求,这个时候就可以将返回的结果交给Connector了,Connector在通过Socket的方式将结果返回给客户端。
至此,我们已经对Tomcat的整体架构有了大致的了解,从图A、B、C、D可以看出来每一个组件的基本要素和作用。我们在脑海里应该有一个大概的轮廓了!如果你面试的时候,让你简单的聊一下Tomcat,上面的内容你能脱口而出吗?当你能够脱口而出的时候,这位面试官一定会对你刮目相看的!
Tomcat是一个JSP/Servlet容器。其作为Servlet容器,有三种工作模式:独立的Servlet容器、进程内的Servlet容器和进程外的Servlet容器。
进入Tomcat的请求可以根据Tomcat的工作模式分为如下两类:
Tomcat作为应用程序服务器:请求来自于前端的web服务器,这可能是Apache, IIS, Nginx等;
Tomcat作为独立服务器:请求来自于web浏览器;
HAproxy:HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。HAProxy运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中,同时可以保护你的web服务器不被暴露到网络上。
1)HAProxy 也是支持虚拟主机的。
2)HAProxy 的优点能够补充 Nginx 的一些缺点,比如支持 Session 的保持,Cookie的引导;同时支持通过获取指定的 url 来检测后端服务器的状态。
3)HAProxy 跟 LVS 类似,本身就只是一款负载均衡软件;单纯从效率上来讲HAProxy 会比 Nginx 有更出色的负载均衡速度,在并发处理上也是优于 Nginx 的。
4)HAProxy 支持 TCP 协议的负载均衡转发,可以对 MySQL 读进行负载均衡,对后端的 MySQL 节点进行检测和负载均衡,大家可以用 LVS+Keepalived 对 MySQL主从做负载均衡。
Haproxy有8种负载均衡算法(balance),分别如下:
1.balance roundrobin # 轮询,软负载均衡基本都具备这种算法
2.balance static-rr # 根据权重,建议使用
3.balance leastconn # 最少连接者先处理,建议使用
4.balance source # 根据请求源IP,建议使用
5.balance uri # 根据请求的URI
6.balance url_param,# 根据请求的URl参数’balance url_param’ requires an URL parameter name
7.balance hdr(name) # 根据HTTP请求头来锁定每一次HTTP请求
8.balance rdp-cookie(name) # 根据据cookie(name)来锁定并哈希每一次TCP请求
由于负载请求分发到不同服务器,可能导致Session会话不同步的问题,若想实现会话共享或保持,可采用如下3种方式:
1.用户IP 识别
haroxy 将用户IP经过hash计算后 指定到固定的真实服务器上(类似于nginx 的IP hash 指令)
配置指令:balance source
2.Cookie 识别
haproxy 将WEB服务端发送给客户端的cookie中插入(或添加加前缀)haproxy定义的后端的服务器COOKIE ID。
配置指令例举:cookie SESSION_COOKIE insert indirect nocache
用firebug可以观察到用户的请求头的cookie里 有类似” Cookie jsessionid=0bc588656ca05ecf7588c65f9be214f5; SESSION_COOKIE=app1” SESSION_COOKIE=app1就是haproxy添加的内容
3.Session 识别
haproxy 将后端服务器产生的session和后端服务器标识存在haproxy中的一张表里。客户端请求时先查询这张表。
配置指令例举:appsession JSESSIONID len 64 timeout 5h request-learn
Keepalived:Keepalived是一个保证集群高可用的服务软件,用来防止单点故障,使用VRRP协议实现。在master和backup之间通过master主动降低自己的权值或者backup检测到master出现故障时,backup将会接管master的工作,继续服务。
主从、主主、性能调优、数据备份恢复
详述MySQL主从复制原理及配置主从的完整步骤
主从复制的原理如下:
主库开启binlog功能并授权从库连接主库,从库通过change master得到主库的相关同步信息,然后连接主库进行验证,主库IO线程根据从库slave线程的请求,从master.info开始记录的位置点向下开始取信息,同时把取到的位置点和最新的位置与binlog信息一同发给从库IO线程,从库将相关的sql语句存放在relay-log里面,最终从库的sql线程将relay-log里的sql语句应用到从库上,至此整个同步过程完成,之后将是无限重复上述过程
完整步骤如下:
1、主库开启binlog功能,并进行全备,将全备文件推送到从库服务器上
2、show master status\G 记录下当前的位置信息及二进制文件名
3、登陆从库恢复全备文件
4、执行change master to 语句
5、执行start slave and show slave status\G
/etc/init.d/mysqld start
service mysqld start
systemctl start mysqld
lsof -i :3306
netstat -lntup |grep 3306
设置密码
mysql -uroot -ppassword -e "set passowrd for root = passowrd('passowrd')"
mysqladmin -uroot passowrd "NEWPASSWORD"
更改密码
mysqladmin -uroot passowrd oldpassowrd "NEWPASSWORD"
use mysql;
update user set passowrd = PASSWORD('newpassword') where user = 'root';flush privileges;
msyql 5.7以上版本修改默认密码命令
alter user 'root'@'localhost' identified by 'root'
mysql -uroot -ppassword
show create database DB_NAME;
mysql -V
mysql -uroot -ppassowrd -e "use mysql;select version();"
select user();
create database mingongge DEFAULT CHARSET GBK COLLATE gbk_chinese_ci;
grant all on mingongge.* to 'mingongge'@'localhost' identified by 'mingongge';
show grants for mingongge@localhost
select user from mysql.user;
use mingongge
create table test (
id int(4),
name varchar(16)
)ENGINE=innodb DEFAULT CHARSET=gbk;
desc test;
show create table test\G
insert into test values('1','mingongge');
insert into test values('2','民工哥'),('3','mingonggeedu');
select * from test where name = 'mingongge';
update test set name = 'mgg' where id = '1';
alter table test add age tinyint(2) after id;
system mysqldump -uroot -pMgg123.0. -B mingongge >/root/mingongge_bak.sql
delete from test;
select * from test;
drop table test;
show tables;
drop database mingongge;
show databases;
system mysql -uroot -pMgg123.0.
alter database mingongge default character set utf8;
alter table test default character set utf8;
alter table test add primary key(id);
create index mggindex on test(name(16));
alter table test add shouji char(11);
#默认就是在最后一列后面插入新增列
insert into test values('4','23','li','13700000001'),('5','26','zhao','13710000001');
28.在手机字段上对前8个字符创建普通索引
create index SJ on test(shouji(8));
show index from test;
show create table test\G
#下面的命令也可以查看索引类型
show keys from test\G
drop index SJ on test;
drop index mggindex on test;
create index lianhe on test(name(6),shouji(8));
select * from test where shouji like '137%' and name = 'zhao';
explain select * from test where name = 'zhao' and shouji like '137%'\G
alter table test engine=MyISAM;
revoke select on mingongge.* from mingongge@localhost;
drop user migongge@localhost;
drop database mingongge
mysqladmin -uroot -pMgg123.0. shutdown
lsof -i :3306
mysqld_safe --skip-grant-tables & #启动数据库服务
mysql -uroot -ppassowrd -e "use mysql;update user set passowrd = PASSWORD('newpassword') where user = 'root';flush privileges;"
关系型数据库模型是把复杂的数据结构归结为简单的二元关系,对数据的操作都是建立一个或多个关系表格上,最大的特点就是二维的表格,通过SQL结构查询语句存取数据,保持数据一致性方面很强大
1、mysql 互联网企业常用
2、oracle 大型传统企业应用软件
3、 如数据备份、复杂连接查询、一致性数据存储等,还是使用MySQL或者其他传统的关系型数据库最合适
非关系型数据库也被称为NoSQL数据库,数据存储不需有特有固定的表结构
特点:高性能、高并发、简单易安装
1、memcaced 纯内存
2、redis 持久化缓存
3、mongodb 面向文档
如果需要短时间响应的查询操作,没有良好模式定义的数据存储,或者模式更改频繁的数据存储还是用NoSQL
sql语句分类如下
DDL 数据定义语言,用来定义数据库对象:库、表、列
代表性关键字:create alter drop
DML 数据操作语言,用来定义数据库记录
代表性关键字:insert delete update
DCL 数据控制语言,用来定义访问权限和安全级别
代表性关键字:grant deny revoke
DQL 数据查询语言,用来查询记录数据
代表性关键字:select
char长度是固定不可变的,varchar长度是可变的(在设定内)比如同样写入cn字符,char类型对应的长度是4(cn+两个空格),但varchar类型对应长度是2
create database mingongge default character utf8 collate utf8_general_ci;
grant all on . to mingongge@‘172.16.1.0/24’ identified by ‘123456’;
mysql多实例就是在同一台服务器上启用多个mysql服务,它们监听不同的端口,运行多个服务进程,它们相互独立,互不影响的对外提供服务,便于节约服务器资源与后期架构扩展
多实例的配置方法有两种:
1、一个实例一个配置文件,不同端口
2、同一配置文件(my.cnf)下配置不同实例,基于mysqld_multi工具
1、删除数据库不使用的默认用户
2、配置相应的权限(包括远程连接)
3、不可在命令行界面下输入数据库的密码
4、定期修改密码与加强密码的复杂度
参考前面的回答
前者删除数据可以恢复,它是逐条删除速度慢
后者是物理删除,不可恢复,它是整体删除速度快
1、可以杀掉sleep进程,kill PID
2、修改配置,重启服务
[mysqld]
wait_timeout = 600
interactive_timeout=30
#如果生产服务器不可随便重启可以使用下面的方法解决
set global wait_timeout=600
set global interactive_timeout=30;
在每个connection(session)第一次连接时需要使用到,来提访问性能
set global sort_buffer_size = 2M
MySQL中的binlog日志记录了数据中的数据变动,便于对数据的基于时间点和基于位置的恢复
但日志文件的大小会越来越大,点用大量的磁盘空间,因此需要定时清理一部分日志信息
手工删除:
首先查看主从库正在使用的binlog文件名称
show master(slave) status\G
删除之前一定要备份
purge master logs before’2017-09-01 00:00:00’;
#删除指定时间前的日志
purge master logs to’mysql-bin.000001’;
#删除指定的日志文件
自动删除:
通过设置binlog的过期时间让系统自动删除日志
show variables like ‘expire_logs_days’;
et global expire_logs_days = 30;
#查看过期时间与设置过期时间
1.Row(行模式);
日志中会记录成每一行数据被修改的形式,然后在slave端再对相同的数据进行修改
2.Statement(语句模式)
每一条修改的数据都会完整的记录到主库master的binlog里面,在slave上完整执行在master执行的sql语句
3.mixed(混合模式)
结合前面的两种模式,如果在工作中有使用函数 或者触发器等特殊功能需求的时候,使用混合模式
数据量达到比较高时候,它就会选择 statement模式,而不会选择Row Level行模式
1、停止主从复制,在主库上执行锁表并刷新binlog操作,接着恢复之前的全备文件(比如0点的全备)
2、将0点时的binlog文件与全备到故障期间的binlog文件合并导出成sql语句
mysqlbinlog --no-defaults mysql-bin.000011 mysql-bin.000012 >bin.sql
3、将导出的sql语句中drop语句删除,恢复到数据库中
mysql -uroot -pmysql123 < bin.sql
-A 此参数作用是备份所有数据库(相当于–all-databases)
-B databasename 备份指定数据(单库备份使用)
主从复制的原理如下:
主库开启binlog功能并授权从库连接主库,从库通过change master得到主库的相关同步信息,然后连接主库进行验证,主库IO线程根据从库slave线程的请求,从master.info开始记录的位置点向下开始取信息,同时把取到的位置点和最新的位置与binlog信息一同发给从库IO线程,从库将相关的sql语句存放在relay-log里面,最终从库的sql线程将relay-log里的sql语句应用到从库上,至此整个同步过程完成,之后将是无限重复上述过程
完整步骤如下:
1、主库开启binlog功能,并进行全备,将全备文件推送到从库服务器上
2、show master status\G 记录下当前的位置信息及二进制文件名
3、登陆从库恢复全备文件
4、执行change master to 语句
5、执行start slave and show slave status\G
修改配置文件加上下面的配置
log_bin=slave-bin
log_bin_index=slave-bin.index
需要重启服务生效
双向同步主要应用于解决单一主库写的压力,具体配置如下
主库配置
[mysqld]
auto_increment_increment = 2 #起始ID
auto_increment_offset = 1 #ID自增间隔
log-slave-updates
从库配置
[mysqld]
auto_increment_increment = 2 #起始ID
auto_increment_offset = 2 #ID自增间隔
log-slave-updates
主从库服务器都需要重启mysql服务
级联同步主要应用在从库需要做为其它数据库的主库
在需要做级联同步的数据库配置文件增加下面的配置即可
log_bin=slave-bin
log_bin_index=slave-bin.index
登陆从库
1、执行stop slave;停止主从同步
2、然后set global sql_slave_skip_counter = 1;跳过一步错误
3、最后执行 start slave;并查看主从同步状态
需要重新进行主从同步操作步骤如下
进入主库
1、进行全备数据库并刷新binlog,查看主库此的状态
2、恢复全备文件到从库,然后执行change master
3、开启主从同步start slave;并查看主从同步状态
mysql -uroot -ppassowrd -e “show slave status\G” |grep -E “Slave_IO_Running|Slave_SQL_Running”|awk ‘{print $2}’|grep -c Yes
通过判断Yes的个数来监控主从复制状态,正常情况等于2
1、通过开发程序实现
2、通过其它工具实现(如mysql-mmm)
1、执行stop slave 或者停止服务
2、修复好从库数据库
3、然后重新操作主库同步
1、登陆各个从库停止同步,并查看谁的数据最新,将它设置为新主库让其它从库同步其数据
2、修复好主库之后,生新操作主从同步的步骤就可以了
#需要注意的新的主库如果之前是只读,需要关闭此功能让其可写
#需要在新从库创建与之前主库相同的同步的用户与权限
#其它从库执行change master to master_port=新主库的端口,start slave
1、开发使用root用户在从库上写入数据造成主从数据不一致,并且前端没有展示需要修改的内容(仍旧是老数据)
2、内网测试环境服务器突然断电造成主从同步故障
1、需要同步的从库数据太多
2、从库的硬件资源较差,需要提升
3、网络问题,需要提升网络带宽
4、主库的数据写入量较大,需要优配置和硬件资源
5、sql语句执行过长导致,需要优化
1、双主多从,主从同步的架构,然后实行某个从库专业做为备份服务器
2、编写脚本实行分库分表进行备份,并加入定时任务
3、最终将备份服务推送至内网专业服务器,数据库服务器本地保留一周
4、备份服务器根据实际情况来保留备份数据(一般30天)
数据库事务是指逻辑上的一组sql语句,组成这组操作的各个语句,执行时要么成功,要么失败
特点:具有原子性、隔离性、持久性、一致性
全备:数据库所有数据的一次完整备份,也就是备份当前数据库的所有数据
增备:就在上次备份的基础上备份到现在所有新增的数据
冷备:停止服务的基础上进行备份操作
热备:实行在线进行备份操作,不影响数据库的正常运行
全备在企业中基本上是每周或天一次,其它时间是进行增量备份
热备使用的情况是有两台数据库在同时提供服务的情况,针对归档模式的数据库
冷备使用情况有企业初期,数据量不大且服务器数量不多,可能会执行某些库、表结构等重大操作时
建立主键与增加索引
1、集群架构可采用双主多从的模式,但实际双主只有一主在线提供服务,两台主之间做互备
2、另外的从可做读的负载均衡,然后将其中一台抽出专业做备份
1、需要注意语句是否有格式上的错误,执行会出错导致过程中断
2、还需要注意语句的执行时间是否过长,是否会对服务器负载产生压力影响实际生产
1、首先导出库的表结构 -d 只导出表结构,然后批量替换
2、导出库中的所有数据(在不产生新数据的前提下)
3、然后全局替换set names = xxxxx
4、删除原有库与表,并新创建出来,再导入建库与建表语句与所有数据
服务器系统、数据库、客户端三方字符集不一致导致,需要统一字符
1、提升服务器硬件资源与网络带宽
2、优化mysql服务配置文件
3、开启慢查询日志然后分析问题所在
高可用方案有
1、主从架构
2、MySQL+MMM
3、MySQL+MHA
4、mysql+haproxy+drbd
5、mysql+proxy+amoeba
通过mysqldump命令备份出一个sql文件,再使用sed命令替换
或者执行下面的脚本进行修改
#!/bin/sh
user=root
passwd=123456
cmd="mysql -u u s e r − p user -p user−ppasswd "
dump=“mysqldump -u u s e r − p user -p user−ppasswd”
for database in $cmd -e "show databases;"|sed '1,2d'|egrep -v "mysql|performance_schema"
do
for tables in dump -e "show tables from $databses;"|sed '1d'
do
$cmd “alter table d a t a b a s e . database. database.tables engine = MyISAm;”
done
done
通过mysqldump命令备份出一个sql文件,再使用sed命令替换sed -i ‘s/GBK/UTF8/g’
1、可以使用top free 等命令分析系统性能等方面的问题
2、如是因为数据库的原因造成的,就需要查看慢查询日志去查找并分析问题所在
https://www.jianshu.com/p/c82737b5485c
https://blog.csdn.net/zisefeizhu/article/details/83345398
./script argument
例子: 显示文件名称脚本
./show.sh file1.txt
cat show.sh
#!/bin/bash
echo $1
第一个参数 : $1,第二个参数 : $2
例子 : 脚本会复制文件(arg1) 到目标地址(arg2)
./copy.sh file1.txt /tmp/
cat copy.sh
#!/bin/bash
cp $1 $2
$#
$0
$?
tail-1
head-1
awk'{print $3}'
awk'{ if ($1 == "FIND") print $2}'
将 -xv 参数加到 #!/bin/bash 后
例子:
#!/bin/bash –xv
function example {
echo "Hello world!"
}
V1="Hello"
V2="World"
V3=${V1}${V2}
echo $V3
输出
HelloWorld
V1=1
V2=2
let V3=$V1+$V2
echo $V3
输出
3
据 @kashu 的意见,本题的更佳回答为:
两个整数相加,还有若干种方法实现:
A=5
B=6
echo $(($A+$B)) # 方法 2
echo $[$A+$B] # 方法 3
expr $A + $B # 方法 4
echo $A+$B | bc # 方法 5
awk 'BEGIN{print '"$A"'+'"$B"'}' # 方法 6
if [ -f /var/log/messages ]
then
echo "File exists"
fi
for 循环 :
foriin$(ls);do
echo item:$i
done
while 循环 :
#!/bin/bash
COUNTER=0
while [ $COUNTER -lt 10 ]; do
echo The counter is $COUNTER
let COUNTER=COUNTER+1
done
until 循环 :
#!/bin/bash
COUNTER=20
until [ $COUNTER -lt 10 ]; do
echo COUNTER $COUNTER
let COUNTER-=1
done
这一行说明要使用的 shell
。#!/bin/bash
表示脚本使用 /bin/bash
。对于 python 脚本,就是
#!/usr/bin/python
。
head -10 file|tail -1
#
0
使变量在子 shell
中可用。
在脚本后面添加 “&”
。
据 @kashu 的意见,更好的答案是:
nohup command&
大部分时间我们可能是远程使用Linux,我碰到过由于网络断线使得在后台运行的command &
没了…
使脚本所有者拥有可执行权限。
重定向输出流到文件或另一个流。
&
- 希望脚本在后台运行的时候使用它 &&
- 当前一个脚本成功完成才执行后面的命令/脚本的时候使用它当条件满足时需要运行多条命令的时候。
variable
#
variable
'
- 当我们不希望把变量转换为值的时候使用它。 "
- 会计算所有变量的值并用值代替。在脚本文件中添加 "exec >log.txt 2>&1"
命令。
echo ${variable:x:y}
x - 起始位置
y - 长度
例子:
variable="My name is Petras, and I am developer."
echo ${variable:11:6} # 会显示 Petras
echo ${variable#*:*:*:}
或
echo ${variable##*:}
echo ${variable%:*:*:*}
或
echo ${variable%%:*}
awk -F: '$3<100' /etc/passwd
cat /etc/passwd|cut -d: -f4|sort|uniq -c|while read c g
do
{ echo $c; grep :$g: /etc/group|cut -d: -f1;}|xargs -n 2
done
IFS=":"
${#variable}
echo ${variable: -5}
${variable:-10}
- 如果之前没有给 variable 赋值则输出 10;如果有赋值则输出该变量${variable: -10}
- 输出 variable 的最后 10 个字符echo ${variable//pattern/replacement}
tr '[:lower:]' '[:upper:]'
wc -l /etc/passwd|cut -d" " -f1 或者 cat /etc/passwd|wc -l
set ${string}
echo $#
export variable
ls -d ?[ab]*
c=$((a+b))
或
c= `expr $a + $b`
或
c=`echo “ a + a+ a+b”|bc`
echo $string|tr -d " "
item="car"; echo "I like ${item}s"
for i in {0..100..3}; do echo $i; done
或
for (( i=0; i<=100; i=i+3 )); do echo "Welcome $i times"; done
echo $*
或
echo $@
[ $a == $b ]
- 用于字符串比较 [ $a -eq $b ]
- 用于数字比较=
- 用于为变量赋值 ==
- 用于字符串比较[ $a -gt 12 ]
[ $b -le 12 ]
[[ $string == abc* ]]
[[ $string == abc* ]]
- 检查字符串是否以字母 abc 开头 [[ $string == "abc" ]]
- 检查字符串是否完全等于 abcegrep "^ab|^xy" /etc/passwd|cut -d: -f1
后台最近执行命令的 PID.
前台最近命令的结束状态。
echo $$
echo $#
(LCTT 译注:和第3题重复了。)
$*
- 以一个字符串形式输出所有传递到脚本的参数 $@
- 以 $IFS 为分隔符列出所有传递到脚本中的参数array=("Hi" "my" "name" "is")
echo ${array[0]}
echo ${array[@]}
echo ${!array[@]}
unset array[2]
array[333]="New_element"
a) 通过参数
./script param1 param2
b) 通过 read 命令
read -p "Destination backup Server : " desthost
/usr/bin/expect << EOD
spawn rsync -ar ${line} ${desthost}:${destpath}
expect "*?assword:*"
send "${password}\r"
expect eof
EOD
top(能了解top后的每一个字段意思)
grep,sed,awk