博客 (12)

客户端:Failed to connect to host.

服务端:无任何日志

原因:可能是域名、IP 或端口有误,或端口未开放。


客户端/服务端:530 Login incorrect.

原因:用户名或密码错误。


客户端/服务端503 Use AUTH first.

原因:服务端开启了 FTPS 协议(FTP over TLS),且禁止了 FTP 协议(plain FTP)。

解决方法:不建议服务端恢复不安全的 FTP 协议,客户端应配置 client.Config 的 EncryptionMode、DataConnectionEncryption、SslProtocols、ValidateCertificate 等参数。


客户端/服务端:530 This server does not allow plain FTP. You have to use FTP over TLS.

原因:服务端启用了 FTPS。

解决方法:给 client.Config.EncryptionMode 正确的赋值(FtpEncryptionMode.Explicit 或 FtpEncryptionMode.Auto)。


服务端:[Error] TLS session of data connection not resumed.

原因:证书版本有误。

解决方法:给 client.Config.SslProtocols 赋值正确的 TLS 版本。


服务端:521 PROT P required

原因:服务端开启了Require TLS session resumption on data connection when using PROT P”

解决方法:client.Config.DataConnectionEncryption = true;


客户端/服务端450 TLS session of data connection has not resumed or the session does not match the control connection

原因:TLS 与控制连接不匹配,即服务端开启了“Require TLS session resumption on data connection when using PROT P”

解决方法:我暂时还不知道原因,临时关闭了Require TLS session resumption on data connection when using PROT P”(不建议)。该问题出现在 FileZilla Server 0.x 版本,在 1.x 版本中没有该配置选项。

xoyozo 6 个月前
690

ASP.NET MVC 使用 Authorize 过滤器验证用户登录。Authorize 过滤器首先运行在任何其它过滤器或动作方法之前,主要用来做登录验证或者权限验证。

示例:使用 Authorize 过滤器实现简单的用户登录验证。

1、创建登录控制器 LoginController

/// <summary>
/// 登录控制器
/// </summary>
[AllowAnonymous]
public class LoginController : Controller
{
    /// <summary>
    /// 登录页面
    /// </summary>
    public ActionResult Index()
    {
        return View();
    }
 
    /// <summary>
    /// 登录
    /// </summary>
    [HttpPost]
    public ActionResult Login(string loginName, string loginPwd)
    {
        if (loginName == "admin" && loginPwd == "123456")
        {
            // 登录成功
            Session["LoginName"] = loginName;
            return RedirectToAction("Index", "Home");
        }
        else
        {
            // 登录失败
            return RedirectToAction("Index", "Login");
        }
    }
 
    /// <summary>
    /// 注销
    /// </summary>
    public ActionResult Logout()
    {
        Session.Abandon();
        return RedirectToAction("Index", "Login");
    }
}

注意:在登录控制器 LoginController 上添加 AllowAnonymous 特性,该特性用于标记在授权期间要跳过 AuthorizeAttribute 的控制器和操作。

2、创建登录页面

@{
    ViewBag.Title = "登录页面";
    Layout = null;
}
 
<h2>登录页面</h2>
 
<form action='@Url.Action("Login","Login")' id="form1" method="post">
    用户:<input type="text" name="loginName" /><br />
    密码:<input type="password" name="loginPwd" /><br />
    <input type="submit" value="登录">
</form>

效果图:

3、创建主页控制器 LoginController

public class HomeController : Controller
{
    public ActionResult Index()
    {
        // 获取当前登录用户
        string loginName = Session["LoginName"].ToString();
        ViewBag.Message = "当前登录用户:" + loginName;
        return View();
    }
}

4、创建主页页面

@{
    ViewBag.Title = "Index";
    Layout = null;
}
 
<h2>Index</h2>
<h3>@ViewBag.Message</h3>
<a href="@Url.Action("Logout","Login")">注销</a>

效果图:

5、创建授权过滤器 LoginAuthorizeAttribute 类

创建 Filter 目录,在该目录下创建授权过滤器 LoginAuthorizeAttribute 类,继承 AuthorizeAttribute。

using System.Web.Mvc;
 
namespace MvcApp.Filter
{
    /// <summary>
    /// 授权过滤器
    /// </summary>
    public class LoginAuthorizeAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            // 判断是否跳过授权过滤器
            if (filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true)
               || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true))
            {
                return;
            }
 
            // 判断登录情况
            if (filterContext.HttpContext.Session["LoginName"] == null || filterContext.HttpContext.Session["LoginName"].ToString()=="")
            {
                //HttpContext.Current.Response.Write("认证不通过");
                //HttpContext.Current.Response.End();
 
                filterContext.Result = new RedirectResult("/Login/Index");
            }
        }
    }
}

通常 Authorize 过滤器也是在全局过滤器上面的,在 App_Start 目录下的 FilterConfig 类的 RegisterGlobalFilters 方法中添加:

using System.Web;
using System.Web.Mvc;
using MvcApp.Filter;
 
namespace MvcApp
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
 
            // 添加全局授权过滤器
            filters.Add(new LoginAuthorizeAttribute());
        }
    }
}

Global.asax 下的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
 
namespace MvcApp
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
}


xoyozo:暂时没有按区域(Area)来统一配置的方法,建议加在 Controller 上。https://stackoverflow.com/questions/2319157/how-can-we-set-authorization-for-a-whole-area-in-asp-net-mvc


p
转自 pan_junbiao 4 年前
2,838

前提:

若需获取用户 unionid,则小程序必须已绑定到微信开放平台。


  1. 小程序调用 wx.login(),将 code 发送到开发者服务器

  2. 开发者服务器请求微信接口 code2Session,获得 session_keyopenid,有机会获得 unionid参 UnionID 机制说明)。因此无需任何用户授权即可获取 openid

  3. 访问须要已获取用户信息的页面时,可通过小程序端使用 button + getUserInfo 的方式请求用户授权

  4. 访问须要已获取手机号码的页面时,可通过小程序端使用 button + getPhoneNumber 的方式请求用户授权

  5. code2session、getUserInfo、getPhoneNumber 等接口返回数据存入数据库 dt_weapp_user

  6. 服务端的任何接口均返回口令状态包(含自定义会话口令等信息),小程序端应保存于 storage

  7. 请求 getUserInfo 后应判断 detail.errMsg 是否为 getUserInfo:ok,请求 getPhoneNumber 后应判断 detail.errMsg 是否为 getPhoneNumber:ok

  8. 授权窗口的弹出情况此文

  9. 口令状态包是用来传递到客户端用来标识用户唯一凭证的,包含字段:会话口令(自定义用户凭证)、会话口令有效时间(秒)、是否已获取 unionid 或昵称(视业务需求)、是否已获取手机号码uid(可选),以及其他用来标识业务身份字段。服务端可根据会话口令从数据库中获取该用户的所有已知信息。

    一般情况下,当已获取手机号码时,uid 必有值,否则,uid 必为空。因此 uid 不是必须传递到客户端的。

    通过 code2Session 获得的 session_key、以及 openidunionid手机号码等机密信息不允许包含在口令状态包中并缓存在客户端,客户端需要用到手机号码时单独调用接口获取。

  10. 若业务不要求以手机号码作为用户唯一标识,那么口令状态包中不需要包含是否已获取手机号码,仅 uid 即可。在客户端访问须要业务用户登录的页面时,也仅判断 uid 有值即可。


流程图:


微信小程序授权登录获取 unionid、用户信息流程.png


为更好地适应 2017.7.19 发布的《小程序内用户帐号登录规范调整和优化建议》开发者服务器提供的所有业务逻辑接口的返回值中都应包含口令状态包,约定有以下相关的返回值和处理动作(返回值按个人喜好来定):

口令状态接口返回ASP.NET Web API 语句处理动作
access_token 空或失效401 状态码return Unauthorized();login() + code2Session,获取 openid,生成 access_token
access_token 有效,但未获取 uniond 或用户信息401 状态码,http 头 WWW-Authenticate 中标注 getUserInforeturn Unauthorized(new AuthenticationHeaderValue("getUserInfo"));getUserInfo()
access_token 有效,但未获取手机号码(即未找到业务用户)401 状态码,http 头 WWW-Authenticate 中标注 getPhoneNumberreturn Unauthorized(new AuthenticationHeaderValue("getPhoneNumber"));getPhoneNumber()
xoyozo 5 年前
8,065

【推荐】临时口令和会话口令合二为一的流程(适合随时授权)


前提:

小程序已绑定到微信开放平台。


分两种场景:

场景一:仅需要获取 unionid,且不需要获取头像昵称等用户信息,且已经有很大部分用户仅通过 code2Session 就能获取到 unionid(如:已关注了绑定同一微信开放平台的其它公众号,参 UnionID 机制说明);

场景二:仅需要获取 unionid,或需要获取 unionid 及头像昵称等用户信息,或很大部分用户不能通过 code2Session 获取到 unionid。


场景一步骤:

  1. 小程序调用 wx.login(),将 code 发送到开发者服务器

  2. 开发者服务器请求微信接口 code2Session,获得 session_key、openid,有机会获得 unionid

  3. 若没有返回 unionid,尝试用 openid 从数据库中获取 unionid

  4. 如果数据库中没有找到对应的 unionid,告知小程序端使用 button + getUserInfo 的方式请求用户授权

  5. 授权允许(判断 detail.errMsg 是否为 getUserInfo:ok)则将加密数据传回开发者服务器进行解密,得到 unionid、头像、昵称等信息,保存到数据库

  6. 若授权拒绝,则无动作,用户再次点击 button 会重新弹起授权框

* 该流程仅部分用户的首次使用才要求授权。其它注意事项和流程细节见下方流程图。


场景二步骤:

  1. 小程序调用 wx.login(),将 code 发送到开发者服务器

  2. 开发者服务器请求微信接口 code2Session,获得 session_key、openid

  3. 尝试用 openid 从数据库中获取 unionid 和/或 用户信息

  4. 如果数据库中没有找到对应的 unionid 和/或 用户信息,告知小程序端使用 button + getUserInfo 的方式请求用户授权

  5. 授权允许(判断 detail.errMsg 是否为 getUserInfo:ok)则将加密数据传回开发者服务器进行解密,得到 unionid、头像、昵称等信息,保存到数据库

  6. 若授权拒绝,则无动作,用户再次点击 button 会重新弹起授权框

* 该流程仅每个用户的首次使用才要求授权。其它注意事项和流程细节见下方流程图。


上述两种场景的设计流程,只要数据库中已保存用户的 unionid(和/或 用户信息),都不再需要用户再次授权(即使在“设置”中关闭了“用户信息”授权,点击小程序右上角三点按钮,选择关于小程序,点击右上角的三点,选择设置)。


场景一流程图:

微信小程序授权登录获取 unionid(仅部分用户的首次使用才要求授权).png

场景二流程图:

微信小程序授权登录获取 unionid、头像昵称等(仅首次使用才要求授权).png


流程图中的“临时口令”仅用于关联“通过 code2Session 获得的 session_key”,并在用户授权后带回换取 session_key。原因是 session_key 是机密数据,不允许被传到小程序端。临时口令用完即删(设置表 dt__weapp_code2session 中相应记录的该字段为空)。


【推荐】临时口令和会话口令合二为一的流程(适合随时授权)

xoyozo 5 年前
10,464

微信小程序 login 后,在用 code 换 session 时,如果小程序绑定了微信开放平台,应该会返回 unionid。

文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/code2Session.html

但实际上部分用户仍然是没有 unionid 的,把上述接口返回的数据记录下来如:

image.png

仔细阅读官方 UnionID 机制说明,通过用户授权 wx.getUserInfo 才会保证有 unionid 返回,否则只会在“用户关注了绑定同一微信开放平台的同主体的公众号”等情况下才会返回 unionid。


确保获取 unionid 流程参此文

xoyozo 5 年前
6,538

常用获取英文的方法是查看英文版 App。


微信:WeChat

小程序:Mini Programs

公众号:Official Accounts

订阅号:Subscriptions

朋友圈:Moments

已登录的:Logged

服务通知:Service Messages

置顶:Sticky on Top / Remove from Top

发送给朋友:Share to Friends

微信号:WeChat ID

钱包:Wallet

余额:Balance

资金/零钱/基金:Funds

金额:Amount

明细:Details

账单:Transactions

资产:Assets

收入/收益:Income

财富:Fortune

登录:Log In / Login

退出登录:Log Out / Logout

xoyozo 5 年前
4,675

本文作为 多平台用户登录模块设计 的扩展设计,即以手机号作为用户的唯一凭证。


官方文档的小程序登录时序:
https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html



(图片摘自 2018.10.30)


session_key 是密钥,仅保存于开发者服务器,用于将小程序通过前端接口获取到的数据解密来验证其真实性。详见 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html


小程序与服务器是通过自定义登录态来识别用户身份的,以下简称口令(token)。


由于微信未告知 session_key 的有效期,那么为保证小程序发起业务请求成功,token 须要永久有效,但这会带来安全隐患。

如果设置 token 的有效期(如 7200 秒),那么小程序发起业务请求后,服务器必须把 token 的验证结果告知小程序,若失效则重新登录。


微信授权登录(含绑定手机号码)流程图

1.png


子流程:授权登录

2.png


子流程:绑定手机号

2.png


为保证数据安全,针对每个须要授权登录的业务请求,服务器都都会检验 token 的有效性。如果小程序同时发起多个业务请求,并几乎同时收到 token 过期,那么会同时发起多个重新登录流程,服务器多次 code2Session,重新生成多个 token 返回到小程序,那么小程序最终保存的 token 可能不是服务器上认为的最新的一个 token。这样,如果程序设计为获取到 token 继而重新发起业务请求,可能会进入死循环。解决的方法是在同时发起多个业务请求之前先向服务器验证一次 token 的有效性,再发起多个业务请求时就不会出现都过期的情况了。

查看详细的短信验证码登录或绑定流程

xoyozo 6 年前
16,206

本文不定时更新中……

收集了一些在开发过程中遇到的一些问题的解决方法,适合新手。


异常:

出现脚本错误或者未正确调用 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

填坑:待填


xoyozo 6 年前
16,583

〓 系统

功能命令--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
查看进程psaux
-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 源文件 目标文件
移动文件mvmv 一个或多个文件 目标目录
下载文件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示例
tartar-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 spooluserdel 用户
添加用户组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 请求及端口

xoyozo 6 年前
5,316

附加消息:暂无该开发者或未上传过应用

原因: 没有上架应用(隐藏的不算上架),应用设置显示后记得在版本管理中将版本也设为显示。


附加消息:抱歉,开发者验证无效

原因:可能是没有达到认证要求,不允许加群(譬如:需应用最低总安装量 1000 次)


DZ 水很深,慎入:http://open.discuz.net/?ac=document&page=xootan


2018.8.14 踩坑:

还有,加群要开发者中填写的 QQ 才能加,因为验证是全自动程序判断的。

如果要跳过安装量 1000 次的要求,就直接花钱购买会员,不过购买会员也是一件非常艰难的事情,在与“Q群管家”这个机器人 QQ 的对话中发送“@购买vip”,绝对能让你体验到一种有钱也花不出去的感受。

做这么多花哨的东西,不如踏踏实实把产品做好。


2018.8.15 踩坑:

跟Q群管家对话,@login 时,由于密码过于复杂,消息没反应,特殊符号别提了,连纯大小写字母数字也不行,后改成纯数字密码登录成功。

加群完全看基本信息中填写的 QQ 客服 号,群主是机器人,只要应用是上架显示的,版本是显示的,就可以用这个QQ客服申请入群,(可以改)。

xoyozo 6 年前
3,216