0%

背景

因为启动虚拟机后,默认使用 DHCP 获取 IP。这样就会导致每次终端连接的时候,都需要查看服务器的地址是什么,并不方便。所以编写该文章记录如何设置为静态 IP。

配置

在 Ubuntu 22.04 中,使用 netplan 命令来配置静态 IP。

首先查看 /etc/netplan 下的文件都有什么:

1
2
$ ls /etc/netplan/
00-installer-config.yaml

这里,就会修改 /etc/netplan/00-installer-config.yaml 文件

我们先看看该文件的现有内容:

1
2
3
4
5
6
# This is the network config written by 'subiquity'
network:
ethernets:
ens32:
dhcp4: true
version: 2

我们可以看到这里设置的 dhcp4yes。表示是 dhcp 模式。

好了,下面我们要进行修改了。下面是改好的格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# This is the network config written by 'subiquity'
network:
ethernets:
ens32:
dhcp4: false
dhcp6: false
addresses:
- 192.168.1.254/24
routes:
- to: default
via: 192.168.1.1
nameservers:
addresses:
- 114.114.114.114
version: 2

现在我们解释一下修改的内容:

  • dhcp4:IPv4 的自动分配,设置为 no 表示不进行 IPv4 地址的自动分配。
  • dhcp6:IPv6 的自动分配,设置为 no 表示不进行 IPv6 地址的自动分配。
  • addresses:设置固定的 ip。这里有个 /24,我们需要对这一块单独说下。
  • routes:指定网关地址,之前是 gateway4,如果继续使用,会提示: `gateway4` has been deprecated, use default routes instead
  • nameservers: DNS 服务器。addresses 的数组表示可以设置多个。

子网掩码

如果有人设置过 Windows 的静态 IP 或者说之前的版本的 Ubuntu 的静态 ip 的,可能会觉得少了一个东西,没错,就是子网掩码。

这里就是说的 /24 了。它其实就是设置的子网掩码。下面有前缀对应的 ip,我们可以通过这个来进行响应的设置了。

前缀大小 子网掩码
/24 255.255.255.0
/25 255.255.255.128
/26 255.255.255.192
/27 255.255.255.224
/28 255.255.255.240
/29 255.255.255.248
/30 255.255.255.252

执行命令

好了,我们把配置文件的内容按照实际情况修改好了之后。执行以下命令进行部署:

可以使用如下命令进行检测是否正确:

1
sudo netplan try

这里需要注意的一个事情就是不要使用远程终端执行此命令。因为它的解释是:Try to apply a new netplan config to running system, with automatic rollback

1
sudo netplan apply

如果没有问题,固态ip就设置成功了。好了,是不是非常简单呢?

我的火狐浏览器默认主页是123.sogou.com 但是,我希望把我的首页变成百度。

然后我按照以前的习惯,在设置里面将主页的链接设置成了baidu.com

结果发现,后来还是会偷偷的给改成搜狗主页。

居然这么流氓!!!

这个时候我就发挥我的程序员能力了。

我想到一个办法,就是将这个域名绑定到127.0.0.1,这样就不会给搜狗做推广了。

然后发现还是有问题,就是不能直接访问网页,还需要输入一次。

所以使用nginx的rewrite功能来重写URL,发现重写之后会带着get参数,这个时候,百度会自动跳转到错误页面,还是不行。

于是我就想到编写一个php文件,当请求的时候,就使用header进行重定向。

尝试了之后,发现非常ok。

下面提供以下操作方法:

首先修改hosts文件,增加以下内容:

1
127.0.0.1	123.sogou.com

然后在**/etc/nginx/conf.d/增加123.sogou.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
server {
listen 80;
server_name 123.sogou.com;

charset utf-8;
#access_log logs/host.access.log main;
root html;
index sogou.php;

# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
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;
}
}

然后在**/usr/share/html/新增sogou.php**文件,内容如下:

1
2
<?php
header("Location: https://www.baidu.com");

然后重启nginx。

最后我们测试一下,在浏览器里面点击主页图标。我这里就直接跳转到baidu
首页了。

完美!

我的系统使用的优麒麟。它跟ubuntu是一个派系的。

所以都是使用apt命令。

首先是安装nginx

1
sudo apt install nginx

非常简单,nginx就安装完成了。

接下来会安装php

1
sudo apt install php php-fpm

这个时候默认安装是php7.1的,不得不说,ubuntu对于php的更新还是比较频繁的,因为我之前用的centos7.4使用的php版本好像还是5.4的,无语了。

这个时候可能会提示,apache不能启动的错误,这是因为nginx已经把80端口给占用了,而后面apache再去绑定端口的时候,就会提示绑定失败了。不用管他。因为这次是实现LNMP环境。

接着就是安装mysql了。也是一条命令:

1
sudo apt-get install mysql-server-5.7

中间会提示让你输入密码。

接下来就是环境的配置了。

首先我们使用以下命令打开fpm的配置文件:

1
sudo vim /etc/php/7.1/fpm/pool.d/www.conf

listen参数改为监听端口的。(个人习惯,也可以使用socket)

1
2
3
4
5
6
7
listen = 127.0.0.1:9000
````

然后执行以下命令重启**php-fpm**

```bash
sudo systemctl reload php7.1-fpm

接下来就是配置nginx了。

首先我们查看目录下的配置文件:

1
ls /etc/nginx/conf.d/

发现目录为为空,之前在centos 之后yum安装的时候还有一个default.conf文件呢,这个直接没了,也不知道是不是忘了给加上。[偷笑]

我们可以将以下文件放入**/etc/nginx/conf.d/default.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
26
server {
listen 80;
server_name localhost;

charset utf-8;

#access_log logs/host.access.log main;

root html;
index index.html index.php;

# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
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;
}
}

然后使用以下命令重启nginx

1
sudo systemctl reload nginx

然后我们在浏览器访问localhost,就可以看到我们期待已久的ningx默认页面了。

我在公司的时候,无意中安装的优麒麟,觉得UI还是比较不错的,而且字体的显示我还是比较喜欢的。正好我也想尝试将我的电脑系统换成了linux,朋友说我这种行为就是在作死,还说祝我好运。嘿嘿,死不了的。

我想,其实是这样的,因为没有办法正常使用windows的一系列软件,比如QQ。其实也就是QQ了,其他的软件都有办法进行替代,但是通讯工具,只有这一个,你没办法换,我也挺好奇为啥QQ 就是不能出一个linux版的。如果出一个linux版的,估计会让中国的linux大幅度发展的。

吐嘈太多没用,还是记录一下我自己安装的情况把。

首先就是执行下面的命令将系统更新到最新。

1
2
sudo apt update
sudo apt upgrade

更新了之后,正常就是正常的安装安装软件环节了。

我安装了phpstorm。sublime,以及网易云音乐,至少这三个软件不用寻找替代版了。

同时寻找在linux上替代windows的软件。

首先是有道云笔记,因为我使用的是火狐浏览器,但是有道云笔记的web版结果只有老版的支持,结果我登录进去,发现保存的东西已经不是我最新的东西了。

所以逐而放弃,从而寻找新的工具,后来找到Simplenote,下载了一个尝试了一下,发现非常简洁,没有多余的功能,而且支持markdown。非常方便。

在此记录一下sublime的安装方式。非常简单。

1
2
3
4
5
wget -qO - https://download.sublimetext.com/sublimehq-pub.gpg | sudo apt-key add -
sudo apt-get install apt-transport-https
echo "deb https://download.sublimetext.com/ apt/stable/" | sudo tee /etc/apt/sources.list.d/sublime-text.list
sudo apt-get update
sudo apt-get install sublime-text

执行上面的一套组合拳,嗖嗖的就能安装上sublime了。

sublime text 的 package control 安装可参考我

其实这并不是我自己的总结,而是作者在最后一页为自己写的总结,原因是,篇幅太长,怕读者懒得看,我不知道,然后一页一页的看下去了。结果最后看到了这个。。。

下面是总结的内容:

  • 软件开发多种多样,不存在谁好谁坏。但是它们互相都看不起。
  • 好的程序员之所以出色是因为熟能生巧。
  • 只要你愿意,随时都可以学习新语言。
  • 如果你想要当经理,那你很可能不是一个好经理。
  • Lisp很难掌握,但它是唯一能让我继续快乐的语言。
  • Emacs很难掌握,但却是终身受益的投资。
  • 离开舒适区。时不时的学点新东西。
  • 为自己写点东西。只有这样你才知道那时不时对的。
  • 多笑一点。这很健康,也让人感觉很好。
  • 记得自嘲,不过不要在公开场合大声自嘲,也不要忘了解释。

我想说,其实作者吐槽了很多,只是在总结中并没有体现出来,比如JAVA的不好用;自由派与保守派,对于重构的看法;弱类型与强类型的选择;项目的代码量应该要精简;编程语言的营销;学习离散数学;学习编写编译器等。

希望大家也能去读一下这本书。非常值得一看。

比如我们在新增一篇文章的时候,我们一般会写如下的表单验证。

1
2
3
$this->validate($request, [
'title' => 'required|unique:article|max:255',
]);

这样在新增的时候是没什么问题的,但是在更新的时候就出现了一个问题,就是当我们的title没有发生改变的时候,我们使用unique的时候,会将原来的记录行进行扫描,这样就会提示我们该标题已经存在

这样就比较坑爹了,那么有没有什么办法可以解决呢。办法是有的,其实很简单,我们只需要跟下面那样写就好了:

1
2
3
4
$id = $request->input("id", 0);
$this->validate($request, [
'title' => "required|unique:article,id,{$id}|max:255",
]);

这样的话在验证唯一的时候就会不去验证id=$id的记录。这样就可以防止我们刚才碰到的问题了。

那么不管新增还是更新,套路就是这样了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$id = $request->input("id", 0);
$this->validate($request, [
'title' => "required|unique:article,id,{$id}|max:255",
]);

if ($id < 1) { // 新增
$info = new Article();
} else {
$info = Article::where("id", $id)->first();
}

$info->title = $request->input("title");

if ($info->save()) {
// 操作成功
} else {
// 操作失败
}

Laravel真是最好的框架。

哈哈

参考网址:

https://stackoverflow.com/questions/23587833/laravel-validation-unique-on-update

好久没发表文章了。今天说一下单例模式。

单例模式主要有以下几个关键点:

  • 对象应该可以被系统中的任何对象使用。
  • 对象不应该被存储在会被覆写的全局变量中。
  • 系统中不应超过一个要单例的对象。

其实实现单例的方法很简单。比如我们现在声明一个类Config。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Config {
private $configs = [];

private function __construct() {}

public function set($key, $value){
$this->configs[$key] = $value;
}

public function get($key) {
return $this->configs[$key];
}
}

此时的类还是无法使用的。因为构造函数已经被私有化了。我们需要一个静态方法和静态变量来间接的实例化对象。代码如下:

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
class Config {
private $configs = [];
private static $instacne;
private function __construct() {}
private function __clone() {}
private function __sleep() {}
private function __wakeup() {}

/**
* 获取实例化对象
*/
public static function getInstance() {
if (empty(self::$instacne)) {
self::$instacne = new self;
}

return self::$instacne;
}

public function set($key, $value){
$this->configs[$key] = $value;
}

public function get($key) {
return $this->configs[$key];
}
}

我们使用Config::getInstanct()来获取对象实例,并将其保存到$instance静态变量中。

接下来,我们写一个demo,来检测代码是否能够正常工作:

1
2
3
4
5
6
7
$config = Config::getInstance();

$config->set("name", "matt");
unset($config);

$config = Config::getInstance();
var_dump($config->get("name"));

执行即可得出结果正是我们最早写入的值。 好了,单例模式就介绍完成了。

本教程是在 Rocky 9.0 系统下执行的。

启用 CRB 仓储库

1
dnf config-manager --set-enabled crb

安装 EPEL 和 Remi

EPEL:

1
dnf install epel-release

Remi:

1
dnf install https://rpms.remirepo.net/enterprise/remi-release-9.rpm

设置默认使用版本

查看目前可以启用的版本都有哪些:

1
2
3
4
5
6
7
8
9
# dnf module list php
Last metadata expiration check: 0:36:18 ago on Thu Aug 18 07:57:35 2022.
Remi's Modular repository for Enterprise Linux 9 - x86_64
Name Stream Profiles Summary
php remi-7.4 common [d], devel, minimal PHP scripting language
php remi-8.0 common [d], devel, minimal PHP scripting language
php remi-8.1 common [d], devel, minimal PHP scripting language

Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled

这样就设置默认安装的 PHP 版本为 8.1

1
2
dnf module reset php
dnf module install php:remi-8.1

更新资源包:

1
dnf update

这样就会安装上了 PHP 了。

这里看下安装的情况:

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
# php -v
PHP 8.1.9 (cli) (built: Aug 2 2022 13:02:24) (NTS gcc x86_64)
Copyright (c) The PHP Group
Zend Engine v4.1.9, Copyright (c) Zend Technologies
# php -m
[PHP Modules]
bz2
calendar
Core
ctype
curl
date
dom
exif
fileinfo
filter
ftp
gettext
hash
iconv
json
libxml
mbstring
openssl
pcntl
pcre
Phar
readline
Reflection
session
SimpleXML
sockets
SPL
standard
tokenizer
xml
xmlreader
xmlwriter
xsl
zlib

[Zend Modules]

php支持的扩展

我们可以通过以下命令查看支持安装的php扩展:

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# dnf search php81-
Last metadata expiration check: 0:37:25 ago on Thu Aug 18 07:57:35 2022.
============================================ Name & Summary Matched: php81- ============================================
php81-php-pecl-http-message-devel.x86_64 : php81-php-pecl-http-message developer files (headers)
php81-php-pecl-pcsc-devel.x86_64 : php81-php-pecl-pcsc developer files (header)
php81-php-pecl-psr-devel.x86_64 : php81-php-pecl-psr developer files (header)
php81-php-pecl-raphf-devel.x86_64 : php81-php-pecl-raphf developer files (header)
php81-php-pecl-xmldiff-devel.x86_64 : php81-php-pecl-xmldiff developer files (header)
php81-php-pecl-yaconf-devel.x86_64 : php81-php-pecl-yaconf developer files (header)
php81-php-zephir-parser-devel.x86_64 : php81-php-zephir-parser developer files (headers)
php81-php-zstd-devel.x86_64 : php81-php-zstd developer files (header)
================================================= Name Matched: php81- =================================================
php81-build.x86_64 : Package shipping basic build configuration
php81-php.x86_64 : PHP scripting language for creating dynamic web sites
php81-php-ast.x86_64 : Abstract Syntax Tree
php81-php-bcmath.x86_64 : A module for PHP applications for using the bcmath library
php81-php-brotli.x86_64 : Brotli Extension for PHP
php81-php-cli.x86_64 : Command-line interface for PHP
php81-php-common.x86_64 : Common files for PHP
php81-php-dba.x86_64 : A database abstraction layer module for PHP applications
php81-php-dbg.x86_64 : The interactive PHP debugger
php81-php-devel.x86_64 : Files needed for building PHP extensions
php81-php-embedded.x86_64 : PHP library for embedding in applications
php81-php-enchant.x86_64 : Enchant spelling extension for PHP applications
php81-php-ffi.x86_64 : Foreign Function Interface
php81-php-fpm.x86_64 : PHP FastCGI Process Manager
php81-php-gd.x86_64 : A module for PHP applications for using the gd graphics library
php81-php-geos.x86_64 : PHP module for GEOS
php81-php-gmp.x86_64 : A module for PHP applications for using the GNU MP library
php81-php-imap.x86_64 : A module for PHP applications that use IMAP
php81-php-intl.x86_64 : Internationalization extension for PHP applications
php81-php-ioncube-loader.x86_64 : Loader for ionCube Encoded Files with ionCube 24 support
php81-php-ldap.x86_64 : A module for PHP applications that use LDAP
php81-php-libvirt.x86_64 : PHP language binding for Libvirt
php81-php-libvirt-doc.noarch : Document of php-libvirt
php81-php-litespeed.x86_64 : LiteSpeed Web Server PHP support
php81-php-lz4.x86_64 : LZ4 Extension for PHP
php81-php-maxminddb.x86_64 : MaxMind DB Reader extension
php81-php-mbstring.x86_64 : A module for PHP applications which need multi-byte string handling
php81-php-mysqlnd.x86_64 : A module for PHP applications that use MySQL databases
php81-php-oci8.x86_64 : A module for PHP applications that use OCI8 databases
php81-php-odbc.x86_64 : A module for PHP applications that use ODBC databases
php81-php-opcache.x86_64 : The Zend OPcache
php81-php-pdo.x86_64 : A database access abstraction module for PHP applications
php81-php-pdo-dblib.x86_64 : PDO driver for Microsoft SQL Server and Sybase databases
php81-php-pdo-firebird.x86_64 : PDO driver for Interbase/Firebird databases
php81-php-pear.noarch : PHP Extension and Application Repository framework
php81-php-pecl-ahocorasick.x86_64 : Effective Aho-Corasick string pattern matching algorithm
php81-php-pecl-amqp.x86_64 : Communicate with any AMQP compliant server
php81-php-pecl-apcu.x86_64 : APC User Cache
php81-php-pecl-apcu-devel.x86_64 : APCu developer files (header)
php81-php-pecl-apfd.x86_64 : Always Populate Form Data
php81-php-pecl-awscrt.x86_64 : AWS Common Runtime PHP bindings
php81-php-pecl-base58.x86_64 : Encode and decode data with base58
php81-php-pecl-bitset.x86_64 : BITSET library
php81-php-pecl-cassandra.x86_64 : DataStax PHP Driver for Apache Cassandra
php81-php-pecl-couchbase3.x86_64 : Couchbase Server PHP extension
php81-php-pecl-couchbase4.x86_64 : Couchbase Server PHP extension
php81-php-pecl-crypto.x86_64 : Wrapper for OpenSSL Crypto Library
php81-php-pecl-csv.x86_64 : CSV PHP extension
php81-php-pecl-datadog-trace.x86_64 : APM and distributed tracing for PHP
php81-php-pecl-dbase.x86_64 : dBase database file access functions
php81-php-pecl-decimal.x86_64 : Arbitrary-precision floating-point decimal
php81-php-pecl-dio.x86_64 : Direct I/O functions
php81-php-pecl-ds.x86_64 : Data Structures for PHP
php81-php-pecl-eio.x86_64 : Provides interface to the libeio library
php81-php-pecl-env.x86_64 : Load environment variables
php81-php-pecl-ev.x86_64 : Provides interface to libev library
php81-php-pecl-event.x86_64 : Provides interface to libevent library
php81-php-pecl-excimer.x86_64 : Interrupting timer and low-overhead sampling profiler
php81-php-pecl-fann.x86_64 : Wrapper for FANN Library
php81-php-pecl-gearman.x86_64 : PHP wrapper to libgearman
php81-php-pecl-geoip.x86_64 : Extension to map IP addresses to geographic places
php81-php-pecl-geospatial.x86_64 : PHP Extension to handle common geospatial functions
php81-php-pecl-gmagick.x86_64 : Provides a wrapper to the GraphicsMagick library
php81-php-pecl-gnupg.x86_64 : Wrapper around the gpgme library
php81-php-pecl-grpc.x86_64 : General RPC framework
php81-php-pecl-hdr-histogram.x86_64 : PHP extension wrapper for the C hdrhistogram API
php81-php-pecl-http.x86_64 : Extended HTTP support
php81-php-pecl-http-devel.x86_64 : Extended HTTP support developer files (header)
php81-php-pecl-http-message.x86_64 : PSR-7 HTTP Message implementation
php81-php-pecl-ice.x86_64 : Simple and fast PHP framework
php81-php-pecl-igbinary.x86_64 : Replacement for the standard PHP serializer
php81-php-pecl-igbinary-devel.x86_64 : Igbinary developer files (header)
php81-php-pecl-imagick-im6.x86_64 : Extension to create and modify images using ImageMagick 6
php81-php-pecl-imagick-im6-devel.x86_64 : imagick extension developer files (header)
php81-php-pecl-imagick-im7.x86_64 : Extension to create and modify images using ImageMagick 7
php81-php-pecl-imagick-im7-devel.x86_64 : imagick extension developer files (header)
php81-php-pecl-inotify.x86_64 : Inotify
php81-php-pecl-ion.x86_64 : Amazon ION support
php81-php-pecl-ip2location.x86_64 : Get geo location information of an IP address
php81-php-pecl-ip2proxy.x86_64 : Get proxy information of an IP address
php81-php-pecl-json-post.x86_64 : JSON POST handler
php81-php-pecl-jsonpath.x86_64 : Extract data using JSONPath notation
php81-php-pecl-krb5.x86_64 : Kerberos authentification extension
php81-php-pecl-krb5-devel.x86_64 : Kerberos extension developer files (header)
php81-php-pecl-leveldb.x86_64 : LevelDB PHP bindings
php81-php-pecl-luasandbox.x86_64 : Lua interpreter with limits and safe environment
php81-php-pecl-lzf.x86_64 : Extension to handle LZF de/compression
php81-php-pecl-mailparse.x86_64 : PHP PECL package for parsing and working with email messages
php81-php-pecl-mcrypt.x86_64 : Bindings for the libmcrypt library
php81-php-pecl-memcache.x86_64 : Extension to work with the Memcached caching daemon
php81-php-pecl-memcached.x86_64 : Extension to work with the Memcached caching daemon
php81-php-pecl-memprof.x86_64 : Memory usage profiler
php81-php-pecl-mongodb.x86_64 : MongoDB driver for PHP
php81-php-pecl-msgpack.x86_64 : API for communicating with MessagePack serialization
php81-php-pecl-msgpack-devel.x86_64 : MessagePack developer files (header)
php81-php-pecl-mustache.x86_64 : Mustache templating language
php81-php-pecl-mysql.x86_64 : MySQL database access functions
php81-php-pecl-mysql-xdevapi.x86_64 : MySQL database access functions
php81-php-pecl-nsq.x86_64 : PHP extension for NSQ client
php81-php-pecl-oauth.x86_64 : PHP OAuth consumer extension
php81-php-pecl-opencensus.x86_64 : A stats collection and distributed tracing framework
php81-php-pecl-openswoole.x86_64 : PHP's asynchronous concurrent distributed networking framework
php81-php-pecl-pam.x86_64 : PAM integration
php81-php-pecl-parle.x86_64 : Parsing and lexing
php81-php-pecl-pcov.x86_64 : Code coverage driver
php81-php-pecl-pcsc.x86_64 : An extension for PHP using the winscard PC/SC API
php81-php-pecl-pkcs11.x86_64 : PHP Bindings for PKCS11 modules
php81-php-pecl-pq.x86_64 : PostgreSQL client library (libpq) binding
php81-php-pecl-protobuf.x86_64 : Mechanism for serializing structured data
php81-php-pecl-ps.x86_64 : An extension to create PostScript files
php81-php-pecl-psr.x86_64 : PSR interfaces
php81-php-pecl-quickhash.x86_64 : Set of specific strongly-typed classes for sets and hashing
php81-php-pecl-raphf.x86_64 : Resource and persistent handles factory
php81-php-pecl-rar.x86_64 : PHP extension for reading RAR archives
php81-php-pecl-rdkafka5.x86_64 : Kafka client based on librdkafka
php81-php-pecl-rdkafka6.x86_64 : Kafka client based on librdkafka
php81-php-pecl-redis5.x86_64 : Extension for communicating with the Redis key-value store
php81-php-pecl-rpminfo.x86_64 : RPM information
php81-php-pecl-rrd.x86_64 : PHP Bindings for rrdtool
php81-php-pecl-runkit7.x86_64 : For all those things you... shouldn't have been doing anyway... but surely do!
php81-php-pecl-scoutapm.x86_64 : Native Extension Component for ScoutAPM's PHP Agent
php81-php-pecl-scrypt.x86_64 : Scrypt hashing function
php81-php-pecl-sdl.x86_64 : Simple DirectMedia Layer for PHP
php81-php-pecl-sdl-image.x86_64 : SDL_image bindings for PHP
php81-php-pecl-sdl-mixer.x86_64 : Binding of SDL_mixer for PHP
php81-php-pecl-sdl-ttf.x86_64 : SDL_ttf bindings for PHP
php81-php-pecl-seaslog.x86_64 : An effective, fast, stable log extension for PHP
php81-php-pecl-seassnowflake.x86_64 : PHP Extension for Distributed unique ID generator
php81-php-pecl-selinux.x86_64 : SELinux binding for PHP scripting language
php81-php-pecl-simple-kafka-client.x86_64 : Kafka client based on librdkafka
php81-php-pecl-skywalking.x86_64 : The PHP instrument agent for Apache SkyWalking
php81-php-pecl-solr2.x86_64 : API orientée objet pour Apache Solr
php81-php-pecl-ssdeep.x86_64 : Wrapper for libfuzzy library
php81-php-pecl-ssh2.x86_64 : Bindings for the libssh2 library
php81-php-pecl-stats.x86_64 : Routines for statistical computation
php81-php-pecl-stomp.x86_64 : Stomp client extension
php81-php-pecl-swoole4.x86_64 : PHP's asynchronous concurrent distributed networking framework
php81-php-pecl-swoole5.x86_64 : PHP's asynchronous concurrent distributed networking framework
php81-php-pecl-sync.x86_64 : Named and unnamed synchronization objects
php81-php-pecl-teds.x86_64 : Tentative Extra Data Structures
php81-php-pecl-tensor.x86_64 : Objects for scientific computing in PHP
php81-php-pecl-trader.x86_64 : Technical Analysis for traders
php81-php-pecl-translit.x86_64 : Transliterates non-latin character sets to latin
php81-php-pecl-trie.x86_64 : PHP Trie extension
php81-php-pecl-uopz.x86_64 : User Operations for Zend
php81-php-pecl-uploadprogress.x86_64 : An extension to track progress of a file upload
php81-php-pecl-uuid.x86_64 : Universally Unique Identifier extension for PHP
php81-php-pecl-var-representation.x86_64 : var_representation extension
php81-php-pecl-varnish.x86_64 : Varnish Cache bindings
php81-php-pecl-vips.x86_64 : PHP extension for interfacing with libvips
php81-php-pecl-vld.x86_64 : Dump the internal representation of PHP scripts
php81-php-pecl-wddx.x86_64 : Web Distributed Data Exchange
php81-php-pecl-xattr.x86_64 : Extended attributes
php81-php-pecl-xdebug3.x86_64 : Provides functions for function traces and profiling
php81-php-pecl-xdiff.x86_64 : File differences/patches
php81-php-pecl-xhprof.x86_64 : PHP extension for XHProf, a Hierarchical Profiler
php81-php-pecl-xlswriter.x86_64 : An efficient and fast xlsx file extension
php81-php-pecl-xmldiff.x86_64 : XML diff and merge
php81-php-pecl-xmlrpc.x86_64 : Functions to write XML-RPC servers and clients
php81-php-pecl-xxtea.x86_64 : XXTEA encryption algorithm extension for PHP
php81-php-pecl-yac.x86_64 : Lockless user data cache
php81-php-pecl-yaconf.x86_64 : Yet Another Configurations Container
php81-php-pecl-yaf.x86_64 : Yet Another Framework
php81-php-pecl-yaml.x86_64 : PHP Bindings for yaml
php81-php-pecl-yar.x86_64 : Light, concurrent RPC framework
php81-php-pecl-yaz.x86_64 : Z39.50/SRU client
php81-php-pecl-zip.x86_64 : A ZIP archive management extension
php81-php-pecl-zmq.x86_64 : ZeroMQ messaging
php81-php-pgsql.x86_64 : A PostgreSQL database module for PHP
php81-php-phalcon5.x86_64 : Phalcon Framework
php81-php-phpiredis.x86_64 : Client extension for Redis
php81-php-process.x86_64 : Modules for PHP script using system process interfaces
php81-php-pspell.x86_64 : A module for PHP applications for using pspell interfaces
php81-php-realpath-turbo.x86_64 : Use realpath cache despite open_basedir restriction
php81-php-smbclient.x86_64 : PHP wrapper for libsmbclient
php81-php-snappy.x86_64 : Snappy Extension for PHP
php81-php-snmp.x86_64 : A module for PHP applications that query SNMP-managed devices
php81-php-snuffleupagus.x86_64 : Security module for PHP
php81-php-soap.x86_64 : A module for PHP applications that use the SOAP protocol
php81-php-sodium.x86_64 : Wrapper for the Sodium cryptographic library
php81-php-sqlsrv.x86_64 : Microsoft Drivers for PHP for SQL Server
php81-php-tidy.x86_64 : Standard PHP module provides tidy library support
php81-php-xml.x86_64 : A module for PHP applications which use XML
php81-php-xz.x86_64 : XZ (LZMA2) compression/decompression
php81-php-zephir-parser.x86_64 : Zephir code parser
php81-php-zstd.x86_64 : Zstandard extension
php81-runtime.x86_64 : Package that handles php81 Software Collection.
php81-scldevel.x86_64 : Package shipping development files for php81
php81-syspaths.x86_64 : System-wide wrappers for the php81 package
php81-unit-php.x86_64 : PHP module for NGINX Unit
php81-uwsgi-plugin-php.x86_64 : uWSGI - Plugin for PHP support
php81-xhprof.noarch : A Hierarchical Profiler for PHP - Web interface

比如可以通过执行如下命令安装 FPM 扩展:

1
dnf install php-mysqlnd

其实如果不支持的话,我们也可以手动安装。但是需要执行以下命令:

1
dnf install php-devel

PHP-FPM 命令管理

  • 启动
1
systemctl start php-fpm
  • 停止
1
systemctl stop php-fpm
  • 重载
1
systemctl reload php-fpm
  • 运行状态
1
systemctl status php-fpm
  • 设置开机启动
1
systemctl enable php-fpm 
  • 取消开机启动
1
systemctl disable php-fpm

总结

至此,dnf 安装 PHP 已经结束。如果有什么问题,可以在 GitHub 给我留言,我会再进行补充。

参考

我只会用,不清楚原理。

再次感谢军哥的一键linux安装包,我是从它的安装包中借鉴的代码

直接上代码,大家自行测试即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function color_red($str = ''){
echo "\e[0;31m{$str}\e[0m" . "\n";
}
function color_green($str = ''){
echo "\e[0;32m{$str}\e[0m" . "\n";
}
function color_yellow($str = ''){
echo "\e[0;33m{$str}\e[0m" . "\n";
}
function color_blue($str = ''){
echo "\e[0;34m{$str}\e[0m" . "\n";
}
color_red('red');
color_green('green');
color_yellow('yellow');
color_blue('blue');

注意,以上代码请在shell环境中执行。

简介

Elasticsearch 是面向文档的,这就意味着它可以像MongoDB一样存储整个对象或者文档。然而它不仅仅是存储,还会索引每个文档的内容使值可以被索引。我们也可以对文档进行索引,搜索,排序,过滤。

它存储的文档格式是JSON格式的。比如:

1
2
3
4
5
6
7
8
9
10
11
{
"email": "john@smith.com",
"first_name": "John",
"last_name": "Smith",
"info": {
"bio": "Eco-warrior and defender of the weak",
"age": 25,
"interests": [ "dolphins", "whales" ]
},
"join_date": "2014/05/01"
}

理论

在Elasticsearch中存储数据的行为就叫做索引indexing)。文档属于一种类型type),而这些类型存储在索引index)中。

我们可以使用下面这个图来简单解释一下:

1
2
3
MySQL           ->  Database    ->  Tables      -> Row       -> Columns
MongoDB -> Database -> Collections -> Documents -> Fields
Elasticsearch -> Indices -> Types -> Documents -> Fields

Elasticsearch集群可以包含多个索引(indices)(数据库),每一个索引可以包含多个类型(types)(表),每一个类型包含多个文档(documents)(行),然后每个文档包含多个段(Fields)(列)。

[索引]含义的区分

你可能已经注意到索引(index)这个词在Elasticsearch中有着不同的含义,所以有必要在此做一下区分:

  • 索引(名词) 如上文所述,一个索引(index)就像是传统关系数据库中的数据库,它是相关文档存储的地方,index的复数是indicesindexes
  • 索引(动词) 「索引一个文档」表示把一个文档存储到索引词)里,以便它可以被检索或者查询。这很像SQL中的INSERT关键字,差别是,如果文档已经存在,新的文档将覆盖旧的文档。
  • 倒排索引 传统数据库为特定列增加一个索引,例如B-Tree索引来加速检索。Elasticsearch和Lucene使用一种叫做倒排索引(inverted index)的数据结构来达到相同目的。

操作

插入文档

单个插入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
require_once './vendor/autoload.php';

$client = Elasticsearch\ClientBuilder::create();
$client->setHosts(['127.0.0.1']);
$client = $client->build();

$params = [
'index' => 'megacorp', //索引
'type' => 'employee', //类型
'id' => 1, //ID 如果不加,则会自动生成
'body' => [ //要添加的数据
'first_name' => 'Join',
'last_name' => 'Smith',
'age' => 25,
'about' => 'I love to go rock climbing',
'interests' => ['sports', 'music'],
]
];
$response = $client->index($params);
print_r($response);
?>

输出为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Array
(
[_index] => megacorp
[_type] => employee
[_id] => 1
[_version] => 1
[result] => created
[_shards] => Array
(
[total] => 2
[successful] => 1
[failed] => 0
)
[created] => 1
)

就表示已经插入成功了。

这里的插入的数组中有个字段为id,如果我们不对其进行填写的话,它会自动生成一个id

这个自动生成的_id会有22个字符长。我们把它称作UUIDs

批量插入

下面我们接着插入。我们需要插入同时插入两个:

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
<?php
require_once './vendor/autoload.php';
$client = Elasticsearch\ClientBuilder::create();
$client->setHosts(['127.0.0.1']);
$client = $client->build();

$params = [];
$params['body'] = [
[
'index' => [
'_index' => 'megacorp',
'_type' => 'employee',
'_id' => 2
],
],
[
"first_name" => "Jane",
"last_name" => "Smith",
"age" => 32,
"about" => "I like to collect rock albums",
"interests" => ["music"],
],
[
'index' => [
'_index' => 'megacorp',
'_type' => 'employee',
'_id' => 3
],
],
[
"first_name" => "Douglas",
"last_name" => "Fir",
"age" => 35,
"about" => "I like to build cabinets",
"interests" => [ "forestry" ]
]
];
$responses = $client->bulk($params);
print_r($responses);
?>

显示如下就表示插入成功了:

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
Array
(
[took] => 217
[errors] =>
[items] => Array
(
[0] => Array
(
[index] => Array
(
[_index] => megacorp
[_type] => employee
[_id] => 2
[_version] => 1
[result] => created
[_shards] => Array
(
[total] => 2
[successful] => 1
[failed] => 0
)
[created] => 1
[status] => 201
)
)
[1] => Array
(
[index] => Array
(
[_index] => megacorp
[_type] => employee
[_id] => 3
[_version] => 1
[result] => created
[_shards] => Array
(
[total] => 2
[successful] => 1
[failed] => 0
)
[created] => 1
[status] => 201
)
)
)
)

获取文档

现在我们尝试获取文档。获取文档可以获取指定文档的全部字段或者指定字段。我们分开来讲解:

获取单个文档

获取全部字段

比如我们现在要获取id=2的文档。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
require_once './vendor/autoload.php';
$client = Elasticsearch\ClientBuilder::create();
$client->setHosts(['127.0.0.1']);
$client = $client->build();

$params = [
'index' => 'megacorp',
'type' => 'employee',
'id' => 2,
];

print_r($client->get($params));
?>

运行之后输出的结果就是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Array
(
[_index] => megacorp
[_type] => employee
[_id] => 2
[_version] => 1
[found] => 1
[_source] => Array
(
[first_name] => Jane
[last_name] => Smith
[age] => 32
[about] => I like to collect rock albums
[interests] => Array
(
[0] => music
)
)
)

这里我们可以看到_source字段包含的就是我们插入的内容。而found字段为1表示文档已经找到,如果我们请求一个不存在的文档,也会返回一个json,只不过found就会变成0了。

获取指定字段

比如我们这里用不到这么多的字段。我们仅仅需要first_name, last_nameage。我们可以这么请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
require_once './vendor/autoload.php';
$client = Elasticsearch\ClientBuilder::create();
$client->setHosts(['127.0.0.1']);
$client = $client->build();

$params = [
'index' => 'megacorp',
'type' => 'employee',
'id' => 2,
'_source' => ['first_name', 'last_name', 'age']
];

print_r($client->get($params));
?>

返回的结果仅仅是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Array
(
[_index] => megacorp
[_type] => employee
[_id] => 2
[_version] => 1
[found] => 1
[_source] => Array
(
[last_name] => Smith
[first_name] => Jane
[age] => 32
)
)

检查文档是否存在

如果我们不需要返回指定文档的内容,而仅仅是想知道文档是否存在,我们可以这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
require_once './vendor/autoload.php';
$client = Elasticsearch\ClientBuilder::create();
$client->setHosts(['127.0.0.1']);
$client = $client->build();

$params = [
'index' => 'megacorp',
'type' => 'employee',
'id' => 2,
];

var_dump($client->exists($params));
?>

返回的结果不是数组了。而是一个bool值:

1
bool(true)

获取多个文档

获取全部的字段:

1
暂无

更新文档

部分文档更新

此处的更新只适合修改现有字段或者增加新的字段。我们需要在body字段中指定doc字段。
比如我说现在要修改id为2的员工。

首先我们先看看2号员工的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Array
(
[_index] => megacorp
[_type] => employee
[_id] => 2
[_version] => 1
[found] => 1
[_source] => Array
(
[first_name] => Jane
[last_name] => Smith
[age] => 32
[about] => I like to collect rock albums
[interests] => Array
(
[0] => music
)
)
)

接下来我们要修改它的信息,我们要将他的年龄修改成33,并且增加一个信息,mobile_phone1234567890

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
require_once './vendor/autoload.php';
$client = Elasticsearch\ClientBuilder::create();
$client->setHosts(['127.0.0.1']);
$client = $client->build();

$response = $client->update([
'index' => 'megacorp',
'type' => 'employee',
'id' => 2,
'body' => [
'doc' => [
'age' => 33,
'mobile_phone' => '1234567890'
]
]
]);
print_r($response);
?>

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Array
(
[_index] => megacorp
[_type] => employee
[_id] => 2
[_version] => 2
[result] => updated
[_shards] => Array
(
[total] => 2
[successful] => 1
[failed] => 0
)
)

我们再来看一下之前的员工的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Array
(
[_index] => megacorp
[_type] => employee
[_id] => 2
[_version] => 2
[found] => 1
[_source] => Array
(
[first_name] => Jane
[last_name] => Smith
[age] => 33
[about] => I like to collect rock albums
[interests] => Array
(
[0] => music
)
[mobile_phone] => 1234567890
)
)

脚本更新文档

有时候我们需要执行计数器更新,或者向数组中添加新值。我们就可以使用脚本式更新。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$params = [
'index' => 'megacorp',
'type' => 'employee',
'id' => 2,
'body' => [
'script' => 'ctx._source.interests.add("sports")';
]
]; // 数组中添加新值

$params = [
'index' => 'megacorp',
'type' => 'employee',
'id' => 2,
'body' => [
'script' => 'ctx._source.age += 2';
]
]; // 计数器更新

upsert

upsert 其实是更新或者插入操作,这意味着upsert将尝试更新操作,如果文档不存在,那么将插入默认值。

更新和冲突

为了避免更新数据,updateAPI在解锁阶段检索文档当前的_version,然后在重建索引阶段通过index请求提交,如果其它进程在检索和重建索引阶段修改了文档,_version将不能被匹配,然后更新失败。

对于这种情况,我们只需要重新尝试更新就好了,其实这些我们可以通过retry_on_conflict参数设置重试次数来自动完成,这样update操作将会在发生错误前重试——这个值默认为0。

总结

其实update这个操作似乎允许你修改文档的局部,但实际上还是遵循先查后改的过程,步骤如下:

  1. 从旧文档中检索JSON
  2. 修改它
  3. 删除旧文档
  4. 索引新文档

唯一的不同是update这个操作只需要一个客户端请求就好,不需要getindex请求了。

删除

比如我们要删除id为3的员工:

我们先查询一下这个员工:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Array
(
[_index] => megacorp
[_type] => employee
[_id] => 3
[_version] => 1
[found] => 1
[_source] => Array
(
[first_name] => Douglas
[last_name] => Fir
[age] => 35
[about] => I like to build cabinets
[interests] => Array
(
[0] => forestry
)
)
)

下面我们来执行操作:

1
2
3
4
5
print_r($client->delete([
'index' => 'megacorp',
'type' => 'employee',
'id' => 3,
]));

返回结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Array
(
[found] => 1
[_index] => megacorp
[_type] => employee
[_id] => 3
[_version] => 2
[result] => deleted
[_shards] => Array
(
[total] => 2
[successful] => 1
[failed] => 0
)
)

注意看found为1,并且_version相比之前,已经变为2了。

当我们再次执行一下之前的删除操作,我们再看一下返回结果:

1
{"found":false,"_index":"megacorp","_type":"employee","_id":"3","_version":1,"result":"not_found","_shards":{"total":2,"successful":1,"failed":0}}
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"found": false,
"_index": "megacorp",
"_type": "employee",
"_id": "3",
"_version": 2,
"result": "not_found",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
}
}

删除不存在的文档的时候,抛出了一个错误。我们可以看到found的值是false,且_version也有记录值。这是内部记录的一部分,它确保再多节点不同操作可以有正确的顺序。

我的系统是CentOS

我们首先先看一下我们现在的限制:

1
2
[root@bogon ~]# ulimit -n
1024

这肯定是不够的,所以我们要把这个数量给变成65535。

首先我们一般查询到的方法是这个:

1
ulimit –n 65535

但是这个只能在本次开机有效,重启之后就不行了。

所以我们要使用另外一种办法,来实现开机启动之后文件打开数量也是65535。

首先我们打开/etc/security/limits.conf

1
vim /etc/security/limits.conf

然后添加如下内容到此文件的最后:

1
2
3
4
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535

关闭文件之后,我们使用reboot对系统进行重新启动。

启动成功后我们再次使用查看连接数的命令:

1
2
[root@bogon ~]# ulimit -n
65535

这样我们就能看到文件最大打开数量已经从1024变成65535了。

当前系统版本是 CentOS 8,其实该版本已经不维护了,我只是为了升级相关内容。

我之前在 nginx 的官方文档中看到使用 yum 安装 php 方法。觉得如果有嫌编译麻烦的。可以尝试使用 yum 快速安装 nginx 。减少搭建环境之苦。

添加 yum 源文件

将以下内容粘贴进入 /etc/yum.repos.d/nginx.repo 文件中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[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
module_hotfixes=true

[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
module_hotfixes=true

默认安装的是稳定版本。如果是安装主线版本。需要执行如下命令:

1
sudo yum install yum-utils -y && sudo yum-config-manager --enable nginx-mainline

安装 nginx

1
sudo yum install nginx -y

禁止更新

我们在安装之后,为了能够正常运行,我们一般会禁止 nginx 进行更新。因为在 yum 更新了 nginx 之后,nginx 会自动重启。这对于我们来说是没有必要的,所以我们可以屏蔽更新。我们可以这样,将下列指定放到你的 /etc/yum.conf 文件中:

1
exclude=nginx

更新 nginx

一般在生产环境,我们都是禁用更新的。所以说,这里只是作为一个参考。我们需要执行的命令就是:

1
sudo yum update nginx

注意:在使用 yum 更新之后,nginx 会自动重启。

命令管理:

启动

1
sudo systemctl start nginx

重启

1
sudo systemctl restart nginx

测试配置文件语法是否正确

1
sudo nginx -t

重载配置文件

1
sudo systemctl reload nginx

停止

1
sudo systemctl stop nginx

启动开机启动

1
sudo systemctl enable nginx

禁止开机启动

1
sudo systemctl diasble nginx

总结

上面实现了 nginx 的安装,命令管理,屏蔽更新以及更新。希望能对大家有所帮助。

这本书是在逛知乎的时候发现的,说的神乎其神的,也没多想就买了本,并在一个周六的下午看完了,读的过程倒是很轻松,速度也挺快,因为毕竟是一本励志书,多少有点“鸡汤”。总体来说,这本书可圈可点,有干货,也有“鸡汤”,主要分为职业、自我营销、学习、生产力、理财、健身、精神七大模块,不论是不是码农,取其精华来安利一下自己还是不错的!

下面我就谈谈书中一些不错的干货,湿货就自己去慢慢看吧。

一、如何对待上班这件事情?

把自己当做一个软件企业,把雇主当做企业的一个客户,你应当能够提供某种产品或者服务(把一个想法通过技术手段变成一个产品的能力),不断提升你的服务质量,专注于为某一类客户提供特定的服务,做好自我营销,为更多更优质的雇主服务。

二、如何注意人际关系?

不是教你搞办公室政治,而是让你在这上面少踩坑。书中有句话比较经典:“一旦你贬低他人,削弱他们的成就感,在某种程度上就如同切断了他们的氧气补给,获得的回馈将完全是抓狂和绝望”。

  • 所以切记不要贬低他人,而是应该多激励
  • 学会聚精会神地聆听,并指出问题所在以及相关解决方案
  • 在小事情上放弃立场或承认错误有时候能为你赢得意想不到的尊重

三、如何搞定面试?

作者的观点并不新颖,但是的确这种方式最有效,同时也说明了其他方式的不靠谱!

  • 找人内推
  • 即便不换工作也要多面试增加面试经验

四、技术做到什么程度?

是一个方向钻到底,还是什么都搞?一门技术钻的越深,潜在的机会就会越少,但获得这些工作机会的可能性就越大。所以我觉得规划好自己的技术栈很有必要,总体来说一专多能可能会好一些。永远不要陷入对技术的狂热之中,只要明白不同的场景需要不同的技术方案解决就行!

五、如何晋升?

  • 承担更多的责任
  • 做了事情要及时反馈给上面,上面不知道一切都是徒劳
  • 提升自己的技能
  • 不是提出问题,而是解决问题,相信一切问题都可以解决

六、如何创业?

  • 要利用业余时间做起来,后期到一定阶段再辞职也不迟,不仅降低了风险,还提高了成功率。
  • 创业要从小处着手,也就是朝着某个独角兽方向发展,比如国内的Face++,就是只做人脸识别算法。

七、技术人员如何自我营销?

  • 写博客
  • 社交媒体
  • 演讲、培训别人
  • 写书

八、如何学习?

  • 培养自学能力
  • 筛选出重点,快速突破
  • 动手实践才是王道

九、如何管好自己?

中国的教育模式导致我们基本上都是靠外部因素来左右我们的行为,很少有自我驱动型。良好的生活习惯是自律的有效保证,所以从现在开始让自己的生活变得井然有序,培养起自己的生活习惯!改掉坏习惯,培养好习惯,把大的目标转换为一个个小的计划!

十、时间去哪了?

  • 看手机推送的所谓新闻(实际上都是毫无营养的标题党)
  • 看视频
  • 沉迷于刷社交软件

十一、为何你总是逃避努力工作?

努力工作——>辛苦——>有价值的东西——>带来的幸福感持久

偷懒——>愉悦——>消费价值的东西——>带来的幸福感短暂

十二、要不要健身?

每天必须健身,每天必须健身,每天必须健身!

剩下的其他没说的东西要么不是干货,要么不适合中国国情,虽然书名是软技能,但是这些东西从长远来看远胜于技术硬技能本身,这些东西均是在长期的工作生活中潜移默化的,非一日之寒,仅仅知道肯定不行,慢慢践行才是根本,软技能培养好了,自然就转化为了硬技能!

来源:《软技能——代码之外的生存指南》 - 知乎专栏

提示:这个应该仅仅是在Python2中出现这个问题。因为Python2的默认编码是ascii,Python3的默认编码已经编程了utf-8

我在Linux中使用make html的时候,提示:

1
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

一直不知道是什么原因,通过查阅一个资料,才知道,原来是编码问题。

字符串在进行unicode的时候,要使用什么编码格式进行转换呢?utf-8?gb2312?utf-16?这个时候就要根据 sys.getdefaultencoding()来确定了。而sys.getdefaultencoding()ascii编码,在ascii字符表中不存在0xe5这种大于128的字符存在。所以当然会报错。

可以这样修改:

1
2
3
4
#coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding("utf-8")

而因为我是使用的make html,通过查找,发现是/usr/bin/sphinx-build这个文件在捣鬼。所以我修改这个文件就好了。

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/python

# -*- coding: utf-8 -*-
import re
import sys
reload(sys) #新添加的
sys.setdefaultencoding("utf-8") #新添加的
from sphinx import main

if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

这样就正常了。

http://my.oschina.net/leejun2005/blog/74430

我首先执行pip安装命令:

1
pip3 install scrapy

结果提示以下错误:

1
2
  Could not find a version that satisfies the requirement Twisted>=13.1.0 (from scrapy) (from versions: )
No matching distribution found for Twisted>=13.1.0 (from scrapy)

因为pip3 暂时还没有Twisted,所以我们需要手动安装:

1
2
cd /usr/local/src
wget -c https://twistedmatrix.com/Releases/Twisted/16.6/Twisted-16.6.0.tar.bz2

这个包国内下载有些慢,我建议使用迅雷进行下载,然后通过rz命令进行上传。

下面我们进行解压

1
tar jxf Twisted-16.6.0.tar.bz2

提示下列错误:

1
2
3
4
tar (child): bzip2:无法 exec: 没有那个文件或目录
tar (child): Error is not recoverable: exiting now
tar: Child returned status 2
tar: Error is not recoverable: exiting now

说明我们缺少bzip2这个类文件,我们需要进行安装类库:

1
yum install bzip2 -y

我们回过头去继续执行刚才的解压命令,解压成功后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cd Twisted-16.6.0
python3 setup.py install
````

提示:

````shell
Using /usr/local/python3/lib/python3.6/site-packages
Finished processing dependencies for Twisted==16.6.0
````

这样就表示安装成功了。现在我们开始执行最开始安装`scrapy`的命令:

````shell
pip3 install scrapy
````

如果显示如下信息:

```shell
Successfully installed PyDispatcher-2.0.5 attrs-16.3.0 cffi-1.9.1 cryptography-1.7.2 cssselect-1.0.1 idna-2.2 lxml-3.7.2 parsel-1.1.0 pyOpenSSL-16.2.0 pyasn1-0.1.9 pyasn1-modules-0.0.8 pycparser-2.17 queuelib-1.4.2 scrapy-1.3.0 service-identity-16.0.0 six-1.10.0 w3lib-1.16.0

则表示已经安装成功了。

我们测试一下:

1
2
[root@iZ28zkjw87oZ ~]# scrapy version
-bash: scrapy: 未找到命令

这个很奇怪,我们使用find命令找一下:

1
2
3
[root@iZ28zkjw87oZ Twisted-16.6.0]# find / -name scrapy
/usr/local/python3/bin/scrapy
/usr/local/python3/lib/python3.6/site-packages/scrapy

我们创建一个软连接:

1
ln -sf /usr/local/python3/bin/scrapy /usr/local/bin/scrapy

然后我们继续执行一下刚才查看版本的命令:

1
2
[root@iZ28zkjw87oZ ~]# scrapy version
Scrapy 1.3.0

这样就表示安装成功了。

启动命令

首先先看看我的mysite.ini文件内容:

1
2
3
4
5
6
7
8
9
10
11
[uwsgi]
chdir=/data/custom/mysite
module=mysite.wsgi:application
master=True
pidfile=/tmp/project-mysite.pid
vacuum=True
max-requests=5000
#daemonize=/var/log/uwsgi/project-mysite.log
http=0.0.0.0:8002
stats=127.0.0.1:8000
processes=1

我们主要看pidfile,它指定的位置是:**/tmp/project-mysite.pid**

然后启动命令就是:

1
uwsgi --ini mysite.ini

重启命令

下面命令的pid文件就是我们启动时指定的pid文件。

1
uwsgi --reload /tmp/project-mysite.pid

停止命令

下面命令的pid文件就是我们启动时指定的pid文件。

1
uwsgi --stop /tmp/project-mysite.pid

参考:https://uwsgi-docs.readthedocs.io/en/latest/Management.html

我的使用环境是Python-3.5.3。Django版本是1.10.5.

按照教程创建项目:

1
django-admin startproject blog_python

然后在启动的时候,结果报错了:

1
python3 manage.py runserver

结果报错信息如下:

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
55
56
57
58
59
60
61
62
63
64
65
Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x7fdc67089f28>
Traceback (most recent call last):
File "/usr/local/python3/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py", line 34, in <module>
from pysqlite2 import dbapi2 as Database
ImportError: No module named 'pysqlite2'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/python3/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py", line 36, in <module>
from sqlite3 import dbapi2 as Database
File "/usr/local/python3/lib/python3.5/sqlite3/__init__.py", line 23, in <module>
from sqlite3.dbapi2 import *
File "/usr/local/python3/lib/python3.5/sqlite3/dbapi2.py", line 27, in <module>
from _sqlite3 import *
ImportError: No module named '_sqlite3'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/python3/lib/python3.5/site-packages/django/utils/autoreload.py", line 226, in wrapper
fn(*args, **kwargs)
File "/usr/local/python3/lib/python3.5/site-packages/django/core/management/commands/runserver.py", line 113, in inner_run
autoreload.raise_last_exception()
File "/usr/local/python3/lib/python3.5/site-packages/django/utils/autoreload.py", line 249, in raise_last_exception
six.reraise(*_exception)
File "/usr/local/python3/lib/python3.5/site-packages/django/utils/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/usr/local/python3/lib/python3.5/site-packages/django/utils/autoreload.py", line 226, in wrapper
fn(*args, **kwargs)
File "/usr/local/python3/lib/python3.5/site-packages/django/__init__.py", line 27, in setup
apps.populate(settings.INSTALLED_APPS)
File "/usr/local/python3/lib/python3.5/site-packages/django/apps/registry.py", line 108, in populate
app_config.import_models(all_models)
File "/usr/local/python3/lib/python3.5/site-packages/django/apps/config.py", line 199, in import_models
self.models_module = import_module(models_module_name)
File "/usr/local/python3/lib/python3.5/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 986, in _gcd_import
File "<frozen importlib._bootstrap>", line 969, in _find_and_load
File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 673, in exec_module
File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
File "/usr/local/python3/lib/python3.5/site-packages/django/contrib/auth/models.py", line 4, in <module>
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
File "/usr/local/python3/lib/python3.5/site-packages/django/contrib/auth/base_user.py", line 52, in <module>
class AbstractBaseUser(models.Model):
File "/usr/local/python3/lib/python3.5/site-packages/django/db/models/base.py", line 119, in __new__
new_class.add_to_class('_meta', Options(meta, app_label))
File "/usr/local/python3/lib/python3.5/site-packages/django/db/models/base.py", line 316, in add_to_class
value.contribute_to_class(cls, name)
File "/usr/local/python3/lib/python3.5/site-packages/django/db/models/options.py", line 214, in contribute_to_class
self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
File "/usr/local/python3/lib/python3.5/site-packages/django/db/__init__.py", line 33, in __getattr__
return getattr(connections[DEFAULT_DB_ALIAS], item)
File "/usr/local/python3/lib/python3.5/site-packages/django/db/utils.py", line 211, in __getitem__
backend = load_backend(db['ENGINE'])
File "/usr/local/python3/lib/python3.5/site-packages/django/db/utils.py", line 115, in load_backend
return import_module('%s.base' % backend_name)
File "/usr/local/python3/lib/python3.5/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "/usr/local/python3/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py", line 39, in <module>
raise ImproperlyConfigured("Error loading either pysqlite2 or sqlite3 modules (tried in that order): %s" % exc)
django.core.exceptions.ImproperlyConfigured: Error loading either pysqlite2 or sqlite3 modules (tried in that order): No module named '_sqlite3'

最后在这里查到了解决办法:

http://stackoverflow.com/questions/1210664/no-module-named-sqlite3

首先我们先执行一下命令:

1
yum install sqlite-devel

然后使用以下命令进行Python重装:

./configure如下:

1
2
./configure --prefix=/usr/local/python3/ --enable-loadable-sqlite-extensions
make && make install

这样重新执行前面的程序,就正常了:

1
2
3
4
5
6
7
8
9
10
[root@localhost blog_python]# python3 manage.py runserver
Performing system checks...

System check identified no issues (0 silenced).

Not checking migrations as it is not possible to access/create the django_migrations table.
February 12, 2017 - 14:42:20
Django version 1.10.5, using settings 'blog_python.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Locale (区域)在 Linux 终端中定义语言和字符集设置。

从这篇文章中可以学到如何在 Linux 命令行中检测和修改当前区域和语言设置。

将会展示如何检测当前语言和区域设置以及如何获取有效的区域列表。

也可以学到如何针对当前会话设置临时区域和语言设置以及修改系统默认设置。

查看

执行 locale 命令获取当前区域和语言设置相关信息:

1
locale

运行以下命令查看所有启用的区域:

1
locale -a

区域使用下列格式定义:

1
<language>_<territory>.<codeset>[@<modifiers>]
标识符 注释
language ISO 639-1 语言代码。
territory ISO 3166-1 国家代码。
codeset 字符集或者编码标识符,像是 ISO-8859-1 或者 UTF-8

为当前会话设置区域

在命令行执行以下命令,就可以设置为中文 UTF-8 字符:

1
LANG="zh_CN.UTF-8"

但是有个问题,这样仅能用于当前会话,如果会话关闭了,那么又回到了开始的情况。

为用户设置区域

可以将以下代码加入到 ~/.bashrc 或者 ~/.profile

1
export LANG="zh_CN.UTF-8"

默认退出会话并重新登录会话后才会生效。但是可以使用以下方法强制立即生效:

1
source ~/.profile

或者

1
source ~/.bashrc

设置为系统默认区域设置:

修改配置文件vim /etc/locale.conf

修改 LANG 为:

1
LANG=zh_CN.UTF-8

注意:该设置只有在重启后才有效。

参考

居然提示不存在mysql扩展。那我就安装呗。

我通过查阅文档,说python3需要安装的包已经不是MySQLdb了,而是mysqlclient。那我们就安装这个包了。

执行下面的命令:

1
pip3 install mysqlclient

居然报错了:

1
OSError: mysql_config not found

因为我是使用Yum 安装 MySQL的方式来安装MySQL的。所有我需要安装开发包。如果你是编译安装的,就不会出现这个问题。

好了,现在安装开发包:

1
yum install mysql-devel -y

好了。安装成功了。那么就反过头来继续安装之前的mysql包:

1
pip3 install mysqlclient

好了,我们继续执行一下django,看看是否已经正常了:

1
python3 manage.py runserver 0.0.0.0:8001

显示信息如下:

1
2
3
Django version 1.10.5, using settings 'blog_python.settings'
Starting development server at http://0.0.0.0:8001/
Quit the server with CONTROL-C.

这样就表示已经正常了。我们可以继续往下开发了。

今天看到以前知乎上别人提问的关于模板和逻辑进行分离的问题。

一直都没有回答过。

今天终于回答了。我来记录以下:

首先是模板文件,我定义他为index.html,内容如下:

1
2
3
4
5
6
<h1><?=$title?></h1>
<ul>
<?php foreach($list as $value): ?>
<li><?=$value?></li>
<?php endforeach; ?>
</ul>

这里我们就不用自定义标签啊,之类的等等,我相信鸟哥的那句话,PHP本身就是一个非常好的模板引擎,我们没有必要再去造一个轮子。

所以,我们直接来写PHP的解析:

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
<?php
/**
* 模板解析
*/
class View{
protected $path;
protected $vars;
public function __construct($path, $vars = []){
if (is_file($path)) {
$this->path = $path;
}
$this->vars = $vars;
}

public function fetch(){
ob_start();
ob_implicit_flush(0);
extract($this->vars, EXTR_OVERWRITE);
require_once $this->path;
return ob_get_clean();
}
}

$view = new View('./index.html', ['title' => 'test', 'list' => ['a', 'b', 'c']]);
echo $view->fetch();
?>

好了。直接运行一下,就能看到结果了。

不写了。太晚了。晚安。