1 | SELECT |
###
]]>1 | [Xdebug] |
xdebug.remote_enable = 0
或者xdebug.remote_autostart = 0
,关掉这两项中的任意一项,就不会出现很慢的情况,但是关掉后就不能监听断点就行调试了;xdebug.remote_host
改成127.0.0.1
,而不是localhost
,phpstorm中的设置也是;xdebug.remote_port
只要是一个可用的端口并和phpstorm中的配置一样就行;1 | 切换成root |
假设现在在图形用户界面,打开终端,输入如下命令:
1 | sudo systemctl set-default multi-user.target |
现在如果想进入图形用户界面(仅进入一次,重启系统后仍然会进入命令行模式),可执行如下命令:
1 | sudo systemctl start lightdm |
如果想设置为系统启动后默认进入图形用户界面,执行如下命令:
1 | systemctl set-default graphical.target |
然后执行reboot命令重启系统即可。
备份默认源地址
sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup
删除sources.list
文件,并新建此文件,粘贴下面这些内容:
1 | 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释 |
更新源
apt-get update
软件操作的相关命令
1 | sudo apt-get update 更新源 |
备份文件
1 | cd /etc/ssh |
修改sshd_config
1 | sudo vim sshd_config |
重启ssh
sudo service ssh restart
xshell/xftp登录
1 | xshell连接 |
安装
apt-get -y install nginx
nginx默认根目录 /usr/share/nginx/html
修改端口
1 | 找到nginx.conf |
配置文件
1 | server { |
1 | cd /etc/ssh |
1 | sudo vim sshd_config |
sudo service ssh restart
1 | ip:127.0.0.1 |
1 | ip:127.0.0.1 |
1 |
|
正确运行的输出结果: "yabadabadoo" does not contain "yaba"
strpos 是返回字符串 str2 在 str1 的位置,没有找到则返回 false ,然而实际上这次返回了 0 而在if语句中0也被当作false,所以我们需要对false做类型判断,正确的代码如下:
1 |
|
需要注意的是我们使用了 !== ,在php 和 JS中 !=相对== 更为严格需要要求数据类型一致.
1 |
|
关于 $x++ 和 $x– 这个问题其实非常容易遇见,我们只需记住 $x++ 使用最近的值,然后才自增。运算符的优先级, ++ 是明显高于 + ,因此先执行++ 再执行 + 。关于运算符的优先级,有的时候我们真的可以通过括号来让我们的程序更让人直观的了解,毕竟代码不光是用于执行的,有的时候或许团队的可读性也是提高效率的一种。
1 |
|
请问 $a 和 $b 的值各位多少?
部分第一时间会想到 $a=’1’ $b=’21’ ,仔细一看 $b=&$a ,这里 $b 是变量 $a 的引用,而不是直接赋值。
这里输出 a=21;b=21
1 |
|
var_dump(0123 == 123);// false
,PHP会默认把0123当作8进制来处理,实际转化为10进制就是83,显然这不是相等的。var_dump('0123' == 123);// true
这里php会非常有趣的将’0123’转换成一个数字而且默认去掉了前面的0也就是 123==123var_dump('0123' === 123);// false
很显然上面的问题已经说过了数字和字符串类型不一致。
1 |
|
实际输出如下:
array(2) { [0]=> int(1) [1]=> int(2) }
NULL
NULL
运行的时候你或许还能看到下面的警告
Warning: array_merge(): Argument #2 is not an array
Warning: array_merge(): Argument #1 is not an array
array_merge 需要传入的参数都是数组,如果不是,则会返回null。 你可以这样修改
1 |
|
1 |
|
这里依旧是强调运算符的优先级,= 会比 and级别高点,因此等同下面的代码
$x = true;
true and false
答案显而易见。
1 |
|
答案是 18 ,PHP是会根据上下文实现 类型的自动转换上面的代码我们可以这样理解:
如果我们在与字符串进行数学运算,实际php会尽可能将字符串中的数组进行转换,如果是数字开头的话则转换成改数字比如”15%”会变成15,如果不是数字开头则会变成0; 上面的运算类似下面 :$x = 3 + 15 + 0
1 |
|
这里依旧是强调运算符的优先级,= 会比 and级别高点,因此等同下面的代码
$x = true;
true and false
答案显而易见。
1 |
|
上面代码执行完毕后 $text = "John D" (John后面会有连续的5个空格) strlen($text) 会返回11
1 |
|
"no"
,只要仔细分析就不难得出$l>$m
会转换成1 ,则这个时候再和$m比较。
1 |
|
$x=0
而不是255.首先'oxFF' == 255
我们好判断,会进行转换将16进制数字转换成10进制数字,0xff -> 255
.PHP使用 is_numeric_string 判断字符串是否包含十六进制数字然后进行转换。但是 $x = (int)'0xFF'
; 是否也会变成255呢?显然不是,将一个字符串进行强制类型转换实际上用的是 convert_to_long ,它实际上是将字符串从左向右进行转换,遇到非数字字符则停止。因此 0xFF 到x就停止了。所以 $x=0
虽然说很多技术名词本来就是一个名词各自表述,但基本概念通常都不会相差太远,只有在细节上会有些许的争议以及讨论而已。
身為致力於要让新手更容易搞懂技术名词的人,不如就让我来尝试看看讲解这几个东西吧!
这篇文章的目标是:「只要你有网页前端的基础,就能够搞懂我在说什麼」,如果你搞不懂的话,别担心,不是你的错,是我没写好。麻烦在下面留言一下让我知道哪裡可以再改进。
接下来我会以主角小明為中心点出发,试著从一段虚拟的故事不断带出:「為什麼 XXX 会出现」、「為什麼我们需要 XXX」这些问题。如果你只对真实歷史的名词演进有兴趣,那你可能要去维基百科才能找到比较正确的资料。本故事纯属虚构,如有雷同…应该不太可能会有雷同啦,就让我们开始吧!
(先打个预防针,故事有点长,如果这些概念你都理解了应该会觉得这篇文章超级废又超级长)
小明是一个初学程式的新手,在这之前有用 Dreamweaver 写过一些简单的静态网页,对 HTML、CSS 以及 JavaScript 都有一些基础,而朋友们都推荐他去学 PHP 来补足后端的部分。
经过了一个月的苦练之后,小明终於完成了他的第一个后端程式,是一个非常简单的留言板系统(怕大家伤眼睛,这边只截给大家看其中一部分)
别笑,这就是你年轻时会写出来的东西
PHP 程式码、商业逻辑、HTML,全部东西都混在一起做撒尿牛丸,写了这样的程式码之后,小明每次考试都考一百分呢!
小明一开始觉得很兴奋,自己终於能够通晓前后端,成為全端工程师,便兴冲冲的持续精进自己的后端技术,每天都加一个新的 feature 进去。过了两个礼拜之后,小明整理了一下资料夹,发现总共有 100 个 PHP 档案,每个档案有超过 300 行 code,而且全部都是 PHP 跟 HTML 混在一起写。
他随便点开其中一个档案,看了 10 秒之后大喊:
我到底写了三小
意识到自己写的 code 很烂,是迈向一个好的工程师的第一步。
发现自己写的程式码连自己都看不懂的时候,小明觉得这样不行,阿岳也觉得不行,我也觉得不行。
因此呢,小明跑去十分瀑布下面打坐了三天三夜,不断想著该怎麼样让他的程式码变得更好,能够更好维护、更好读懂。他不求一步登天,只希望三个月之后当他回顾自己写的 code 时,不要骂脏话就好。
就在第三天的晚上,他突然有了灵感,大喊了一声:
Eureka!
就赶紧跑回家去重构自己的 code 了,而下面是他重构的结果:
纯属范例,绝对没办法跑
这个范例跟之前差在哪边呢?
首先,他把任何跟资料有关的操作都放到一个叫做 Model 的地方去,所以你要改任何跟资料有关的东西,都到那边就对了。
再来,他也把所有跟显示画面有关的东西都放到其他地方去,我们就叫做 View 吧,View 裡面用一个 template 来塞入资料,不做任何跟资料有关的处理。
如此一来,他就把资料跟画面显示这两者切开了,并且让开头那段 PHP code 把这两者连接起来,先去 Model 拿资料,再把资料塞入 View 裡面输出。那这个「连接两者」的角色,就叫做 Controller 吧!
於是,MVC 就这样出现了。為的就是要把原来乱七八糟的程式码理出一个头绪来,是你的就是你的,不是你的就给我滚远点。你要存取资料库就是去 Model 裡面,你要写 HTML 就去 View,绝对不会出现在 View 裡面下 SQL Query 这种事情。
所以 MVC 是什麼?就是一种设计模式,你只要把你的 code 像这样子切开,都可以叫做 MVC,所以你不可能只看一个画面就跟你朋友说:「欸欸,这个网站是 MVC,因為他有好多个页面」,除非你可以通灵看到背后程式码的架构长什麼样子。
话说后来又陆陆续续出现很多种模式,而且 MVC 其实也没有想像中的职责这麼分明,在这边我就不细讲了,我自己对那整段歷史也没有很熟,有兴趣的可以参考:
MVC是一个巨大误会
_我是web工程师,从刚开始学MVC就深感困惑: 怎麼每个地方说的MVC都不太一样? 有些文章讲的MVC,跟我正在用的MVC,怎麼像完全不同的东西?…_blog.turn.tw
然后我上面那段 code 是乱写的,如果你对真实世界的 MVC 框架写出来的 code 有兴趣的话,会长成这样:
PHP 的框架 CodeIgniter 写出来的
讲到这裡我们做一个小总结,问自己三个问题:
三个问题可以一起回答:
因為小明写的 code 太脏了太难维护,所以需要重构。而后来他发现用 Model、View、Controller 这三个概念来切的话可以把 code 写得漂亮很多又好维护,就这样做了。差别在於原本的 code 混在一起,遵守 MVC 的规范之后职责变得清楚很多。所以呢,MVC 就是一种架构,后端可以遵守 MVC 的架构去开发,前端也可以,就算不是 Web 也可以用 MVC。
小明把自己的烂 code 利用 MVC 模式重构之后,看起来还挺不赖的,至少比以前好很多,三个月过去了,也能看得懂自己以前写的 code。把留言板的程式码重构得差不多之后,小明决定把这个专案公开,开放给大家註册使用,让每个人都可以有自己的留言板。
一开始状况都还行,大家纷纷感激小明的无私奉献,「祝楼主一生平安」、「感谢大大无私的分享」,可是好景不常,有天小明收到了一个回馈:
我每次留言之后页面都会刷新,我家网速又慢,每次都要等个十几秒,有没有可能不要重新整理页面?你看人家 Gmail,我寄完信它也没有重新整理啊!人家做得到你应该也做得到吧
身為一个滥好人,小明乖乖的去研究 Gmail 到底是如何做到的,发现秘诀就在於一个神奇的东西:Ajax,全名 Asynchronous JavaScript and XML。
全名听起来很吓人,但说穿了其实就是你在 JavaScript 裡面可以非同步的去呼叫 Server 的 API 并且拿资料回来,在 Ajax 出现之前,你要把资料带过去都必须透过 Form 的方式,一定要换页。可是有了 Ajax 以后,不换页也能跟 Server 沟通。
Gmail 就是利用这样的原理,才能达成寄信不换页。
小明研究了一个假日之后便著手改造自己的留言板,把原本利用 Form 发送留言的地方变成 Ajax,可是他碰到了一个问题:
原本我新增留言之后重新整理页面就可以看到新的留言了,因為 Server 会把最新的结果传回去;可是我现在用 Ajax,我要怎麼在不刷新页面的前提下在画面上新增留言?
总而言之呢,利用 Ajax 之后的确是发了一个 Request 跟 Server 说你要新增留言,也成功了,可是画面上不会平白无故就跑出一个新的留言。在经过短暂的思考后,小明得到一个很直觉的解法:「阿我就用 JavaScript 来新增就好啦!」
经过一番修改之后,新增留言的程式码从原本很简单的一个 Form 表单,变成下面这个样子:
Ajax 送出资料之后利用 jQuery prepend 上去
使用者的需求被解决了,小明也有了技术上的成长,可谓是一石二鸟、一举两得,但小明天真的地方就在於他把使用者想得太简单了。
过了一个礼拜之后,同一个使用者又写信给小明:
很感谢你上次新增的功能,可是我有个疑问。我看 Gmail 无论做什麼操作都不会换页,你的留言板也可以改成这样吗?这样比较方便,谢谢。
滥好人小明没有仔细深究「比较方便」到底是怎样的方便,纯粹站在一个希望满足使用者所有需求的角度跳下去研究 Gmail 到底还能够做到什麼。
他发现了 Gmail 跟其他网站不同的地方就是:「无论做什麼操作都不会换页」,换页指的是「你会有一段时间看到整个画面全白,因為瀏览器正在等待 Server 的 Response 才能载入 HTML」。
你在用 Gmail 的时候,无论你是写信、读信、整理信件或是切换到设定页,儘管你的网路跟乌龟一样,你还是看不到任何全白画面。
為什麼?因為 Gmail 所有跟 Server 沟通的地方都是用 Ajax。
这是改造前的范例,我们利用表单 POST 来新增一笔留言,所以你会看到一小段的白画面:
此范例改自我学生 Kris 的作业,http://thinkr.tw/
这是改造后的范例,因為我们用 Ajax 来新增留言的关係,所以你不会看到任何白画面的出现,使用者体验好很多:
利用 Ajax 跟 JavaScript 在前端新增留言
我们再举一个简单的小例子,假设小明今天写了一个没有用 Ajax 的 Minmail,他删除一封信的流程是这样的:
可是如果是像 Gmail 那样子全部改成 Ajax 的话,就会变成:
后者利用 Ajax 跟后端同步资料,并且在前端用 JavaScript 更改画面,所以你无论做什麼操作都不会换页,也可以保证前后端的资料是同步的。
知道区别以及原理之后,小明把整个网站都改造成这种形式,只要是任何原本用到 Form 的地方,现在全部都用 Ajax 拿资料并搭配 JavaScript 来做画面上的处理。
因此,留言列表现在变成 Ajax 拿资料回来之后由 JavaScript 把留言 append 到画面上,就像我们刚刚示范的新增留言那样。
此时,小明突然有个非常惊人的发现:
咦,如果我全部画面都是由前端利用 JavaScript 动态產生的话,那我原本后端的 View 要干嘛?
咦,对啊,既然现在所有画面都是在前端由 JavaScript 动态產生,那我后端不就永远都输出同一个档案就好?如此一来,使用者看到的其实都是同一个页面,而我们利用 JavaScript 在这个页面上做变化。
这个概念就叫做 SPA,全名是 Single Page Application,单页式应用。与之对应的概念是 MPA,Multiple Page Application。
SPA 与 MPA 的对照
就如同小明领悟的一样,前端如果利用 SPA 来实作的话,会把原本应该是后端处理的一部份职责给搬到前端去,例如说状态的管理跟路由。
举例来说,在以往 Server 根据不同的路径对应到不同的 Controller,进而渲染出不同的 View。可是现在 Server 无论什麼路径都会输出同一个档案,所以你在前端也要判断现在的网址是哪个,才能决定在前端应该渲染出哪个画面。
再举一个例子,假设我现在写了一个电影列表的网站,首页列出许多热门电影,点进去可以看到个别电影的详细资料。而我们做了以下动作:
如果是 SPA 的话,实作的逻辑应该会是:「点进单独电影时发送一个 Request,等 Response 回来之后把资料显示在画面上」,乍听之下没什麼问题,但若是你在第三步的时候,第一步所发出去的电影 A 的 Response 才传回来,你的画面就会显示出电影 A 的资讯,可是使用者点的明明就是电影 B。
这就是我所说的状态管理变复杂了,有些地方需要花点心思做处理。在以往 MPA 的时候完全不会发生这种事,你可以保证 Server 会回传正确的结果,因為画面是在后端 render 再回传回来的,而且每一个页面之间的状态不会互相干扰。
如果写得好,我相信 SPA 的使用者体验一定很不错,因為用起来就跟你在用 Native App 差不多嘛,但你必须付出的代价是前端变得超级复杂,有一堆非同步的问题要考虑还有一大堆事情要做。此时的前端复杂度已经跟我们最开头示范的那种简单留言板相差许多了。
在这种时候,前端也可以参考我们前面所说的 MVC 架构或是其他相关架构来让程式码的职责变得更分明,让整个专案更好维护。所以你可以又有 MVC 又有 SPA,或是没有 MVC 但有 SPA,这两者是完全不同的概念。
我之前写过另外一篇文章,有兴趣的话可以参考看看:
前后端分离与 SPA
_TechBridge Weekly 技术週刊团队是一群对用技术改变世界怀抱热情的团队。本技术共笔部落格初期专注於Web前后端、行动网路、机器人/物联网、数据分析与產品设计等技术分享。_blog.techbridge.cc
最后我举一个一定要用 SPA 的例子:音乐播放网站。
如果音乐播放网站是用 MPA 的话,每去一个新的网址就会把整个页面换掉,那你的网页播放器就会中断了,这是完全没办法接受的事。所以唯一的解法就是:播放器永远都在页面上,只有其他部分的内容换掉。而这一切都是在前端用 JavaScript 来处理的。
小明花了整整一个月的时间不眠不休不吃不喝(夸饰法,开玩笑的),终於把整个网站改造成 SPA,而且还优化了不少地方,让整个使用者体验变得非常非常好。
不久过后,这个留言板系统因為体验实在是太好了,有越来越多人使用,短短一个月内就有了一百万个来自世界各地的使用者註册。还有来自国外的使用者甚至写信给小明希望能够付钱来拥有更多功能:
Hey, thanks for building such a cool website, I really like it. Is there any premium plan? I am glad to pay for the additional features like custom domain or custom template.
听过一大堆创业讲座的小明知道时候到了,可以把这个 side project 当作创业项目了!
凭著现有的成绩,小明很快地就募到了天使轮,找了几个伙伴成立了一间公司,想要把这个留言板系统做成全世界第一的留言板,期许自己能成為留言板界的 WordPress。
可是好景不常,过了一两个月之后不知道為什麼,新的会员越来越少,砸下大笔的广告费也只带来短暂的成效而已,一旦广告停了就又恢復以往冷清的样子。
奇怪,就算是热潮退烧也没退烧得这麼快才对,到底是发生什麼事呢?
一个礼拜过后,专长是数位行销的合伙人气噗噗的跑到小明的位子前,口气很差地质问他:
你做了什麼?為什麼在搜寻引擎上面搜寻我们的网站,结果只会出现一大堆看不懂的程式码?我们的网站 SEO 做的奇差无比你知道吗?
小明一开始觉得很委屈,他什麼都没做,怎麼会落得如此下场。但经过左思右想之后,终於发现了癥结点:SPA。
由於 SPA 是由前端的 JavaScript 动态產生内容,因此如果你对 SPA 的网站按下右键 -> 检视原始码,只会看到空荡荡的一片,只看得到一个 JavaScript 档案跟一些最基本的 tag。
内容在哪裡?不在这裡,因為那是由 JavaScript 动态產生的。只有你的网站经由瀏览器载入并且执行 JavaScript,等 Response 回来之后才会动态產生出内容。因此无论是哪个页面,你检视原始码都看不到动态新增后的内容。
惨了,这可是天大的坏消息。
但其实也没有那麼坏,因為强大的 Google 的爬虫其实支援执行 JavaScript,所以他依然会 index 你在前端渲染之后的页面。
不过还是有两个问题,第一个是我们不知道 Google 如何执行,会不会前端还没完全渲染完就已经爬完了?第二个是除了 Google,还有其他很多搜寻引擎,有些可能没有像 Google 这麼强大,碰到 SPA 就只能索引空荡荡的 HTML,内容几乎空白。
该怎麼办呢?
苦恼的小明跟公司请了长假,再度跑到十分瀑布下面修行,希望能够重演当年想出 MVC 架构的剧本。很幸运地,过了三天之后,小明终於想到解法了,大喊了一声:
干我知道了!
小明的想法是这样的,既然问题出在「第一次渲染」,那我们只要在第一次渲染的时候把该输出的资料都输出就好啦,对使用者来说还是一个 SPA,差别在於使用者接收到 HTML 的时候,就已经有完整的资料了。
举例来说,假设使用者拜访显示所有留言的页面,我在 Server Side 先把所有留言都準备好然后 render 出来,这样使用者一收到 Response 的时候就能够看到所有留言,搜寻引擎也能顺利地爬到。
而后续的操作还是由 JavaScript 来处理,依旧能保持 SPA 的优点。或者我们能用一句话来总结:
第一个页面由 Server side render,之后的操作还是由 Client side render
没错,这个概念就叫做 SSR,Server Side Rendering。
CSR vs SSR
有了 SSR 以后,就解决了 SEO 的问题,对网路爬虫来说你有没有用 SPA 都无所谓,他所抓到的内容都是一样的。可是对使用者来说,一样能享受到 SPA 所带来的好处(不用换页)。
虽然我在这边只用几句话带过去,看起来轻鬆写意,但真的实作过的话你就会发现这不是一件容易的事,有很多细节要去考虑。总之呢,小明花了整整两个月的时间才把整个网站都改成 SSR。
不久后,在每个月的员工大会(新创嘛,一个月一次很合理)中 CMO 很开心地跟大家宣布產品在搜寻引擎上面的排名越来越高,自然流量也越来越多,註册会员比起上个月增长了 200%。
CMO 很开心,搜寻引擎很开心,员工很开心,小明当然也很开心。
一天又平安的过去了,感谢飞天小明警的努力。
因為科技进步快速加上网路的普及,世界变动的比以前快很多。
十年前手机还只是让你打电话以及斤斤计较简讯字数的工具,十年后就变成人手一台,不可或缺的小型电脑。
身為经歷过这一切的人,小明在深夜裡边刷著 leetcode 边回忆起前端的发展,遥想十年前他以為 HTML 跟 CSS 才是主角,JavaScript 只是阻止使用者点右键或是做出会跟著鼠标移动的酷炫跑马灯的小玩具。
可是一切发展的越来越快,jQuery 的出现一统江湖,解决了恼人的跨瀏览器问题,CSS 也因為预处理器的出现而变得更好维护,可以用更程式化的角度来撰写。再过个两三年,大家都不谈 jQuery 了,而是谈 Angular。可是又过了几年,最潮的名词变成 React,到现在 React 也没那麼潮了,要潮的话请去写 Vue。
更别提 SPA 的遍地开花以及 SSR 的出现,更是将前端的复杂度提升了不只一个档次。有了 SSR 你就不再只是前端了,毕竟 SSR 的 S 可是 Server 的意思,还必须要会一点 Server side 的技术才行。
在 Mobile 的流量渐渐超越 Desktop 之后,前端的目标就迈向「可以逼近 Native App」的体验。又像是个 App 可是又不用安装,那该有多好,省了安装这个步骤转换率大幅提升,使用者开心公司也开心。
於是大家开始提倡 PWA,Progressive Web App。Web 不再单纯只是 Web,而是要用起来像个 App,看起来也像个 App。甚至利用 Service Worker 搭配快取,在没有网路时也能够使用部分功能,也可以用 Skeleton 先把画面的骨架显示出来。
这一切的一切都為了一个目的:增进使用者体验。
前端复杂归复杂,但身為真心喜爱前端的人,小明可是对未来充满了希望。一想到能够接触更多新的技术,更多新的解法,可以打造出更好的產品,小明内心涌起的情绪不是挫折而是兴奋,无比的兴奋。
东方的太阳缓缓升起,散射出的光芒洒在小明的房裡,提醒著他新的一天即将开始。
对我来说,一个技术的出现绝对是有其理由的。而不是简单一句:「前端现在就是这麼复杂」,我认為只要能理解他出现的脉络,就能更轻易的从宏观的角度去理解这项技术。
我们可以用三个问题来帮助自己理解一项事物:
MVC 就是因為 code 变得越来越乱,所以将职责区分清楚的一种设计模式。SPA 就是因為想增进使用者体验,而出现的一种在前端利用 Ajax 达成不换页的方法。SSR 就是因為要解决 SPA 的 SEO 问题而出现的解法。
一切都是有理由的,一切都是有原因的。你可以不懂它怎麼实作,但你一定要懂它是為了什麼而生。程式是工具,工具的目的是解决问题,重要的不是工具本身,而是背后要解决的那个问题。
感谢大家的阅读,如果有任何错误麻烦不吝指出。另外,此篇文章只希望能给出一个大方向,对於细节如果要讨论的话其实每个细节都可以再写一篇专文,例如说 MVC 到底是在讲哪个 MVC?SPA 在 Google 上的 SEO 真的比较差吗?SSR 在首次加载页面上牺牲的时间(因為要等 API 的资料回来才能 render)与增进 SEO 之间的取捨等等。
喜欢的话可以拍个手,你知道 Medium 最多可以拍 50 下吗?可以根据你的喜好程度拍不同次数的手,想要拍好拍满的话我也是乐见其成。
最后,再次感谢你的阅读。
此文章是在一技术讨论群里看到的,看后觉得很有感悟,便转载了过来,但当时只是把内容复制了过来,原文的链接忘了,后来找了群里面的聊天记录和浏览器的访问历史,都没有找到,在此就不注明原文章的链接了。
]]>最近在用laravel开发微信小程序的接口,因为服务器PHP版本的问题,分别用了laravel 5.6(php 7.1,开发环境)
和 laravel 5.4 (php 5.6,服务器环境)
,开发完成后,两个项目绝大部分的代码都差不多,不想再建一个仓库放php 5.6
版的代码,便试着在原有仓库新建分支来存储php 5.6
的项目,捣鼓的一上午终于搞出来了,现在记录下。
主要步骤:
laravel54
);laravel54
分支上的所有文件;laravel54
上。文章中的代码没有高亮化,看着可能不太舒服,其他平台地址:segmentfault 简书
1 | 沐@ MINGW64 /d/PHP/xampp/htdocs/apple/laravel5.4 |
注意,建立远程分支后,暂时还不能在本地建立其他分支,因为刚创建的git仓库默认的master分支要在第一次commit之后才会真正建立,这时创建其他分支会报错,解决办法在后面说明。
1 | 沐@ MINGW64 /d/PHP/xampp/htdocs/apple/laravel5.4 (master) |
1 | 沐@ MINGW64 /d/PHP/xampp/htdocs/apple/laravel5.4 (master) |
新建的分支默认与master分支一样,所以要在推送之前先把分支上的内容拉下来。
1 |
|
这个时候会报错,是正常现象,,原因是本地仓库和远程仓库不一样,有类似两者有完全不相同的commit历史,只需要在在pull的同时加上一行代码即可,代码如下:
1 | 沐@ MINGW64 /d/PHP/xampp/htdocs/apple/laravel5.4 (master) |
这步操作的时候,会有merge的commit说明,简单写下,这个只是merge的说明,并不会真正和mater合并。
经过这一步操作,就已经把远程仓库laravel54分支里面的文件都拉下来了,接下来建立与远程仓库对应的本地分支。
1 | 沐@ MINGW64 /d/PHP/xampp/htdocs/apple/laravel5.4 (master) |
1 | 沐@ MINGW64 /d/PHP/xampp/htdocs/apple/laravel5.4 (laravel54) |
这个时候,远程仓库的laravel54
分支便和本地仓库的laravel54
分支一样都是空白的,这样就可以随心所欲的推送了。
这时就可以把之前的项目拷进这个文件夹里面,然后按照正常的推送流程进行推送。
1 | 沐@ MINGW64 /d/PHP/xampp/htdocs/apple/laravel5.4 (laravel54) |
经过如上操作,就可以实现master分支和laravel54是两个完全不同的项目,可以保持两个项目平行发展,因为两个分支的提交历史不一样,所以即便是误操作,提交错了分支,git会给出相应的报错,不会把两个分支直接合并,下面是代码演示:
本地laravel54向远程master分支推送
1 | 沐@ MINGW64 /d/PHP/xampp/htdocs/apple/laravel5.4 (laravel54) |
本地master分支向远程master分支推送
1 | 沐@ MINGW64 /d/PHP/xampp/htdocs/apple/laravel5.4 (master) |
为打印数据方便,简单自定义一个打印函数。
1 | /** |
一群人排成一圈,按1,2,…,30依次编号。然后从第1个开始数,数到第7个把他踢出圈,从他后面再开始数,再数到第7个,在把他踢出去,如此不停的进行下去,直到最后个剩下一个人为止,求出最后剩下的那个人是谁。
1 | $arr = range(1,30); |
unset($arr[$k]);
不能替换成unset($v)
,unset($v)
这只是把$v这个数字删除掉,但并没有把数组中这个值对应的键删掉。 1 | function theLastOne($peopleCount,$remove){ |
将10000块钱分成5份,且每一份之间的相差的值$d不一样,并且相差$d得大于100。
1 | // 判断数组内是否有差值相等 |
下载后,进行解压,我的目录为:D:\APP\MySQL
1 | [Client] |
mysqld --install
返回结果为 Service successfully installed
net start MySQL
或在服务中启动mysql服务
mysqld --initialize-insecure
这个命令在运行时,光标一直闪,表示正在安装中,直到cmd可以进行输入,即是安装完成;
我看别人有这样安装的:mysqld --initialize --console
两者的区别是上面这个会展示安装过程并生成一个默认的数据库密码,而我用的方法,不展示安装过程,默认密码为空。
1 | use mysql; |
这期间还涉及MySQL的密码认证插件是mysql_native_password
,而现在使用的是caching_sha2_password
。
因为当前有很多数据库工具和链接包都不支持caching_sha2_password
,为了方便,我暂时还是改回了mysql_native_password
认证插件。
在MySQL中执行命令:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
修改密码验证插件,同时修改密码。
如果想默认使用mysql_native_password
插件认证,可以在配置文件中配置default_authentication_plugin
项,这个在新建my.ini
中已经设置过了。 参考链接
1 | [mysqld] |
1 | CREATE USER 'root'@'%' IDENTIFIED BY '111111'; |
在网上看到了两种开启远程方法的方法:
在使用第一种方法时会报这样的错误:
开启远程访问这块还分为root账户的远程访问或者指定某个非root账户,网上有很多,就不说明了。
]]>安装好后,至今还没有什么问题,若你预遇见了问题,欢迎和我交流。
1 |
|
1 | /** |
1 | $gpsx = '11712.7609'; |
电脑中已经安装了git
和node.js
,直接随便找个文件夹在 git bash
中执行 npm install -g hexo-cli
,这一步是安装hexo
。
检测hexo
是否成功安装,在 git bash
执行 hexo v
看到hexo
的版本号就说明安装成功了。
之后创建本地hexo
仓库,hexo init <folder>
也可以cd
到目标目录,执行hexo init
(这里用blog
文件夹做说明 hexo init <blog>
或者新建一个blog
的文件夹然后执行 hexo init
),这一步文件夹内会生成一些基本的文件,这些都是hexo
自动部署的,跟git init
同一个道理。
然后 执行 npm install hexo-deployer-git --save
安装hexo
提供的快速方便的一键部署功能,然后改 _config.yml
中最下面的配置文件:
1 | deploy: |
至此,全部安装工作已经完成,可以在blog
的目录下用hexo s
测试是否正常。
若本机中已经有ssh
,直接添加到github
的ssh
里面即可,本地没有话,先生成 ssh-keygen -t rsa -C "qq-email@qq.com"
(执行期间会让选择放置ssh的目录和ssh密码),用文本编辑器打开ssh.pub文件,拷贝其中的内容,将其添加到 github
的 Add SSH Key
,添加完成后用 ssh -T git@github.com
若提示 Hi *****! You've successfully authenticated, but GitHub does not provide shell access.
,这就说明与github
连接成功了。
这个概念跟网上说的,如何在另外一台电脑写博客是一个意思,没有很多繁琐的操作,只需要把 source
、themes
、 _config.yml
覆盖到 blog
的那个文件夹即可 ,只要hexo
环境没问题,hexo
的一系列操作都没问题(在第一次hexo d
可能会有些慢,耐心等待)。
同样,在新电脑上只要把环境搭建好,只要把两个文件夹一个配置文件覆盖过去,都没问题。
包括在备份时也只需要把这两个文件夹一个配置文件备份好,其他的都不用管了。
至于说迁移,只要本机的hexo
环境没问题,把blog
文件夹随便放哪都可以。
折腾了一下午总结出来的:
hexo
的时候,只需要在hexo
环境搭建好的基础上,只需要把 source
、themes
、 _config.yml
覆盖到新的博客目录下即可。hexo
环境没问题,把blog
文件夹随便放哪都可以。hexo
版本更新了的缘故,hexo d
时只能在git bash
中执行,其他(window环境)命令行模式都是提示无法获取远程仓库或者没有权限。1 | function color_txt($str){ |
1 | /** |
1 | /* |
1 | function is_mobile(){ |
1 | function strToArray(){ |
1 | $arr = array( |
1 | /** |
1 | /** |
1 | /** |
1 | /** |
1 | /** |
1 | function codeType($str){ |
1 | //gb2312转utf8 |
1 |
|
1 |
|
1 | /** |
1 | /** |
1 | /** |
1 | /** |
1 | function getUrlVars(){ |
1 | var str= window.location.href; |
1 | function GetQueryString(name){ |
1 | /** |
1 | /** |
1:先引入jQuery插件文件1
<script type="text/JavaScript" src="../../public/js/jquery.qrcode.min.js"></script>
2:生成可以保存的二维码图片和不可保存的二维码1
2
3
4
5
6
7
8
9
10
11$(function() {
var str = window.location.href;
var payUrl = str.slice(-35); //获取微信支付的url
//不生成二维码
$('#qrcode').qrcode(payUrl);
$(".qrcodes").hide();
//生成二维码图片,可保存至本地
var qrcode= $('#qrcode').qrcode(payUrl).hide();
var canvas=qrcode.find('canvas').get(0);
$('#imgOne').attr('src',canvas.toDataURL('image/jpg'))
});
生成可保存至本地二维码图片的html1
<img id='imgOne' src="">
1 | function rec() { |
1 | //在不可返回的页面添加下面这段JS |
1 | <input class="weui-btn weui-btn_warn" id="getVerify" type="button" value="获取验证码" onclick="sendCode(this)"> |
1 | function sendCode(thisBtn){ |
1 | <input id="upFile" class="weui-uploader__input" type="file" accept="image/*" multiple/> |
1 | $("#upFile").on("change",function () { |
1 | <input type="checkbox" checked class="weui-agree__checkbox"> |
1 | var check = $('input[class="weui-agree__checkbox"]').is(':checked'); |
1 | <input type="checkbox" value="1" class="test">11 |
1 | $("#btn").click(function(){ |
1.漂浮的窗口肯定是position:absolute
脱离文档流的
2.在浏览器可视范围内飘动
3.飘动过程可分解为垂直(上、下)和水平(左、右)方向,同一时间内会同时向垂直和水平两个方向同时移动,可能的情况会有上左、上右、下左、下右
基本的思路是创建一个函数,函数的作用是使元素移动,然后定时执行这个函数,以让元素持续移动,形成漂浮效果。基本上这些持续的元素移动都是基于 setInterval(func,delay)
函数,例如:setInterval(move,30)
,第一个参数是要定时执行的函数,第二个参数是时间间隔,单位是毫秒。如果不懂setInterval的请见:setInterval 介绍
首先这是基于JQuery写的,调用都是一些基础的接口,应该任何版本的JQuery都可以,我用的是1.9的。
浮窗Css样式1
2
3
4
5<style>
.floadAd { position: absolute;z-index: 999900; display: none; }
.floadAd .item { display: block; }
.floadAd .item img { vertical-align: bottom; }/* a img 的组合浏览器默认下边会有几个像素的空白,这里可以消除空白*/
</style>
Html 标记,里面的内容是可以按自己的需要来写的
1 | <div id="floadAD" class="floadAd"> |
Js代码,我没有把它封装到JQuery的插件里面,有需要可以自己去封装
1 | FloatAd("#floadAD");//调用 |
我已经把注释写的很清楚,这里就不再做多解释了,如果有有问题欢迎提出交流,一起进步。
第一次写博客,写的不好欢迎提出来让我改进
之前的博主把内容写得很清楚,我就不做多余的说明,我只想说一句:666。
原文链接:基于JQuery网页漂浮广告窗口Js详解
Linux,免费开源,多用户多任务系统。基于Linux有多个版本的衍生。RedHat、Ubuntu、Debian
安装VMware或VirtualBox虚拟机。具体安装步骤,找百度。
再安装Ubuntu。具体安装步骤,找百度。
安装完后,可以看到Linux系统的目录结构,见链接http://www.cnblogs.com/laov/p/3409875.html
1 | ls 显示文件或目录 |
1 | stat 显示指定文件的详细信息,比ls更详细 |
1 | gzip: |
例:
tar -cvf /home/abc.tar /home/abc
只打包,不压缩
tar -zcvf /home/abc.tar.gz /home/abc
打包,并用gzip压缩
tar -jcvf /home/abc.tar.bz2 /home/abc
打包,并用bzip2压缩
当然,如果想解压缩,就直接替换上面的命令 tar -cvf / tar -zcvf / tar -jcvf
中的“c” 换成“x” 就可以了。
1 | shutdown |
将一个命令的标准输出作为另一个命令的标准输入。也就是把几个命令组合起来使用,后一个命令除以前一个命令的结果。
例:grep -r "close" /home/* | more
在home目录下所有文件中查找,包括close的文件,并分页输出。
比如安装tree命令的安装包,先将tree.deb
传到Linux
系统中。再使用如下命令安装。
sudo dpkg -i tree_1.5.3-1_i386.deb
安装软件
sudo dpkg -r tree
卸载软件
注:将tree.deb
传到Linux
系统中,有多种方式。VMwareTool
,使用挂载方式;使用winSCP
工具等;
依然以tree为例
sudo apt-get install tree
安装tree
sudo apt-get remove tree
卸载tree
sudo apt-get update
更新软件
sudo apt-get upgrade
将.** rpm**
文件转为.** deb**
文件
.rpm
为RedHat
使用的软件格式。在Ubuntu
下不能直接使用,所以需要转换一下。
sudo alien abc.rpm
vim三种模式:命令模式、插入模式、编辑模式。使用ESC或i或:来切换模式。
命令模式下:
1 | :q 退出 |
1 | /etc/passwd 存储用户账号 |
sudo chown [-R] owner[:group] {File|Directory}
例如:还以jdk-7u21-linux-i586.tar.gz
为例。属于用户hadoop
,组hadoop
要想切换此文件所属的用户及组。可以使用命令。
sudo chown root:root jdk-7u21-linux-i586.tar.gz
三种基本权限1
2
3
4
5
6
R 读 数值表示为4
W 写 数值表示为2
X 可执行 数值表示为1
如图所示,jdk-7u21-linux-i586.tar.gz
文件的权限为-rw-rw-r--
-rw-rw-r-
-一共十个字符,分成四段。
第一个字符“-”表示普通文件;这个位置还可能会出现“l”链接;“d”表示目录
第二三四个字符“rw-”表示当前所属用户的权限。 所以用数值表示为4+2=6
第五六七个字符“rw-”表示当前所属组的权限。 所以用数值表示为4+2=6
第八九十个字符“r–”表示其他用户权限。 所以用数值表示为2
所以操作此文件的权限用数值表示为662
sudo chmod [u所属用户 g所属组 o其他用户 a所有用户] [+增加权限 -减少权限] [r w x]
目录名
例如:有一个文件filename,权限为“-rw-r----x”
,将权限值改为"-rwxrw-r-x"
,用数值表示为765
sudo chmod u+x g+w o+r filename
上面的例子可以用数值表示
sudo chmod 765 filename
Xdebug
的下载和安装,二是PHPStorm
上的对Xdebug
的配置。查看phpinfo
,搞清楚php版本等信息:
根据PHP版本下载合适版本的Xdebug
在php.ini
的最后加入下面这些代码。
zend_extension
的路径是Xdebug
文件的目录。
1 | [Xdebug] |
已下配置信息是根据我本地的配置,而做的配置,请勿直接复制。
如上图:这里配置端口(9000)的需要和在php.ini中的配置要一致,不一定非要用9000端口,只要是一个未被占用的端口都行。
如上图:
VC6:legacy Visual Studio 6 compiler
,就是使用这个编译器编译的VC9:Visual Studio 2008 compiler
,就是用微软的VS编辑器编译的TS:Thread Safe
线程安全, 执行时会进行线程(Thread)
安全检查NTS:Non Thread Safe
非线程安全, 在执行时不进行线程(Thread)
安全检查以windows
为例,看看下载到得php zip
的文件名
php-5.4.4-nts-Win32-VC9-x86.zip
VC6:legacy Visual Studio 6 compiler
,就是使用这个编译器编译的。
VC9:Visual Studio 2008 compiler
,就是用微软的VS编辑器编译的。
这个其实没有什么太大的影响,因为从php 5.3
,已经没有vc6
版本提供下载了
TS:Thread Safe
线程安全, 执行时会进行线程(Thread)
安全检查
NTS:Non Thread Safe
非线程安全, 在执行时不进行线程(Thread)
安全检查
我使用Apache+PHP
的模式下,一般是把PHP
作为一个Module load
到apache
中,那么以apache
父进程-多子进程的工作模式,是需要进行线程安全检查的,所以如果是以这种方式执行php
,选择ts
版本
那么如果是使用fastcgi
,比如说用php-fpm
管理php
执行,则不需要进行线程安全检查,则选择nts
版本的php
php 5.5.0 beta 1
发布后, 安装出现问题, 家中电脑升级是成功的, 可公司的电脑一直提示无法加载到服务. 操作系统都一样的, 没什么区别www.php.net
官网左侧的说明提醒了我.
php-5.5.0beta1-Win32-VC11-x86
安装包的名字也已经说明了, 要运行必须安装vc11
, x86
表示32位, 假如是x64
就是64位, 位数对于安装vc11
有帮助, 个人建议vc11 x86
, x64
两个版本都安装上比较好, 反正没冲突.
然后启动服务, 搞定phpinfo
信息如下:
VC6:legacy Visual Studio 6 compiler
,就是使用这个编译器编译的。
VC9:Visual Studio 2008 compiler
,就是用微软的VS编辑器编译的。
由于apache.or
g只提供VC6
的版本,所以使用原版apache
时只能使用VC6
。(www.apachelounge.com
上有apache VC9
的版本提供,应该可以和PHP VC9
配合,没用过)
TS:Thread Safe
线程安全, 执行时会进行线程(Thread)
安全检查,以防止有新要求就启动新线程的CGI
执行方式而耗尽系统资源
NTS:Non Thread Safe
非线程安全, 在执行时不进行线程(Thread)
安全检查
PHP
的两种执行方式:ISAPI
和FastCGI
。
ISAPI`
(Internet Server Application Programming Interface)执行方式是以
DLL动态库的形式使用,可以在被用户请求后执行,在处理完一个用户请求后不会马上消失,所以需要进行线程安全检查,这样来提高程序的执行效率,所以如果是以
ISAPI来执行
PHP,建议选择
hread Safe`版本
apache
中的配置方式:
下面这个是加载TS
版本的php
必须的
LoadModule php5_module “xxx/php5apache2_2.dll”
下面这行可有可无
AddType application/x-httpd-php-source .phpsAddType application/x-httpd-php .php .php5 .php4 .php3 .phtml .phpt
FastCGI
执行方式是以单一线程来执行操作,所以不需要进行线程的安全检查,除去线程安全检查的防护反而可以提高执行效率,所以,如果是以FastCGI
来执行PHP
,建议选择Non Thread Safe
版本。
apache
中的配置方式:
下面这两行是加载NTS版本的php必须的,不可以直接写成Action application/x-httpd-php “c:/wamp/bin/php/php3.5.6/php-cgi.exe”!
1 | ScriptAlias /php/ "C:/wamp/bin/php/php3.5.6/" |
另外,还要有之前的AddType application/x-httpd-php .php .php5 .php4 .php3 .phtml .phpt
,这样才能认识php
格式的文件
这样配置完可能还会因为权限问题而无法用php-cgi.exe解析php网页,所以还要加上下面这段
1 | <Directory "C:/wamp/bin/php/php5.3.6/"> |
官方并不建议你将Non Thread Safe
应用于生产环境,所以我们选择Thread Safe
版本的PHP来使用。
XAMPP在http-xampp.conf
中默认配置是使用ISAPI
的方式
String类型
的数据定义一个数据库的数据库类型,一般参考的都是char
或者varchar
,这两种选择有时候让人很纠结,今天想总结一下它们两者的区别,明确一下选择它们的理由。首先明确的是,char
的长度是不可变的,而varchar
的长度是可变的,也就是说,定义一个char[10]和varchar
[10],如果存进去的是csdn
,那么char
所占的长度依然为10,除了字符csdn
外,后面跟六个空格,而varchar
就立马把长度变为4了,取数据的时候,char类型的要用trim()去掉多余的空格,而varchar
是不需要的,尽管如此,char
的存取数度还是要比varchar
要快得多,因为其长度固定,方便程序的存储与查找;
但是char
也为此付出的是空间的代价,因为其长度固定,所以难免会有多余的空格占位符占据空间,可谓是以空间换取时间效率,而varchar
是以空间效率为首位的。
再者,char
的存储方式是,对英文字符(ASCII)占用1个字节,对一个汉字占用两个字节;而varchar
的存储方式是,对每个英文字符占用2个字节,汉字也占用2个字节,两者的存储数据都非unicode
的字符数据。
]]>
去PHPExcel的官网或者github去下载最新PHPExcel放到ThinkPHP/Library/Vendor
目录下,Vendor
目录是放置PHP扩展包的默认文件夹,在Vendor
目录下建立PHPExcel
文件夹,将下载的文件,解压到此处。
将PHPExcel.php
文件,重命名成PHPExcel.class.php
。
至此,插件安装已经做好,目录结构如下图,接下来做功能部分。
1 | /** |
第9行的
$xlsName = $fileName.date("_Y.m.d_H.i.s"); //or $xlsTitle 文件名称可根据自己情况设定
是设置文件名,上面所写是文件名_Y.m.d_H.i.s
,_Y.m.d_H.i.s
即是导出的时间,因为windows下,文件名中不能含有:
,所以即便写成_Y.m.d_H:i:s
,导出的文件也是_Y.m.d_H.i.s
这种样式。
第13行~15行的
1 | import("Vendor.PHPExcel.PHPExcel"); |
这三行即是引入PHPExcel,因为当时的文件目录结构是ThinkPHP/Library/Vendor/PHPExcel
,所以import("Vendor.PHPExcel.PHPExcel");,注意目录结构,只要引入的位置和放置PHPExcel的目录相同即可;
第20、21行的
1 | $objPHPExcel->getActiveSheet(0)->mergeCells('A1:'.$cellName[$cellNum-1].'1');//合并单元格 |
此作用是,在Excel文件的第一行合并一行单元格,用作表格的标题或简介。如下图所示:
setCellValue('A1', $fileName.' Export time:'.date('Y-m-d H:i:s'));
值可以根据自己需求修改;
第34行的header("Content-Disposition:attachment;filename=$xlsName.xls");//attachment新窗口打印inline本窗口打印
可以设置输出的文件格式,此处写的是.xls
,可修改成.xlsx
。
此方法调用时需要传入三个参数(在方法开头的注释中已经说了),这里再具体说明一下:
1 | $fileName 导出的文件的文件名 |
1 | /**导出**/ |
第3行$excel = A('Excel');
这个方法我写在了Application/Admin/Controller/ExcelController.class.php
中,当前用的控制器是MainController.class.php
,调用其他控制器中的方法,用TP中自带的A()
,所以第51行,用的是$excel->exportExcel($xlsName,$xlsCell,$xlsData);
,如果你的exportExcel()
方法和当前调用的方法在同一个控制器内,那么第三行可以不写,第51行改成$this->exportExcel($xlsName,$xlsCell,$xlsData);
。
第4行$xlsCell
是导出这张表中所有的字段,以及字段的注释,导出后,不能把字段作为表格的列名,不知道数据库字段是什么意思的用户,看了这张表也不知所以然。
第17~24行
是根据$xlsCell
数组中,提取出来字段名,作为一个字符串,在查询时使用。当然也可以把这个字段名的字符串手写出来,我这里用的是foreach处理。
第27~38行
是查询条件和查询结果,如果没有查询条件,想把整张表导出的话,直接用$xlsData = $xlsModel->Field($field)->order('id DESC')->select();
即可。
第47~50行
是对$xlsData
结果进行处理,我写的两个意思是:
1、当create_time
字段为空的时候,值为 -
,有值的时候,就用date()
函数把时间戳处理成日期;
2、当status
字段的值为1的时候,显示为正常
,当值为0的时候禁用
。
有点罗嗦了,见谅。
模板文件很简单,就一个提交。
1 | <form action="{:U('Main/msgOut')}" method="post" class="form-horizontal"> |
form
表单中三个input
,是搜索条件,如果没有的话,直接写button
即可。
虽然是好事,但我依然认为最近一轮的PR做的有点多,甚至拉动了整个杀毒概念股,这多少有点误导,所以这篇文章从产业和技术的角度再来谈谈wannacry病毒这件事。
根据最新消息,比特币检测机构的数据显示wannacry的制作者们目前获得了7万美元的赎金。
而造成如此全球大规模的破坏,最终只获得了7万美元的赎金,黑客们还要像淘宝客服一样一个个发货,清点仓库,不断研究新病毒,想想也真不容易。
简单的说,造成如此大规模破坏,与其最后的收益多少是不成正比的 ,就这点赎金,真的还不如卖上几个G的大公司数据库赚钱。
这种规模不经济背后,反应的是PC到移动的产业链变革,以及技术的变迁。
先聊聊过去的黑客产业,确实非常发达。
以前的黑客都喜欢建立长期价值,更多都是在制作木马病毒,并实现对用户电脑的控制,业内简称“抓肉鸡”,这样就可以通过各种黑产来变现,我这里举3个关键产业。
CPA赚钱:即给各路软件,金山毒霸、360、9158等等进行每台机器的安装,每安装一台就会分成0.5-3元。
CPC赚钱:一般都是在利用肉鸡制造虚假的广告流量点击,或者用于服务器攻击,搜索引擎关键词欺骗,恶意点击对手关键词等等,总之都是在做违法流量。
盗号赚钱:比如说,淘宝上最早的半价QQ会员、黄钻、红钻、蓝钻、QB这些,都是黑客通过入侵宽带账号,对其进行的宽带费盗刷的结果。
当然,最赚钱的还是游戏账号,通过安装各类游戏密码,截获各游戏账号,当年比较火热的传奇、梦幻西游、仙剑、DNF等等。黑客一般都是先改密码再转移装备,在游戏中与其他玩家交易成金币后,然后放到淘宝上卖金币,最后还会再观察这个账号是否还会被找回,如果不被找回,那么就会也拿出来卖。
可以说,以前的PC时代,有着非常多的黑产变现手法,通过控制一台电脑,就能获得相当多的收益。
蠕虫病毒都是一波流,媒体一曝光全都见光死,漏洞补上就没机会了,高手黑客都是做木马病毒,控制电脑建立长期价值。
现在的黑客开始对PC电脑进行一波流的收割,是因为PC的商业时代过去了,都集中在移动手机了。
既然智能手机的产业那么大,那黑客为什么不入侵安卓,IOS?
这里我再从技术角度谈谈为什么智能手机大规模入侵为什么那么少。
因为权限问题。
PC电脑需要应对用户无数需求,编程需求、图像处理需求、显卡更换需求、内存更换需求…….
这些无数种乱七八糟的需求,导致了微软不得不做成极度开放的系统,让用户可以自由操控底层权限,自由拔插各种软硬件,这也导致了黑客更容易找到漏洞。
找到不是问题,问题是,一次入侵后就可以实现全面的掌控,比如你在国内安装一个软件,往往安装的都是全家桶,你随便点击一个“确定”,一堆软件就到桌面上了,任何软件都有能力操控底层代码,这是由于过分开放导致的必然结果。
智能手机的权限就比较严格。
安卓和苹果本质上都差不多,给软件的权限都非常严格,比如你要读取个通讯录是需要用户允许的,你要连接个wifi是需要用户允许的,你要后台跑流量还是需要用户允许的…….
这样就导致了杀毒软件只能在既定的范围内行事,能做的事情比较少,之前360由于越界还被苹果下架过,UBER也做出过出格行为被苹果约谈,可以看出苹果的监控有多严格。
这就保证了真正的底层权限都甚至不会被用户掌握,也自然不会下放给其他软件,你安装一个软件,也不会出现安装全家桶的现象。
对于智能手机而言,用户没事不会去换主板、换CPU、换各种设备,也不会用手机编程,需要底层环境变量配置,需要取得各种底层权限,因此智能手机的权限可以对用户实行全面封闭,即使root权限,也依然受到严格限制。
而这种权限设计,也导致了没有那么多的漏洞需要补,黑客入侵也非常困难。
当然,没有不能攻破的系统,智能手机的权限再严格,只要有利益在,还是挡不住黑客的。
智能手机稍有入侵,还有个原因在于,黑产也受到了智能手机的冲击,很多黑产给断了。
比如CPC、CPA这种广告联盟变现逻辑,就很难通过强行静默安装的方式实现,因为没有权限。
而盗号产业,现在大家都是用手机注册各种账号,黑客必须实现短信拦截,这就导致了需要建伪基站,或者入侵用户的线上短信接收平台,等等,成本极高,机会也少。
当然,这么做最终依然无法实现盗号,因为账号都与手机绑定,一个验证码就能找回,根本不能永久拿下。
所以智能手机的黑产集中在了盗刷层面,之前网易邮箱账号泄露,就有大批的Appstore的账号被盗刷,被用于购买了各种游戏装备,但是只要用户通过合理的申诉,还是能够通过苹果找回,黑客弄了半天,其实很容易竹篮打水一场空。
另外,苹果手机此前也出现过勒索局面,黑客通过获得苹果账号,设置icloud丢失锁定手机,来要求用户赎回苹果账号。当然这和入侵无关,是低级的暴库行为,主要是下游产业链完成,没技术含量的。
所以,智能手机除了封锁权限,还把黑产财路也截断了很大一部分。
PC和智能手机两边都在截断黑产收入,在这两边的收入锐减情况下,此次CY病毒选择了一波收割。
但我依然认为CY只是纸老虎,一波收割的蠕虫病毒,不是建立对电脑的暗中长期控制,没什么吓人的。
公司或者机构电脑上可能会有值钱的资料,但是普通个人用户有多少值钱的资料?我认为绝大多数的人资料基本不会超 过300美元,## 如果绝大多数人的电脑资料超过300美元,那么此次黑客们都要赚翻了。##
举个 例子,比如说论文这种东西吧,300美元这么贵,在国内完全都可以找人代写了代发了,重写就行了,绝大多数人不会交这个赎金。
另外,现在都是云端时代,很多人都已经把资料放到云端,是云端实时备份的,电脑中毒对于这些已经备份云端的人群来说,一点都不重要。
再说学校机、加油站、出入境管理处的电脑中毒,我认为也不是什么大事,所有资料都在服务器里面,黑客入侵的不是后端服务器,一个前端电脑坏了重装就行了,用户的信息没丢就根本不是什么大事。
大惊小怪的往往是外行。
说了这么多,既然手机的病毒木马都没啥怕的,都是纸老虎,那么真老虎是啥?
真老虎是服务器入侵。
TOC越来越难以收割,因此这波黑产已经全面进入到TOB阶段,靠入侵各个公司,盗取数据库资料,这是远比非标准化的个人PC和智能收机入侵更赚钱的事情。
比如之前icloud的明星艳照,就非常值钱,刚开始能卖好多钱。再比如之前泄露的网易邮箱数据库、雅虎数据库、优酷数据库,58简历数据库等等,都是非常值钱的。
尤其是邮箱数据库,很多黑客可以通过邮箱数据库去盗刷各个游戏账号,锁定用户的icloud勒索,自己用完后最后再倒卖几波,虽然产业链下游的人辛苦点,但整个产业还是能赚很多。
不过以上依然不算是太严重的破坏。
各位想想,这次入侵只不过是在逼你删掉一些本来就没用的文件,但是如果这次攻击的不是PC电脑,而是服务器,黑客把各个国家公民的数据锁了(甚至连同各地备份服务器数据一起锁住),把你的房产信息锁了,那该有多可怕?
不过幸运的是,这次依然是低级入侵,其只不过是在利用微软3月份就已经打过补丁的漏洞在做事,高级的入侵是直接入侵服务器,大面积的入侵全球服务器的漏洞,这才是能够令人恐慌的。
所以我认为,未来值得警惕的是服务器安全。
但是这和360这些杀毒公司半毛钱都没有,因为现在都是云服务器,是AWS和阿里云的天下,要做好安全把控的是这些云服务商。
但对于这些云服务商来说,他们做的其实非常不错,一旦发现漏洞,就会立即全网打补丁,这种中心化的控制,不会错过一台电脑。相比于混乱的个人电脑,这种中心化的管理,更能够防御黑客的漏洞入侵。
所以云服务器的安全才是未来整个安全行业的焦点,这次如果要是aws和阿里云如果被入侵了,事情的严重程度就比较高了。
这次杀毒概念股疯长,我认为需要冷静,未来的安全攻防战一定是服务器端的,而不是用户端,杀毒软件依然是用户端产品。
黑客 可以制造出这么严重的全球性破坏,却只收获了几万美元,还要充当客服角色,反映的是当前的黑产的整体萧条状况。
不过无论怎么样,杀毒软件们做的事情是对的,但是这种短期PR有些过头,个人安全并不是未来的发展方向,服务器安全才是,而杀毒软件要想获得全新的增长,则必须找到自己全新的增量。
而作为个人,将自己的资料同步到云端,其实比安装一个杀毒软件更重要。
作者微信公众号:“首席发言者”
]]>