分类 技术 下的文章

Nginx 是最快和最强大的 Web 服务器之一,以其高性能和低资源占用率而闻名。它既可以被安装为一个独立的 Web 服务器,也可以安装成反向代理 Web 服务器。在这篇文章,我将讨论在安装了 cPanel 管理系统的 Centos 7 服务器上安装 Nginx 作为 Apache 的反向代理服务器。

Nginx 作为前端服务器用反向代理为静态文件提供服务,Apache 作为后端为动态文件提供服务。这个设置将整体提高服务器的性能。

让我们过一遍在已经安装好 cPanel 11.52 的 CentOS 7 x86\_64 服务器上配置 Nginx 作为反向代理的安装过程。

首先,我们需要安装 EPEL 库来启动这个进程

第一步: 安装 EPEL 库

root@server1 [/usr]# yum -y install epel-release
Loaded plugins: fastestmirror, tsflags, universal-hooks
Loading mirror speeds from cached hostfile
* EA4: 66.23.237.210
* base: mirrors.linode.com
* extras: mirrors.linode.com
* updates: mirrors.linode.com
Resolving Dependencies
--> Running transaction check
---> Package epel-release.noarch 0:7-5 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

========================================================================================
    Package Arch Version Repository Size
========================================================================================
Installing:
epel-release noarch 7-5 extras 14 k

第二步: 可以安装 nDeploy 的 CentOS RPM 库来安装我们所需的 nDeploy Web 类软件和 Nginx 插件

root@server1 [/usr]# yum -y install http://rpm.piserve.com/nDeploy-release-centos-1.0-1.noarch.rpm
Loaded plugins: fastestmirror, tsflags, universal-hooks
nDeploy-release-centos-1.0-1.noarch.rpm | 1.7 kB 00:00:00
Examining /var/tmp/yum-root-ei5tWJ/nDeploy-release-centos-1.0-1.noarch.rpm: nDeploy-release-centos-1.0-1.noarch
Marking /var/tmp/yum-root-ei5tWJ/nDeploy-release-centos-1.0-1.noarch.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package nDeploy-release-centos.noarch 0:1.0-1 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

========================================================================================
Package Arch Version Repository Size
========================================================================================
Installing:
nDeploy-release-centos noarch 1.0-1 /nDeploy-release-centos-1.0-1.noarch 110

第三步:安装 nDeploy 和 Nginx nDeploy 插件

root@server1 [/usr]# yum --enablerepo=ndeploy install nginx-nDeploy nDeploy
Loaded plugins: fastestmirror, tsflags, universal-hooks
epel/x86_64/metalink | 9.9 kB 00:00:00
epel | 4.3 kB 00:00:00
ndeploy | 2.9 kB 00:00:00
(1/4): ndeploy/7/x86_64/primary_db | 14 kB 00:00:00
(2/4): epel/x86_64/group_gz | 169 kB 00:00:00
(3/4): epel/x86_64/primary_db | 3.7 MB 00:00:02

Dependencies Resolved

========================================================================================
Package Arch Version Repository Size
========================================================================================
Installing:
nDeploy noarch 2.0-11.el7 ndeploy 80 k
nginx-nDeploy x86_64 1.8.0-34.el7 ndeploy 36 M
Installing for dependencies:
PyYAML x86_64 3.10-11.el7 base 153 k
libevent x86_64 2.0.21-4.el7 base 214 k
memcached x86_64 1.4.15-9.el7 base 84 k
python-inotify noarch 0.9.4-4.el7 base 49 k
python-lxml x86_64 3.2.1-4.el7 base 758 k

Transaction Summary
========================================================================================
Install 2 Packages (+5 Dependent packages)

通过以上这些步骤,我们完成了在我们的服务器上 Nginx 插件的安装。现在我们可以配置 Nginx 作为反向代理和为已有的 cPanel 用户账户创建虚拟主机,为此我们可以运行如下脚本。

第四步:启动 Nginx 作为默认的前端 Web 服务器,并创建默认的配置文件

root@server1 [/usr]# /opt/nDeploy/scripts/cpanel-nDeploy-setup.sh enable
Modifying apache http and https port in cpanel

httpd restarted successfully.
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.
Created symlink from /etc/systemd/system/multi-user.target.wants/ndeploy_watcher.service to /usr/lib/systemd/system/ndeploy_watcher.service.
Created symlink from /etc/systemd/system/multi-user.target.wants/ndeploy_backends.service to /usr/lib/systemd/system/ndeploy_backends.service.
ConfGen:: saheetha
ConfGen:: satest

你可以看到这个脚本将修改 Apache 的端口从 80 到另一个端口来让 Nginx 作为前端 Web 服务器,并为现有的 cPanel 用户创建虚拟主机配置文件。一旦完成,确认 Apache 和 Nginx 的状态。

Apache 状态:

root@server1 [/var/run/httpd]# systemctl status httpd
● httpd.service - Apache Web Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Active: active (running) since Mon 2016-01-18 06:34:23 UTC; 12s ago
Process: 25606 ExecStart=/usr/sbin/apachectl start (code=exited, status=0/SUCCESS)
Main PID: 24760 (httpd)
CGroup: /system.slice/httpd.service
‣ 24760 /usr/local/apache/bin/httpd -k start

Jan 18 06:34:23 server1.centos7-test.com systemd[1]: Starting Apache Web Server...
Jan 18 06:34:23 server1.centos7-test.com apachectl[25606]: httpd (pid 24760) already running
Jan 18 06:34:23 server1.centos7-test.com systemd[1]: Started Apache Web Server.

Nginx 状态:

root@server1 [~]# systemctl status nginx
● nginx.service - nginx-nDeploy - high performance web server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
Active: active (running) since Sun 2016-01-17 17:18:29 UTC; 13h ago
Docs: http://nginx.org/en/docs/
Main PID: 3833 (nginx)
CGroup: /system.slice/nginx.service
├─ 3833 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
├─25473 nginx: worker process
├─25474 nginx: worker process
└─25475 nginx: cache manager process

Jan 17 17:18:29 server1.centos7-test.com systemd[1]: Starting nginx-nDeploy - high performance web server...
Jan 17 17:18:29 server1.centos7-test.com nginx[3804]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Jan 17 17:18:29 server1.centos7-test.com nginx[3804]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Jan 17 17:18:29 server1.centos7-test.com systemd[1]: Started nginx-nDeploy - high performance web server.

Nginx 作为前端服务器运行在 80 端口,Apache 配置被更改为监听 http 端口 9999 和 https 端口 4430。请看他们的情况:

root@server1 [/usr/local/src]# netstat -plan | grep httpd
tcp 0 0 0.0.0.0:4430 0.0.0.0:* LISTEN 17270/httpd
tcp 0 0 0.0.0.0:9999 0.0.0.0:* LISTEN 17270/httpd
tcp6 0 0 :::4430 :::* LISTEN 17270/httpd
tcp6 0 0 :::9999 :::* LISTEN 17270/httpd

apacheport

root@server1 [/usr/local/src]# netstat -plan | grep nginx
tcp 0 0 127.0.0.1:80 0.0.0.0:* LISTEN 17802/nginx: master
tcp 0 0 45.79.183.73:80 0.0.0.0:* LISTEN 17802/nginx: master

为已有用户创建的虚拟主机的配置文件在 “/etc/nginx/sites-enabled”。 这个文件路径包含了 Nginx 主要配置文件。

root@server1 [/etc/nginx/sites-enabled]# ll | grep .conf
-rw-r--r-- 1 root root 311 Jan 17 09:02 saheetha.com.conf
-rw-r--r-- 1 root root 336 Jan 17 09:02 saheethastest.com.conf

一个域名的示例虚拟主机:

server {

listen 45.79.183.73:80;
#CPIPVSIX:80;

# ServerNames
server_name saheetha.com www.saheetha.com;
access_log /usr/local/apache/domlogs/saheetha.com main;
access_log /usr/local/apache/domlogs/saheetha.com-bytes_log bytes_log;

include /etc/nginx/sites-enabled/saheetha.com.include;

}

我们可以启动浏览器查看网站来确定 Web 服务器的工作状态。安装后,请阅读服务器上的 web 服务信息。

root@server1 [/home]# ip a | grep -i eth0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 45.79.183.73/24 brd 45.79.183.255 scope global dynamic eth0
root@server1 [/home]# nginx -v
nginx version: nginx/1.8.0

webserver-status

Nginx 将会为任何最新在 cPanel 中创建的账户创建虚拟主机。通过这些简单的的步骤,我们能够在一台 CentOS 7 / cPanel 的服务器上配置 Nginx 作为反向代理。

Nginx 作为反向代理的优势

  1. 便于安装和配置。
  2. 效率高、性能好。
  3. 防止 Ddos 攻击。
  4. 支持使用 .htaccess 作为 PHP 的重写规则。

我希望这篇文章对你们有用。感谢你看它。我非常高兴收到你的宝贵意见和建议,并进一步改善。


via: http://linoxide.com/linux-how-to/set-nginx-reverse-proxy-centos-7-cpanel/

作者:Saheetha Shameer 译者:bestony 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

由于 2016 年 2 月 2 号开始启用了新的 LFCS 考试要求,我们在已经发表的 LFCS 系列 基础上增加了一些必要的主题。为了准备考试,同时也建议你看看 LFCE 系列 文章。

第十四讲: 监控 Linux 进程并为每个用户设置进程限制

每个 Linux 系统管理员都应该知道如何验证硬件、资源和主要进程的完整性和可用性。另外,基于每个用户设置资源限制也是其中一项必备技能。

在这篇文章中,我们会介绍一些能够确保系统硬件和软件正常工作的方法,这些方法能够避免潜在的会导致生产环境下线或钱财损失的问题发生。

报告 Linux 进程统计信息

你可以使用 mpstat 单独查看每个处理器或者系统整体的活动,可以是每次一个快照或者动态更新。

为了使用这个工具,你首先需要安装 sysstat

# yum update && yum install sysstat              [基于 CentOS 的系统]
# aptitutde update && aptitude install sysstat   [基于 Ubuntu 的系统]
# zypper update && zypper install sysstat        [基于 openSUSE 的系统]

你可以在 在 Linux 中学习 Sysstat 和其中的工具 mpstat、pidstat、iostat 和 sar 了解更多和 sysstat 和其中的工具相关的信息。

安装完 mpstat 之后,就可以使用它生成处理器统计信息的报告。

你可以使用下面的命令每隔 2 秒显示所有 CPU(用 -P ALL 表示)的 CPU 利用率(-u),共显示 3 次。

# mpstat -P ALL -u 2 3

示例输出:

Linux 3.19.0-32-generic (tecmint.com)   Wednesday 30 March 2016     _x86_64_    (4 CPU)

11:41:07  IST  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:41:09  IST  all    5.85    0.00    1.12    0.12    0.00    0.00    0.00    0.00    0.00   92.91
11:41:09  IST    0    4.48    0.00    1.00    0.00    0.00    0.00    0.00    0.00    0.00   94.53
11:41:09  IST    1    2.50    0.00    0.50    0.00    0.00    0.00    0.00    0.00    0.00   97.00
11:41:09  IST    2    6.44    0.00    0.99    0.00    0.00    0.00    0.00    0.00    0.00   92.57
11:41:09  IST    3   10.45    0.00    1.99    0.00    0.00    0.00    0.00    0.00    0.00   87.56

11:41:09  IST  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:41:11  IST  all   11.60    0.12    1.12    0.50    0.00    0.00    0.00    0.00    0.00   86.66
11:41:11  IST    0   10.50    0.00    1.00    0.00    0.00    0.00    0.00    0.00    0.00   88.50
11:41:11  IST    1   14.36    0.00    1.49    2.48    0.00    0.00    0.00    0.00    0.00   81.68
11:41:11  IST    2    2.00    0.50    1.00    0.00    0.00    0.00    0.00    0.00    0.00   96.50
11:41:11  IST    3   19.40    0.00    1.00    0.00    0.00    0.00    0.00    0.00    0.00   79.60

11:41:11  IST  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:41:13  IST  all    5.69    0.00    1.24    0.00    0.00    0.00    0.00    0.00    0.00   93.07
11:41:13  IST    0    2.97    0.00    1.49    0.00    0.00    0.00    0.00    0.00    0.00   95.54
11:41:13  IST    1   10.78    0.00    1.47    0.00    0.00    0.00    0.00    0.00    0.00   87.75
11:41:13  IST    2    2.00    0.00    1.00    0.00    0.00    0.00    0.00    0.00    0.00   97.00
11:41:13  IST    3    6.93    0.00    0.50    0.00    0.00    0.00    0.00    0.00    0.00   92.57

Average:     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
Average:     all    7.71    0.04    1.16    0.21    0.00    0.00    0.00    0.00    0.00   90.89
Average:       0    5.97    0.00    1.16    0.00    0.00    0.00    0.00    0.00    0.00   92.87
Average:       1    9.24    0.00    1.16    0.83    0.00    0.00    0.00    0.00    0.00   88.78
Average:       2    3.49    0.17    1.00    0.00    0.00    0.00    0.00    0.00    0.00   95.35
Average:       3   12.25    0.00    1.16    0.00    0.00    0.00    0.00    0.00    0.00   86.59

要查看指定的 CPU(在下面的例子中是 CPU 0),可以使用:

# mpstat -P 0 -u 2 3

示例输出:

Linux 3.19.0-32-generic (tecmint.com)   Wednesday 30 March 2016     _x86_64_    (4 CPU)

11:42:08  IST  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:42:10  IST    0    3.00    0.00    0.50    0.00    0.00    0.00    0.00    0.00    0.00   96.50
11:42:12  IST    0    4.08    0.00    0.00    2.55    0.00    0.00    0.00    0.00    0.00   93.37
11:42:14  IST    0    9.74    0.00    0.51    0.00    0.00    0.00    0.00    0.00    0.00   89.74
Average:       0    5.58    0.00    0.34    0.85    0.00    0.00    0.00    0.00    0.00   93.23

上面命令的输出包括这些列:

  • CPU: 整数表示的处理器号或者 all 表示所有处理器的平均值。
  • %usr: 运行在用户级别的应用的 CPU 利用率百分数。
  • %nice: 和 %usr 相同,但有 nice 优先级。
  • %sys: 执行内核应用的 CPU 利用率百分比。这不包括用于处理中断或者硬件请求的时间。
  • %iowait: 指定(或所有)CPU 的空闲时间百分比,这表示当前 CPU 处于 I/O 操作密集的状态。更详细的解释(附带示例)可以查看这里
  • %irq: 用于处理硬件中断的时间所占百分比。
  • %soft: 和 %irq 相同,但是是软中断。
  • %steal: 虚拟机非自主等待(时间片窃取)所占时间的百分比,即当虚拟机在竞争 CPU 时所从虚拟机管理程序那里“赢得”的时间。应该保持这个值尽可能小。如果这个值很大,意味着虚拟机正在或者将要停止运转。
  • %guest: 运行虚拟处理器所用的时间百分比。
  • %idle: CPU 没有运行任何任务所占时间的百分比。如果你观察到这个值很小,意味着系统负载很重。在这种情况下,你需要查看详细的进程列表、以及下面将要讨论的内容来确定这是什么原因导致的。

运行下面的命令使处理器处于极高负载,然后在另一个终端执行 mpstat 命令:

# dd if=/dev/zero of=test.iso bs=1G count=1
# mpstat -u -P 0 2 3
# ping -f localhost # Interrupt with Ctrl + C after mpstat below completes
# mpstat -u -P 0 2 3

最后,和 “正常” 情况下 mpstat 的输出作比较:

Linux 处理器相关统计信息报告

正如你在上面图示中看到的,在前面两个例子中,根据 %idle 的值可以判断 CPU 0 负载很高。

在下一部分,我们会讨论如何识别资源饥饿型进程,如何获取更多和它们相关的信息,以及如何采取恰当的措施。

Linux 进程报告

我们可以使用有名的 ps 命令,用 -eo 选项(根据用户定义格式选中所有进程) 和 --sort 选项(指定自定义排序顺序)按照 CPU 使用率排序列出进程,例如:

# ps -eo pid,ppid,cmd,%cpu,%mem --sort=-%cpu

上面的命令只会显示 PIDPPID、和进程相关的命令、 CPU 使用率以及 RAM 使用率,并按照 CPU 使用率降序排序。创建 .iso 文件的时候运行上面的命令,下面是输出的前面几行:

根据 CPU 使用率查找进程

一旦我们找到了感兴趣的进程(例如 PID=2822 的进程),我们就可以进入 /proc/PID(本例中是 /proc/2822) 列出目录内容。

这个目录就是进程运行的时候保存多个关于该进程详细信息的文件和子目录的目录。

例如:

  • /proc/2822/io 包括该进程的 IO 统计信息(IO 操作时的读写字符数)。
  • /proc/2822/attr/current 显示了进程当前的 SELinux 安全属性。
  • /proc/2822/cgroup 如果启用了 CONFIGCGROUPS 内核设置选项,这会显示该进程所属的控制组(简称 cgroups),你可以使用下面命令验证是否启用了 CONFIGCGROUPS:
# cat /boot/config-$(uname -r) | grep -i cgroups

如果启用了该选项,你应该看到:

CONFIG_CGROUPS=y

根据 红帽企业版 Linux 7 资源管理指南 第一到四章的内容、openSUSE 系统分析和调优指南 第九章、Ubuntu 14.04 服务器文档 Control Groups 章节,你可以使用 cgroups 管理每个进程允许使用的资源数目。

/proc/2822/fd 这个目录包含每个打开的描述进程的文件的符号链接。下面的截图显示了 tty1(第一个终端) 中创建 .iso 镜像进程的相关信息:

查找 Linux 进程信息

上面的截图显示 stdin(文件描述符 0)、stdout(文件描述符 1)、stderr(文件描述符 2) 相应地被映射到 /dev/zero/root/test.iso/dev/tty1

更多关于 /proc 信息的可以查看 Kernel.org 维护的 “/proc 文件系统” 和 Linux 开发者手册。

在 Linux 中为每个用户设置资源限制

如果你不够小心、让任意用户使用不受限制的进程数,最终你可能会遇到意外的系统关机或者由于系统进入不可用的状态而被锁住。为了防止这种情况发生,你应该为用户可以启动的进程数目设置上限。

你可以在 /etc/security/limits.conf 文件末尾添加下面一行来设置限制:

*       hard    nproc   10

第一个字段可以用来表示一个用户、组或者所有人(*), 第二个字段强制限制可以使用的进程数目(nproc) 为 10。退出并重新登录就可以使设置生效。

然后,让我们来看看非 root 用户(合法用户或非法用户) 试图引起 shell fork 炸弹 (参见 WiKi) 时会发生什么。如果我们没有设置限制, shell fork 炸弹会无限制地启动函数的两个实例,然后无限循环地复制任意一个实例。最终导致你的系统卡死。

但是,如果使用了上面的限制,fort 炸弹就不会成功,但用户仍然会被锁在外面直到系统管理员杀死相关的进程。

运行 Shell Fork 炸弹

提示limits.conf 文件中可以查看其它 ulimit 可以更改的限制。

其它 Linux 进程管理工具

除了上面讨论的工具, 一个系统管理员还可能需要:

a) 通过使用 renice 调整执行优先级(系统资源的使用)。这意味着内核会根据分配的优先级(众所周知的 “niceness”,它是一个范围从 -2019 的整数)给进程分配更多或更少的系统资源。

这个值越小,执行优先级越高。普通用户(而非 root)只能调高他们所有的进程的 niceness 值(意味着更低的优先级),而 root 用户可以调高或调低任何进程的 niceness 值。

renice 命令的基本语法如下:

# renice [-n] <new priority> <UID, GID, PGID, or empty> identifier

如果 new priority 后面的参数没有(为空),默认就是 PID。在这种情况下,PID=identifier 的进程的 niceness 值会被设置为 <new priority>

b) 需要的时候中断一个进程的正常执行。这也就是通常所说的“杀死”进程。实质上,这意味着给进程发送一个信号使它恰当地结束运行并以有序的方式释放任何占用的资源。

按照下面的方式使用 kill 命令杀死进程

# kill PID

另外,你也可以使用 pkill 结束指定用户(-u)、指定组(-G) 甚至有共同的父进程 ID (-P) 的所有进程。这些选项后面可以使用数字或者名称表示的标识符。

# pkill [options] identifier

例如:

# pkill -G 1000

会杀死组 GID=1000 的所有进程。而

# pkill -P 4993 

会杀死 PPID 是 4993 的所有进程。

在运行 pkill 之前,先用 pgrep 测试结果、或者使用 -l 选项列出进程名称是一个很好的办法。它需要和 pkill 相同的参数、但是只会返回进程的 PID(而不会有其它操作),而 pkill 会杀死进程。

# pgrep -l -u gacanepa

用下面的图片说明:

在 Linux 中查找用户运行的进程

总结

在这篇文章中我们探讨了一些监控资源使用的方法,以便验证 Linux 系统中重要硬件和软件组件的完整性和可用性。

我们也学习了如何在特殊情况下采取恰当的措施(通过调整给定进程的执行优先级或者结束进程)。

我们希望本篇中介绍的概念能对你有所帮助。如果你有任何疑问或者评论,可以使用下面的联系方式联系我们。


via: http://www.tecmint.com/monitor-linux-processes-and-set-process-limits-per-user/

作者:Gabriel Cánepa 译者:ictlyh 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

由于 LFCS 考试需求的变动已于 2016 年 2 月 2 日生效,因此我们向 LFCS 系列 添加了一些必要的话题。为了准备认证考试,我们也强烈推荐你去看看 LFCE 系列

LFCS 系列第十三讲:配置并排除 Grub 引导加载程序故障。

本文将会向你介绍 GRUB 的知识,并会说明你为什么需要一个引导加载程序,以及它是如何给系统增加功能的。

Linux 引导过程 是从你按下你的电脑电源键开始,直到你拥有一个全功能的系统为止,整个过程遵循着这样的主要步骤:

    1. 一个叫做 POST上电自检)的过程会对你的电脑硬件组件做全面的检查。
    1. POST 完成后,它会把控制权转交给引导加载程序,接下来引导加载程序会将 Linux 内核(以及 initramfs)加载到内存中并执行。
    1. 内核首先检查并访问硬件,然后运行初始化进程(主要以它的通用名 init 而为人熟知),接下来初始化进程会启动一些服务,最后完成系统启动过程。

在该系列的第七讲(“SysVinit、Upstart 和 Systemd”)中,我们介绍了现代 Linux 发行版使用的一些服务管理系统和工具。在继续学习之前,你可能想要回顾一下那一讲的知识。

GRUB 引导装载程序介绍

在现代系统中,你会发现有两种主要的 GRUB 版本(一种是有时被称为 GRUB Legacyv1 版本,另一种则是 v2 版本),虽说多数最新版本的发行版系统都默认使用了 v2 版本。如今,只有 红帽企业版 Linux 6 及其衍生系统仍在使用 v1 版本。

因此,在本指南中,我们将着重关注 v2 版本的功能。

不管 GRUB 的版本是什么,一个引导加载程序都允许用户:

  1. 通过指定使用不同的内核来修改系统的行为;
  2. 从多个操作系统中选择一个启动;
  3. 添加或编辑配置区块来改变启动选项等。

如今,GNU 项目负责维护 GRUB,并在它们的网站上提供了丰富的文档。当你在阅读这篇指南时,我们强烈建议你看下 GNU 官方文档

当系统引导时,你会在主控制台看到如下的 GRUB 画面。最开始,你可以根据提示在多个内核版本中选择一个内核(默认情况下,系统将会使用最新的内核启动),并且可以进入 GRUB 命令行模式(使用 c 键),或者编辑启动项(按下 e 键)。

GRUB 启动画面

你会考虑使用一个旧版内核启动的原因之一是之前工作正常的某个硬件设备在一次升级后出现了“怪毛病(acting up)”(例如,你可以参考 AskUbuntu 论坛中的这条链接)。

在启动时会从 /boot/grub/grub.cfg/boot/grub2/grub.cfg 文件中读取GRUB v2 的配置文件,而 GRUB v1 使用的配置文件则来自 /boot/grub/grub.conf/boot/grub/menu.lst。这些文件不应该直接手动编辑,而应通过 /etc/default/grub 的内容和 /etc/grub.d 目录中的文件来更新。

CentOS 7 上,当系统最初完成安装后,会生成如下的配置文件:

GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="vconsole.keymap=la-latin1 rd.lvm.lv=centos_centos7-2/swap crashkernel=auto  vconsole.font=latarcyrheb-sun16 rd.lvm.lv=centos_centos7-2/root rhgb quiet"
GRUB_DISABLE_RECOVERY="true"

除了在线文档外,你也可以使用下面的命令查阅 GNU GRUB 手册:

# info grub

如果你对 /etc/default/grub 文件中的可用选项特别感兴趣的话,你可以直接查阅配置一节的帮助文档:

# info -f grub -n 'Simple configuration'

使用上述命令,你会发现 GRUB_TIMEOUT 用于设置启动画面出现和系统自动开始启动(除非被用户中断)之间的时间。当该变量值为 -1 时,除非用户主动做出选择,否则不会开始启动。

当同一台机器上安装了多个操作系统或内核后,GRUB_DEFAULT 就需要用一个整数来指定 GRUB 启动画面默认选择启动的操作系统或内核条目。我们既可以通过上述启动画面查看启动条目列表,也可以使用下面的命令:

在 CentOS 和 openSUSE 系统上

# awk -F\' '$1=="menuentry " {print $2}' /boot/grub2/grub.cfg

在 Ubuntu 系统上

# awk -F\' '$1=="menuentry " {print $2}' /boot/grub/grub.cfg

如下图所示的例子中,如果我们想要使用版本为 3.10.0-123.el7.x86_64 的内核(第四个条目),我们需要将 GRUB_DEFAULT 设置为 3(条目从零开始编号),如下所示:

GRUB_DEFAULT=3

使用旧版内核启动系统

最后一个需要特别关注的 GRUB 配置变量是 GRUB_CMDLINE_LINUX,它是用来给内核传递选项的。我们可以在 内核变量文件man 7 bootparam 中找到能够通过 GRUB 传递给内核的选项的详细文档。

我的 CentOS 7 服务器上当前的选项是:

GRUB_CMDLINE_LINUX="vconsole.keymap=la-latin1 rd.lvm.lv=centos_centos7-2/swap crashkernel=auto  vconsole.font=latarcyrheb-sun16 rd.lvm.lv=centos_centos7-2/root rhgb quiet"

为什么你希望修改默认的内核参数或者传递额外的选项呢?简单来说,在很多情况下,你需要告诉内核某些由内核自身无法判断的硬件参数,或者是覆盖一些内核检测的值。

不久之前,就在我身上发生过这样的事情,当时我在自己已用了 10 年的老笔记本上尝试了衍生自 SlackwareVector Linux。完成安装后,内核并没有检测出我的显卡的正确配置,所以我不得不通过 GRUB 传递修改过的内核选项来让它工作。

另外一个例子是当你需要将系统切换到单用户模式以执行维护工作时。为此,你可以直接在 GRUB_CMDLINE_LINUX 变量中直接追加 single 并重启即可:

GRUB_CMDLINE_LINUX="vconsole.keymap=la-latin1 rd.lvm.lv=centos_centos7-2/swap crashkernel=auto  vconsole.font=latarcyrheb-sun16 rd.lvm.lv=centos_centos7-2/root rhgb quiet single"

编辑完 /etc/default/grub 之后,你需要运行 update-grub (在 Ubuntu 上)或者 grub2-mkconfig -o /boot/grub2/grub.cfg (在 CentOSopenSUSE 上)命令来更新 grub.cfg 文件(否则,改动会在系统启动时丢失)。

这条命令会处理早先提到的那些启动配置文件来更新 grub.cfg 文件。这种方法可以确保改动持久化,而在启动时刻通过 GRUB 传递的选项仅在当前会话期间有效。

修复 Linux GRUB 问题

如果你安装了第二个操作系统,或者由于人为失误而导致你的 GRUB 配置文件损坏了,依然有一些方法可以让你恢复并能够再次启动系统。

在启动画面中按下 c 键进入 GRUB 命令行模式(记住,你也可以按下 e 键编辑默认启动选项),并可以在 GRUB 提示中输入 help 命令获得可用命令:

修复 Linux 的 Grub 配置问题

我们将会着重关注 ls 命令,它会列出已安装的设备和文件系统,并且我们将会看看它查找到的东西。在下面的图片中,我们可以看到有 4 块硬盘(hd0hd3)。

貌似只有 hd0 已经分区了(msdos1 和 msdos2 可以证明,这里的 1 和 2 是分区号,msdos 则是分区方案)。

现在我们来看看能否在第一个分区 hd0msdos1)上找到 GRUB。这种方法允许我们启动 Linux,并且使用高级工具修复配置文件,或者如果有必要的话,干脆重新安装 GRUB:

# ls (hd0,msdos1)/

从高亮区域可以发现,grub2 目录就在这个分区:

查找 Grub 配置

一旦我们确信了 GRUB 位于 (hd0, msdos1),那就让我们告诉 GRUB 该去哪儿查找它的配置文件并指示它去尝试启动它的菜单:

set prefix=(hd0,msdos1)/grub2
set root=(hd0,msdos1)
insmod normal
normal

查找并启动 Grub 菜单

然后,在 GRUB 菜单中,选择一个条目并按下回车键以使用它启动。一旦系统成功启动后,你就可以运行 grub2-install /dev/sdX 命令修复问题了(将 sdX 改成你想要安装 GRUB 的设备)。然后启动信息将会更新,并且所有相关文件都会得到恢复。

# grub2-install /dev/sdX

其它更加复杂的情景及其修复建议都记录在 Ubuntu GRUB2 故障排除指南 中。该指南中阐述的概念对于其它发行版也是有效的。

总结

本文向你介绍了 GRUB,并指导你可以在何处找到线上和线下的文档,同时说明了如何面对由于引导加载相关的问题而导致系统无法正常启动的情况。

幸运的是,GRUB 是文档支持非常丰富的工具之一,你可以使用我们在文中分享的资源非常轻松地获取已安装的文档或在线文档。

你有什么问题或建议吗?请不要犹豫,使用下面的评论框告诉我们吧。我们期待着来自你的回复!


via: http://www.tecmint.com/configure-and-troubleshoot-grub-boot-loader-linux/

作者:Gabriel Cánepa 译者:ChrisLeeGit 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

当你需要保存日期时间数据时,一个问题来了:你应该使用 MySQL 中的什么类型?使用 MySQL 原生的 DATE 类型还是使用 INT 字段把日期和时间保存为一个纯数字呢?

在这篇文章中,我将解释 MySQL 原生的方案,并给出一个最常用数据类型的对比表。我们也将对一些典型的查询做基准测试,然后得出在给定场景下应该使用什么数据类型的结论。

如果你想直接看结论,请翻到文章最下方。

原生的 MySQL Datetime 数据类型

Datetime 数据表示一个时间点。这可以用作日志记录、物联网时间戳、日历事件数据,等等。MySQL 有两种原生的类型可以将这种信息保存在单个字段中:Datetime 和 Timestamp。MySQL 文档中是这么介绍这些数据类型的:

DATETIME 类型用于保存同时包含日期和时间两部分的值。MySQL 以 'YYYY-MM-DD HH:MM:SS' 形式接收和显示 DATETIME 类型的值。

TIMESTAMP 类型用于保存同时包含日期和时间两部分的值。

DATETIME 或 TIMESTAMP 类型的值可以在尾部包含一个毫秒部分,精确度最高到微秒(6 位数)。

TIMESTAMP 和 DATETIME 数据类型提供自动初始化和更新到当前的日期和时间的功能,只需在列的定义中设置 DEFAULT CURRENTTIMESTAMP 和 ON UPDATE CURRENTTIMESTAMP。

作为一个例子:

CREATE TABLE `datetime_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;

除了原生的日期时间表示方法,还有另一种常用的存储日期和时间信息的方法。即使用 INT 字段保存 Unix 时间(从1970 年 1 月 1 日协调世界时(UTC)建立所经过的秒数)。

MySQL 也提供了只保存时间信息中的一部分的方式,通过使用 Date、Year 或 Time 类型。由于这篇文章是关于保存准确时间点的最佳方式的,我们没有讨论这些不那么精确的局部类型。

使用 INT 类型保存 Unix 时间

使用一个简单的 INT 列保存 Unix 时间是最普通的方法。使用 INT,你可以确保你要保存的数字可以快速、可靠地插入到表中,就像这样:

INSERT INTO `vertabelo`.`sampletable`
(
 `id`,
 `measured_on` ### INT 类型的列
)
VALUES
(
 1,
 946684801
 ### 至 01/01/2000 @ 12:00am (UTC) 的 UNIX 时间戳 http://unixtimestamp.com
);

这就是关于它的所有内容了。它仅仅是个简单的 INT 列,MySQL 的处理方式是这样的:在内部使用 4 个字节保存那些数据。所以如果你在这个列上使用 SELECT 你将会得到一个数字。如果你想把这个列用作日期进行比较,下面的查询并不能正确工作:

SELECT
    id, measured_on, FROM_UNIXTIME(measured_on)
FROM
    vertabelo.inttimestampmeasures
WHERE
    measured_on > '2016-01-01' ### measured_on 会被作为字符串比较以进行查询
LIMIT 5;

这是因为 MySQL 把 INT 视为数字,而非日期。为了进行日期比较,你必须要么获取( LCTT 译注:从 1970-01-01 00:00:00)到 2016-01-01 经过的秒数,要么使用 MySQL 的 FROM\_UNIXTIME() 函数把 INT 列转为 Date 类型。下面的查询展示了 FROM\_UNIXTIME() 函数的用法:

SELECT
    id, measured_on, FROM_UNIXTIME(measured_on)
FROM
    vertabelo.inttimestampmeasures
WHERE
    FROM_UNIXTIME(measured_on) > '2016-01-01'
LIMIT 5;

这会正确地获取到日期在 2016-01-01 之后的记录。你也可以直接比较数字和 2016-01-01 的 Unix 时间戳表示形式,即 1451606400。这样做意味着不用使用任何特殊的函数,因为你是在直接比较数字。查询如下:

SELECT
    id, measured_on, FROM_UNIXTIME(measured_on)
FROM
    vertabelo.inttimestampmeasures
WHERE
   measured_on > 1451606400
LIMIT 5;

假如这种方式不够高效甚至提前做这种转换是不可行的话,那该怎么办?例如,你想获取 2016 年所有星期三的记录。要做到这样而不使用任何 MySQL 日期函数,你就不得不查出 2016 年每个星期三的开始和结束时间的 Unix 时间戳。然后你不得不写很大的查询,至少要在 WHERE 中包含 104 个比较。(2016 年有 52 个星期三,你不得不考虑一天的开始(0:00 am)和结束(11:59:59 pm)...)

结果是你很可能最终会使用 FROM\_UNIXTIME() 转换函数。既然如此,为什么不试下真正的日期类型呢?

使用 Datetime 和 Timestamp

Datetime 和 Timestamp 几乎以同样的方式工作。两种都保存日期和时间信息,毫秒部分最高精确度都是 6 位数。同时,使用人类可读的日期形式如 "2016-01-01" (为了便于比较)都能工作。查询时两种类型都支持“宽松格式”。宽松的语法允许任何标点符号作为分隔符。例如,"YYYY-MM-DD HH:MM:SS" 和 "YY-MM-DD HH:MM:SS" 两种形式都可以。在宽松格式情况下以下任何一种形式都能工作:

2012-12-31 11:30:45
2012^12^31 11+30+45
2012/12/31 11*30*45
2012@12@31 11^30^45

其它宽松格式也是允许的;你可以在 MySQL 参考手册 找到所有的格式。

默认情况下,Datetime 和 Timestamp 两种类型查询结果都以标准输出格式显示 —— 年-月-日 时:分:秒 (如 2016-01-01 23:59:59)。如果使用了毫秒部分,它们应该以小数值出现在秒后面 (如 2016-01-01 23:59:59.5)。

Timestamp 和 Datetime 的核心不同点主要在于 MySQL 在内部如何表示这些信息:两种都以二进制而非字符串形式存储,但在表示日期/时间部分时 Timestamp (4 字节) 比 Datetime (5 字节) 少使用 1 字节。当保存毫秒部分时两种都使用额外的空间 (1-3 字节)。如果你存储 150 万条记录,这种 1 字节的差异是微不足道的:

150 万条记录 * 每条记录 1 字节 / (1048576 字节/MB) = 1.43 MB

Timestamp 节省的 1 字节是有代价的:你只能存储从 '1970-01-01 00:00:01.000000' 到 '2038-01-19 03:14:07.999999' 之间的时间。而 Datetime 允许你存储从 '1000-01-01 00:00:00.000000' 到 '9999-12-31 23:59:59.999999' 之间的任何时间。

另一个重要的差别 —— 很多 MySQL 开发者没意识到的 —— 是 MySQL 使用服务器的时区转换 Timestamp 值到它的 UTC 等价值再保存。当获取值是它会再次进行时区转换,所以你得回了你“原始的”日期/时间值。有可能,下面这些情况会发生。

理想情况下,如果你一直使用同一个时区,MySQL 会获取到和你存储的同样的值。以我的经验,如果你的数据库涉及时区变换,你可能会遇到问题。例如,服务器变化(比如,你把数据库从都柏林的一台服务器迁移到加利福尼亚的一台服务器上,或者你只是修改了一下服务器的时区)时可能会发生这种情况。不管哪种方式,如果你获取数据时的时区是不同的,数据就会受影响。

Datetime 列不会被数据库改变。无论时区怎样配置,每次都会保存和获取到同样的值。就我而言,我认为这是一个更可靠的选择。

MySQL 文档:

MySQL 把 TIMESTAMP 值从当前的时区转换到 UTC 再存储,获取时再从 UTC 转回当前的时区。(其它类型如 DATETIME 不会这样,它们会“原样”保存。) 默认情况下,每个连接的当前时区都是服务器的时区。时区可以基于连接设置。只要时区设置保持一致,你就能得到和保存的相同的值。如果你保存了一个 TIMESTAMP 值,然后改变了时区再获取这个值,获取到的值和你存储的是不同的。这是因为在写入和查询的会话上没有使用同一个时区。当前时区可以通过系统变量 time\_zone 的值得到。更多信息,请查看 MySQL Server Time Zone Support

对比总结

在深入探讨使用各数据类型的性能差异之前,让我们先看一个总结表格以给你更多了解。每种类型的弱点以红色显示。

特性DatetimeTimestampInt (保存 Unix 时间)
原生时间表示否,所以大多数操作需要先使用转换函数,如 FROM\_UNIXTIME()
能保存毫秒是,最高 6 位精度是,最高 6 位精度
合法范围'1000-01-01 00:00:00.000000' 到 '9999-12-31 23:59:59.999999'1970-01-01 00:00:01.000000' 到 '2038-01-19 03:14:07.999999'若使用 unsigned, '1970-01-01 00:00:01.000000; 理论上最大到 '2106-2-07 06:28:15'
自动初始化(MySQL 5.6.5+)
宽松解释 (MySQL docs否,必须使用正确的格式
值被转换到 UTC 存储
可转换到其它类型是,如果值在合法的 Timestamp 范围中是,总是是,如果值在合法的范围中并使用转换函数
存储需求(MySQL 5.6.4+5 字节(如果使用了毫秒部分,再加最多 3 字节)4 字节 (如果使用了毫秒部分,再加最多 3 字节)4 字节 (不允许毫秒部分)
无需使用函数即可作为真实日期可读否,你必须格式化输出
数据分区是,使用 UNIX\_TIMESTAMP();在 MySQL 5.7 中其它表达式是不允许包含 TIMESTAMP 值的。同时,注意分区裁剪时的这些考虑是,使用 INT 上的任何合法操作

基准测试 INT、Timestamp 和 Datetime 的性能

为了比较这些类型的性能,我会使用我创建的一个天气预报网络的 150 万记录(准确说是 1,497,421)。这个网络每分钟都收集数据。为了让这些测试可复现,我已经删除了一些私有列,所以你可以使用这些数据运行你自己的测试。

基于我原始的表格,我创建了三个版本:

  • datetimemeasures 表在 measured_on 列使用 Datetime 类型,表示天气预报记录的测量时间
  • timestampmeasures 表在 measured_on 列使用 Timestamp 类型
  • inttimestampmeasures 表在 measured_on 列使用 INT (unsigned) 类型

这三个表拥有完全相同的数据;唯一的差别就是 measured_on 字段的类型。所有表都在 measured_on 列上设置了一个索引。

基准测试工具

为了评估这些数据类型的性能,我使用了两种方法。一种基于 Sysbench,它的官网是这么描述的:

... 一个模块化、跨平台和多线程的基准测试工具,用以评估那些对运行高负载数据库的系统非常重要的系统参数。

这个工具是 MySQL 文档中推荐的。

如果你使用 Windows (就像我),你可以下载一个包含可执行文件和我使用的测试查询的 zip 文件。它们基于 一种推荐的基准测试方法

为了执行一个给定的测试,你可以使用下面的命令(插入你自己的连接参数):

sysbench --MySQL-table-engine=innodb --MySQL-db=vertabelo --MySQL-user=root --MySQL-host=localhost --MySQL-password= --test=sysbench_test_file.lua --num-threads=8 --max-requests=100 run

这会正常工作,这里 sysbench_test_file.lua 是测试文件,并包含了各个测试中指向各个表的 SQL 查询。

为了进一步验证结果,我也运行了 mysqlslap。它的官网是这么描述的:

mysqlslap 是一个诊断程序,为模拟 MySQL 服务器的客户端负载并报告各个阶段的用时而设计。它工作起来就像是很多客户端在同时访问服务器。”

记得这些测试中最重要的不是所需的绝对时间。而是在不同数据类型上执行相同查询时的相对时间。这两个基准测试工具的测试时间不一定相同,因为不同工具的工作方式不同。重要的是数据类型的比较,随着我们深入到测试中,这将会变得清楚。

基准测试

我将使用三种可以评估几个性能方面的查询:

  • 时间范围选择

    • 在 Datetime 和 Timestamp 数据类型上这允许我们直接比较而不需要使用任何特殊的日期函数。
    • 同时,我们可以评估在 INT 类型的列上使用日期函数相对于使用简单的数值比较的影响。为了做到这些我们需要把范围转换为 Unix 时间戳数值。
  • 日期函数选择

    • 与前个测试中比较操作针对一个简单的 DATE 值相反,这个测试使得我们可以评估使用日期函数作为 “WHERE” 子句的一部分的性能。
    • 我们还可以测试一个场景,即我们必须使用一个函数将 INT 列转换为一个合法的 DATE 类型然后执行查询。
  • count() 查询

    • 作为对前面测试的补充,这将评估在三种不同的表示类型上进行典型的统计查询的性能。

我们将在这些测试中覆盖一些常见的场景,并看到三种类型上的性能表现。

关于 SQL\_NO\_CACHE

当在查询中使用 SQL\_NO\_CACHE 时,服务器不使用查询缓存。它既不检查查询缓存以确认结果是不是已经在那儿了,也不会保存查询结果。因此,每个查询将反映真实的性能影响,就像每次查询都是第一次被调用。

测试 1:选择一个日期范围中的值

这个查询返回总计 1,497,421 行记录中的 75,706 行。

查询 1 和 Datetime:

SELECT SQL_NO_CACHE
    measured_on
FROM
    vertabelo.datetimemeasures m
WHERE
    m.measured_on > '2016-01-01 00:00:00.0'
      AND m.measured_on < '2016-02-01 00:00:00.0';

性能

响应时间 (ms)Sysbenchmysqlslap
最小152296
最大12613203
平均362809
Sysbench cmd> sysbench --MySQL-table-engine=innodb --MySQL-db=vertabelo --MySQL-user=root --MySQL-host=localhost --MySQL-password= --test=datetime.lua --num-threads=8 --max-requests=100 run
mysqlslap cmd> mysqlslap --query="SELECT SQL_NO_CACHE measured_on FROM vertabelo.datetimemeasures m WHERE m.measured_on > '2016-01-01 00:00:00.0' AND m.measured_on < '2016-02-01 00:00:00.0'" --host=localhost --user=root --concurrency=8 --iterations=100  --no-drop --create-schema=vertabelo

查询 1 和 Timestamp:

SELECT SQL_NO_CACHE
    measured_on
FROM
    vertabelo.timestampmeasures m
WHERE
    m.measured_on > '2016-01-01 00:00:00.0'
        AND m.measured_on < '2016-02-01 00:00:00.0';

性能

响应时间 (ms)Sysbenchmysqlslap
最小214359
最大13893313
平均4311004
Sysbench cmd> sysbench --MySQL-table-engine=innodb --MySQL-db=vertabelo --MySQL-user=root --MySQL-host=localhost --MySQL-password= --test=timestamp.lua --num-threads=8 --max-requests=100 run
mysqlslap cmd> mysqlslap --query="SELECT SQL_NO_CACHE measured_on FROM vertabelo.timestampmeasures m WHERE m.measured_on > '2016-01-01 00:00:00.0' AND m.measured_on < '2016-02-01 00:00:00.0'" --host=localhost --user=root --concurrency=8 --iterations=100  --no-drop --create-schema=vertabelo

查询 1 和 INT:

SELECT SQL_NO_CACHE
    measured_on
FROM
    vertabelo.inttimestampmeasures m
WHERE
    FROM_UNIXTIME(m.measured_on) > '2016-01-01 00:00:00.0'
        AND FROM_UNIXTIME(m.measured_on) < '2016-02-01 00:00:00.0';

性能

响应时间 (ms)Sysbenchmysqlslap
最小24727968
最大655410312
平均41078527
Sysbench cmd> sysbench --MySQL-table-engine=innodb --MySQL-db=vertabelo --MySQL-user=root --MySQL-host=localhost --MySQL-password= --test=int.lua --num-threads=8 --max-requests=100 run
mysqlslap cmd> mysqlslap --query="SELECT SQL_NO_CACHE measured_on FROM vertabelo.inttimestampmeasures m WHERE FROM_UNIXTIME(m.measured_on) > '2016-01-01 00:00:00.0' AND FROM_UNIXTIME(m.measured_on) < '2016-02-01 00:00:00.0'" --host=localhost --user=root --concurrency=8 --iterations=100  --no-drop --create-schema=vertabelo

另一种 INT 上的查询 1:

由于这是个相当直接的范围搜索,而且查询中的日期可以轻易地转为简单的数值比较,我将它包含在了这个测试中。结果证明这是最快的方法 (你大概已经预料到了),因为它仅仅是比较数字而没有使用任何日期转换函数:

SELECT SQL_NO_CACHE
    measured_on
FROM
    vertabelo.inttimestampmeasures m
WHERE
    m.measured_on > 1451617200
        AND m.measured_on < 1454295600;

性能

响应时间 (ms)Sysbenchmysqlslap
最小88171
最大2752157
平均165514
Sysbench cmd> sysbench --MySQL-table-engine=innodb --MySQL-db=vertabelo --MySQL-user=root --MySQL-host=localhost --MySQL-password= --test=basic_int.lua --num-threads=8 --max-requests=100 run
mysqlslap cmd> mysqlslap --query="SELECT SQL_NO_CACHE measured_on FROM vertabelo.inttimestampmeasures m WHERE m.measured_on > 1451617200 AND m.measured_on < 1454295600" --host=localhost --user=root --concurrency=8 --iterations=100  --no-drop --create-schema=vertabelo

测试 1 总结

平均响应时间 (ms)Sysbench相对于 Datetime 的速度mysqlslap相对于 Datetime 的速度
Datetime362-809-
Timestamp431慢 19%1004慢 24%
INT4107慢 1134%8527慢 1054%
另一种 INT 查询165快 55%514快 36%

两种基准测试工具都显示 Datetime 比 Timestamp 和 INT 更快。但 Datetime 没有我们在另一种 INT 查询中使用的简单数值比较快。

测试 2:选择星期一产生的记录

这个查询返回总计 1,497,421 行记录中的 221,850 行。

查询 2 和 Datetime:

SELECT SQL_NO_CACHE measured_on
FROM
    vertabelo.datetimemeasures m
WHERE
    WEEKDAY(m.measured_on) = 0; # MONDAY

性能

响应时间 (ms)Sysbenchmysqlslap
最小18744343
最大61687797
平均31276103
Sysbench cmd> sysbench --MySQL-table-engine=innodb --MySQL-db=vertabelo --MySQL-user=root --MySQL-host=localhost --MySQL-password= --test=datetime_1.lua --num-threads=8 --max-requests=100 run
mysqlslap cmd> mysqlslap --query="SELECT SQL_NO_CACHE measured_on FROM vertabelo.datetimemeasures m WHERE WEEKDAY(m.measured_on) = 0" --host=localhost --user=root --concurrency=8 --iterations=25 --no-drop --create-schema=vertabelo

查询 2 和 Timestamp:

SELECT SQL_NO_CACHE
    measured_on
FROM
    vertabelo.timestampmeasures m
WHERE
    WEEKDAY(m.measured_on) = 0; # MONDAY

性能

响应时间 (ms)Sysbenchmysqlslap
最小26885953
最大666613531
平均36538412
Sysbench cmd> sysbench --MySQL-table-engine=innodb --MySQL-db=vertabelo --MySQL-user=root --MySQL-host=localhost --MySQL-password= --test=timestamp_1.lua --num-threads=8 --max-requests=100 run
mysqlslap cmd> mysqlslap --query="SELECT SQL_NO_CACHE measured_on FROM vertabelo.timestampmeasures m WHERE WEEKDAY(m.measured_on) = 0" --host=localhost --user=root --concurrency=8 --iterations=25 --no-drop --create-schema=vertabelo

查询 2 和 INT:

SELECT SQL_NO_CACHE
    measured_on
FROM
    vertabelo.inttimestampmeasures m
WHERE
    WEEKDAY(FROM_UNIXTIME(m.measured_on)) = 0; # MONDAY

性能

响应时间 (ms)Sysbenchmysqlslap
最小20515844
最大700710469
平均34868088
Sysbench cmd> sysbench --MySQL-table-engine=innodb --MySQL-db=vertabelo --MySQL-user=root --MySQL-host=localhost --MySQL-password= --test=int_1.lua --num-threads=8 --max-requests=100 run
mysqlslap cmd> mysqlslap --query="SELECT SQL_NO_CACHE measured_on FROM vertabelo.inttimestampmeasures m WHERE WEEKDAY(FROM_UNIXTIME(m.measured_on)) = 0" --host=localhost --user=root --concurrency=8 --iterations=25  --no-drop --create-schema=vertabelo

测试 2 总结

平均响应时间 (ms)Sysbench相对于 Datetime 的速度mysqlslap相对于 Datetime 的速度
Datetime3127-6103-
Timestamp3653慢 17%8412慢 38%
INT3486慢 11%8088慢 32%

再次,在两个基准测试工具中 Datetime 比 Timestamp 和 INT 快。但在这个测试中,INT 查询 —— 即使它使用了一个函数以转换日期 —— 比 Timestamp 查询更快得到结果。

测试 3:选择星期一产生的记录总数

这个查询返回一行,包含产生于星期一的所有记录的总数(从总共 1,497,421 行可用记录中)。

查询 3 和 Datetime:

SELECT SQL_NO_CACHE
    COUNT(measured_on)
FROM
    vertabelo.datetimemeasures m
WHERE
    WEEKDAY(m.measured_on) = 0; # MONDAY

性能

响应时间 (ms)Sysbenchmysqlslap
最小17204063
最大45947812
平均27975540
Sysbench cmd> sysbench --MySQL-table-engine=innodb --MySQL-db=vertabelo --MySQL-user=root --MySQL-host=localhost --MySQL-password= --test=datetime_1_count.lua --num-threads=8 --max-requests=100 run
mysqlslap cmd> mysqlslap --query="SELECT SQL_NO_CACHE COUNT(measured_on) FROM vertabelo.datetimemeasures m WHERE WEEKDAY(m.measured_on) = 0" --host=localhost --user=root --concurrency=8 --iterations=25 --no-drop --create-schema=vertabelo

查询 3 和 Timestamp:

SELECT SQL_NO_CACHE
    COUNT(measured_on)
FROM
    vertabelo.timestampmeasures m
WHERE
    WEEKDAY(m.measured_on) = 0; # MONDAY

性能

响应时间 (ms)Sysbenchmysqlslap
最小19074578
最大543710235
平均34087102
Sysbench cmd> sysbench --MySQL-table-engine=innodb --MySQL-db=vertabelo --MySQL-user=root --MySQL-host=localhost --MySQL-password= --test=timestamp_1_count.lua --num-threads=8 --max-requests=100 run
mysqlslap cmd> mysqlslap --query="SELECT SQL_NO_CACHE COUNT(measured_on) FROM vertabelo.timestampmeasures m WHERE WEEKDAY(m.measured_on) = 0" --host=localhost --user=root --concurrency=8 --iterations=25 --no-drop --create-schema=vertabelo

查询 3 和 INT:

SELECT SQL_NO_CACHE
    COUNT(measured_on)
FROM
    vertabelo.inttimestampmeasures m
WHERE
    WEEKDAY(FROM_UNIXTIME(m.measured_on)) = 0; # MONDAY

性能

响应时间 (ms)Sysbenchmysqlslap
最小21085609
最大47649735
平均33077416
Sysbench cmd> sysbench --MySQL-table-engine=innodb --MySQL-db=vertabelo --MySQL-user=root --MySQL-host=localhost --MySQL-password= --test=int_1_count.lua --num-threads=8 --max-requests=100 run
mysqlslap cmd> mysqlslap --query="SELECT SQL_NO_CACHE COUNT(measured_on) FROM vertabelo.inttimestampmeasures m WHERE WEEKDAY(FROM_UNIXTIME(m.measured_on)) = 0" --host=localhost --user=root --concurrency=8 --iterations=25  --no-drop --create-schema=vertabelo

测试 3 总结

平均响应时间 (ms)Sysbench相对于 Datetime 的速度mysqlslap相对于 Datetime 的速度
Datetime2797-5540-
Timestamp3408慢 22%7102慢 28%
INT3307慢 18%7416慢 33%

再一次,两个基准测试工具都显示 Datetime 比 Timestamp 和 INT 快。不能判断 INT 是否比 Timestamp 快,因为 mysqlslap 显示 INT 比 Timestamp 略快而 Sysbench 却相反。

注意: 所有测试都是在一台 Windows 10 机器上本地运行的,这台机器拥有一个双核 i7 CPU,16GB 内存,运行 MariaDB v10.1.9,使用 innoDB 引擎。

结论

基于这些数据,我确信 Datetime 是大多数场景下的最佳选择。原因是:

  • 更快(根据我们的三个基准测试)。
  • 无需任何转换即是人类可读的。
  • 不会因为时区变换产生问题。
  • 只比它的对手们多用 1 字节
  • 支持更大的日期范围(从 1000 年到 9999 年)

如果你只是存储 Unix 时间戳(并且在它的合法日期范围内),而且你真的不打算在它上面使用任何基于日期的查询,我觉得使用 INT 是可以的。我们已经看到,它执行简单数值比较查询时非常快,因为只是在处理简单的数字。

Timestamp 怎么样呢?如果 Datetime 相对于 Timestamp 的优势不适用于你特殊的场景,你最好使用时间戳。阅读这篇文章后,你对三种类型间的区别应该有了更好的理解,可以根据你的需要做出最佳的选择。


via: http://www.vertabelo.com/blog/technical-articles/what-datatype-should-you-use-to-represent-time-in-mysql-we-compare-datetime-timestamp-and-int

作者:Francisco Claria 译者:bianjp 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这篇教程说明你应该怎样配置 nginx、设置 HTTP 头部过期时间,用 Cache-Control 中的 max-age 标记为静态文件(比如图片、 CSS 和 Javascript 文件)设置一个时间,这样用户的浏览器就会缓存这些文件。这样能节省带宽,并且在访问你的网站时会显得更快些(如果用户第二次访问你的网站,将会使用浏览器缓存中的静态文件)。

1、准备事项

我想你需要一个正常工作的 nginx 软件,就像这篇教程里展示的:在 Ubuntu 16.04 LTS 上安装 Nginx,PHP 7 和 MySQL 5.7 (LEMP)

2 配置 nginx

可以参考 expires 指令手册来设置 HTTP 头部过期时间,这个标记可以放在 http {}server {}location {} 等语句块或者 location {} 语句块中的条件语句中。一般会在 location 语句块中用 expires 指令控制你的静态文件,就像下面一样:

location ~*  \.(jpg|jpeg|png|gif|ico|css|js)$ {
   expires 365d;
}

在上面的例子中,所有后缀名是 .jpg.jpeg.png.gif.ico.css.js 的文件会在浏览器访问该文件之后的 365 天后过期。因此你要确保 location {} 语句块仅仅包含能被浏览器缓存的静态文件。

然后重启 nginx 进程:

/etc/init.d/nginx reload

你可以在 expires 指令中使用以下的时间设置:

  • offExpiresCache-Control 头部不能被更改。
  • epochExpires 头部设置成 1970 年 1 月 1 日 00:00:01。
  • max 设置 Expires 头部为 2037 年 12 月 31 日 23:59:59,设置 Cache-Control 的最大存活时间为 10 年
  • 没有 @ 前缀的时间意味着这是一个与浏览器访问时间有关的过期时间。可以指定一个负值的时间,就会把 Cache-Control 头部设置成 no-cache。例如:expires 10d 或者 expires 14w3d
  • @ 前缀的时间指定在一天中的某个时间过期,格式是 Hh 或者 Hh:Mm,H 的范围是 0 到 24,M 的范围是 0 到 59,例如:expires @15:34

你可以用以下的时间单位:

  • ms: 毫秒
  • s: 秒
  • m: 分钟
  • h: 小时
  • d: 天
  • w: 星期
  • M: 月 (30 天)
  • y: 年 (365 天)

例如:1h30m 表示一小时三十分钟,1y6M 表示一年六个月。

注意,要是你用一个在将来很久才会过期的头部,当组件修改时你就要改变组件的文件名。因此给文件指定版本是一个不错的方法。例如,如果你有个 javascript.js 文件 并且你要修改它,你可以在修改的文件名字后面添加一个版本号。这样浏览器就要下载这个文件,如果你没有更改文件名,浏览器将从缓存里面加载(旧的)文件。

除了把基于浏览器访问时间设置 Expires 头部(比如 expires 10d)之外,也可以通过在时间前面的 modified 关键字,将 Expires 头部的基准设为文件修改的时间(请注意这仅仅对存储在硬盘的实际文件有效)。

expires modified 10d;

3 测试

要测试你的配置是否有效,可以用火狐浏览器的开发者工具中的网络分析功能,然后用火狐访问一个静态文件(比如一张图片)。在输出的头部信息里,应该能看到 Expires 头部和有 max-age 标记的 Cache-Control 头部(max-age 标记包含了一个以秒为单位的值,比如 31536000 就是指今后的一年)

4 链接

nginx 的 Http 头部模块(HttpHeadersModule): http://wiki.nginx.org/HttpHeadersModule


via: https://www.howtoforge.com/tutorial/how-to-cache-static-files-on-nginx/

作者:Falko Timme 译者:GitFuture 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

当你回顾所有到目前为止我们已经覆盖的 awk 实例,从 awk 系列的开始,你会注意到各种实例的所有指令是顺序执行的,即一个接一个地执行。但在某些情况下,我们可能希望基于一些条件进行文本过滤操作,即流程控制语句允许的那些语句。

在 awk 编程中有各种各样的流程控制语句,其中包括:

  • if-else 语句
  • for 语句
  • while 语句
  • do-while 语句
  • break 语句
  • continue 语句
  • next 语句
  • nextfile 语句
  • exit 语句

然而,对于本系列的这一部分,我们将阐述:if-elseforwhiledo while 语句。请记住,我们已经在这个 awk 系列的第 6 部分介绍过如何使用 awk 的 next 语句。

1. if-else 语句

如你想的那样。if 语句的语法类似于 shell 中的 if 语句:

if  (条件 1) {
     动作 1
}
else {
      动作 2
}

在上述语法中,条件 1条件 2 是 awk 表达式,而动作 1动作 2 是当各自的条件得到满足时所执行的 awk 命令。

条件 1 满足时,意味着它为真,那么动作 1 被执行并退出 if 语句,否则动作 2 被执行。

if 语句还能扩展为如下的 if-else_if-else 语句:

if (条件 1){
     动作 1
}
else if (条件 2){
      动作 2
}
else{
     动作 3
}

对于上面的形式,如果条件 1 为真,那么动作 1 被执行并退出 if 语句,否则条件 2 被求值且如果值为真,那么动作 2 被执行并退出 if 语句。然而,当条件 2 为假时,那么动作 3 被执行并退出 if 语句

这是在使用 if 语句的一个实例,我们有一个用户和他们年龄的列表,存储在文件 users.txt 中。

我们要打印一个清单,显示用户的名称和用户的年龄是否小于或超过 25 岁。

aaronkilik@tecMint ~ $ cat users.txt
Sarah L         35      F
Aaron Kili      40      M
John  Doo       20      M
Kili  Seth      49      M

我们可以写一个简短的 shell 脚本来执行上文中我们的工作,这是脚本的内容:

#!/bin/bash
awk ' {
        if ( $3 <= 25 ){
           print "User",$1,$2,"is less than 25 years old." ;
        }
        else {
           print "User",$1,$2,"is more than 25 years old" ;
        }
}'    ~/users.txt

然后保存文件并退出,按如下方式使脚本可执行并运行它:

$ chmod +x test.sh
$ ./test.sh

输出样例

User Sarah L is more than 25 years old
User Aaron Kili is more than 25 years old
User John Doo is less than 25 years old.
User Kili Seth is more than 25 years old

2. for 语句

如果你想在一个循环中执行一些 awk 命令,那么 for 语句为你提供一个做这个的合适方式,格式如下:

for ( 计数器的初始化 ; 测试条件 ; 计数器增加 ){
      动作
}

这里,该方法是通过一个计数器来控制循环执行来定义的,首先你需要初始化这个计数器,然后针对测试条件运行它,如果它为真,执行这些动作并最终增加这个计数器。当计数器不满足条件时,循环终止。

在我们想要打印数字 0 到 10 时,以下 awk 命令显示 for 语句是如何工作的:

$ awk 'BEGIN{ for(counter=0;counter<=10;counter++){ print counter} }'

输出样例

0
1
2
3
4
5
6
7
8
9
10

3. while 语句

while 语句的传统语法如下:

while ( 条件 ) {
          动作
}

这个条件是一个 awk 表达式而动作是当条件为真时被执行的 awk 命令。

下面是一个说明使用 while 语句来打印数字 0 到 10 的脚本:

#!/bin/bash
awk ' BEGIN{ counter=0;
        while(counter<=10){
              print counter;
              counter+=1;
        }
}'

保存文件并使脚本可执行,然后运行它:

$ chmod +x test.sh
$ ./test.sh

输出样例

0
1
2
3
4
5
6
7
8
9
10

4. do while 语句

它是上文中 while 语句的一个变型,具有以下语法:

do {
     动作
}
 while (条件)

这轻微的区别在于,在 do while 语句下,awk 的命令在求值条件之前执行。使用上文 while 语句的例子,我们可以通过按如下所述修改 test.sh 脚本中的 awk 命令来说明 do while 语句的用法:

#!/bin/bash

awk ' BEGIN{ counter=0;
        do{
            print counter;
            counter+=1;
        }
        while (counter<=10)
}'

修改脚本之后,保存文件并退出。按如下方式使脚本可执行并执行它:

$ chmod +x test.sh
$ ./test.sh

输出样例

0
1
2
3
4
5
6
7
8
9
10

总结

这不是关于 awk 的流程控制语句的一个全面的指南,正如我早先提到的,在 awk 里还有其他几个流程控制语句。

尽管如此,awk 系列的这一部分使应该你明白了一个明确的基于某些条件控制的 awk 命令是如何执行的基本概念。

你还可以了解其余更多的流程控制语句以获得更多关于该主题的理解。最后,在 awk 的系列下一节,我们将进入编写 awk 脚本。


via: http://www.tecmint.com/use-flow-control-statements-with-awk-command/ 作者:Aaron Kili 译者:robot527 校对:wxy

本文由 LCTT 原创编译,Linux 中国 荣誉推出