豪翔天下

Change My World by Program

0%

基本命令

  • npm install -g cordova ios-deploy
  • 如果要运行在xcode需要用xcode打开项目名.xcworkspace文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 创建工程
cordova create 目录名 com.haofly.mobile 应用名

# 平台管理
cordova platform add ios
cordova platform add android
cordova platform list # 列出当前添加了的平台
cordova platform rm android

# 编译运行,如果更新了www目录,可以直接重新build即可
cordova build # 编译所有平台
cordova build android # 仅编译指定平台,这条命令相当于cordova prepare android && codova compile android
cordova emulate ios # 启动模拟器
cordova run browser # 在指定平台运行

# 插件管理
cordova prepare # 复制assets中的文件到平台中去
cordova requirements # 检查依赖关系
cordova plugin search facebook # 搜索插件
cordova plugin ls # 列出当前已安装的插件
cordova plugin rm cordova-plugin-facebook4 # 移除插件
cordova plugin add cordova-plugin-facebook4 # 添加插件
corodva plugin add https://github.com/myproject#branch_name # 从github安装指定分支的cordova插件
阅读全文 »

后台配置

  • 配置是否需要用户登陆Settings->Checkout ->Customer accounts,如果用户登陆是可选的,那么可以做一个Continue as Guest按钮

Shopify前端开发

  • shopify的搜索功能无法做更多自定义,但是他们的搜索匹配方式有点奇怪,很多时候不能搜到我们想要的东西,不用去想了,没有解决方案

命令行工具

1
2
theme download	# 将shpify那边的主题文件同步到本地
theme watch # 监听本地文件改动,如果有改动会自动上传上去

Liquid手册

  • 因为是后端渲染的,不要尝试在liquid里面获取query参数(js除外),但是shopify的语法里有些方法可以获取到product/variant等参数的

模板结构

  • templates/index.liquid就是首页了
阅读全文 »

安装

  • Releases Note,他们的源代码没有在github上

  • 因为我目前使用的是付费的,所以是把Nova目录直接放到了根目录,升级的时候只需要在后台重新下载一个包覆盖即可

  • 安装步骤:和普通的包安装方式不一样,因为需要购买license,商用$199/project

资源

  • php artisan nova:resource Post生成资源管理类,一般和Model名一样即可
阅读全文 »

  • 每月1万分钟的免费额度,可以说相当不错的了

生成token

  • 无论是主持人还是用户还是录制UID进入频道前都需要先生成一个token
  • token的生成方式点击标题即可,里面有各种语言生成token的方式
  • 生成token必须提供一个UID,得自己找办法和数据库中原有的用户关联
  • token相关错误码

服务端

  • 服务端的Restful API都有频率限制且阈值并不高,这是官方提供的超出频率限制解决方法,可以参考一下,之前我以为hook能够帮助我减少很多请求,但发现并不如我的预期,主要是实效和顺序性的问题
阅读全文 »

最近在学习AWS的Redshift,它是基于PostgreSQL的,顺便学习下。

安装PostgreSQL

1
2
3
4
5
6
sudo apt-get install -y postgresql	# 安装后默认就启动了的
sudo apt-get install -y postgresql-client postgresql-client-common # 安装命令行客户端

# 完整卸载postgresql
sudo systemctl stop postgresql # 注意如果已经启动了postgresql必须在重装前将其停止,否则5432端口被占用后重新安装的实例默认会是5433端口
sudo apt-get --purge remove postgresql\* -y && sudo rm -rf /etc/postgresql-common/ && sudo rm -rf /etc/postgresql/

配置

  • 默认端口为5432,默认用户名为postgres
  • Mysql安装postgres命令行工具pg_dump等: brew install libpq
  • 配置文件默认在: /etc/postgresql/{version}/main/postgresql.conf,配置文件修改后需要重启sudo systemctl restart postgresql
    • 监听0.0.0.0,需要修改listen_addresses = 'localhost'为listen_addresses = '*'

系统表

  • pg_class: 记录数据库中的表,索引及视图
  • pg_namespace: 记录数据库中的名字空间
  • pg_attribute: 记录数据库中表的字段的详细信息。(attname字段名字,atttypid字段类型id,attlen字段长度,attnotnull)
  • pg_type: 记录数据库中所有的数据类型
  • pg_description: 记录数据库中对象的注释(表以及字段)。(objoid对象ID,objsubid字段号,description描述)
阅读全文 »

官方文档

使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var swiper = new Swiper('.swiper-container', {
slidesPerView: 'auto', // 每一页的slide数量自动确定,这样可以做到不用整数个显示,也不会导致左右空白
spaceBetween: 10, // 每两个slide之间的间隔
centeredSlides: false, // 不用从居中开始,否则左边是空白的
pagination: {
el: '.swiper-pagination', // 分页元素位置
clickable: true,
},
direction: 'vertical', // horizontal滚动方向
width: 500, // 设置slide的高度和宽度,单位职能是px
height: 500,
breakpoints: { // 可以自定义不同的breakpoints里面的不同参数
1280: { // 屏幕宽度>=1280时候的breakpoings
width: 1000,
height: 1000,
direction: 'vertical', // 任何参数都可以breakpoint
}
}
scrollbar: {
el: '.swiper-scrollbar', // scrollbar的位置
clickable: true,
hide: true
},
navigation: { // 指定翻页按钮
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
on: { // 使用对应的事件
afterInit: function () {}
activeIndexChange: function () {}, // 这个事件触发时active图片还没改变
slideChange: function() {}, // 这个事件触发时图片就改变了
slideChangeTransitionEnd: function() {}, // 感觉这个方法才是真正的改变完成了
}
});
阅读全文 »

安装

1
pip install django-celery-beat

配置

  1. settings.py中添加如下配置
1
2
3
4
5
6
7
8
9
10
INSTALLED_APPS = (
...,
'django_celery_beat',
)

CELERY_BROKER_URL = 'sqla+sqlite:///' + os.path.join(BASE_DIR, 'db.sqlite3')
CELERY_IMPORTS = ['schedules'] # 指定需要在哪些目录扫描定时任务,如果不添加则会出现 Received unregistered task of type 错误
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'
CELERY_RESULT_BACKEND = 'django-db' # 这是下面的django-celery-results保存结果使用的
  1. 使用命令python manage.py migrate创建数据库迁移,会生成这几张表:
1
2
3
django_celery_beat.models.PeriodicTask # 周期性任务
django_celery_beat.models.IntervalSchedule # 间隔性任务
django_celery_beat.models.CrontabSchedule # 定时任务
  1. 创建启动文件,在manage.py所在目录创建一个启动文件celery.py:
1
2
3
4
5
6
7
8
9
10
import os

from celery import Celery

from life_console import settings

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "项目名.settings")
celery_app = Celery("项目名", broker=settings.CELERY_BROKER_URL)
celery_app.config_from_object("django.conf:settings", namespace="CELERY")
celery_app.autodiscover_tasks()
阅读全文 »

本来以为现在写去年的年终总结已经太晚了,可是copy去年的总结的时候发现去年是2月19日写的,还不算太晚,毕竟今年比去年更忙。

Ok,接下来是每年的总结及计划模版。

2020总结

这是2020年初列的计划

阅读全文 »

  • Aws的密钥只能下载一次,下载后请小心保存
  • AWS的命令行或者代码的环境变量是: AWS_ACCESS_KEY_ID(或AWS_ACCESS_KEY)/AWS_SECRET_ACCESS_KEY(或AWS_SECRET_KEY)/AWS_DEFAULT_REGION/AWS_REGION,除了放到环境变量,它一般也可以存储在~/.ssh/aws/credentials文件里

EC2

  • ubuntu系统默认用户为ubuntu,amazon系统默认的用户名为ec2-user
  • 默认会有12个月750小时的免费套餐,但是仅限个别低配类型
  • 要想查看在所有region下的所有的ec2实例,可以在VPC dashboard中查看,Running Instances -> See all regions
  • EC2实力类型列表,注意t2、t3是突发性能实例,CPU的使用采用积分制(CPU credits),如果某一时间发现CPU不行或者网站很卡,有可能是因为CPU资源无法使用了,这种情况要么等积分恢复,要么升级实例

如何删除EC2实例

  • 先选中要删除的实例,Stop,再Terminate(终止实例),这个时候虽然实例还在,但其实已经删除了,大概等个10分钟左右就没了

EC2实例升级/修改实例类型

  • IP会变更,请注意是否启用弹性IP或者负载均衡器
  • 关机,需要接近一分钟
  • 操作->实例设置->更改实例类型
  • 开机

EC2实例扩容

关机扩容

  1. 关机扩容很简单,但是IP会变更,请注意是否启用弹性IP或者负载均衡器
  2. 首先关机Actions -> Instance State -> Stop
  3. 进入卷管理: Elastic Block Store -> Volumes
  4. 选择需要更改的磁盘: Modify Volume,然后输入大小
  5. 重启实例,并进入终端
  6. 使用df -h查看当前磁盘容量

不关机扩容

  1. 在实例详里面找到root volumn,进入volumn详情

  2. Actions -> Modify Volume,输入扩容后的大小点击确定

  3. 进入实例,此时用df -h查看依然是原来的大小,使用lsblk命令可以查看有新的大小,该命令用于查看是否具有必须扩展的分区,例如:

    1
    2
    xvda    202:0    0   30G  0 disk
    └─xvda1 202:1 0 20G 0 part / # df -h只能看到这个分区
  4. 执行扩容命令

    1
    2
    3
    4
    5
    6
    # 有时候lsblk看到的磁盘名称和df -h显示的磁盘名称不一致,没关系,下面的命令按照lsblk的来就行

    sudo growpart /dev/xvda 1
    lsblk # 验证xvda1的大小是否已经变化,不过此时用df -h依然看不出变化

    sudo resize2fs /dev/xvda1 # 此时用df -h就能看到变化了,扩容过程也完成了

EC2增加磁盘

  • 步骤

    1. 创建卷

    2. 操作->连接卷,默认会挂载到/dev/sdf

    3. 进入实例,执行lsblk可以看到附加的卷(磁盘)

    4. 新卷默认是没有文件系统的,可以这样确定:

      1
      2
      sudo file -s /dev/xvdf # 如果输出是/dev/xvdf: data表示没有文件系统
      sudo mkfs -t xfs /dev/xvdf # 创建文件系统,如果找不到mkfs命令,可以安装xfsprogs
    5. 挂载

      1
      2
      3
      sudo mkdir /data	# 创建挂载点
      sudo mount /dev/xvdf /data # 挂载
      df -h # 确认是否挂载成功

Ec2绑定Elastic IP弹性IP

  • 弹性IP只要是绑定在运行中的ec2实例上就是免费的,所以如果仅仅是要一个不会随着机器状态变化的IP那么推荐用弹性IP而不是用负载均衡器
  • 当一个新建的弹性IP被关联到一个实例上的时候,该实例的公有IP地址也会变成一样的,不过之后如果实例重启公有IP会改变,弹性IP则不会了
  • 一个账号最多绑定5个弹性IP,超过了需要单独提交申请,所以有时候还是用elb代替吧

安全组

  • 注意如果安全组的target设置为另外一个安全组,那么在访问另外一个安全组的实例的时候不能使用外网IP,只能用内网IP才行

EC2配置Cloudwatch监控

添加自定义指标

阅读全文 »

Model定义

  • 如果不定义collection的名称,mongoose会自动将Model名转换为小写复数形式作为collection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import mongoose from 'mongoose';
var Schema = mongoose.Schema;

var UserSchema = new Schema(
{
name: String,
is_active: {
type: Boolean,
default: false
},
created_at: {
type: Date,
default: Date.now
},
friends: [{ // 可以直接用.populate查出关联对象
type: Schema.Types.ObjectId,
ref: 'User'
}],
father: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
meta: Object,
meta1: { // 也可以这样定义Object
name: String,
age: Number
},
tags: {
type: [String],
index: true // 定义某个字段为索引
}
}, {
collection: "自定义collection名称",
toJSON: {virtuals: true},
toObject: {virtuals: true}
}
)
UserSchema.index({name: 1, type: -1}); // 在最后指定索引

// 给Model添加查询帮助方法
UserShchema.query.byName = function(name) {
return this.where({ name: new RegExp(name, 'i')})
};
UserSchema.find().byName('name').exec((err, animals) => {});

// 给实例添加自定义的方法
UserSchema.methods.myFunc = function() {
mongoose.model('UserSchema') // 在实例定义里面可以通过这个方法获取Schema Model
return this // this就是该实例本身
}

// 给Model添加静态方法
UserSchema.statics.findByName = function(name) {
return this.find({name: new RegExp(name, 'i')});
}
// 或者这样定义,不要用ES6里面的=>,因为用=>无法通过this获取到Schema
UserSchema.static('findByName', function(name) { return ... });
const user = await UserSchema.findByName('name')

export default mongoose.model('User', UserSchema);

// 甚至可以不定义每个字段,直接用
mongoose.model('User', new Schema(), 'UserSchema');
阅读全文 »