php错误日志
php.ini
log_erros
log_erros_max_len
error_log
display_errors
php-fpm.conf
slowlog
request_slowlog_timeout
access.log
log_erros
log_erros_max_len
error_log
display_errors
slowlog
request_slowlog_timeout
access.log
官网 下载自己机器系统对应的二进制安装包,解压到相应目录.
解压目录说明:
/usr/local/go
c:\Go
目录本次安装过程实际在 Ubuntu 机器上执行的命令如下:
|
|
/usr/local/go
或 c:\Go
,需要根据实际安装情况自行调整本将安装过程 Ubuntu 机器上新建 /etc/profile.d/go.sh
文件内容如下:
|
|
创建完go.sh文件后,注销用户重新登录或是运行
|
|
注:关于环境变量相关的设置,需要了解各平台相关知识,这里不细述,自行百度或谷歌
一个 Go 程序项目一般包含三个目录
一个工作空间目录结构看起来像这样:
|
|
此工作空间包含三个代码库(goauth2、streak 和 todo),两个命令(streak 和 todo) 以及两个库(oauth 和 task)。
前面介绍环境变量 GOPATH 的时候提到,为了避免每次新建一个项目都去修改系统环境变量的麻烦。我们可以使用一个脚本来设置特定项目的 GOPATH 变量。
install.sh 脚本:
|
|
Windows 下的 install.bat 脚本(未验证):
|
|
通过之前的介绍,现在我们来写一个hello,world的例子
|
|
src\hello.go
文件
|
|
install.sh
文件
|
|
|
|
离线运行官方文档
|
|
离线运行官方入门学习教程
|
|
主要会操作三个配置文件:
/etc/pptpd.conf
/etc/ppp/options.pptpd
/etc/ppp/chap-secrets
编辑 /etc/pptpd.conf
去掉前面的#去掉:
解释下: localip是pptp使用的ip, 可以随意; remoteip链接到vpn的用户分配到ip的访问, 和localip同一个网段即可.
编辑 /etc/ppp/options.pptpd
去掉ms-dns前面的#,修改成下面的数据:
解释: 设置链接到vpn的用户如果访问网络时使用的dns, 和他们自己电脑与服务器设置的dns没任何关系.
编辑 /etc/ppp/chap-secrets
,直接输入如下字段,vpsma可以换成其他字段,
格式: 用户名 pptpd 密码 IP
的形式编写,如果需要多个账号就写多行,一行一个
解释: 这是链接vpn的用户密码, 每行一个, 代表一个用户.
格式说明: 第一列为用户, 依次是 服务器名称, 密码和ip, 中间使用一个空格或者tab隔开.
用户和密码可随意。服务器名(pptpd)不要改,如果修改请保证和/etc/pptpd.conf
中的name
保持一致。后面的*代表ip由pptpd自动分配
编辑 /etc/sysctl.conf
文件
|
|
ipdables 配置文件位于 /etc/sysconfig/iptables
|
|
|
|
|
|
|
|
|
|
linux下pptp搭建的vpn代理上网很慢解决方法。
在pptp所在的linux服务的iptables的*filter表中加入
或者在命令提示符运行
拨通vpn,在服务器上用netstat –i查看接口,得到
可知ppp的最大mtu为1396,当然,对应的mss应为(mtu-20字节的IP头部+20字节的TCP 头部=)1356
MSS就是TCP数据包每次能够传输的最大数据分段。为了达到最佳的传输效能,TCP协议在建立连接的时候通常要协商双方的MSS值,这个值TCP协议在实现的时候往往用MTU值代替(需要减去IP数据包包头的大小20Bytes和TCP数据段的包头20Bytes)所以往往MSS为1460。通讯双方会根据双方提供的MSS值得最小值确定为这次连接的最大MSS值。
当然传输的时候其他的协议还要加些包头在前面,总之mtu就是总的最后发出去的报文大小。mss就是你需要发出去的数据大小。
假设PC建立了到SERVER的HTTP连接,PC希望从SERVER下载一个大的网页。SERVER接收到PC的请求后开始发送大网页文件,其IP的DF位置1,不允许分片,IP报文长度为1500字节。到达VPN网关2的外网口(以太)后,VPN网关2发现其长度超过了1500个字节,于是将其丢弃,并给SERVER发回一个目的地址不可达的ICMP信息,同时指出“MTU of next hop: 1500”。PC接收到该消息后,又按照1500字节对外发送,又被丢弃,于是就形成了循环,无法通讯。
根据上述的分析,很容易得到如下解决方式,在VPN网关2的出接口设置MTU为1500-4-20=1476,这样VPN网关2返回ICMP不可达消息时将给出”MTU of next hop: 1476”。SERVER将以1476作为自己的最大MTU对外发送,到达VPN网关1,封装GRE和外层IP头后就不会超过1500而顺利发到对端。
|
|
因为mss是在TCP连接建立开始时,通过带有syn标志的IP数据包进行传输的,所以我们在iptables里面规定,在转发数据时,只要发现产生于ppt的带有 syn标志数据包时,将其mss设定为1356字节,这样就与ppp0接口的路径MTU向匹配了,数据自然就可以畅通无阻啦。
(注,vpn拨入一个,则建立一个ppt的虚拟设备,这个可以再linux上用ifcpnfig看到,第一个为ppp1,第二个为ppp2……)
|
|
因为mss是在TCP连接建立开始时,通过带有syn标志的IP数据包进行传输的,所以我们在iptables里面规定,在转发数据时,只要发现带有 syn标志并且源地址为主机B的IP数据包时,将其mss设定为1356字节,这样就与ppp0接口的路径MTU向匹配了,数据自然就可以畅通无阻啦。
因为mss是在TCP连接建立开始时,通过带有syn标志的IP数据包进行传输的,所以我们在iptables里面规定,在转发数据时,只要发现带有 syn标志并且源地址为主机B的IP数据包时,将其mss设定为1356字节,这样就与ppp0接口的路径MTU向匹配了,数据自然就可以畅通无阻啦。
|
|
本地项目部分页面使用 react ,通常就是一两个jsx文件需要编译。所以不打算使用 webpack 等打包工具。只需要最简单的能通过命令行编译 ES6 语法编写的 jsx 源文件为普通js文件
在官方网站安装说明部分,建议安装 babel CLI 使用本地方式,而非全局方式。一是因为本地开发中,各个项目依赖的 Babel 版本不尽相同,另外一方面是让项目更加独立,不依赖于具体的机器环境
There are two primary reasons for this.
在项目根目录中运行
因为全局安装运行 Babel 弊大于利,如果你之前已经全局安装过 Babel,可以使用如下命令卸载全局的 Babel
在项目根目录中运行
准备工具完成后,我们可以开始编写代码了。在代码编写过程中,通过如下命令实时监控代码变动并编译生成转换文件
我们也可以使用如下命令,将 src 目录下的所有文件编译到 lib 目录下
Yii 提供了 assetManager 来管理相对独立的资源内容,通过 assetManager 可以很方便地将相关功能的 js,css,图片等资源进行管理和二次发布。当我们的资源放置位置不是位于网络可访问目录中时,Yii 的 assetManager 会自动将这些资源自动发布到 @web/assets 目录中,并且随机生成一个资源文件夹名称。当我们的程序是单机部署时,没有问题。而当我们进行多机部署时,会发现在在每台机器上生成的资源文件夹名称不一致的情况。这将导致页面上部分资源文件无法加载,报 404 错误。
为了解决这个问题,我们先来看一下 Yii2 中关于资源文件夹目录名称生成的源码片断(文件位于 web/AssetManager.php
)
|
|
在Yii内部,资源发布的时候调用的就是这个 publish 函数,可以看到,这里面主要有两个相关函数 publishFile 和 publishDirectory
|
|
通过源码我们可以看到,这两个函数在生成随机目录名 dir
时实际上都调用了一个 hash方法,让我们来看一下这个方法:
到这里,应该能很明白的看到是什么原因导致了在多机器上部署会导致文件名不一致了。核心原因就在于 filemtime($path)
这个部分。filemtime() 函数的作用是返回文件内容上次的修改时间。多机器部署的时候,我们通常不能保证同一个文件在每台机器上的这个时间一致。所以导致最终计算出来的名称不一致。
现在让我们来看一下,如何解决这个问题,在上面的代码中,我们看到有一个 hashCallBack
属性,这个属性值是一个可执行的自定义资源目录生成函数。
解决方法一: 配置文件中全局设置 assetManager 组件
|
|
解决方法一: 局部动态设置
|
|
React本身仅只是一个视图层的解决方案,真实项目中还需要配合其它库来进行开发。这里介绍的是一个可进行完整项目开发的技术栈。将介绍以下这些库及它们之间如何配合来完成一个完整的项目开发。
react的核心是组件,了解组件的核心是搞清楚组件生命周期。组件之后,需要了解的是react组件之间信息流的传递,主要是通过props
(包含回调函数,组件渲染所需要的数据等)
组件定义,组件通过 React.createClass()创建,包含以下一些定义
react组件生命周期函数:
包含所有定义和生命周期函数的组件定义看起来像下面这样
|
|
ES6
的写法略有不同,看起来像这样
|
|
没有太多学习成本,主要功能就是提供路由和组件的绑定。
|
|
解释,上面的代码定义了一个路由规则
/
路径的时候,渲染Home组件/about
路径的时候,渲染About组件/other
路径的时候,渲染Other组件需要注意到Home
和About
被包含在App组件中,这样定义实现的效果是,Home
和About
组件的渲染会包裹在App组件中,实际上相当于我们平时开发流程中使用的layout
视图层,这里的App
组件就相当于Home
和About
的layout
。来看一下App组件的render()方法
|
|
上面的代码,在App组件中,我们通过 this.props.children
来获取当前路由对应的子组件(本例中的Home或About),可以看出,在App组件中,我们还增加了Header
和Footer
两个组件,给About
和Home
加上了页头页尾
另外需要注意的是history
这个props
,它有三个选项
#
之后的部分)其它常用的组件:
<Link>
<Redirect>
以上是简单介绍,更多信息可访问官方文档,查看说明
redux是JavaScript状态容器,用于管理应用的状态(个人理解实际就是应用的数据和引起数据变更的操作,在react应用开发里,就是指定渲染react组件需要的数据和各种回调函数)
redux基础概念
前端各种组件在特定的state下渲染会有所不同,一个展示组件就是通过state的变化来渲染界面的。
Store就是用来维持应用所有的state树的一个对象。应用的所有state以单一的对象存在一个单一的store中.可以理解为应用的数据库,存放渲染应用需要的所有数据。通过dispatch一个action来修改store中的state
Store对象的方法
实际就是一个对像,必须包含一个type
字段,type
字段相当于定义了action的名字。通常长下面这个样子
|
|
通常我们通过一个函数来封装action
实际就是回调函数的处理逻辑,响应的是action
定义的操作,当action
被调用的时候,触发指定的reducers函数,函数接受旧的state和action作为参数,返回一个新的state,新的state引起页面组件发生变化,从而使页面展示的信息发生变化
需要特别理解的是,reducers函数必须返回一个新的state对象
|
|
有了action
和reducers
定义,那怎么把它们联系起来呢,这时候就要用到dispatch
了。通常就是下面这个样子
|
|
dispatch
的参数必须是一个action
对象(稍后会在react-thunk中再提到这个),调用dispatch
后,指定的reducers
将接收到这个调用,然后处理调用,返回新的状态。我们执行上面的dispatch
后,state会变成下面这个样子
|
|
action
和reducers
store
对象dispatch
方法触发action
,改变state
通过提供容器组件把sotre和dispatch绑定到真正展示用的组件中去
API
<Provider
connect()
|
|
上面的代码中,我们通过传入`todoReducer`给redux库
的createStore
API函数,创建了App
组件的唯一`store`对象。
然后再通过`react-redux`的Provider
组件使得Provider
之下的组件都能通过 connect()
方法获得 Redux store。
在App组件中
|
|
因为App组件包裹在Provider之下,所以App下的Header组件也能通过connect获取store对象
上面谈dispatch
的时候,我们说到,`dispatch`必须接受一个`action`对象作为参数,像如下这样
|
|
react-thunk是redux中间件,让dispatch
能使用除了action
以外的其它内容作为参数.比如下面的例子,我们定义一个fetchTodo函数,从某个远程接口获取一条todo数据,然后把这条数据通过dispatch添加到新的todo列表中
|
|
cross-env
跨平台设置NODE_ENVpackage.json文件中命令设置环境变量时
windows 环境下报错: ‘NODE_ENV’ 不是内部或外部命令,也不是可运行的程序或批处理文件。
|
|
rimraf
nodejs版 rm -rf命令当前应用的数据状态,决定了UI应该如何展示,state变化通常将导致UI变化
描述“发生了什么的”对象,用于数据传递。必须包含一个type字段用于表示将执行的动作.
通常被 store.dispatch()调用
例如以下action可用于描述id为42的文章被点赞这个行为
计算数据,将变化的数据合并或去除,返回变化后的state。实际上就是响应store.dispatch()调用。
处理action返回新的state
存放应用中所有的state,将action和reducer联系在一起。通过dispatch一个action触发reducer,从而改变应用的state
Store 有以下职责:
createStore(reducer, [initialState])
创建一个 Redux store 来以存放应用中所有的 state
参数
reducer (Function):
接收两个参数,分别是当前的 state 树和要处理的 action,返回新的 state 树。
[initialState] (any):
初始时的 state。在同构应用中,你可以决定是否把服务端传来的 state 水合(hydrate)后传给它,或者从之前保存的用户会话中恢复一个传给它。如果你使用 combineReducers 创建 reducer,它必须是一个普通对象,与传入的 keys 保持同样的结构。否则,你可以自由传入任何 reducer 可理解的内容。
combineReducers(reducers)
随着应用变得复杂,需要对 reducer 函数 进行拆分,拆分后的每一块独立负责管理 state 的一部分。
combineReducers 辅助函数的作用是,把一个由多个不同 reducer 函数作为 value 的 object,合并成一个最终的 reducer 函数,然后就可以对这个 reducer 调用 createStore。
合并后的 reducer 可以调用各个子 reducer,并把它们的结果合并成一个 state 对象。state 对象的结构由传入的多个 reducer 的 key 决定。
<Provider store={}>
对组件注入Redux Store
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
连接 React
组件与 Redux store
参数
mapStateToProps(state, [ownProps]): stateProps
如果定义该参数,组件将会监听 Redux store 的变化。任何时候,只要 Redux store 发生改变,mapStateToProps 函数就会被调用。该回调函数必须返回一个纯对象,这个对象会与组件的 props 合并。如果你省略了这个参数,你的组件将不会监听 Redux store。如果指定了该回调函数中的第二个参数 ownProps,则该参数的值为传递到组件的 props,而且只要组件接收到新的 props,mapStateToProps 也会被调用。
mapDispatchToProps(dispatch, [ownProps]): dispatchProps
如果传递的是一个对象,那么每个定义在该对象的函数都将被当作 Redux action creator,而且这个对象会与 Redux store 绑定在一起,其中所定义的方法名将作为属性名,合并到组件的 props 中。如果传递的是一个函数,该函数将接收一个 dispatch 函数,然后由你来决定如何返回一个对象,这个对象通过 dispatch 函数与 action creator 以某种方式绑定在一起(提示:你也许会用到 Redux 的辅助函数 bindActionCreators())。如果你省略这个 mapDispatchToProps 参数,默认情况下,dispatch 会注入到你的组件 props 中。如果指定了该回调函数中第二个参数 ownProps,该参数的值为传递到组件的 props,而且只要组件接收到新 props,mapDispatchToProps 也会被调用。
mergeProps(stateProps, dispatchProps, ownProps): props
如果指定了这个参数,mapStateToProps() 与 mapDispatchToProps() 的执行结果和组件自身的 props 将传入到这个回调函数中。该回调函数返回的对象将作为 props 传递到被包装的组件中。你也许可以用这个回调函数,根据组件的 props 来筛选部分的 state 数据,或者把 props 中的某个特定变量与 action creator 绑定在一起。如果你省略这个参数,默认情况下返回 Object.assign({}, ownProps, stateProps, dispatchProps) 的结果。
options 如果指定这个参数,可以定制 connector 的行为。
pure = true
如果为 true,connector 将执行 shouldComponentUpdate 并且浅对比 mergeProps 的结果,避免不必要的更新,前提是当前组件是一个“纯”组件,它不依赖于任何的输入或 state 而只依赖于 props 和 Redux store 的 state。默认值为 true。
withRef = false
如果为 true,connector 会保存一个对被包装组件实例的引用,该引用通过 getWrappedInstance() 方法获得。默认值为 false
<Provider store>
组件中,从页实现绑定Composer 是 PHP 的一个依赖管理工具。它允许你申明项目所依赖的代码库,它会在你的项目中为你安装他们
Xdebug是一个开放源代码的PHP程序调试器(即一个Debug工具),可以用来跟踪,调试和分析PHP程序的运行状况
如果php安装了xdebug扩展,当使用composer的时候,会有如下警告提示。提示信息里的连接给出了官方解决方案 (这个地址竟然也被天朝墙,还让不让干活了)
引起的主要问题就是当你使用composer的时候,下载速度会被得奇慢无比
You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug
官方的链接给出了以下几个解决方案
禁用xdebug,在*nix系统下,再利用别名来使得命令行直接调用php可加载xdebug。通过以下两步实现
php.ini配置里禁用xdebug
|
|
*nix系统里定义命令别名
|
|
新建一个禁用了xdebug的xdebug-disabled-php.ini文件,还是使用别名,将composer命令重新定义
|
|
…官方给出了另外的复杂方案,太麻烦,就不贴了,有兴趣到这里自行查看
针对Linux平台,因为我自己开发机器用的是php-fpm启动脚本
主要诉求是希望我机器上开机默认启动php的时候,能加载xdebug扩展,命令行下运行composer调用php命令的时候,不加载。解决思路是,在php.ini文件中禁用xdebug扩展,然后在php-fpm启动脚本中增加参数,加载xdeubg
具体操作就是直接修改启动脚本/etc/init.d/php-fpm
下的参数,增加-dzend_extension=xdebug.so
(注意,这里你可能需要传入xdebug.so文件的绝对路径)
|
|