第一种方式,直接执行上一页的原生方法:
var pages = getCurrentPages();
if (pages.length > 1) {
var prePage = pages[pages.length - 2];
prePage.onPullDownRefresh();
}第二种方式,在上一页的 onShow() 中对数据进行更新。
推荐使用第一种方式,但只能调用原生方法,不能直接调用 methods 中的自定义方法(详见)。第二种方式的缺点是,有时候不需要在返回上一页时更新数据,但它仍会执行。
当使用在线编辑器编辑一篇文章(或从 Word 复制)后,会得到包含 HTML 标签的字符串内容,可以直接将它输出到页面上而不需要进行 HTML 编码。
但是,当我们需要改变图片大小时,我们发现有些图片的尺寸是直接使用 style 属性固定的,除了用 JS 进行后期处理,我们可以在服务端对 <img /> 进行修正。
这个场景会在小程序开发的时候遇到。
我们可以在客户端用 JS 进行处理,也可以在服务端用类似的方法处理(使用正则表达式)。参此文
这里使用 HtmlAgilityPack 通过递归节点来处理:
/// <summary>
/// 给所有指定节点添加样式
/// </summary>
/// <param name="html"></param>
/// <param name="tag">节点名称(小写),如:img</param>
/// <param name="styles">要添加的样式,如:max-width:100%;</param>
/// <returns></returns>
public static string AddStyleToHtmlNode(string html, string tag, string styles)
{
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
for (var i = 0; i < doc.DocumentNode.ChildNodes.Count; i++)
{
doc.DocumentNode.ChildNodes[i] = AddStyleToHtmlNode(doc.DocumentNode.ChildNodes[i], tag, styles);
}
return doc.DocumentNode.OuterHtml;
}
private static HtmlNode AddStyleToHtmlNode(HtmlNode node, string tag, string styles)
{
if (node.Name == tag)
{
var style = node.GetAttributeValue("style", null);
node.SetAttributeValue("style", ((string.IsNullOrWhiteSpace(style) ? "" : style.Trim() + ";") + styles).Replace(";;", ";"));
}
for (var i = 0; i < node.ChildNodes.Count; i++)
{
node.ChildNodes[i] = AddStyleToHtmlNode(node.ChildNodes[i], tag, styles);
}
return node;
}直接调用:
Content = zStringHTML_190126.AddStyleToHtmlNode(Content, "img", "max-width:100%;height:auto;");一、显示信息的命令
console.log("normal"); // 用于输出普通信息
console.info("information"); // 用于输出提示性信息
console.error("error"); // 用于输出错误信息
console.warn("warn"); // 用于输出警示信息
二、点位符:字符(%s)、整数(%d或%i)、浮点数(%f)和对象(%o);
console.log("%s","string"); //字符(%s)
console.log("%d年%d月%d日",2016,8,29); //整数(%d或%i)
console.log("圆周率是%f",3.1415926); //浮点数(%f)
var dog = {};
dog.name = "大毛";
dog.color = "黄色";
dog.sex = "母狗";
console.log("%o",dog); //对象(%o)
三、信息分组 (console.group(),console.groupEnd())
console.group("第一组信息");
console.log("第一组第一条:我的博客");
console.log("第一组第二条:CSDN");
console.groupEnd();
console.group("第二组信息");
console.log("第二组第一条:程序爱好者QQ群");
console.log("第二组第二条:欢迎你加入");
console.groupEnd(); 
四、将对象以树状结构展现 (console.dir()可以显示一个对象所有的属性和方法)
var info = {
name : "Alan",
age : "27",
grilFriend : "nothing",
getName : function(){
return this.name;
}
}
console.dir(info);
五、显示某个节点的内容 (console.dirxml()用来显示网页的某个节点(node)所包含的html/xml代码)
var node = document.getElementById("info");
node.innerHTML += "<p>追加的元素显示吗</p>";
console.dirxml(node);
六、判断变量是否是真 (console.assert()用来判断一个表达式或变量是否为真,只有表达式为false时,才输出一条相应作息,并且抛出一个异常)
var testObj = false; console.assert(testObj, '当testObj为false时才输出!');

七、计时功能 (console.time()和console.timeEnd(),用来显示代码的运行时间)
console.time("控制台计时器");
for(var i = 0; i < 10000; i++){
for(var j = 0; j < 10000; j++){}
}
console.timeEnd("控制台计时器");
八、性能分析performance profile (就是分析程序各个部分的运行时间,找出瓶颈所在,使用的方法是console.profile()和console.proileEnd();)
function All(){
// alert(11);
for(var i = 0; i < 10; i++){
funcA(100);
}
funcB(1000);
}
function funcA(count){
for(var i = 0; i < count; i++){};
}
function funcB(count){
for(var i = 0; i < count; i++){};
}
console.profile("性能分析器");
All();
console.profileEnd();详细的信息在chrome控制台里的"profile"选项里查看

九、console.count()统计代码被执行的次数
function myFunction(){
console.count("myFunction 被执行的次数");
}
myFunction(); //myFunction 被执行的次数: 1
myFunction(); //myFunction 被执行的次数: 2
myFunction(); //myFunction 被执行的次数: 3
十、keys和values,要在浏览器里输入

十一、console.table表格显示方法
var mytable = [
{
name: "Alan",
sex : "man",
age : "27"
},
{
name: "Wu",
sex : "gril",
age : "28"
},
{
name: "Tao",
sex : "man and gril",
age : "29"
}
]
console.table(mytable);
十二、Chrome 控制台中原生支持类jQuery的选择器,也就是说你可以用$加上熟悉的css选择器来选择DOM节。
$("body"); //选择body节点
十三、copy通过此命令可以将在控制台获取到的内容复制到剪贴板
copy(document.body); //复制body
copy(document.getElementById("info")); //复制某id元素的的节点
十四、$_命令返回最近一次表达式执行的结果,$0-$4代表了最近5个你选择过的DOM节点

十五、利用控制台输出文字,图片,以%c开头,后面的文字就打印的信息,后面一个参数就是样式属性;
console.log("请在邮件中注明%c 来自:console","font-size:16px;color:red;font-weight:bold;");
当我们用 ASP.NET Web API 作服务端接口时,如果客户端以 GET 方式请求的 URL 中,由于拼接错误导致“?”和“&”并列出现,会发生 400 Bad Request,那么需要在 IIS 中使用 URL 重写模块来纠正。
请求 URL 如:
http://www.abc.com/api/obj?&foo=bar
需要重写为:
http://www.abc.com/api/obj?foo=bar
打开 IIS 管理器中对应网站的 URL 重写,

添加空白规则。
匹配的 URL 不包含域名,如上述 URL 则匹配的范围是:
api/obj
不包含我们要查找的字符串 ?&,所以此处模式只能匹配所有:
.*
又因为重定向路径中需要包含这部分,所以用括号包裹,即:
(.*)

继续添加条件匹配:
条件输入:{QUERY_STRING},表示匹配查询字符串,
匹配的部分是“?”后面的字符串:
&foo=bar
那么可以填写模式:
^\&.*
因为 & 后面的部分仍然需要使用,所以用括号包裹:
^\&(.*)

“操作”中选择类型“重定向”,URL 填写:
{R:1}?{C:1}
其中 {R:1} 指代 api/obj,{C:1} 指代 foo=bar
取消“附加查询字符串”前面的勾
重定向类型在测试时可以选择 302 或 307,没问题后选择 301。

完成。
最终我们可以在网站的配置文件 web.config 中看到:
<rewrite>
<rules>
<rule name="uni-app-h5-replace-q" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{QUERY_STRING}" pattern="^\&(.*)" />
</conditions>
<action type="Redirect" url="{R:1}?{C:1}" appendQueryString="false" redirectType="Temporary" />
</rule>
</rules>
</rewrite>我们要把这段代码复制到开发环境源代码的 web.config 中,以免发布网站时将我们设置好的配置覆盖掉。
在学习和使用 ASP.NET Web API 之前,最好先对 RESTful 有所了解。它是一种软件架构风格、设计风格,而不是标准。
推荐视频教程:https://www.imooc.com/learn/811
讲师:会飞的鱼Xia
需时:2小时25分
REST API 测试工具:
在 Chrome 网上应用店中搜索:Restlet Client
或网站 https://client.restlet.com
>>> 资源路径
SCHEME :// HOST [ ":" PORT ] [ PATH [ "?" QUERY ]]
其中 PATH 中的资源名称应该使用复数名词,举例:
GET https://xoyozo.net/api/Articles/{id}
POST https://xoyozo.net/api/Articles
>>> HTTP verb(对应 CURD 操作):
| 方法 | 功能 | ASP.NET Web API 接口返回类型(一般的) |
|---|---|---|
| GET | 取一个或多个资源 | T 或 IEnumerable<T> |
| POST | 增加一个资源 | T |
| PUT | 修改一个资源 | T |
| DELETE | 删除一个资源 | void |
| PATCH | 更新一个资源(资源的部分属性) | |
| HEAD | 获取报头 | |
| OPTIONS | 查询服务器性能或资源相关选项和需求 |
>>> 过滤信息:
如分页、搜索等
>>> 常用状态码:
| 200 | OK | 指示请求已成功 |
| 201 | Created | 资源创建成功(常见用例是一个 PUT 请求的结果) |
| 202 | Accepted | 该请求已被接收但尚未起作用。它是非承诺的,这意味着HTTP中没有办法稍后发送指示处理请求结果的异步响应。 |
| 204 | No Content | 成功 PUT(修改)或 DELETE(删除)一个资源后返回空内容(ASP.NET Web API 中将接口返回类型设置为 void 即可) |
| 400 | Bad Request | 服务器无法理解请求(如必填项未填、内容超长、分页大小超限等),幂等 |
| 401 | Unauthorized | 未授权(如用户未登录时执行了须要登录才能执行的操作),通俗地讲,是服务器告诉你,“你没有通过身份验证 - 根本没有进行身份验证或验证不正确 - 但请重新进行身份验证并再试一次。”这是暂时的,服务器要求你在获得授权后再试一次。 |
| 403 | Forbidden | 服务器理解请求但拒绝授权(是永久禁止的并且与应用程序逻辑相关联(如不正确的密码、尝试删除其它用户发表的文章)、IP 被禁止等),通俗地讲,是服务器告诉你,“我很抱歉。我知道你是谁 - 我相信你说你是谁 - 但你只是没有权限访问此资源。” |
| 404 | Not Found | 找不到请求的资源(指资源不存在,如果找到但无权访问则应返回 403) |
| 405 | Method Not Allowed | 请求方法被禁用(HTTP 动词) |
| 500 | Internal Server Error | 服务器遇到阻止它履行请求的意外情况(如数据库连接失败) |
| 503 | Service Unavailable | 服务器尚未准备好处理请求(常见原因是服务器因维护或重载而停机,这是临时的,可用于在单线程处理事务时遇到被锁定时的响应,如抽奖活动、抢楼活动,防止因并发导致逻辑错误) |
>> 错误处理:
C# 例:throw new HttpResponseException(HttpStatusCode.NotFound);
PHP 例:throw new Exception('文章不存在', 404);
>>> 返回结果:
JSON/XML
不要返回密码等机密字段
>>> 其它:
身份验证窗口(浏览器弹窗,类似 alert,非页面表单),明文传输,安全性不高,不建议使用。实现:
在 Headers 中添加 Authorization:Basic “用户名:密码”的 Base64 编码
本文不定时更新中……
收集了一些在开发过程中遇到的一些问题的解决方法,适合新手。
异常:
出现脚本错误或者未正确调用 Page()
原因:不小心删了第一行内容:<template>
异常:
模块编译失败:TypeError: Cannot read property 'for' of undefined
at fixDefaultIterator (D:\HBuilderX\plugins\uniapp\lib\mpvue-template-compiler\build.js:4277:24)
at mark (D:\HBuilderX\plugins\uniapp\lib\mpvue-template-compiler\build.js:4306:5)
at markComponent (D:\HBuilderX\plugins\uniapp\lib\mpvue-template-compiler\build.js:4371:5)
at baseCompile (D:\HBuilderX\plugins\uniapp\lib\mpvue-template-compiler\build.js:4384:15)
at compile (D:\HBuilderX\plugins\uniapp\lib\mpvue-template-compiler\build.js:4089:28)
at Object.module.exports (D:\HBuilderX\plugins\uniapp\lib\mpvue-loader\lib\template-compiler\index.js:43:18)
原因:新建的页面(简单模板)只有以下 3 个标签,须在 <template /> 中添加一些代码,如 <view />
<template>
</template>
<script>
</script>
<style>
</style>异常:
模块编译失败:TypeError: Cannot read property 'toString' of undefined
at Object.preprocess (D:\HBuilderX\plugins\uniapp\lib\preprocess\lib\preprocess.js:56:15)
at Object.module.exports (D:\HBuilderX\plugins\uniapp\lib\preprocessor-loader.js:9:25)
原因:没有原因,纯抽风,HX 关掉再开就好了。
异常:
Cannot set property 'xxx' of undefined;at pages/... onLoad function;at api request success callback function
原因:属性未定义,例如
data() {
return {
item: { }
}
}而直接赋值 this.item.abc.xxx = '123';
解决:
data() {
return {
item: {
abc: ''
}
}
}问:page 页面怎样修改 tabBar?
答:官方文档未给出答案,百度了一圈也无果(2018-10-23),但有人说小程序的 setTabBarBadge() 方法设置角标是可以用的。
坑:
VM1694:1 获取 wx.getUserInfo 接口后续将不再出现授权弹窗,请注意升级
参考文档: https://developers.weixin.qq.com/community/develop/doc/0000a26e1aca6012e896a517556c01
填坑:放弃使用 uni.getUserInfo 接口来获取用户信息,uni.login 可返回用于换取 openid / unionid 的 code,参:uni.login、 code2Session
坑:字符搜索(当前目录)(Ctrl+Alt+F)搜不出所有结果
填坑:顾名思义他只搜索当前目录,即当前打开文件所在目录,而非我误认为的整个项目根目录。在“项目管理器”中选中要搜索字符的目录即可。
坑:uni.navigateTo() 或 uni.redirectTo() 没反应
填坑:这两个方法不允许跳转到 tabbar 页面,用 uni.switchTab() 代替。
坑:使用“Ctrl+/”快捷键弹出“QQ五笔小字典”窗口
解决:打开QQ五笔“属性设置”,切换到“快捷键设置”选项卡,把“五笔小字典”前的勾取消(即使该组合键是设置为Ctrl+?)。
坑:<rich-text /> 中的 <img /> 太大,超出屏幕宽度
填坑:用正则表达式给 <img /> 加上最大宽度
data.data.Content = data.data.Content.replace(/\<img/gi, '<img style="max-width:100%;height:auto" ');坑:无法重命名或删除目录或文件
填坑一:“以管理员身份运行”HBuilder X 后再试。
填坑二:关闭微信开发者工具、各种手机和模拟器后再试。
填坑三:打开“任务管理器”,结束所有“node.exe”进程后再试。
坑:
thirdScriptError
sdk uncaught third Error
(intermediate value).$mount is not a function
TypeError: (intermediate value).$mount is not a function
Page[pages/xxxx/xxxx] not found. May be caused by: 1. Forgot to add page route in app.json. 2. Invoking Page() in async task.
Page is not constructed because it is not found.填坑:关闭微信开发者工具、各种手机和模拟器后,删除“unpackage”目录。
坑:
Unexpected end of JSON input;at "pages/news/view" page lifeCycleMethod onLoad function
SyntaxError: Unexpected end of JSON input填坑:给 uni.navigateTo() 的 url 传参时,如果简单地将对象序列化 JSON.stringify(item),那么如果内容中包含“=”等 url 特殊字符,就会发生在接收页面 onLoad() 中无法获取到完整的 json 对象,发生异常。
uni.navigateTo({
url: "../news/view?item=" + JSON.stringify(item)
})所以应该把参数值编码:
uni.navigateTo({
url: "../news/view?item=" + escape(JSON.stringify(item))
})如果是一般的 web 服务器来接收,那么会自动对参数进行解码,但 uni-app 不会,如果直接使用:
onLoad(e) {
this.item = JSON.parse(e.item);
}会发生异常:
Unexpected token % in JSON at position 0;at "pages/news/view" page lifeCycleMethod onLoad function
SyntaxError: Unexpected token % in JSON at position 0需要解码一次:
onLoad(e) {
this.item = JSON.parse(unescape(e.item));
}需要注意的是,unescape(undefined) 会变成 'undefined',如果要判断是否 undefined,应是 unescape 之前。
坑:图片变形
填坑:mode="widthFix"
坑:页面如何向 tabBar 传参
填坑:全局或缓存
坑:编译为 H5 后,出现:Access-Control-Allow-Origin
填坑:参阅
坑:编译为 H5 后,GET 请求的 URL 中出现“?&”
填坑 :客户端只求 DCloud 官方能够尽快修复这个 bug,IIS 端可以暂时用 URL 重写来防止报 400 错误,参此文。
坑:[system] errorHandler TypeError: Cannot read property 'forEach' of undefined
填坑:待填
〓 系统
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 关机 | halt | halt | |
| 重启 | reboot | reboot | |
| 系统监视器 | top | 系统时间, 运行天数, 当前登录用户数, 系统负载 总进程数, 运行中的, 睡眠的, 停止的, 未响应的 Cpu(s):us 用户, sy 系统, ni XX, id 空闲, wa 等待, hi XX, si XX Mem, 已使用, 空余, 缓冲 Swap, 已使用, 空余, 缓冲 快捷键: M 按占内存排序 P 按占Cpu排序 1 显示每个 Cpu k 杀死进程 q 退出 | top |
| 查看进程 | ps | aux -ef | 列出包含 java 的进程 ps aux |grep java ps -ef |grep java |
| 查看内存及 Swap 用量 | free | -b,-k,-m,-g 按单位显示 | free -m |
| 查看系统时间 | date | 显示 CST 时间 -R 显示时区 -u 显示 UTC 时间 | date |
| 查看硬件时间 | clock | clock | |
| 设置系统日期 | date -s 月/日/年 | ||
| 设置系统时间 | date -s 时:分:秒 | ||
| 将系统时间写入到硬件时间 | clock -w | ||
| 查看系统版本 | cat /etc/*release | ||
| 升级系统软件 | yum update -y |
〓 文件
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 进入目录 | cd | cd .. # 上一层目录 cd /root # 根目录 | |
| 列出目录 | ls | 白色:表示普通文件 蓝色:表示目录 绿色:表示可执行文件 红色:表示压缩文件 浅蓝色:链接文件 红色闪烁:表示链接的文件有问题 黄色:表示设备文件 灰色:表示其他文件 | ls |
| 创建目录 | mkdir | mkdir XXX | |
| 删除目录 | rm | rm -rf XXX | |
| 删除文件 | rm | rm XXX | |
| 复制文件 | cp | cp XXX YYY | |
| 复制目录 | cp | -r 复制目录及目录内的所有项目 -v 详细显示进行的步骤 | cp -rv XXX YYY |
| 重命名文件 | mv | -i: 若指定目录已有同名文件,则先询问是否覆盖旧文件; -f: 在mv操作要覆盖某已有的目标文件时不给任何指示; | mv 源文件 目标文件 |
| 移动文件 | mv | mv 一个或多个文件 目标目录 | |
| 下载文件 | wget | 下载到当前目录 | wget http://XXX.tar.gz |
| 计算文件/目录的磁盘用量 | du | -a 不仅显示目录,同时显示文件 -h 容易阅读方式显示 --max-depth=N 可指定计算深度 | du -ah --max-depth=1 | sort -n |
| 查找文件 | find | find /home -name *.apk |
〓 tar
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| tar | tar | -z 是否压缩 -c 打包 -x 解包 -v 详细地列出处理的文件 -f | 打包:tar -cvf abc.tar abc 解包:tar -xvf abc.tar 压缩打包:tar -zcvf abc.tar.gz abc 解压解包:tar -zxvf abc.tar.gz |
〓 磁盘
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 查看所有磁盘及分区 | fdisk -l | fdisk -l | |
| 查看当前挂载 | df | -h 按可阅读的方式打印数值和单位 -T 显示文件系统类型 | df -hT |
| 管理磁盘分区 | fdisk /dev/*** | 进入后的操作说明: m 显示命令菜单 d 删除一个分区 n 创建一个分区(e 扩展分区;p 主分区) t 改变分区ID q 不保存退出 w 保存退出 | fdisk /dev/vdb |
| 格式化分区 | mkfs.*** /dev/***N | mkfs.xfs /dev/vdb1 | |
| 挂载分区 | mount /dev/***N /*** | mount /dev/vdb1 /www | |
| 卸载分区 | umount /dev/***N | umount /dev/vdb1 | |
| 开机自动挂载 | vi /etc/fstab | 配置文档格式:设备 挂载点 文件系统类型 defaults 0 0 | 打开:vi /etc/fstab 配置:/dev/vdb1 /www xfs defaults 0 0 |
〓 网络
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 查看 IP 配置 | ifconfig | ifconfig | |
| 配置网卡 IP | 配置文件目录:/etc/sysconfig/network-scripts/ 配置文件格式: DEVICE=eth0 / eth0:0 / ... # 在配置多线时若使用 cp 命令复制配置文件,必须修改此项以防止冲突 HWADDR=XX:XX:XX:XX:XX:XX # 网卡地址 TYPE=Ethernet # 以太网 UUID=******** ONBOOT=yes # 开机启动 NM_CONTROLLED=yes BOOTPROTO=static # 使用静态 IP IPADDR=192.168.1.2 # IP 地址 NETMASK=255.255.255.XXX # 子网掩码 GATEWAY=192.168.1.1 # 网关 DNS1=114.114.114.114 DNS2=8.8.8.8 | vi ifcfg-XXXN(:N) | |
| 重启网卡 | 使配置生效 | service network restart |
〓 防火墙
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 配置 iptables | 添加需要允许的端口的方法同 22 端口 | vi /etc/sysconfig/iptables | |
| 重启使配置生效 | service iptables restart |
〓 用户/权限
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 添加用户 | useradd | -g 组名 # 加入到该组 -s /bin/false #不允用户直接登录系统 | useradd –g 组名 用户名 -s /bin/false |
| 修改密码 | passwd | passwd 用户 | |
| 查看所有用户 | cut -d : -f 1 /etc/passwd | ||
| 查看可以登录系统的用户 | cat /etc/passwd | grep -v /sbin/nologin | cut -d : -f 1 | ||
| 删除用户 | -r, --remove remove home directory and mail spool | userdel 用户 | |
| 添加用户组 | groupadd | groupadd 组名 | |
| 为组添加用户(用户必须已存在) | gpasswd | gpasswd -a 用户 组 | |
| 将用户移出组 | gpasswd | gpasswd -d 用户 组 | |
| 查看用户所属组 | groups | groups 用户 | |
| 查看组中有哪些用户 | groupmems | groupmems -g 组 -l | |
| 更改文件/目录所有者 | chown | -R 递归处理所有的文件及子目录 | chown -R 用户:组 *** |
| 更改文件/目录权限 | chmod | -R 以递归方式更改所有的文件及子目录 | chmod -R 777 *** |
〓 vi 编辑器
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 打开文件 | vi | vi XXX | |
| 进入编辑模式 | 按 a/i/o/Insert 等 | ||
| 进入末行模式/命令模式 | 按 Esc后: :w 保存不退出 :q 退出(提示是否保存) :wq 保存并退出 :w XXX 另存到文件 XXX :q! 不保存退出 |
〓 计划任务
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 设置计划任务 | crontab | 详细步骤见本页底部 | crontab -l # 查看计划任务 crontab -e # 编辑计划任务 |
〓 网站
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 简单审查日志 | cat | grep | cat 日志文件 | grep 关键词1 | grep 关键词2 | more | |
| 日志分析 | goaccess | 见下文 |
〓 goaccess
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 安装 | yum install goaccess | ||
| 日志格式 | NCSA Commbined Log Format | date_format %d/%b/%Y log_format %h %^[%d:%^] "%r" %s %b "%R" "%u" | |
| 参数 | -f | 需要解析的日志文件 | |
| 参数 | -e | 指定 IP 地址统计 | |
| 参数 | -p | 指定配置文件 | 可以将上面的日志格式内容保存到文件 ~/.goacessrc |
| 参数 | -H | 显示 HTTP 协议信息 | |
| 参数 | -M | 显示 HTTP 方法信息 | |
| 生成文件 | goaccess -f 日志文件 -p ~/.goaccessrc > 目标文件.htm |
〓 lnmp
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 重启 LNMP | /root/lnmp restart | ||
| 重启 MySQL | /etc/init.d/mysql restart | ||
| 重启 PureFTPd | /root/pureftpd restart | ||
| 安装 LNMP | http://lnmp.org/install.html | ||
| 常见问题 | http://lnmp.org/faq.html | ||
| 状态管理命令 | http://lnmp.org/faq/lnmp-status-manager.html | ||
| 相关软件目录及文件位置 | http://lnmp.org/faq/lnmp-software-list.html | ||
| 防跨站、跨目录安全设置(仅支持 PHP 5.3.3 以上版本) | http://www.vpser.net/security/lnmp-cross-site-corss-dir-security.html | ||
| 查看 Nginx 版本 | nginx -V | ||
| 查看 MySQL 版本 | mysql -V | ||
| 查看 PNP 版本 | php -v | ||
| 查看 Apache 版本 | httpd -v | ||
| 查内存 | cat /proc/meminfo | ||
| php.ini | vim /usr/local/php/etc/php.ini | ||
| MySQL 配置文件 | vim /etc/my.cnf | ||
| 添加网站 | /root/vhost.sh | ||
| 添加 ProFTPd 用户 | /root/proftpd_vhost.sh |
〓 nginx
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 启动/停止/重启 | service nginx 或 /etc/rc.d/init.d/nginx | service nginx start service nginx stop service nginx restart | |
| 伪静态 | 在 .conf 文件中配置 | rewrite ^(.*)/read-htm-(.*)\.html(.*)$ $1/read.php?$2.html? last; rewrite ^(.*)/thread-htm-(.*)\.html(.*)$ $1/thread.php?$2.html? last; rewrite ^(.*)-htm-(.*)$ $1.php?$2 last; rewrite ^(.*)/simple/([a-z0-9\_]+\.html)$ $1/simple/index.php?$2 last; rewrite ^(.*)/data/(.*)\.(htm|php)$ 404.html last; rewrite ^(.*)/attachment/(.*)\.(htm|php)$ 404.html last; rewrite ^(.*)/html/(.*)\.(htm|php)$ 404.html last; | |
| 防盗链 | 在 .conf 文件中配置 | HttpRefererModule | location ~* \.(gif|jpg|png|swf|flv)$ { valid_referers none blocked *.0574bbs.com *.eyuyao.com 0574bbs.com eyuyao.com; if ($invalid_referer) { rewrite ^/ http://web1.eyuyao.com/yyad/src/3122.jpg; # return 404; } } |
| 浏览器缓存 | 在 .conf 文件中配置 | location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; } |
〓 vsftpd
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 安装 | yum install vsftpd | ||
| 查看是否已安装 | rpm -q vsftpd | ||
| 启动/停止/重启 | service vsftpd | service vsftpd start service vsftpd stop service vsftpd restart | |
| 配置文件 | vi /etc/vsftpd/vsftpd.conf |
〓 MySQL
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 登录 | mysql | mysql -u username -p | |
| 登出 | exit | ||
| 查看信息 | status; | ||
| 查询当前正在执行的 SQL 语句 | show processlist; | ||
| 删除指定时间之前的日志 | PURGE | PURGE MASTER LOGS BEFORE '2015-1-1 0:00:00'; |
〓 scp 远程文件/目录传输命令 (yum install openssh-clients) 用法
scp 会把文件权限(读取/写入/执行)带过来,但所有者为当前执行 scp 命令的用户。
scp 低版本有许多漏洞,用完最好 yum remove openssh-clients
scp 采用直接覆盖的机制,如需判断文件无差异则跳过,应改用 rsync 命令。查看 rsync 详细使用方式及与 scp 对比
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 若远程服务器 SSH 端口非默认 | scp | -P 端口号 | |
| 下载远程服务器上的文件到本地 | scp | scp 远程用户@远程服务器:远程文件 本地文件 | |
| 下载远程服务器上的目录到本地 | scp | -P 端口 -v 显示进度 -r 递归 | scp -r 远程用户@远程服务器:远程目录 本地目录 实例:scp -r root@x.x.x.x:/a/b/ /c/d/ 结果:/c/d/b/,即将整个 b 复制到 d 下(注意与 rsync 命令的区别) |
| 将本地文件上传到远程服务器 | scp | scp 本地文件 远程用户@远程服务器:远程文件 | |
| 将本地目录上传到远程服务器 | scp | 最终目录结构参:远程->本地 | scp -r 本地目录 远程用户@远程服务器:远程目录 |
〓 rsync 远程文件/目录传输命令 (yum install rsync) 用法查看 rsync 详细使用方式及与 scp 对比
rsync 会把文件权限(读取/写入/执行)带过来,所有者也会带过来。
相比于 scp 最大的优势就是可以增量同步
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 下载远程服务器上的目录到本地 | rsync | -a 递归 -v 详细 -p, -- perms 保持权限 -g, -- group 保持属组 -o, --owner 保持属主 -r 递归 --progress 打印 --delete 删除已不存在的文件 -u 表示仅更新较新的文件 -z 表示在传输过程中进行压缩 -e 'ssh -p 2222' 指定其它端口 | rsync 远程用户@远程服务器:远程目录 本地目录 实例:rsync -avu --progress root@x.x.x.x:/a/b/ /c/d/ 结果:/c/d/,即将 b 内的文件(夹)复制到 d 下(注意与 scp 命令的区别) |
| 将本地文件上传到远程服务器 | rsync | rsync 本地文件 远程用户@远程服务器:远程文件 | |
| 将本地目录上传到远程服务器 | rsync | 最终目录结构参:远程->本地 | rsync 本地目录 远程用户@远程服务器:远程目录 |
〓 ftp 客户端 (yum install ftp)
| 功能 | 命令 | --help | 示例 |
|---|---|---|---|
| 登录 | ftp | ftp 目标服务器 | |
| 列出远程当前路径目录/文件 | ls | ls | |
| 创建远程目录 | mkdir | mkdir 目录名 | |
| 删除远程目录(空) | rmrmdir | mkdir 目录名 | |
| 进入远程目录 | cd | cd 目录名 | |
| 显示远程当前路径 | pwd | pwd | |
| 重命名远程文件 | rename | rename 原文件名 新文件名 | |
| 上传文件 | put | put 本地文件名 | |
| 下载文件 | get | get 远程文件名 | |
| 批量下载文件 | mget | 需要单个确认 | |
| 批量下载文件【lftp】 | mirror | 参数有很多 | mirror |
| 返回 shell(不退出) | ! | ! | |
| 返回 ftp(接上步) | exit ftp | exit ftp | |
| 结束 | bye quit | bye quit |
〓 iftop
流量监控工具 教程
〓 GoAccess
实时网站日志分析工具 官网
〓 Cacti
常见问题笔记
加硬盘
插入新硬盘
若有 RAID,则先设置,使操作系统能认到硬盘
使用 fdisk 命令对新设备进行分区
使用 mkfs 命令对新分区进行格式化
使用 mount 命令进行挂载
设置开机自动挂载(vi /etc/fstab)
更改 MySQL 数据库目录位置
停止 MySQL 服务
将原数据目录转移或复制到新位置(若是复制,则修改所有者使原来一致)
找到 my.cnf 配置文件(一般在 /etc/),修改 datadir 值为新路径
启动 MySQL 服务
502 Bad Gateway 问题排查
查看 PHP 日志,路径:/usr/local/php/var/log
一般为“server reached pm.max_children setting (10), consider raising it”连接数问题,在“/usr/local/php/etc”下的所有配置文件中查找并修改相关设置即可(如改成 1000)。
计划任务(实例:定时备份数据库并通过 FTP 同步至其它服务器)
创建可执行文件:vi dotask.sh
dotask.sh 的内容示例:
DATE_TIME=`date +%Y_%m_%d_%H%M%S`;
FILE_NAME=数据库名_backup_$DATE_TIME.sql;
cd /home/mysqlbackup/;
mysqldump -u数据库用户名 -p数据库密码 数据库名>$FILE_NAME;
tar -zcf $FILE_NAME.tar.gz $FILE_NAME;
rm $FILE_NAME;
ftp -v -n FTP地址 << END
user FTP用户名 FTP密码
bin
put 本地目录文件 目标路径文件
bye
END
文件名乱码问题可以在行末加“;”来解决赋予执行权限:chmod 777 dotask.sh (ls 命令时呈绿色)
编辑计划任务:crontab -e
crontab 书写规则:
# 分 时 日 月 周 文件路径
0 3 * * * /home/dotask.sh
30 4 * * * /home/dotask2.sh重启 crond:/etc/init.d/crond restart
netstat
netstat -an | grep xxx.xxx.xxx.xxx 可查看此 IP 的 TCP 请求及端口
本文不定时更新中……
具备 RESTful 相关知识会更有利于学习 ASP.NET Web API:RESTful API 学习笔记
ASP.NET Web API 官网:https://www.asp.net/web-api
服务 URI Pattern
| Action | Http verb | URI | 说明 |
| Get contact list | GET | /api/contacts | 列表 |
| Get filtered contacts | GET | /api/contacts?$top=2 | 筛选列表 |
| Get contact by ID | GET | /api/contacts/id | 获取一项 |
| Create new contact | POST | /api/contacts | 增加一项 |
| Update a contact | PUT | /api/contacts/id | 修改一项 |
| Delete a contact | DELETE | /api/contacts/id | 删除一项 |
| 返回类型 | Web API 创建响应的方式 |
|---|---|
| void | 返回空 204 (无内容) |
| HttpResponseMessage | 转换为直接 HTTP 响应消息。 |
| IHttpActionResult | 调用 ExecuteAsync 来创建 HttpResponseMessage,然后将转换为 HTTP 响应消息。 |
| 其他类型 | 将序列化的返回值写入到响应正文中;返回 200 (正常)。 |
HttpResponseMessage
可提供大量控制的响应消息。 例如,以下控制器操作设置的缓存控制标头。
public class ValuesController : ApiController
{
public HttpResponseMessage Get()
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, "value");
response.Content = new StringContent("hello", Encoding.Unicode);
response.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromMinutes(20)
};
return response;
}
}IHttpActionResult
public IHttpActionResult Get (int id)
{
Product product = _repository.Get (id);
if (product == null)
{
return NotFound(); // Returns a NotFoundResult
}
return Ok(product); // Returns an OkNegotiatedContentResult
}其他的返回类型
响应状态代码为 200 (正常)。此方法的缺点是,不能直接返回错误代码,如 404。 但是,您可以触发 HttpResponseException 的错误代码。
完善 Help 页
一般都是通过元数据注释(Metadata Annotations)来实现的描述的。
显示接口和属性的描述:
打开 HelpPage 区域的 App_Start 目录下的 HelpPageConfig.cs 文件,在 Register 方法的首行取消注释行:
config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));
在项目右键属性“生成”页,勾选“XML 文档文件”,并填写与上述一致的路径(App_Data/XmlDocument.xml)。
给接口加上 ResponseType 显示响应描述和示例:[ResponseType(typeof(TEntity))]
在实体模型的属性上加入 RequiredAttribute 特性可提供请求或响应中的实体的属性描述,如:[Required]
推荐使用:Swashbuckle
关于格式
在 WebApiConfig.Register() 中加入以下代码以禁止以 XML 格式输出(请按需设置):
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();Json 序列化去掉 k__BackingField
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver { IgnoreSerializableAttribute = true };如果属性值为 null 则不序列化该属性
config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };前言:
本文适合 6.x 环境,8.x 请结合参考:如何升级 ASP.NET 项目 MySql.Data 和 Connector/NET 至 8.0.x
使用 ASP.NET Core 的同学请移步:ASP.NET Core 使用 DBFirst 模式连接 MySQL 数据库
安装
开发环境
软件安装:
MySQL for Visual Studio - 用于在 Visual Studio 中连接 MySQL 数据库
Connector/NET - ADO.NET 托管提供程序
Nuget 中搜索安装 MySql.Data 和 MySql.Data.Entity
版本选择:
MySQL for Visual Studio 最新版
Connector/NET 版本必须与 MySql.Data 和 MySql.Data.Entity 版本相同,否则会出现 MySql.Data.MySqlClient.MySqlConnection 无法强制转换的错误
生产环境
软件安装:
MySQL Server - 数据库
Connector/NET - ADO.NET 托管提供程序
版本选择:
MySQL Server 最新版
Connector/NET 应与项目中使用的 MySql.Data 和 MySql.Data.Entity 版本一致。(某些项目在确保 Web.config 的 MySql.Data 版本号与 MySql.Data 和 MySql.Data.Entity 版本一致的前提下,允许服务端的 Connector/NET 小版本略低于 MySql.Data 和 MySql.Data.Entity 版本,某些项目允许安装比 MySql.Data 和 MySql.Data.Entity 版本略高的 Connector/NET 版本,为确保不出问题,严格要求版本全部一致)
升级
MySQL for Visual Studio:直接更新至最新版
MySQL Server:直接更新至最新版
MySql.Data 和 MySql.Data.Entity:升级至两者共有的新版本,更改 Web.config 中 MySql.Data 的版本号,并更新开发环境和生产环境的 Connector/NET 至相同版本(详细步骤见下方说明)
Connector/NET:视是否有相同版本的 MySql.Data 和 MySql.Data.Entity,若有,同时升级。(详细步骤见下方说明)
关于 Connector/NET 和 MySql.Data 及 MySql.Data.Entity 版本一致的说明:
某些项目在确保 Web.config 的 MySql.Data 版本号与 MySql.Data 和 MySql.Data.Entity 版本一致的前提下,允许服务端的 Connector/NET 小版本略低于 MySql.Data 和 MySql.Data.Entity 版本;
某些项目允许安装比 MySql.Data 和 MySql.Data.Entity 版本略高的 Connector/NET 版本;
为确保不出问题,严格要求版本全部一致。
但服务器上同时运行多个项目,一旦出现问题涉及面就很广,为了尽量减少影响,列出下面的升级步骤:
升级开发环境的 Connector/NET
升级各项目的 MySql.Data 和 MySql.Data.Entity
更改 Web.config 中关于 MySql.Data 的版本号(若未自动更新,项目中搜索原版本号即可)
测试运行各项目
同时发布各项目,同时升级服务器上的 Connector/NET(升级 Connector/NET 仅需几十秒)
部分项目需要删除并重新上传 bin 目录才能生效
尽管如此,发布成功以后还是会有各种各样的问题导致无法正常打开,须要有针对性地去解决,所以升级还是要趁夜深人静的时候进行
