Aliyun 盘挂载/扩容

数据盘挂载

原文链接: 分区格式化数据盘(Linux)
适用系统:Linux(Redhat , CentOS,Debian,Ubuntu)
Linux 的云服务器数据盘未做分区和格式化,可以根据以下步骤进行分区以及格式化操作。下面的操作将会把数据盘划分为一个分区来使用。

1. 查看

查看数据盘在没有分区和格式化数据盘之前,使用 df –h 命令,是无法看到数据盘的,可以使用 fdisk -l 命令查看。如下图:

友情提示:若您执行 fdisk -l 命令,发现没有 /dev/xvdb 标明您的云服务无数据盘,那么您无需进行挂载,此时该教程对您不适用

2. 分区 / 格式化

运行以下命令对数据盘进行分区。

1
$ fdisk -u /dev/vdb

输入 p 查看数据盘的分区情况。
本示例中,数据盘没有分区。
输入 n 创建一个新分区。
输入 p 选择分区类型为主分区。

创建一个单分区数据盘可以只创建主分区。如果要创建四个以上分区,您应该至少选择一次 e(extended),创建至少一个扩展分区。

输入分区编号,按回车键。
本示例中,仅创建一个分区,直接按回车键,采用默认值 1。
输入第一个可用的扇区编号,按回车键。
本示例中,直接按回车键,采用默认值 2048。
输入最后一个扇区编号,按回车键。
本示例中,仅创建一个分区,直接按回车键,采用默认值。
输入p 查看该数据盘的规划分区情况。
输入 w 开始分区,并在完成分区后退出。

查看新的分区运行以下命令。

1
$ fdisk -lu /dev/vdb

格式化新分区使用以下对新分区进行格式化,格式化的时间根据硬盘大小有所不同。

1
$ mkfs -t ext4 /dev/vdb1

3. 挂载

挂载到指定文件夹

1
2
# 创建文件夹
$ mkdir /webdata

如果需要把数据盘单独挂载到某个文件夹,比如单独用来存放网页, 需要先创建文件夹可以修改命令中的/mnt部分为文件夹目录

添加分区信息, 实现开机自动挂载使用如下命令写入新分区信息

1
$ echo `blkid /dev/vdb1 | awk '{print $2}' | sed 's/\"//g'` /webdata ext4 defaults 0 0 >> /etc/fstab

然后使用 cat /etc/fstab 命令查看,出现以下信息就表示写入成功。

挂载新分区使用mount -a
命令挂载新分区,然后用 df -h 命令查看,出现以下信息就说明挂载成功,可以开始使用新的分区了。

在线扩容磁盘

1、您先登录服务器执行 yum install -y cloud-utils-growpart 安装扩容工具
2、运行以下命令扩容分区。

1
2
# /dev/vda和1之间需要空格分隔
$ growpart /dev/vda 1

3、执行以下命令

1
2
# /dev/vda和1之间不要带空格
$ resize2fs /dev/vda1

4、运行以下命令检查扩容后结果。

1
$ df -Th

常见问题

  1. unexpected output in sfdisk –version [sfdisk,来自 util-linux 2.23.2]
1
2
3
4
5
6
7
8
9
10
11
12
13
# 输出之前的 $LANG 命令
$ echo $LANG
zh_CN.UTF-8

# 切换语言
$ LANG=en_US.UTF-8

# or
$ export LC_ALL=en_US.UTF-8
# or
$ localectl set-locale LANG=en_US.UTF-8
# or
$ export LANGUAGE=en_US.UTF-8

当成功扩容之后需要切回到原来的语言包

1
$ LANG=zh_CN.UTF-8

切换语言前后对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ df -Th
Filesystem Type Size Used Avail Use% Mounted on
devtmpfs devtmpfs 16G 0 16G 0% /dev
tmpfs tmpfs 16G 0 16G 0% /dev/shm
tmpfs tmpfs 16G 8.6M 16G 1% /run
tmpfs tmpfs 16G 0 16G 0% /sys/fs/cgroup
/dev/vda1 ext4 99G 29G 65G 31% /
/dev/vdb1 ext4 296G 201G 80G 72% /storage
tmpfs tmpfs 3.1G 0 3.1G 0% /run/user/1001
$ LANG=zh_CN.UTF-8
$ df -h
文件系统 容量 已用 可用 已用% 挂载点
devtmpfs 16G 0 16G 0% /dev
tmpfs 16G 0 16G 0% /dev/shm
tmpfs 16G 8.6M 16G 1% /run
tmpfs 16G 0 16G 0% /sys/fs/cgroup
/dev/vda1 99G 29G 65G 31% /
/dev/vdb1 296G 201G 80G 72% /storage
tmpfs 3.1G 0 3.1G 0% /run/user/1001

参考

meilisearch 的安装和使用

MeiliSearch , 一款开源的搜索工具, 和 Agolia 是提供相同服务的竞争对手, 得益于 Agolia 在 Vue 中提供的服务, 实时搜索在项目中的使用也逐渐的频繁起来.

安装

对于 安装, 因为必须要求 GLIBC 2.18 以上, 所以在默认的 centos 7 服务器中无法进行安装, 所以我这里使用的是 ubuntu 服务器.

v2ex 上有人将 glibc 的重新编译会导致系统不稳定, 所以这里不进行测试

安装方法参考 Run MeiliSearch in production: taking it to the next level

[译] 在 CentOS 7 上安装和配置 Redis

原文地址 : How to Install and Configure Redis on CentOS 7

Redis 是一个开源的内存型数据库。它可以用作数据库,缓存或消息代理,并支持各种数据结构,例如字符串,哈希,列表,集合等。Redis 通过 Redis Sentinel 提供高可用性,包括监视,通知,自动故障转移。它还使用 Redis Cluster 在多个 Redis 节点之间提供自动分区。

本教程说明了如何在 CentOS 7 服务器上安装和配置 Redis。

先决条件

在开始本教程之前,请确保您以user with sudo privileges的身份登录。

在 CentOS 7 上安装 Redis

Redis 最新版软件包不包含在默认的 CentOS Repo 中。我们将从 Remi 源安装 Redis 5.x 版。

安装非常简单,只需执行以下步骤:

1). 首先在 SSH 终端中运行以下命令来启用 Remi 存储库:

1
2
3
$ yum install epel-release yum-utils
$ yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
$ yum-config-manager --enable remi

2). 通过键入以下命令安装 Redis 软件包:

1
2
3
4
5
# 安装
$ yum install redis

# 如果是需要升级, 在操作完成以上步骤之后运行
$ yum upgrade redis

3). 安装完成后,启动 Redis 服务并启用以下命令使其在启动时自动启动:

1
2
3
$ systemctl start redis
$ sudo systemctl enable redis
Created symlink from /etc/systemd/system/multi-user.target.wants/redis.service to /usr/lib/systemd/system/redis.service.

要检查服务的状态,请输入以下命令:

1
$ systemctl status redis

应该看到类似以下的内容:

1
2
3
4
5
6
7
8
● redis.service - Redis persistent key-value database
Loaded: loaded (/usr/lib/systemd/system/redis.service; enabled; vendor preset: disabled)
Drop-In: /etc/systemd/system/redis.service.d
└─limit.conf
Active: active (running) since Sat 2018-11-24 15:21:55 PST; 40s ago
Main PID: 2157 (redis-server)
CGroup: /system.slice/redis.service
└─2157 /usr/bin/redis-server 127.0.0.1:6379

如果服务器上禁用了 IPv6,则 Redis 服务将无法启动。

恭喜,这时已经在 CentOS 7 服务器上安装并运行了 Redis。

升级

如果存在之前的数据则需要在更新之前运行下 save 方法, 将数据存储到磁盘

1
2
3
127.0.0.1:6379> save
OK
(0.78s)

配置 Redis 远程访问

默认情况下,Redis 不允许远程连接。只能从运行 Redis 的计算机 127.0.0.1 (localhost) 连接到 Redis 服务器。

仅当你要从远程主机连接到 Redis 服务器时,才执行以下步骤。如果使用单个服务器设置,并且应用程序和 Redis 在同一台计算机上运行,​​ 则不应启用远程访问。

要将 Redis 配置为接受远程连接,请使用文本编辑器打开 Redis 配置文件:

1
$ vim /etc/redis.conf

找到以开头的行,bind 127.0.0.1 然后在后面添加服务器专用 IP 地址 127.0.0.1

/etc/redis.conf

1
2
3
4
# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES
# JUST COMMENT THE FOLLOWING LINE.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bind 127.0.0.1 192.168.121.233

192.168.121.233 替换为你的地址。保存文件并关闭编辑器。

重新启动 Redis 服务以使更改生效:

1
$ systemctl restart redis

使用以下ss命令来验证 Redis 服务器正在 监听 的端口 6379

1
2
3
$ ss -an | grep 6379
tcp LISTEN 0 128 192.168.121.233:6379 *:*
tcp LISTEN 0 128 127.0.0.1:6379 *:*

接下来,需要添加防火墙规则,以启用来自远程计算机上 TCP 端口上的访问 6379

假设正在使用FirewallD 防火墙来管理防火墙,并且希望允许从192.168.121.0/24子网进行访问,则可以运行以下命令:

1
2
3
4
$ firewall-cmd --new-zone=redis --permanent
$ firewall-cmd --zone=redis --add-port=6379/tcp --permanent
$ firewall-cmd --zone=redis --add-source=192.168.121.0/24 --permanent
$ firewall-cmd --reload

上面的命令创建一个名为 redis 的新 zone,打开端口 6379 并允许从专用网络进行访问。

此时,Redis 服务器将接受 TCP 端口 6379 上的远程连接。

确保将防火墙配置为仅接受来自受信任 IP 范围的连接。

要验证所有设置是否正确,您可以尝试使用 redis-cli 实用程序向远程计算机 ping Redis 服务器,该实用程序为 Redis 服务器提供命令行界面:

1
redis-cli -h <REDIS_IP_ADDRESS> ping

该命令应返回以下响应PONG

1
PONG

结论

恭喜你已经在 CentOS 7 服务器上成功安装了 Redis。要了解有关如何使用 Redis 的更多信息,请访问其官方文档

常见问题

1. Centos 如何清空 dns 缓存

1
2
3
4
[root@centos ~]# yum -y install nscd
[root@centos ~]# systemctl enable nscd
[root@centos ~]# systemctl start nscd
[root@centos ~]# nscd -i hosts

2. 用户权限错误 / 无法执行 crontab -e

出现错误场景, 无法执行 su

1
2
3
4
5
6
7
8
$ su root
密码:
su: 鉴定故障

$ crontab -e
crontab: installing new crontab
fchown: 不允许的操作
crontab: edits left in /tmp/crontab.jt1XUI

解决办法: 变更两个应用的权限, 让应用可以执行计划数据

1
2
[root@linux ~]# chmod 4755 /usr/bin/crontab
[root@linux ~]# chmod 4755 /usr/bin/su

参考地址 : crontab -e on gentoo failing: “chown: Operation not permitted”

设置 SSH 安全通过密钥,免密码登录服务器或拉取代码

我们一般使用 PuTTY 等 SSH 客户端来远程管理 Linux 服务器。但是,一般的密码方式登录,容易有密码被暴力破解的问题。所以,一般我们会将 SSH 的端口设置为默认的 22 以外的端口,或者禁用 root 账户登录。其实,有一个更好的办法来保证安全,而且让你可以放心地用 root 账户从远程登录——那就是通过密钥方式登录。

密钥形式登录的原理是:利用密钥生成器制作一对密钥——一只公钥和一只私钥。将公钥添加到服务器的某个账户上,然后在客户端利用私钥即可完成认证并登录。这样一来,没有私钥,任何人都无法通过 SSH 暴力破解你的密码来远程登录到系统。此外,如果将公钥复制到其他账户甚至主机,利用私钥也可以登录。

这个方式同样可以拉取 git 代码, 后续会附上如何在 coding 中配置公钥

1. 制作密钥

下面来讲解如何在 Linux 服务器上制作密钥对,将公钥添加给账户,设置 SSH,最后通过客户端登录。

1) 制作密钥对

首先在服务器上制作密钥对。首先用密码登录到你打算使用密钥登录的账户,然后执行以下命令:

对于 Centos 版本比较高的系统, 需要使用长度较长的密钥, 可能比较弱的密钥在高版本系统中根本无法通过授权
userauth-request for user liexiang service ssh-connection method none [preauth]
可能是无法找到匹配的方法,不安全的密钥已经不支持了

1
2
3
4
5
6
# 使用给定的 email 注释 public/private rsa 密钥
# 需要配置 .ssh/config
cd ~/
ssh-keygen
# or
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

密钥锁码在使用私钥时必须输入,这样就可以保护私钥不被盗用。当然,也可以留空,实现无密码登录。

现在,在指定的目录中生成了一个有两个密钥文件。id_rsa 为私钥,id_rsa.pub 为公钥。

2) 在服务器上安装公钥

方法一 : 使用 ssh-copy-id 命令安装 ​

公钥复制到远程机器, 并自动配置好权限密钥

1
$ ssh-copy-id -i {dir-of-keys}/rsa2.pub user@host

方法二 : 进入服务器手动设定文件和目录的权限

键入以下命令,在服务器上安装公钥:

1
2
$ cd .ssh
$ cat id_rsa.pub >> authorized_keys

如此便完成了公钥的安装。为了确保连接成功,请保证以下文件权限正确:

1
2
$ chmod 600 authorized_keys
$ chmod 700 ~/.ssh

3) 设置 SSH,打开密钥登录功能

编辑 /etc/ssh/sshd_config 文件,进行如下设置:

RSAAuthentication yes  这个选项在 centos 7.4 以后已经废弃, 无需配置此选项

1
PubkeyAuthentication yes

另外,请留意 root 用户能否通过 SSH 登录:

1
PermitRootLogin yes

当你完成全部设置,并以密钥方式登录成功后,再禁用密码登录:

1
PasswordAuthentication no

最后,重启 SSH 服务:

1
$ systemctl restart sshd

2. 客户端配置私钥 config 配置

很多时候,我们开发可能需要连接多台远程服务器,并且需要配置 git 服务器的私钥。那么这么多的服务器不能共用一套私钥,不同的服务器应该使用不同的私钥。但是我们从上面的连接流程可以看到,ssh 默认是去读取 $HOME/.ssh/id_rsa 文件作为私钥登录的。如果想要不同的服务器使用不同的私钥进行登录,那么需要在 .ssh 目录下编写 config 文件来进行配置。

config 的配置很简单,只要指明哪个用户登录哪台远程服务器需要使用哪个私钥即可。下面给出一个配置示例。

1
2
3
4
5
6
Host github.com
User liexiang
IdentityFile ~/.ssh/id_rsa.github
Host 192.168.1.1
User ubuntu
IdentityFile ~/.ssh/id_rsa.xxx

另一种方式 支持名字的映射

1
2
3
4
Host test-liexiang
HostName 192.168.1.21
User liexiang
IdentityFile ~/.ssh/test-liexiang

上面 config 文件字段含义如下:

  • Host 指明了远程主机的 ip,除了使用 ip 地址,也可以直接使用网址。
  • HostName 主机真实名称, ip 或者网址
  • User 指的是登录远程主机的用户。
  • IdentityFile 指明使用哪个私钥文件。

编写好 config 文件之后,需要把 config 文件的权限改为 rw-r--r-- 。如果权限过大,ssh 会禁止登录。

参考文章:

3. Git 无密码进行拉取或者代码推送

所谓部署, 我的理解就是在用户保证代码质量的前提下, 将代码能够快速的自动部署到目标服务器上的一种手段.

具体步骤参照 配置 SSH 公钥

主机配置同上

1). 在 coding 中添加公钥

输出部署公玥

1
$ cat coding.pub

在 git 管理端部分部署公钥

2). 测试是否可以链接到 git@e.coding.net 服务器

1
2
3
4
5
6
7
8
9
10
11
12
# 注意 e.coding.net 接入到 CDN 上所以会解析多个不同的 host ip
$ ssh -T git@e.coding.net
The authenticity of host 'e.coding.net (123.59.85.184)' can't be established.

RSA key fingerprint is 98:ab:2b:30:60:00:82:86:bb:85:db:87:22:c4:4f:b1.

Are you sure you want to continue connecting (yes/no)?

# 这里我们根据提示输入 yes
Warning: Permanently added 'e.coding.net,123.59.85.184' (RSA) to the list of known hosts.

Coding 提示: Hello duoli, You've connected to Coding.net via SSH. This is a deploy key.

这样便算是连接成功

3). 克隆代码

在 coding 网站找到 ssh 对应地址

1
$ git clone git@e.coding.com:user/project.git

这样便可以进行代码的无密码更新了

4. QA:

在配置登录的时候如果遇到了登录问题可以以下几个方式跟踪下

1) 使用 ssh 登录服务器的时候可以使用 verbose 模式调试

1
ssh server_name -vvv

开启 sshd_config 的 debug 模式

可以查看服务器的详细的错误信息

1
2
3
4
5
6
7
8
9
10
11
12
$ vim /etc/ssh/sshd_config

# 之前
# LogLevel INFO
# 更改为
LogLevel DEBUG

$ tail -20f /var/log/secure

Jun 9 12:05:11 23 sshd[26890]: debug1: PAM: setting PAM_RHOST to "192.168.1.101"
Jun 9 12:05:11 23 sshd[26890]: debug1: PAM: setting PAM_TTY to "ssh"
...

查看服务器的登录日志

1
2
3
4
5
6
7
8
9
10
$ tail -20f /var/log/secure

Jun 9 12:05:11 23 sshd[26890]: debug1: PAM: setting PAM_RHOST to "192.168.1.101"
Jun 9 12:05:11 23 sshd[26890]: debug1: PAM: setting PAM_TTY to "ssh"
Jun 9 12:05:11 23 sshd[26890]: debug1: userauth-request for user liexiang service ssh-connection method publickey [preauth]
Jun 9 12:05:11 23 sshd[26890]: debug1: attempt 1 failures 0 [preauth]
Jun 9 12:05:11 23 sshd[26890]: debug1: temporarily_use_uid: 1000/1000 (e=0/0)
Jun 9 12:05:11 23 sshd[26890]: debug1: trying public key file /home/user/.ssh/authorized_keys
Jun 9 12:05:11 23 sshd[26890]: debug1: Could not open authorized keys '/home/user/.ssh/authorized_keys': Permission denied
Jun 9 12:05:11 23 sshd[26890]: debug1: restore_uid: 0/0

2) ssh 登录慢,卡顿在 pledge: network 之后

当 ssh 登录缓慢的时候我们需要 使用

1
$ ssh -v user@host

来查看问题出现的原因, 根据出现的问题来进行处理

我这里出现的问题是在 pledge: network 之后出现卡顿

处理结果

1
# echo "" > /var/log/btmp

主要原因是 22 端口对外暴露,导致大量的爆破扫描,因此导致 btmp 这个文件巨大

参考地址 : ssh connection takes forever to initiate, stuck at “pledge: network”

我们可以通过如下命令查看恶意 ip 试图登录次数:

1
lastb | awk ‘{ print $3}’ | sort | uniq -c | sort -n

3) 修改 ssh 默认登录的端口

用编辑器打开 SSH 配置文件,修改端口:

1
# vi /etc/ssh/sshd_config

找到行 #Port 22 (默认端口为 22),修改端口为其他端口, 不要出现端口冲突

1
Port 5022

重启 SSH 服务:

1
# systemctl restart sshd

修改防火墙,允许访问 5022 的端口,并且重启防火墙服务:

1
2
3
4
# 配置 5022
$ firewall-cmd --permanent --zone=public --add-port=5022/tcp
# 重启
$ firewall-cmd --reload

如果是 Aliyun 主机, 则需要在对应的安全组打开端口访问权限, 否则一样无法访问主机

参考

[转] 如何在 CentOS 7 上修改主机名

在 CentOS 中,有三种定义的主机名:静态的(static),瞬态的(transient),和灵活的(pretty)。静态主机名也称为内核主机名,是系统在启动时从/etc/hostname 自动初始化的主机名。瞬态主机名是在系统运行时临时分配的主机名,例如,通过 DHCP 或 mDNS 服务器分配。静态主机名和瞬态主机名都遵从作为互联网域名同样的字符限制规则。而另一方面,灵活主机名则允许使用自由形式(包括特殊/空白字符)的主机名,以展示给终端用户(如 server-a)。
在 CentOS 7 中,有个叫 hostnamectl 的命令行工具,它允许你查看或修改与主机名相关的配置。

查看主机名相关的设置

1
2
3
4
5
6
7
8
9
10
11
[root@localhost ~]# hostnamectl
Static hostname: localhost.localdomain
Icon name: computer-vm
Chassis: vm
Machine ID: 21ff9d4ebdd94e949b9fd6cbdb1926c0
Boot ID: 2a952e91c02841e3ae10de0d16dd3f01
Virtualization: kvm
Operating System: CentOS Linux 7 (Core)
CPE OS Name: cpe:/o:centos:centos:7
Kernel: Linux 3.10.0-327.el7.x86_64
Architecture: x86-64
1
2
3
4
5
6
7
8
9
10
11
[root@localhost ~]# hostnamectl status
Static hostname: localhost.localdomain
Icon name: computer-vm
Chassis: vm
Machine ID: 21ff9d4ebdd94e949b9fd6cbdb1926c0
Boot ID: 2a952e91c02841e3ae10de0d16dd3f01
Virtualization: kvm
Operating System: CentOS Linux 7 (Core)
CPE OS Name: cpe:/o:centos:centos:7
Kernel: Linux 3.10.0-327.el7.x86_64
Architecture: x86-64

查看静态、瞬态或灵活主机名

只查看静态、瞬态或灵活主机名,分别使用--static--transient--pretty选项。

1
2
3
4
5
[root@localhost ~]# hostnamectl --static
localhost.localdomain
[root@localhost ~]# hostnamectl --transient
localhost.localdomain
[root@localhost ~]# hostnamectl --pretty

修改主机名

要同时修改所有三个主机名:静态、瞬态和灵活主机名:

1
2
3
4
5
6
[root@localhost ~]# hostnamectl set-hostname server-a
[root@localhost ~]# hostnamectl --pretty
[root@localhost ~]# hostnamectl --static
server-a
[root@localhost ~]# hostnamectl --transient
server-a

就像上面展示的那样,在修改静态/瞬态主机名时,任何特殊字符或空白字符会被移除,而提供的参数中的任何大写字母会自动转化为小写。
一旦修改了静态主机名,/etc/hostname  将被自动更新。然而,/etc/hosts  不会更新以保存所做的修改,所以你每次在修改主机名后一定要手动更新/etc/hosts,之后再重启 CentOS 7。否则系统再启动时会很慢。

手动更新/etc/hosts

1
2
3
4
5
vim /etc/hosts
#127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
127.0.0.1 server-a
#::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
::1 server-a

重启 CentOS 7 之后(reboot -f )

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@server-a ~]# hostname
server-a
[root@server-a ~]# hostnamectl
Static hostname: server-a
Icon name: computer-vm
Chassis: vm
Machine ID: 21ff9d4ebdd94e949b9fd6cbdb1926c0
Boot ID: 2a952e91c02841e3ae10de0d16dd3f01
Virtualization: kvm
Operating System: CentOS Linux 7 (Core)
CPE OS Name: cpe:/o:centos:centos:7
Kernel: Linux 3.10.0-327.el7.x86_64
Architecture: x86-64

如果你只想修改特定的主机名(静态,瞬态或灵活),你可以使用--static--transient--pretty选项。例如,要永久修改主机名,你可以修改静态主机名:

1
[root@localhost ~]# hostnamectl --static set-hostname server-a

重启 CentOS 7 之后(reboot -f),

1
2
3
4
5
6
7
8
[root@localhost ~]# hostnamectl --static
server-a
[root@localhost ~]# hostnamectl --transient
server-a
[root@localhost ~]# hostnamectl --pretty
server-a
[root@localhost ~]# hostname
server-a

其实,你不必重启机器以激活永久主机名修改。上面的命令会立即修改内核主机名。
注销并重新登入后在命令行提示来观察新的静态主机名

参考

[转+] CentOS 7 更新 curl 为最新版本

介绍

由于 CentOS 7 内置的 curl 和 libcurl 源为较旧的 7.29.0,不支持一些新特性且有安全性问题,所以需要更新一下, 这里使用 city-fan 的更新源来更新。

查看默认版本号

1
2
3
# curl -V
curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.53.1 zlib/1.2.7 libidn/1.28 libssh2/1.8.0
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp

更新 ca-bundle 证书

  1. 备份证书
1
# cp /etc/pki/tls/certs/ca-bundle.crt /etc/pki/tls/certs/ca-bundle.crt.bak
  1. 更新并替换
1
# curl http://curl.haxx.se/ca/cacert.pem -o /etc/pki/tls/certs/ca-bundle.crt

新增 repo 源

新增 repo:

1
2
3
4
5
6
7
# rpm -Uvh http://www.city-fan.org/ftp/contrib/yum-repo/city-fan.org-release-2-1.rhel7.noarch.rpm

Retrieving http://www.city-fan.org/ftp/contrib/yum-repo/city-fan.org-release-2-1.rhel7.noarch.rpm
warning: /var/tmp/rpm-tmp.ttjkC5: Header V4 DSA/SHA1 Signature, key ID b56a8bac: NOKEY
Preparing... ################################# [100%]
Updating / installing...
1:city-fan.org-release-2-1.rhel7 ################################# [100%]

启用 city-fan.org repo:

1
2
# yum install -y yum-utils
# yum-config-manager --enable city-fan.org

更新 curl

直接使用如下命令进行更新:

1
# yum update curl --enablerepo=city-fan.org  -y

安装完成, 查看版本

1
2
# curl -V
curl 7.79.1 (x86_64-redhat-linux-gnu) libcurl/7.79.1 NSS/3.53.1 zlib/1.2.7 libpsl/0.7.0 (+libicu/50.1.2) libssh2/1.10.0 nghttp2/1.33.0 OpenLDAP/2.4.44

QA:

  1. 如果提示缺少依赖  libnghttp2.so.14()(64bit)

    错误:软件包:libcurl-7.75.0-1.1.cf.rhel7.x86_64 (city-fan.org)
              需要:libnghttp2.so.14()(64bit)

1
# rpm -ivh https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/l/libnghttp2-1.33.0-1.1.el7.x86_64.rpm

这里地址是 centos7 版本, 如果是其他系统, 可以在一下路径自己寻找 https://dl.fedoraproject.org/pub/epel/

参考地址

CentOS 安装 Python

安装 pyenv

安装

1
$ curl https://pyenv.run | bash

添加到环境变量到 .bashrc

1
2
3
export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv virtualenv-init -)"

启用

1
$ source ~/.bashrc

更新

1
$ pyenv update

安装编译支持

开发工具

1
$ yum groupinstall -y "Development Tools"

openssl

如果没有安装可能会报如下错误
ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?
原因是 python3.7 的 ssl 模块依赖 openssl 1.0.2 或者 1.1 以上版本,如果 openssl 版本低于以上版本,将无法正常安装 python3.7 的 ssl 模块

这里我们安装最新版的 openssl 模块, 下载地址 : https://www.openssl.org/source/

1
2
3
4
5
6
$ sudo wget https://www.openssl.org/source/openssl-1.1.1l.tar.gz
$ sudo tar -xzvf openssl-1.1.1l.tar.gz
$ cd openssl-1.1.1l
$ sudo ./config --prefix=/usr --openssldir=/usr/openssl shared
$ sudo make
$ sudo make install

开发包

用于编译的时候对这些功能进行支持

1
$ yum install readline-devel zlib-devel sqlite-devel libffi-devel

使用 pyenv 安装 最新版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ pyenv install --list
...
3.9.7
3.9.8
3.10.0
3.10-dev
3.11.0a2
...

$ pyenv install 3.10.0 -vvv
$ pyenv global 3.10.0

$ python3
Python 3.10.0 (default, Nov 8 2021, 08:25:47) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

安装成功

FAQ

ModuleNotFoundError: No module named ‘_ctypes’

Python3 中有个内置模块叫 ctypes,它是 Python3 的外部函数库模块,它提供兼容 C 语言的数据类型,并通过它调用 Linux 系统下的共享库(Shared library),此模块需要使用 CentOS7 系统中外部函数库(Foreign function library)的开发链接库(头文件和链接库)。
由于在 CentOS7 系统中没有安装外部函数库(libffi)的开发链接库软件包,所以在安装 pip 的时候就报了”ModuleNotFoundError: No module named ‘_ctypes’”的错误

1
$  yum install libffi-devel -y

然后再重新安装 python3

参考

CentOS 进行服务器完善和升级

系统软件安装以及升级

基础工具安装

1
2
3
4
5
6
# normal tools
$ yum install wget vim yum-utils gcc
# autojump
$ yum install autojump
# zip
$ yum install zip unzip

升级 curl 为最新版本

查看文章 : CentOS 7 更新 curl 为最新版本

源添加和更换

CentOS 镜像
CentOS,是基于 Red Hat Linux 提供的可自由使用源代码的企业级 Linux 发行版本;是一个稳定,可预测,可管理和可复制的免费企业级计算平台。

1
2
# 更换为 aliyun 提高下载速度, 设置aliyun库
$ wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

Remi 镜像

Remi repository 是包含最新版本 PHP 和 MySQL 包的 Linux 源,由 Remi 提供维护
官方源 : https://rpms.remirepo.net/
Aliyun : https://developer.aliyun.com/mirror/remi

1
2
3
4
5
# 设置 remi 库 , 二选一
# official
$ yum install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
# aliyun mirror
$ yum install https://mirrors.aliyun.com/remi/enterprise/remi-release-7.rpm

系统升级

1
2
3
4
5
6
# 更新元数据
$ yum makecache

# 更新和升级
$ yum update
$ yum upgrade

关闭 Seliunx

这里遇到一个坑, 如果不关闭 SELinux, 可能会遇到开发的坑.
检查 SELinux 是否在运行:

1
$ getenforce

下次重启前禁用 SELinux:

1
$ setenforce Permissive

重新启动 Nginx,看看问题是否仍然存在。如果您想永久更改 Selinux 设置,可以编辑 /etc/sysconfig/selinux

其他参考

CentOS 使用 docker 安装 sentry

服务器配置不能低于 4U 8G


Sentry 是一个开源的实时错误追踪系统,可以帮助开发者实时监控并修复异常问题。它主要专注于持续集成、提高效率并且提升用户体验。Sentry 分为服务端和客户端 SDK,前者可以直接使用提供的在线服务,也可以本地自行搭建;后者提供了对多种主流语言和框架的支持,包括 React、Angular、Node、Django、RoR、PHP、Laravel、Android、.NET、JAVA 等。同时它可提供了和其他流行服务集成的方案,例如 GitHub、GitLab、bitbuck、heroku、slack、Trello 等。

Sentry 本身是基于 Django 开发的,而且也依赖到其他的如 Postgresql、 Redis 等组件,所以一般有两种途径进行安装:通过 Docker 或用 Python 搭建。官网下分别有以下的两个介绍:

如果你选择了通过 Docker 进行安装,其实还有更加便捷的方式 —— docker-compose 。在 github 上有一个开源项目用于部署 Sentry ,我们可以直接使用该项目进行部署,首先是克隆该项目:

地址 : https://github.com/getsentry/onpremise/

安装环境

安装 docker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 安装/更新 Docker
$ yum remove docker docker-common docker-selinux docker-engine

# 安装依赖
$ yum install -y yum-utils device-mapper-persistent-data lvm2

# 添加 docker yum 源
$ yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 官方源比较慢的话可以更换为 Aliyun 的源
$ yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo


# 允许拓展最新的不稳定的repository
$ yum-config-manager --enable docker-ce-edge

# 安装docker
# yum -y install docker-ce

# 开机启动 & 启动 Docker
$ systemctl enable docker
$ systemctl start docker

安装 docker-composer

这里推荐使用 Python 的 pip3 管理工具来安装 docker-compose,
这里不推荐使用 pip, 因为这是 2.0 的包管理

1
2
3
4
5
6
7
8
9
10
11
12
13
# 使用普通用户安装
$ pip3 install --user -U docker-compose

# 查看docker compose版本
$ docker-compose version
docker-compose version 1.29.2, build unknown
docker-py version: 5.0.0
CPython version: 3.6.8
OpenSSL version: OpenSSL 1.0.2k-fips 26 Jan 2017

# 查看 pip version
$ pip3 -V
pip 21.2.4 from /usr/local/lib/python3.6/site-packages/pip (python 3.6)

如果没有 pip, 则按照以下步骤安装 pip

1
2
3
4
5
6
7
8
9
10
11
#上一条语句没有显示版本信息则运行下面语句安装 python-pip3
$ yum -y install epel-release
$ yum -y install python-pip
#查看pip版本
$ pip -v
#pip进行升级
$ pip install --upgrade pip
#进行安装compose 第一条语句报错执行第二条,执行成功则跳过第二条
$ pip install docker-compose
$ pip install docker-compose --ignore-installed requests
$ docker-compose -version

安装 senty 到 docker

克隆 sentry 并安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$ git clone https://github.com/getsentry/onpremise.git
$ ./install.sh
Checking minimum requirements...
Removing network onpremise_default
...
Created internal Sentry project (slug=internal, id=1)

Would you like to create a user account now? [Y/n]: y
Email: username@domain.com
Password:
Repeat for confirmation:
User created: username@domain.com
Added to organization: sentry
Cleaning up...


You're all done! Run the following command to get Sentry running:

docker-compose up -d

# docker images 检查安装结果
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
symbolicator-cleanup-onpremise-local latest aa9f529b9bba 6 minutes ago 168MB
sentry-cleanup-onpremise-local latest c8ce20926772 15 minutes ago 832MB
snuba-cleanup-onpremise-local latest 899555aa0198 15 minutes ago 417MB
sentry-onpremise-local latest 7b49912508f3 15 minutes ago 830MB
getsentry/snuba latest c278520d8aa3 2 hours ago 415MB
getsentry/sentry latest 5351ca5b79c7 3 hours ago 830MB
getsentry/symbolicator latest 857ed4c4c3bb 15 hours ago 167MB
getsentry/relay latest cf4553a1852c 15 hours ago 186MB
busybox latest c7c37e472d31 3 days ago 1.22MB
postgres 9.6 51e37c2850c7 3 weeks ago 200MB
tianon/exim4 latest f077f7830685 3 weeks ago 176MB
redis 5.0-alpine 58084f18c7ec 4 weeks ago 29.7MB
alpine latest a24bb4013296 4 weeks ago 5.57MB
nginx 1.16 dfcfd8e9a5d3 2 months ago 127MB
confluentinc/cp-kafka 5.5.0 89e8e98718a8 2 months ago 598MB
confluentinc/cp-zookeeper 5.5.0 124ff6469e3d 2 months ago 598MB
yandex/clickhouse-server 19.17 f0fa9b979b63 4 months ago 435MB
memcached 1.5-alpine 0dbf6b4c454b 4 months ago 9.19MB

创建项目的 superuser

1
2
3
4
5
6
7
8
9
10
$ docker-compose run --rm web upgrade
Starting sentry_onpremise_redis_1 ... done
Starting sentry_onpremise_smtp_1 ... done
...
Creating missing DSNs
Correcting Group.num_comments counter
09:49:46 [INFO] sentry.plugins.github: apps-not-configured
Email: 1222@qq.com
Password:
Repeat for confirmation:

创建账号和密码

1
2
3
4
5
6
7
8
9
10
11
12
# 创建自己的用户, 根据提示输入邮箱和密码
$ docker-compose run --rm web createuser
Starting onpremise_smtp_1 ... done
Starting onpremise_postgres_1 ... done
Starting onpremise_redis_1 ... done
Starting onpremise_memcached_1 ... done
09:49:39 [WARNING] sentry.utils.geo: settings.GEOIP_PATH_MMDB not configured.
09:49:46 [INFO] sentry.plugins.github: apps-not-configured
Email: 1222@qq.com
Password:
Repeat for confirmation:
Should this user be a superuser? [y/N]: y

生成 key 并设置

1
2
3
4
$ docker-compose run --rm web config generate-secret-key

# 编辑 .env 文件
# 添加到 .env 的 SENTRY_SECRET_KEY 里面

启动 Docker Compose

1
2
3
4
$ docker-compose up -d
sentry_onpremise_smtp_1 is up-to-date
...
Recreating sentry_onpremise_nginx_1 ... done

使用 docker ps 检查

1
2
3
4
5
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7c86739e1904 nginx:1.16 "nginx -g 'daemon of…" 26 minutes ago Up 26 minutes 0.0.0.0:9080->80/tcp sentry_onpremise_nginx_1
...
a85aff3465f8 redis:5.0-alpine "docker-entrypoint.s…" 47 minutes ago Up 39 minutes 6379/tcp sentry_onpremise_redis_1

这样在内网便可以访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 由于没有开放 9080 端口到外网, 所以使用 wget 方式访问, 如果已经开放, 则直接访问 ip:9080 即可访问
$ wget 127.0.0.1:9080
--2020-07-03 10:30:24-- http://127.0.0.1:9080/
正在连接 127.0.0.1:9080... 已连接。
已发出 HTTP 请求,正在等待回应... 302 Found
位置:/auth/login/ [跟随至新的 URL]
--2020-07-03 10:30:25-- http://127.0.0.1:9080/auth/login/
再次使用存在的到 127.0.0.1:9080 的连接。
已发出 HTTP 请求,正在等待回应... 302 Found
位置:/auth/login/sentry/ [跟随至新的 URL]
--2020-07-03 10:30:26-- http://127.0.0.1:9080/auth/login/sentry/
再次使用存在的到 127.0.0.1:9080 的连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:9690 (9.5K) [text/html]
正在保存至: “index.html”

配置 nginx 反向代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
server {
listen 80;
server_name sentry.domain.com;
return 301 https://sentry.domain.com$request_uri;
}

server{
listen 443 ssl;
server_name sentry.domain.com;

# 由于以后会上传 source-map, 需要将sourcemap 上传大小进行放开
client_max_body_size 20m;

location / {
proxy_pass http://127.0.0.1:9080;
}

## ssl
ssl_certificate https/sentry.domain.com.pem;
ssl_certificate_key https/sentry.domain.com.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;

access_log off;
error_log off;
}

这里即可通过域名来进行访问

出现问题

1. Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock

解决方法 : 将用户加入 docker 组, 可以让其进行访问

1
2
3
4
# 把用户加入 docker 组
$ usermod -aG docker $USER
# logout : 注销
$ systemctl restart docker

2. docker-compose 启动报错

ERROR: for sentry_onpremise_nginx_1  Cannot start service nginx: driver failed programming external connectivity on endpoint sentry_onpremise_nginx_1 (9ee80c3b3949749bdb529f949574f6169a4f993c9a0d50aa621228bd57d579fb): Error starting userland proxy: listen tcp 0.0.0.0:9000: bind: address already in use

ERROR: Encountered errors while bringing up the project.

解决方法:
这里一般是端口冲突
参考 .env 文件配置端口映射

1
2
3
4
...
- SENTRY_BIND=9000
+ SENTRY_BIND=9080
...

3. 配置 Sentry 可以发送邮件

编辑 ./sentry/config.yml 文件

1
2
3
4
5
6
7
8
9
10
mail.backend: "smtp" # Use dummy if you want to disable email entirely
mail.host: "smtpdm.aliyun.com"
mail.port: 25
mail.username: "automail@demo.domain.com"
mail.password: "********"
mail.use-tls: false
# The email address to send on behalf of
mail.from: "automail@demo.domain.com"
# 备注: host 就是stmp服务地址
# port 端口和 tls对应 port 25 对应 tls false port 587 对应 tls true

然后运行

1
2
3
$ docker-compose build
$ docker-compose stop
$ docker-compose start -d

这样看下 管理员中的 邮箱配置

测试下收到邮件就配置成功了

ps : 这里用的是网易的客户端

4. 这里配置 register mirror, 加速国内访问

打开 https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors , 这里将镜像设置为使用 aliyun 的加速镜像
针对 Docker 客户端版本大于 1.10.0 的用户 ​
您可以通过修改 daemon 配置文件/etc/docker/daemon.json 来使用加速器

1
2
3
4
5
6
7
8
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://******.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

5. Sentry 对接上之后无法收集日志

需要验证

1
2
3
4
5
# 验证服务器是否接收到请求
$ tail -20f /var/logs/nginx/access.log

# 验证 docker 镜像是否收到日志
$ docker-compose logs -f -t --tail=100

下面是一次执行服务的日志

1
2
3
4
5
6
7
8
9
10
# 接收
nginx_1 | 172.18.0.1 - - [18/Jul/2020:03:10:02 +0000] "POST /api/4/store/ HTTP/1.0" 200 41 "-" "sentry.php.laravel/1.8.0"
# kafka 进行消费
ingest-consumer_1 | 03:10:03 [INFO] batching-kafka-consumer: Flushing 2 items (from {(u'ingest-events', 0): [138L, 139L]}): forced:False size:False time:True
# snuba 进行处理
snuba-cleanup_1 | 2020-07-18 03:10:03,574 Dropped 0 partitions on None
snuba-consumer_1 | 2020-07-18 03:10:04,600 Flushing 2 items (from {Partition(topic=Topic(name='events'), index=0): Offsets(lo=154, hi=156)}): forced:False size:False time:True
snuba-outcomes-consumer_1 | 2020-07-18 03:10:04,603 Flushing 2 items (from {Partition(topic=Topic(name='outcomes'), index=0): Offsets(lo=140, hi=142)}): forced:False size:False time:True
snuba-outcomes-consumer_1 | 2020-07-18 03:10:04,623 Worker flush took 18ms
snuba-consumer_1 | 2020-07-18 03:10:04,730 Worker flush took 129ms

如果出现异常则可以进行重启

1
$ docker-compose restart

Centos 使用 pip3 安装/升级 supervisor

安装的时候, 因为国内外访问环境不同, 可能会出现国内访问速度慢情况, 可以考虑更换源 : 更换镜像源 , 加速 python 安装

安装 Python3

1
2
$ yum install vim git yum-utils python3 python3-devel
$ pip3 install --upgrade pip

安装 Supervisor

安装 Supervisor

1
$ pip3 install supervisor

这里安装完成之后, 执行文件在 /usr/local/bin/ 目录下, 这个目录下存在三个文件

1
2
3
echo_supervisord_conf    # 输出配置文件
supervisorctl # supervisor 控制
supervisord # supervisor 守护进程

如果使用 sudo pip3 install --user supervisor 进行安装,则安装的目录会在 ~/.local/bin 目录下, 这里我们选择使用 root 用户来安装, 然后运行.

使用之前版本或者是 yum 安装的版本安装的位置一般会在 /usr/bin 目录下, 如果是多版本 supervisor 可以通过路径来进行区分

增加配置文件

1
2
# 生成配置文件
$ echo_supervisord_conf > /etc/supervisord.conf

增加服务管理

使用 systemctl 来启动 supervisor,文件内容

文件地址: initscripts/centos-systemd-etcs

1
$ vim /usr/lib/systemd/system/supervisord.service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# supervisord service for systemd (CentOS 7.0+)
# by ET-CS (https://github.com/ET-CS)
[Unit]
Description=Supervisor daemon

[Service]
Type=forking
ExecStart=/usr/local/bin/supervisord -c /etc/supervisord.conf
ExecStop=/usr/local/bin/supervisorctl $OPTIONS shutdown
ExecReload=/usr/local/bin/supervisorctl $OPTIONS reload
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target

启动 Supervisord

1
2
3
# 如果对 supervisord.service 中更改了路径, 则需要重新加载内容
$ systemctl daemon-reload
$ systemctl start supervisord

参考

常用的命令

1
2
3
4
5
supervisorctl stop program
supervisorctl start program
supervisorctl restart program
supervisorctl status
supervisorctl reload

升级

升级的逻辑是安装新的版本, 然后删除旧版本

如果是通过 yum 安装或者 pip(2.x) 版本安装的, 则可以对老板板进行删除

1
2
3
4
$ yum remove supervisor

# 移除 python2 版本的, 如果 pip 链接到 pip3 , 则无法使用这个进行卸载
$ pip uninstall supervisor

使用非 root 用户来管理supervisor

由于默认使用非 root 用户启动服务,所以需要单独配置允许其使用。官方这个 Issue 中提到了解决方法:

Permession denied error when use supervisorctl · Issue #173 · Supervisor/supervisor · GitHub

1
2
3
4
5
$ groupadd supervisor
$ usermod -aG supervisor doraemon

$ sed -i "s/;chmod=0700/chmod=0770/" /etc/supervisord.conf
$ sed -i "s/;chown=nobody:nogroup/chown=root:supervisor/" /etc/supervisord.conf

[转+] 运维中的日志切割(logrotate)操作梳理

原文地址 : 运维中的日志切割操作梳理

对于 Linux 系统安全来说,日志文件是极其重要的工具。不知为何,我发现很多运维同学的服务器上都运行着一些诸如每天切分 Nginx 日志之类的 CRON 脚本,大家似乎遗忘了 Logrotate,争相发明自己的轮子,这真是让人沮丧啊!就好比明明身边躺着现成的性感美女,大家却忙着自娱自乐,罪过!

logrotate 程序是一个日志文件管理工具。用于分割日志文件,删除旧的日志文件,并创建新的日志文件,起到“转储”作用。可以节省磁盘空间。下面就对 logrotate 日志轮转操作做一梳理记录:

Logrotate 介绍

显而易见,Logrotate 是基于 CRON 来运行的,其脚本是/etc/cron.daily/logrotate

1
2
3
4
5
6
7
8
#!/bin/sh

/usr/sbin/logrotate /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
/usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0

实际运行时,Logrotate 会调用配置文件「/etc/logrotate.conf」:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# see "man logrotate" for details
# rotate log files weekly
weekly

# keep 4 weeks worth of backlogs
rotate 4

# create new (empty) log files after rotating old ones
create

# uncomment this if you want your log files compressed
#compress

# RPM packages drop log rotation information into this directory
include /etc/logrotate.d

# no packages own wtmp -- we'll rotate them here
/var/log/wtmp {
monthly
minsize 1M
create 0664 root utmp
rotate 1
}

# system-specific logs may be also be configured here.

这里的设置可以理解为 Logrotate 的缺省值,当然了,可以我们在「/etc/logrotate.d」目录里放置自己的配置文件,用来覆盖 Logrotate 的缺省值。

配置文件介绍

Linux 系统默认安装 logrotate 工具,它默认的配置文件在:

1
2
/etc/logrotate.conf
/etc/logrotate.d/

logrotate.conf 才主要的配置文件,logrotate.d 是一个目录,该目录里的所有文件都会被主动的读入/etc/logrotate.conf 中执行。
另外,如果 /etc/logrotate.d/ 里面的文件中没有设定一些细节,则会以/etc/logrotate.conf 这个文件的设定来作为默认值。

如果等不及 cron 自动执行日志轮转,想手动强制切割日志,需要加-f 参数;不过正式执行前最好通过 Debug 选项来验证一下(-d 参数),这对调试也很重要

1
2
# /usr/sbin/logrotate -f /etc/logrotate.d/nginx
# /usr/sbin/logrotate -d -f /etc/logrotate.d/nginx

logrotate 命令格式:
logrotate [OPTION…]
-d, --debug :debug 模式,测试配置文件是否有错误。
-f, --force :强制转储文件。
-m, --mail=command :压缩日志后,发送日志到指定邮箱。
-s, --state=statefile :使用指定的状态文件。
-v, --verbose :显示转储过程。

根据日志切割设置进行操作,并显示详细信息

1
2
$ /usr/sbin/logrotate -v /etc/logrotate.conf 
$ /usr/sbin/logrotate -v /etc/logrotate.d/php

根据日志切割设置进行执行,并显示详细信息,但是不进行具体操作,debug 模式

1
2
$ /usr/sbin/logrotate -d /etc/logrotate.conf 
$ /usr/sbin/logrotate -d /etc/logrotate.d/nginx

查看各 log 文件的具体执行情况

1
$ cat /var/lib/logrotate.status

切割介绍

比如以系统日志/var/log/message 做切割来简单说明下:
第一次执行完 rotate(轮转)之后,原本的 messages 会变成 messages.1,而且会制造一个空的 messages 给系统来储存日志;
第二次执行之后,messages.1 会变成 messages.2,而 messages 会变成 messages.1,又造成一个空的 messages 来储存日志!
如果仅设定保留三个日志(即轮转 3 次)的话,那么执行第三次时,则 messages.3 这个档案就会被删除,并由后面的较新的保存日志所取代!也就是会保存最新的几个日志。
日志究竟轮换几次,这个是根据配置文件中的 dateext 参数来判定的。

看下 logrotate.conf 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ cat /etc/logrotate.conf

# 底下的设定是 "logrotate 的默认值" ,如果別的文件设定了其他的值,
# 就会以其它文件的设定为主
weekly          //默认每一周执行一次rotate轮转工作
rotate 4        //保留多少个日志文件(轮转几次).默认保留四个.就是指定日志文件删除之前轮转的次数,0 指没有备份
create          //自动创建新的日志文件,新的日志文件具有和原来的文件相同的权限;因为日志被改名,因此要创建一个新的来继续存储之前的日志
dateext        //这个参数很重要!就是切割后的日志文件以当前日期为格式结尾,如xxx.log-20131216这样,如果注释掉,切割出来是按数字递增,即前面说的 xxx.log-1这种格式
compress       //是否通过gzip压缩转储以后的日志文件,如xxx.log-20131216.gz ;如果不需要压缩,注释掉就行

include /etc/logrotate.d
# 将 /etc/logrotate.d/ 目录中的所有文件都加载进来

/var/log/wtmp {         //仅针对 /var/log/wtmp 所设定的参数
monthly                 //每月一次切割,取代默认的一周
minsize 1M              //文件大小超过 1M 后才会切割
create 0664 root utmp   //指定新建的日志文件权限以及所属用户和组
rotate 1                //只保留一个日志.
}
# 这个 wtmp 可记录用户登录系统及系统重启的时间
# 因为有 minsize 的参数,因此不见得每个月一定会执行一次喔.要看文件大小。

由这个文件的设定可以知道/etc/logrotate.d 其实就是由/etc/logrotate.conf 所规划出来的目录,虽然可以将所有的配置都写入/etc/logrotate.conf ,但是这样一来这个文件就实在是太复杂了,尤其是当使用很多的服务在系统上面时, 每个服务都要去修改/etc/logrotate.conf 的设定也似乎不太合理了。 
所以,如果独立出来一个目录,那么每个要切割日志的服务, 就可以独自成为一个文件,并且放置到 /etc/logrotate.d/ 当中

其他重要参数说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
compress                           // 通过gzip 压缩转储以后的日志
nocompress                         // 不做gzip压缩处理
copytruncate                       // 用于还在打开中的日志文件,把当前日志备份并截断;是先拷贝再清空的方式,拷贝和清空之间有一个时间差,可能会丢失部分日志数据。
nocopytruncate                     // 备份日志文件不过不截断
create mode owner group            // 轮转时指定创建新文件的属性,如create 0777 nobody nobody
nocreate                           // 不建立新的日志文件
delaycompress                      // 和compress 一起使用时,转储的日志文件到下一次转储时才压缩
nodelaycompress                    // 覆盖 delaycompress 选项,转储同时压缩。
missingok                          // 如果日志丢失,不报错继续滚动下一个日志
errors address                     // 专储时的错误信息发送到指定的Email 地址
ifempty                            // 即使日志文件为空文件也做轮转,这个是logrotate的缺省选项。
notifempty                         // 当日志文件为空时,不进行轮转
mail address                       // 把转储的日志文件发送到指定的E-mail 地址
nomail                             // 转储时不发送日志文件
olddir directory                   // 转储后的日志文件放入指定的目录,必须和当前日志文件在同一个文件系统
noolddir                           // 转储后的日志文件和当前日志文件放在同一个目录下
sharedscripts                      // 运行postrotate脚本,作用是在所有日志都轮转后统一执行一次脚本。如果没有配置这个,那么每个日志轮转后都会执行一次脚本
prerotate                          // 在logrotate转储之前需要执行的指令,例如修改文件的属性等动作;必须独立成行
postrotate                         // 在logrotate转储之后需要执行的指令,例如重新启动 (kill -HUP) 某个服务!必须独立成行
daily                              // 指定转储周期为每天
weekly                             // 指定转储周期为每周
monthly                            // 指定转储周期为每月
rotate count                       // 指定日志文件删除之前转储的次数,0 指没有备份,5 指保留5 个备份
dateext                            // 使用当期日期作为命名格式
dateformat .%s                     // 配合dateext使用,紧跟在下一行出现,定义文件切割后的文件名,必须配合dateext使用,只支持 %Y %m %d %s 这四个参数
size(或minsize) log-size           // 当日志文件到达指定的大小时才转储,log-size能指定bytes(缺省)及KB (sizek)或MB(sizem).
当日志文件 >= log-size 的时候就转储。 以下为合法格式:(其他格式的单位大小写没有试过)
size = 5 或 size 5 (>= 5 个字节就转储)
size = 100k 或 size 100k
size = 100M 或 size 100M

小示例:下面一个切割 nginx 日志的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ vim /etc/logrotate.d/nginx

/usr/local/nginx/logs/*.log {
daily
rotate 7
missingok
notifempty
dateext
sharedscripts
postrotate
if [ -f /usr/local/nginx/logs/nginx.pid ]; then
kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`
fi
endscript
}

参考文章

[转] Linux 使用 autojump 直达目录

介绍这款神器之前,先来确认一个问题。在 Linux 的使用过程中,如何快速地到达指定目录?

很多人肯定会说,使用 tab 补全大法啊,笨!

嗯,没错,在没认识到 autojump 之前,我也是这么想的,但熟悉使用过这款神器后,才明白什么叫所达即所想。也就是无需考虑中间还有多少层目录,你只需要记住最终目录的名称,就可以快速进入该目录……

安装 autojump

要安装 autojump,得先安装 epel 源:

1
2
sudo yum isntall epel-release;
sudo yum install autojump;

初次安装完成后,执行命令可能会报以下错误:

1
2
3
4
[u@host ~]$ autojump
Please source the correct autojump file in your shell's
startup file. For more information, please reinstall autojump
and read the post installation instructions.

退出用户重新登录就可以了。

配置完成后,执行  autojump  或者  j  没有报错就说明安装成功:

1
2
3
4
[u@host ~]$ autojump
.
[u@host ~]$ j
.

在 Mac 中,由于不能使用 root 权限执行安装,autojump 的环境信息没有加入到环境变量。导致即使退出重登也无法生效。刚开始我也百思不得其解,以为是程序有问题,直到在 reinstall 的过程中,我看到了以下提示:

1
2
3
4
5
6
7
8
9
Add the following line to your ~/.bash_profile or ~/.zshrc file (and remember
to source the file to update your current session):
[ -f /usr/local/etc/profile.d/autojump.sh ] && . /usr/local/etc/profile.d/autojump.sh

If you use the Fish shell then add the following line to your ~/.config/fish/config.fish:
[ -f /usr/local/share/autojump/autojump.fish ]; and source /usr/local/share/autojump/autojump.fish

zsh completions have been installed to:
/usr/local/share/zsh/site-functions

原来需要手动添加 autojump 的环境信息到用户的环境变量,autojump 才会生效。So,那就加起来:

1
2
3
4
5
# 当前用户下生效
echo "[ -f /usr/local/etc/profile.d/autojump.sh ] && . /usr/local/etc/profile.d/autojump.sh" >> ~/.bash_profile

# 所有用户下生效
sudo sh -c 'echo "[ -f /usr/local/etc/profile.d/autojump.sh ] && . /usr/local/etc/profile.d/autojump.sh" >> /etc/profile'

autojump 使用

安装完成后,就可以使用  autojump  或者  j  命令快速调到指定目录,前提是这个目录在安装完 autojump 后进去过。

1
2
3
4
5
6
7
8
9
[hzz@magedu ~]$ cd /var/www/html/
[hzz@magedu html]$ cd
[hzz@magedu ~]$ pwd
/home/hzz
[hzz@magedu ~]$ j html
/var/www/html
[hzz@magedu html]$ pwd
/var/www/html
[hzz@magedu html]$

甚至于只输入部分字符,就可以进入指定目录,比如:

1
2
3
4
5
6
7
[hzz@magedu ~]$ pwd
/home/hzz
[hzz@magedu ~]$ j htm
/var/www/html
[hzz@magedu html]$ pwd
/var/www/html
[hzz@magedu html]$

输入部分字符后,如果不确定目录是否被收录或识别,按一次  tab,就会出现补全提示,也就是能否从 autojump 中找到记录,字符后面出现  __  则表示找到记录;如果没有反应,则说明未找到记录,需要手动进入该目录以便收录。(若未找到记录,而按回车的话,默认会进入当前目录。)

1
2
3
4
5
[hzz@magedu ~]$ j h__
/var/www/html
[hzz@magedu html]$ j x
.
[hzz@magedu html]$

如果默认进入的目录不是你想要的目录,可以在出现  __  后再连按两次  tab,这样就会出现候选项,选择需要进入的目录编号进入即可:

1
2
3
4
5
6
7
8
[hzz@magedu ~]$ j h__
h__1__/var/www/html h__3__/home/hzz/htm h__5__/home/hzz/html h__7__/home/hzz/htm
h__2__/home/hzz/html h__4__/var/www/html h__6__/home/hzz/wwww
[hzz@magedu ~]$ j h__3
/home/hzz/htm
[hzz@magedu htm]$ pwd
/home/hzz/htm
[hzz@magedu htm]$

类似输入法,哪个目录最常进入,说明权重越高(权重可手动调节),就越靠前,直至默认。

autojump 进阶

若是没有特殊要求,上面所说的应该能满足日常使用了,但是通过  j --help,我们可以看到 autojump 还提供了几个参数方便我们使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[hzz@magedu html]$ j --help
usage: autojump [-h] [-a DIRECTORY] [-i [WEIGHT]] [-d [WEIGHT]] [--complete]
[--purge] [-s] [-v]
[DIRECTORY [DIRECTORY ...]]

Automatically jump to directory passed as an argument.

positional arguments:
DIRECTORY directory to jump to

optional arguments:
-h, --help show this help message and exit
-a DIRECTORY, --add DIRECTORY
add path
-i [WEIGHT], --increase [WEIGHT]
increase current directory weight
-d [WEIGHT], --decrease [WEIGHT]
decrease current directory weight
--complete used for tab completion
--purge remove non-existent paths from database
-s, --stat show database entries and their key weights
-v, --version show version information

Please see autojump(1) man pages for full documentation.

下面我们就来说说各参数的用法。

j -a DIRECTORY  添加目录,即不用进入目录,即可将目录添加进 autojump 记录。

1
2
3
4
5
6
7
[hzz@magedu html]$ j et
.
[hzz@magedu html]$ j -a /etc/
[hzz@magedu html]$ j et
/etc
[hzz@magedu etc]$ pwd
/etc

j -s  查看各目录权重,并查看数据信息。

j -i [WEIGHT]  添加权重,权重越高,该目录的优先级就越高。

j -d [WEIGHT]  减少权重,权重越低,该目录的优先级越低。

j --complete  查看关键字的候选项,常用双击  tab  代替。

j --purge  清理 autojump 记录里面那些已不存在的目录数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[u@host ~]$ pwd
/home/hzz
[u@host ~]$ rm -rf wwww
[u@host ~]$ j ww__
ww__1__/home/hzz/wwww ww__3__/home/hzz/wwww ww__5__/var/www/html ww__7__/var/www
ww__2__/var/www ww__4__/var/www ww__6__/home/hzz/wwww
[u@host ~]$ j ww__

# 可以看到,即使 wwww 目录已经被删除,但是候选项里面还是会出现 /home/hzz/wwww 目录,这时就可以使用 j --purge 进行清理。建议设定 crontab 定期自动清理。

[u@host ~]$ j --purge
Purged 1 entries.
[u@host ~]$ j ww__
ww__1__/var/www ww__2__/var/www ww__3__/var/www/html ww__4__/var/www
[u@host ~]$ j ww__

好了,这款神器就介绍到这。总之,有了这款神器后,效率提高了不少,比如,当我需要发布博客时,只需要很少的步骤即可进入发布目录,比建软连接还快。

1
2
3
4
5
6
Hzzs-MacBook-Pro:~ hzz$ j h
/Users/hzz/MyBlog/Hexo
Hzzs-MacBook-Pro:Hexo hzz$ hexo d -g
INFO Start processing
INFO Files loaded in 2.64 s
...

Have fun!

CentOS 7 安装 nginx, php, mysql, redis, supervisor 套件

初始化系统

这里设置的用户是 duoli

在此之前现需要对 CentOS 进行服务器完善和升级

设置软件源

  • mysql
1
2
# 由于mysql 版权方面的限制, centos 7 没有内置mysql 服务器, 必须从mysql 官方进行安装
$ yum install http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm
  • 设置 nginx 源

方式一:(安装 rpm:推荐)

1
$ yum install http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

方式二:(手动创建)

源地址: nginx: Linux packages
创建 vim /etc/yum.repos.d/nginx.repo , 并且填充以下内容来安装 yum repository 库

1
2
3
4
5
6
7
8
9
10
11
12
13
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key

默认情况下,使用稳定 nginx 仓库包。如果您想使用 mainline nginx 包,运行以下命令

1
$ sudo yum-config-manager --enable nginx-mainline

安装基础软件

1
2
3
# 安装常用软件
$ yum install vim git yum-utils
$ yum install redis --enablerepo=remi

安装软件以及配置

安装并配置 Mysql 数据库

1
2
# 安装 mysql server
$ yum install mysql-server

启动 mysql 并且获取密码

1
2
3
4
5
6
$ systemctl start mysqld

# mysql 5.7 在安装完成的时候会生成一个临时密码, 我们需要找到错误日志 `/var/log/mysqld.log`来获取这个临时密码
# use below command to see the password:
$ grep 'temporary password' /var/log/mysqld.log
[Note] A temporary password is generated for root@localhost: m#mMbdga&9Zn

初始化 mysql

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
$ mysql_secure_installation
Securing the MySQL server deployment.
Enter password for user root: ******

New password: ******

Re-enter new password: ******

The 'validate_password' plugin is installed on the server.
The subsequent steps will run with the existing configuration
of the plugin.
Using existing password for root.

Estimated strength of the password: 100
Change the password for root ? ((Press y|Y for Yes, any other key for No) : *

Estimated strength of the password: 100
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.
Remove anonymous users? (Press y|Y for Yes, any other key for No) : Y

Success.


Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : N


... skipping.
By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.


Remove test database and access to it? (Press y|Y for Yes, any other key for No) : N

... skipping.
Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : Y

Success.

All done!

设置密码的方法

1
2
3
$ mysql -uroot -p******
mysql> set password for 'root'@'localhost' = password('markzhao123456');
mysql> exit

配置数据库用户

1
2
3
4
CREATE USER 'remote'@'%' IDENTIFIED WITH mysql_native_password AS 'U*OSy)iKk$XO9dMB';
GRANT ALL PRIVILEGES ON *.* TO 'remote'@'%' REQUIRE NONE WITH GRANT OPTION MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;
GRANT ALL PRIVILEGES ON `1dailian\_v2`.* TO 'remote'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES

让用户可以远程访问
在 my.conf 中 [mysqld] 部分增加以下行并重启 mysqld

1
bind-address=0.0.0.0

开机自启动

1
$ systemctl enable mysqld

安装并配置 nginx

安装 Nginx

1
2
# 安装 nginx
$ yum install nginx --enablerepo=nginx

配置 nginx 时候的运行组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# /etc/nginx/nginx.conf
user duoli;

# max upload setting
http {
# http level
client_max_body_size 20m;

server{
# server level
client_max_body_size 20m;
}

}

这里需要注意 nginx 缓存目录的权限需要和运行用户一致

1
2
3
4
# 目录位置
/var/cache/nginx
/var/lib/nginx
/var/log/nginx

配置 nginx 虚拟主机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
server{
listen 80;
# 如果这里是 IP, 则才会允许访问, 否则, 扯破牛蛋也访问不到
server_name www.domain.com ;
index index.php index.html;
root /webdata/www/domain/public;

# 这里注意和服务器自带不同的是
# fastcgi_param SCRIPT_FILENAME /scripts/$fastcgi_script_name;
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# 会导致 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

location / {
try_files $uri $uri/ /index.php?$query_string;
}

location ~ .*\.(js|css)?$ {
expires 12h;
}


access_log /webdata/logs/domain.access.log main;
error_log /webdata/logs/domain.error.log;
}

安装并配置 php

1
2
3
# 安装 php 基于 remi , 所以需要安装 remi 源
# 如果需要安装其他版本, 则需要将 repo=remi-php7x
$ yum install --enablerepo=remi-php74 php php-pdo php-fpm php-mbstring php-pecl-mcrypt php-gd php-mysqli php-zip php-bcmath php-xml

配置 php-fpm 权限

1
2
3
# /etc/php-fpm.d/www.conf
user = duoli
group = duoli

配置 php.ini

1
2
3
4
5
# 时区
date.timezone = Asia/Shanghai
# upload
post_max_size = 20M
upload_max_filesize = 20M

配置 session 是可写状态

1
$ chown -R duoli:duoli /var/lib/php/

配置系统端口允许访问并加入自启动

配置的端口有 9023/9024/80/3306 等

1
2
3
4
5
6
7
8
9
10
11
# 配置 http
$ firewall-cmd --permanent --zone=public --add-service=http
# 配置 3306
$ firewall-cmd --permanent --zone=public --add-port=3306/tcp
# 重启 防火墙
$ firewall-cmd --reload

# 如未启动服务, 可启动服务
$ systemctl start php-fpm mysqld nginx supervisord redis
# 开机启动
$ systemctl enable php-fpm mysqld nginx supervisord redis

补充

下载安装 mysql

获取最新下载地址:
http://dev.mysql.com/downloads/mysql/

1
2
3
4
5
6
7
# 下载
$ wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-community-client-5.7.*-1.el7.i686.rpm
$ wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-community-server-5.7.*-1.el7.i686.rpm

# 安装
yum localinstall mysql-community-client**.rpm
yum localinstall mysql-community-server**.rpm

mysql 更换安装目录

默认位置在:

1
/var/lib/mysql

新建目标位置并移动数据

1
2
3
4
5
6
# new dir
$ mkdir /webdata/db/
# move data
$ mv -R /var/lib/mysql /webdata/db
# permission
$ chown -R mysql.mysql /webdata/db

编辑配置文件

1
2
3
4
# vi config
$ vi /etc/my.cnf
datadir=/webdata/db/mysql
socket=/webdata/db/mysql/mysql.sock

更改 mysql 链接 socket, 否则 mysql 客户端无法使用默认配置连接

1
2
3
[client]
port=3306
socket=/webdata/db/mysql/mysql.sock

重启服务

1
2
# restart mysql
$ systemctl restart mysqld

Centos 进行 Php 升级(使用 remi-php 源)

安装启用 remi 的工具包

1
2
3
4
5
# 安装 util 工具
$ yum install yum-utils

# 启用相应的源
$ yum-config-manager --enable remi-php74

进行 PHP 升级

1
$ yum upgrade php

升级之后权限会进行重置

/var/lib/php/

1
2
3
drwxrwx--- 2 root apache 4096 10月 20 14:03 opcache
drwxrwx--- 2 root apache 4096 10月 20 14:03 session
drwxrwx--- 2 root apache 4096 10月 20 14:03 wsdlcache

更改目录权限

1
2
3
4
5
6
$ chown -R userxxx.userxxx /var/lib/php/

# 更改文件执行权限(一般升级不用)
$ vim /etc/php-fpm.d/www.conf
# user=...
# group=xxx

FAQ

File not found

nginx/apache 网页文件的 selinux 上下文需要配置, 如果未配置则日志中返回的错误是 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, 暴力解决方法: 关闭

1
$ vim /etc/sysconfig/selinux

设置为禁用

1
2
3
4
5
6
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=disabled

补充附录

变更记录

2021-10-28

  • 增加权限改动示例

2019-09-20

  • pip 更新为 pip3, 不使用 python2
  • 加入 redis

2019-04-03

  • redis 使用 remi 安装最新版
  • supervisor 使用 pip 安装最新版, 系统自带的版本较低
  • supervisor 启动加入自己写入配置文件

2016-10-05

  • 第一版版本

参考文章

[转+] Linux expect 命令介绍和实现交互式免密登录

原文地址 : Linux 下使用 expect 实现跳板机自动跳转/免密登录/自动登录(转)

Expect 是一个用来处理 交互 的命令。借助 Expect,我们可以将交互过程写在一个脚本上,使之自动化完成。形象的说,ssh 登录,ftp 登录等都符合 交互 的定义。

四个命令

Expect 中最关键的四个命令是 send,expect,spawn,interact。

  • send:用于向进程发送字符串
  • expect:从进程接收字符串
  • spawn:启动新的进程
  • interact:允许用户交互

1. send 命令

send 命令接收一个字符串参数,并将该参数发送到进程。

1
2
3
expect1.1> send "hello word\n"
hello word
expect1.2>

2. expect 命令

2.1 基础知识

expect 命令和 send 命令正好相反,expect 通常是用来等待一个进程的反馈。expect 可以接收一个字符串参数,也可以接收正则表达式参数。和上文的 send 命令结合,现在我们可以看一个最简单的交互式的例子:

1
2
expect "hi\n"
send "hello there!\n"

这两行代码的意思是:从 标准输入 中等到 hi 和换行键后,向 标准输出 输出 hello there。

$expect_out(buffer) 存储了所有对 expect 的输入,<$expect_out(0,string)> 存储了匹配到 expect 参数的输入。

比如如下程序:

1
2
3
expect "hi\n"
send "you typed <$expect_out(buffer)>"
send "but I only expected <$expect_out(0,string)>"

当在标准输入中输入

1
2
test
hi

是,运行结果如下

1
2
3
you typed: test
hi
I only expect: hi

2.2 模式-动作

expect 最常用的语法是来自 tcl 语言的模式-动作。这种语法极其灵活,下面我们就各种语法分别说明。

单一分支模式语法:

1
expect "hi" {send "You said hi"}

匹配到 hi 后,会输出”you said hi”

多分支模式语法:

1
2
3
expect "hi" { send "You said hi\n" } \
"hello" { send "Hello yourself\n" } \
"bye" { send "That was unexpected\n" }

匹配到 hi, hello, bye 任意一个字符串时,执行相应的输出。等同于如下写法:

1
2
3
4
5
expect {
"hi" { send "You said hi\n"}
"hello" { send "Hello yourself\n"}
"bye" { send "That was unexpected\n"}
}

3. spawn 命令

上文的所有 demo 都是和标准输入输出进行交互,但是我们跟希望他可以和某一个进程进行交互。spawn 命令就是用来启动新的进程的。spawn 后的 send 和 expect 命令都是和 spawn 打开的进程进行交互的。结合上文的 send 和 expect 命令我们可以看一下更复杂的程序段了。

1
2
3
4
5
6
7
8
9
10
set timeout -1
spawn ftp ftp.test.com //打开新的进程,该进程用户连接远程ftp服务器
expect "Name" //进程返回Name时
send "user\r" //向进程输入anonymous\r
expect "Password:" //进程返回Password:时
send "123456\r" //向进程输入don@libes.com\r
expect "ftp> " //进程返回ftp>时
send "binary\r" //向进程输入binary\r
expect "ftp> " //进程返回ftp>时
send "get test.tar.gz\r" //向进程输入get test.tar.gz\r

这段代码的作用是登录到 ftp 服务器 ftp ftp.uu.net 上,并以二进制的方式下载服务器上的文件 test.tar.gz。程序中有详细的注释。

4. interact

到现在为止,我们已经可以结合 spawn、expect、send 自动化的完成很多任务了。但是,如何让人在适当的时候干预这个过程了。比如下载完 ftp 文件时,仍然可以停留在 ftp 命令行状态,以便手动的执行后续命令。interact 可以达到这些目的。下面的 demo 在自动登录 ftp 后,允许用户交互。

1
2
3
4
5
6
spawn ftp ftp.test.com
expect "Name"
send "user\r"
expect "Password:"
send "123456\r"
interact

解决问题

1. 如何从机器 A 上 ssh 到机器 B 上,然后执行机器 B 上的命令?使之自动化完成?

下面一段脚本实现了从机器 A 登录到机器 B,然后执行机器 B 上的 pwd 命令,并停留在 B 机器上,等待用户交互。具体含义请参考上文。

1
2
3
4
5
6
#!/home/tools/bin/64/expect -f
set timeout -1
spawn ssh $BUser@$BHost
expect "*password:" { send "$password\r" }
expect "$*" { send "pwd\r" }
interact

2. 如何实现登录到跳板机然后再登录到其他机器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#! /usr/bin/expect

set JumpPwd [lindex $argv 0]
set ServerHost [lindex $argv 1]
set ServerPwd [lindex $argv 2]

set timeout 3
spawn ssh server-jump
expect {
"yes/no" {
send "(yes/no)\\?";
exp_continue;
}
"*passphrase*" {
send "$JumpPwd\r"
}
}

# next jump
expect "*user@*" {
send "ssh $ServerHost\r"
}

expect {
"*passphrase*" {send "$ServerPwd\r"}
}
interact

参考