亢奋猫 发布的文章

explain sql语句 可以用来分析索引的一些情况:

idselect_typetabletypepossiable_keyskeykey_lenref

TYPE

显示子查询使用何种类型的查询

从最好到最差依次是:system > const > eq_ref > ref > rang > index > ALL

一般的优化需要达到 `rang` 级别,最好是 `ref` 级别

system

单个表中的一行记录,const 类型的特例,查询速度最快

const

通过索引一次就能找到,通常是查询主键查询或者唯一查询 (primay_key , unique)

eq_ref

唯一索引扫描,用索引查询出了一条记录 select * from users where phone = ''

ref

非唯一索引表,用到了索引查出了多条记录 select * from users where age = 18

- 阅读剩余部分 -

Mac 中有些软件是通过 pkg 包进行安装的,其中有很多是系统包。如果我们只通过删除 Applications 目录下的图标是不能完全删除的。

PKG 包安装原理

pkg 包的安装原理非常简单,它解压后就会把文件分门别类解压到指定的位置。

这样安装虽然简单,但是卸载就非常困难了。我们需要把安装时候散落在各个位置的文件全部找到并删除掉。

PKG 分析

在终端中运行 pkgutil --pkgs 命令就可以看到已经安装过的包名

com.betafish.adblock-mac
org.nodejs.node.pkg
com.diumoo.diumoo
in.sinew.Enpass-Desktop
com.audioguidia.radioFMOSX
com.eusoft.freeeudic
com.hewbo.chmreader
com.netease.163music
com.wutian.weibo
com.teamviewer.teamviewer14AuthPlugin
com.microsoft.Excel
com.atpill.atpill
com.mitledas.ChmPages

com.apple 开头的包多数是系统包,请不要删除

运行 pkgutil --files com.microsoft.Excel 就可以看到分布在各个地方的文件

usr/local/include/node/v8-profiler.h
usr/local/include/node/v8-testing.h
usr/local/include/node/v8-util.h
usr/local/include/node/v8-value-serializer-version.h
usr/local/include/node/v8-version-string.h
usr/local/include/node/v8-version.h
...

PKG 包卸载

如果依据上面的分析,一个目录一个目录删除简直太痛苦了。而系统自带的包管理工具 pkgutil 比起其他系统的包管理来说又非常弱,连最基本的 uninstall 的功能都没有提供。那么我们如何快速删除已经安装过的 pkg 包呢?

uninstall-pkg.png

借助 UninstallPKG 不仅可以轻松查看安装包所有文件的位置,还能卸载那些已经失效的安装包。比起使用终端操作,更加直观方便。

下载地址

https://xclient.info/s/uninstall-pkg.html

loap.jpg

从上面这张图我们可以直观的看到 PostStart 和 PreStop 包括 liveness 和 readiness 是属于主容器的生命周期范围内的,而 Init Container 是独立于主容器之外的,当然他们都属于 Pod 的生命周期范畴之内的,现在我们应该明白 Init Container 和钩子函数之类的区别了吧。

我们说Init Container主要是来做初始化容器工作的,那么他有哪些应用场景呢?

等待其他模块Ready:这个可以用来解决服务之间的依赖问题,比如我们有一个 Web 服务,该服务又依赖于另外一个数据库服务,但是在我们启动这个 Web 服务的时候我们并不能保证依赖的这个数据库服务就已经启动起来了,所以可能会出现一段时间内 Web 服务连接数据库异常。要解决这个问题的话我们就可以在 Web 服务的 Pod 中使用一个InitContainer,在这个初始化容器中去检查数据库是否已经准备好了,准备好了过后初始化容器就结束退出,然后我们的主容器 Web 服务被启动起来,这个时候去连接数据库就不会有问题了。

做初始化配置:比如集群里检测所有已经存在的成员节点,为主容器准备好集群的配置信息,这样主容器起来后就能用这个配置信息加入集群。

其它场景:如将Pod注册到一个中央数据库、配置中心等。

参考链接:初始化容器

将当前用户加入到 docker 用户组

因为 Docker 运行时需要特殊权限,所以默认执行命令时都必须在前面加上 sudo。但这样做确实使人厌烦,一个可行的解决方法是把用户放进 docker 用户组里。在 Ubuntu 下你可以输入:

sudo usermod -aG docker $USER

重启 docker

sudo systemctl restart docker

重新 ssh 登录

ssh [email protected]

此时运行 docker version 就不会报 Got permission denied 错误了

[email protected]:~$ docker version
Client:
 Version:           18.09.6
 API version:       1.39
 Go version:        go1.10.8
 Git commit:        481bc77
 Built:             Sat May  4 02:35:57 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.6
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.8
  Git commit:       481bc77
  Built:            Sat May  4 01:59:36 2019
  OS/Arch:          linux/amd64
  Experimental:     false

大部分情况下,Homestead 的安装是非常简单的,我就基本上没遇到过问题。然而如果你遇到 vagrant up 后卡在 SSH auth method: private key 的情况,可以按照本文办法进行尝试:

问题

homestead-7: Warning: Host appears down. Retrying...
homestead-7: Warning: Host appears down. Retrying...
homestead-7: Warning: Host appears down. Retrying...
homestead-7: Warning: Host appears down. Retrying...
homestead-7: Warning: Host appears down. Retrying...
homestead-7: Warning: Host appears down. Retrying...

解决办法

重新生成 insecure_private_key,运行

> vagrant ssh-config
Host homestead-7
  HostName 10.211.55.3
  User vagrant
  Port 22
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /Users/x/Homestead/.vagrant/machines/homestead-7/parallels/private_key
  IdentitiesOnly yes
  LogLevel FATAL
  ForwardAgent yes

移除文件 /Users/x/Homestead/.vagrant/machines/homestead-7/parallels/private_key

vagrant halt
vagrant up

由于IPV4地址紧缺,如果任意选择IP地址作为本机构内部使用的本地地址,某些情况下会产生麻烦。最大的麻烦就是目的外网和内部IP重合,出现地址二义性。为了解决这个问题,RFC1918指明了A、B、C三类网络的专用地址群,这些地址只能用于机构内部通信,不能用于因特网主机通讯。在外网中的所有路由器,对目的地址是专用地址的数据包一律不进行转发。

以下为地址群:

A类:10.0.0.0到10.255.255.255 16581375 1千万IP地址
B类:172.16.0.0到172.31.255.255 975375 1百万IP地址
C类:192.168.0.0到192.168.255.255 65025 6万IP地址

192.168.0.0/16 指的是什么?

ipv4 是 32 位的, 192.168.0.0 转化为 32 位的二进制地址即是:

11000000.10101000.00000000.00000000

/16 代表其 32 位的前 16 位是固定的

11111111.11111111.00000000.00000000

转化过来就是:

192.168.0.0 - 192.168.255.255
对应的网关是: 255.255.0.0.0

想快速计算这些东西的话可以搜一下关键词“子网掩码计算器”

持续集成(Continuous integration,CI)

指的是在开发过程中持续地将所有开发人员的代码合并到代码库的主线上,然后对该主线代码进行编译、测试运行等操作对代码进行检验,其目的是尽可能早的发现代码集成后导致的问题。

实现持续集成的要点主要有:共享的代码库、自动化编译、自动化测试等,同时要保证合理的集成频率,一般持续集成的时机在于开发人员将代码提交到代码库时自动进行,但是如果提交过于频繁,那么应该使用时间间隔的形式进行持续集成。

持续发布(Continuous delivery,CD)

实际上是持续集成上的一个拓展,在持续集成的基础上将发布工作自动化,避免人为操作从而减少发布时间和发布时人为造成的错误。

参考网站:

Git + Docker 多环境自动化部署

在使用PHP开发Web应用的中,很多的应用都会要求用户注册,而注册的时候就需要我们对用户的信息进行处理了,最常见的莫过于就是邮箱和密码了,本文意在讨论对密码的处理:也就是对密码的加密处理。

MD5

相信很多PHP开发者在最先接触PHP的时候,处理密码的首选加密函数可能就是MD5了,我当时就是这样的:

$password = md5($_POST["password"]);

上面这段代码是不是很熟悉?然而 MD5 的加密方式目前在PHP的江湖中貌似不太受欢迎了,因为它的加密算法实在是显得有点简单了,而且很多破解密码的站点都存放了很多经过MD5加密的密码字符串,所以这里我是非常不提倡还在单单使用 MD5 来加密用户的密码的。

SHA256 和 SHA512

其实跟前面的 MD5 同期的还有一个 SHA1 加密方式的,不过也是算法比较简单,所以这里就一笔带过吧。而这里即将要说到的SHA256SHA512 都是来自于 SHA2 家族的加密函数,看名字可能你就猜的出来了,这两个加密方式分别生成256和512比特长度的 hash 字串。

他们的使用方法如下:

<?php
$password = hash("sha256", $password);

PHP内置了 hash() 函数,你只需要将加密方式传给 hash() 函数就好了。你可以直接指明 sha256, sha512, md5, sha1 等加密方式。

盐值

在加密的过程,我们还有一个非常常见的小伙伴:盐值。对,我们在加密的时候其实会给加密的字符串添加一个额外的字符串,以达到提高一定安全的目的:

<?php
 
function generateHashWithSalt($password) {
    $intermediateSalt = md5(uniqid(rand(), true));
    $salt = substr($intermediateSalt, 0, 6);
    return hash("sha256", $password . $salt);
}

Bcrypt

如果让我来建议一种加密方式的话,Bcrypt 可能是我给你推荐的最低要求了,因为我会强烈推荐你后面会说到的 Hashing API,不过 Bcrypt 也不失为一种比较不错的加密方式了。

<?php
function generateHash($password) {
    if (defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH) {
        $salt = '$2y$11$' . substr(md5(uniqid(rand(), true)), 0, 22);
        return crypt($password, $salt);
    }
}

Bcrypt 其实就是 Blowfishcrypt() 函数的结合,我们这里通过 CRYPT_BLOWFISH 判断 Blowfish 是否可用,然后像上面一样生成一个盐值,不过这里需要注意的是,crypt() 的盐值必须以 $2a$ 或者 $2y$ 开头,详细资料可以参考下面的链接:

http://www.php.net/security/crypt_blowfish.php

更多资料可以看这里:

http://php.net/manual/en/function.crypt.php

Password Hashing API

这里才是我们的重头戏,Password Hashing API是 PHP 5.5 之后才有的新特性,它主要是提供下面几个函数供我们使用:

password_hash() – 对密码加密.
password_verify() – 验证已经加密的密码,检验其hash字串是否一致.
password_needs_rehash() – 给密码重新加密.
password_get_info() – 返回加密算法的名称和一些相关信息.

虽然说crypt()函数在使用上已足够,但是password_hash()不仅可以使我们的代码更加简短,而且还在安全方面给了我们更好的保障,所以,现在PHP的官方都是推荐这种方式来加密用户的密码,很多流行的框架比如Laravel就是用的这种加密方式。

<?php
$hash = password_hash($passwod, PASSWORD_DEFAULT);

对,就是这么简单,一行代码,All done。

PASSWORD_DEFAULT 目前使用的就是Bcrypt,所以在上面我会说推荐这个,不过因为 Password Hashing API 做得更好了,我必须郑重地想你推荐 Password Hashing API。这里需要注意的是,如果你代码使用的都是 PASSWORD_DEFAULT 加密方式,那么在数据库的表中,password 字段就得设置超过60个字符长度,你也可以使用 PASSWORD_BCRYPT,这个时候,加密后字串总是60个字符长度。

这里使用 password_hash() 你完全可以不提供盐值(salt)和消耗值 (cost),你可以将后者理解为一种性能的消耗值,cost越大,加密算法越复杂,消耗的内存也就越大。当然,如果你需要指定对应的盐值和消耗值,你可以这样写:

<?php
$options = [
    'salt' => custom_function_for_salt(), //write your own code to generate a suitable salt
    'cost' => 12 // the default cost is 10
];
$hash = password_hash($password, PASSWORD_DEFAULT, $options);

密码加密过后,我们需要对密码进行验证,以此来判断用户输入的密码是否正确:

<?php
if (password_verify($password, $hash)) {
    // Pass
}
else {
    // Invalid
}

很简单的吧,直接使用 password_verify 就可以对我们之前加密过的字符串(存在数据库中)进行验证了。

然而,如果有时候我们需要更改我们的加密方式,如某一天我们突然想更换一下盐值或者提高一下消耗值,我们这时候就要使用到password_needs_rehash()函数了:

<?php
if (password_needs_rehash($hash, PASSWORD_DEFAULT, ['cost' => 12])) {
    // cost change to 12
    $hash = password_hash($password, PASSWORD_DEFAULT, ['cost' => 12]);
 
    // don't forget to store the new hash!
}

只有这样,PHP的 Password Hashing API 才会知道我们重现更换了加密方式,这样的主要目的就是为了后面的密码验证。

简单地说一下 password_get_info(),这个函数一般可以看到下面三个信息:

algo – 算法实例
algoName – 算法名字
options – 加密时候的可选参数

所以,现在就开始用 PHP 5.5 吧,别再纠结低版本了。


本文转载来自:codecasts
原作者:JellyBool

本教程适用于 homebrew 安装的 [email protected]

首先安装 xdebug 扩展:

sudo pecl install xdebug

创建 xdebug 配置文件:

/usr/local/etc/php/7.2/conf.d 目录下创建 xdebug.ini 文件,并写入以下内容:

[xdebug]

xdebug.remote_autostart=1
xdebug.default_enable=1
xdebug.remote_port=9000
xdebug.remote_host=127.0.0.1
xdebug.remote_connect_back=1
xdebug.remote_enable=1

重启服务 valet restart

配置 PhpStorm:

点击菜单:Run -> Start Listening for PHP Debug Connections
在指定位置打上断点,浏览器输入网址就可以开始调试啦~

效果:

xdebug.png

配置参考:

xdebug-config.png

过程中遇到任何问题请在下方留言反馈 😄

一个语言的“入流”,和是不是英文关键字无关,而是和这种语言进入某一子行业的契机有关。

比如 C 语言的出现解决了系统程序源代码的可移植性问题,使得更多的小型机可以在更短时间内移植 Unix 操作系统。所以 Unix 选择用 C 重写,而 C 成为编写操作系统和实现 TCP/IP 协议的首选语言。今天众多设备上的各类操作系统,TCP/IP 协议实现都要归功于 C 语言;

比如 C++ 的出现适逢图形界面的兴起,需要面向对象技术对图形编程框架建模,同时又要提供能运行于微型处理器的高性能;

Java 的流行适逢企业的信息化浪潮,大量的企业级的复杂任务,需要更短的时间内,写出更大规模的程序。所以 Java 通过更多的权限关键字,垃圾回收等等,带来的是整个行业生产力的提升;

PHP 的流行是因为行业需要快速的编写动态 Web 服务端程序。

而 Python 进入 Web 开发是因为如今 Web 应用日渐复杂,需要更多的交互技术(比如用于实时的长链接)和使用更多的第三方库(必须一些自然语言处理、计算机视觉和机器学习任务)。

以上这些语言如果不是在第一时间出现解决了行业急需解决的问题,可能以后再也没有机会“入流”。再回来看“易语言”,中文关键字解决的是没有一点英文基础的初学者的入门问题。但这个问题不是行业痛点,因为具备基本英文能力的程序员从来就不缺,将来更不可能缺。因此,没有一个行业急需“易语言”解决没有英文基础的初学者入门的问题,“易语言”凭借这个优势就没有任何的“入流”机会。相反,由于面试者普遍看中英文文档、论文的阅读能力,“易语言”反倒会帮助企业剃掉那些没有英文基础的应聘者。

作者:安江泽
链接:https://www.zhihu.com/question/19770358/answer/17497656
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。