Magic Columns failed_login_count 有点类似 rails的 created_at updated_at

选项 consecutive_failed_logins_limit

默认是 50

reset 机制

session/base.rb 的验证

      validate :reset_failed_login_count, if: :reset_failed_login_count?

exceeded_failed_logins_limit? 是否超过了最大登录限制

being_brute_force_protected? 这个method可以看到默认是2个小时

https://github.com/binarylogic/authlogic/blob/b204c8dcc01f0047386a7a8cefa671a05c50f6c1/lib/authlogic/session/base.rb#L591-L599

Rails 测试的时候使用 fixture_file_upload 上传文件

  test "all_active_storage_attachments" do
    assert_empty @order.all_active_storage_attachments
    file = fixture_file_upload(Rails.root.join('public', 'apple-touch-icon.png'), 'image/png')
    @order_credit.idcode_front.attach file
    assert_not_empty @order.all_active_storage_attachments
  end

安装依赖

yum install perl-DB perl-DBD-MySQL perl-IO-Socket-SSL perl-Digest-MD5

安装 percona-toolkit-3.0.13-1.el7.x86_64.rpm

rpm -ivh percona-toolkit-3.0.13-1.el7.x86_64.rpm

demo

[root@rails-prod-2 shared]# pt-duplicate-key-checker --host host --ask-pass --databases dbname --user username
Enter password:
*******************************************************************
 Using the default of SSL_verify_mode of SSL_VERIFY_NONE for client
 is deprecated! Please set SSL_verify_mode to SSL_VERIFY_PEER
 possibly with SSL_ca_file|SSL_ca_path for verification.
 If you really don't want to verify the certificate and keep the
 connection open to Man-In-The-Middle attacks please set
 SSL_verify_mode explicitly to SSL_VERIFY_NONE in your application.
*******************************************************************
  at /usr/bin/pt-duplicate-key-checker line 3914.
*******************************************************************
 Using the default of SSL_verify_mode of SSL_VERIFY_NONE for client
 is deprecated! Please set SSL_verify_mode to SSL_VERIFY_PEER
 possibly with SSL_ca_file|SSL_ca_path for verification.
 If you really don't want to verify the certificate and keep the
 connection open to Man-In-The-Middle attacks please set
 SSL_verify_mode explicitly to SSL_VERIFY_NONE in your application.
*******************************************************************
  at /usr/bin/pt-duplicate-key-checker line 3914.

# A software update is available:
# ########################################################################
# shiji_production.admins_roles
# ########################################################################

# index_admins_roles_on_admin_id is a left-prefix of index_admins_roles_on_admin_id_and_role_id
# Key definitions:
#   KEY `index_admins_roles_on_admin_id` (`admin_id`),
#   KEY `index_admins_roles_on_admin_id_and_role_id` (`admin_id`,`role_id`),
# Column types:
#	  `admin_id` bigint(20) default null
#	  `role_id` bigint(20) default null
# To remove this duplicate index, execute:
ALTER TABLE `shiji_production`.`admins_roles` DROP INDEX `index_admins_roles_on_admin_id`;

# ########################################################################
# shiji_production.partner_users
# ########################################################################

# index_partner_users_on_partner_id is a left-prefix of index_partner_users_on_partner_id_and_user_id
# Key definitions:
#   KEY `index_partner_users_on_partner_id` (`partner_id`),
#   UNIQUE KEY `index_partner_users_on_partner_id_and_user_id` (`partner_id`,`user_id`),
# Column types:
#	  `partner_id` bigint(20) default null
#	  `user_id` bigint(20) default null
# To remove this duplicate index, execute:
ALTER TABLE `shiji_production`.`partner_users` DROP INDEX `index_partner_users_on_partner_id`;

# ########################################################################
# shiji_production.roles
# ########################################################################

# index_roles_on_name is a left-prefix of index_roles_on_name_and_resource_type_and_resource_id
# Key definitions:
#   KEY `index_roles_on_name` (`name`)
#   KEY `index_roles_on_name_and_resource_type_and_resource_id` (`name`,`resource_type`,`resource_id`),
# Column types:
#	  `name` varchar(50) default null
#	  `resource_type` varchar(50) default null
#	  `resource_id` bigint(20) default null
# To remove this duplicate index, execute:
ALTER TABLE `shiji_production`.`roles` DROP INDEX `index_roles_on_name`;

# ########################################################################
# Summary of indexes
# ########################################################################

# Size Duplicate Indexes   2164781
# Total Duplicate Indexes  3
# Total Indexes            341

VMware Fusion 作为虚拟机管理程序

安装 kubectl

https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-on-macos

命令行工具 kubectl 可以对Kubernetes集群进行操作

brew 安装

brew install kubernetes-cli

安装 minikube

brew cask install minikube

启动 minikube 创建集群

minikube start

使用 vmwarefusion

minikube --vm-driver=vmwarefusion --loglevel 2 start

默认是 virtualbox

--vm-driver string                VM driver is one of: [virtualbox xhyve vmwarefusion] (default "virtualbox")

部署 echoserver

部署 一个简单的http server echoserver

$ kubectl run hello-minikube --image=k8s.gcr.io/echoserver:1.10 --port=8080
deployment.apps/hello-minikube created

要访问hello-minikue, 发布服务

选项--type=NodePort指定服务的类型

kubectl expose deployment hello-minikube --type=NodePort

hello-minikube Pod现已启动,但必须等到Pod启动才能通过公开的服务访问它 查看状态 kubectl get pod

获取公开的服务的URL以查看服务详细信息:

地址 http://172.16.105.133:32374

测试nginx

可以访问了

dashboard

minikube dashboard

删除service

 kubectl delete services nginx-minikube
 kubectl delete deployment nginx-minikube

把一台x86的闲置台式机安装了lede路由系统做软路由

终于把去年买好的网卡用上了!!!

openwrt 安装记录

下载地址

http://firmware.koolshare.cn/LEDE_X64_fw867/

combined和 uefi-gpt 两种,前者支持MBR的分区表和BIOS系统,后者支持GPT 分区表和EFI系统

我用的 combined 的 固件

mac或者linux直接用dd写入磁盘就行

下载解压

使用dd 写到硬盘

sudo dd if=./openwrt-koolshare-mod-v2.31-r10822-50aa0525d1-x86-64-combined-squashfs.img   of=/dev/disk2

配置网络tips

外网不能访问, 需要配置下防火墙

openwrt 配置 Portainer 管理 docker记录

LEDE酷软里安装docker 插件, 一个简单的管理docker的管理工具, 不太好用, 看了下可以尝试 Portainer 来管理

Portainer 概述 * [GitHub] https://github.com/portainer/portainer * [Doc] https://portainer.readthedocs.io/en/stable/

配置

这个插件的容器管理有问题, 直接 ssh或者使用 Shellinabox

 docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/mnt/sda3/portainer_data portainer/portainer

/mnt/sda3/portainer_data 是数据目录

容器已经跑起来了

root@Openwrt:/mnt/sda3# docker ps
CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS              PORTS                    NAMES
f3d7ef5f222b        portainer/portainer   "/portainer"        5 seconds ago       Up 4 seconds        0.0.0.0:9000->9000/tcp   epic_shaw

可以进入portainer配置了

选择对 宿主机的docker进行管理

Portainer 界面

https://docs.sentry.io/workflow/integrations/global-integrations/#commit-tracking-4

关于 Releases

https://docs.sentry.io/workflow/releases/?platform=php#create-deploy

如果配置了releases版本, 会有额外的功能

配置发布版本

  1. 在项目sdk配置
  2. 在sentry上创建 releases 版本, 关联 commits
  3. 部署是通知 sentry

ruby sdk release 配置

Create Release and Associate Commits

这一步告诉sentry 这个release 有哪些commit

有两步

  • Organization Settings > Integrations. 配置 gitab 集成
  • 部署的时候告诉sentry 部署了啥, 有哪些commit, 可以用 sentry-cli工具

在gitlab ci 的配置示例

官方 sentry-cli 文档 https://docs.sentry.io/workflow/releases/?platform=php#associate-commits-with-a-release

sentry_commmit_tracking:
  stage: after_deploy
  image: getsentry/sentry-cli
  dependencies:
    - staging_deploy
    - prod_deploy
  script:
    - echo "Sentry Commit Tracking"
    - export SENTRY_URL=https://sentry.shijiplus.com/
    - export SENTRY_AUTH_TOKEN=6db606dd59314e379f65c5d98751e365b6951f8bb79a40a48eda1e17710e4c0c
    - export SENTRY_ORG=sentry
    - export SENTRY_PROJECT=laiwang-backend
    - sentry-cli releases new $CI_COMMIT_SHA
    - sentry-cli releases set-commits --auto $CI_COMMIT_SHA
    - echo $CI_COMMIT_REF_NAME
    - if [[ "$CI_COMMIT_REF_NAME" == "devel" ]] ; then export RAILS_ENV=staging; else export RAILS_ENV=production; fi
    - sentry-cli releases deploys $CI_COMMIT_SHA new -e $RAILS_ENV
  only:
    - master
    - devel

也可以使用api的方式

# Create a new release
curl https://sentry.io/api/0/organizations/:organization_slug/releases/ \
  -X POST \
  -H 'Authorization: Bearer {TOKEN}' \
  -H 'Content-Type: application/json' \
  -d '
 {
 "version": "2da95dfb052f477380608d59d32b4ab9",
 "refs": [{
 "repository":"owner-name/repo-name",
 "commit":"2da95dfb052f477380608d59d32b4ab9",
 "previousCommit":"1e6223108647a7bfc040ef0ca5c92f68ff0dd993"
 }],
 "projects":["my-project","my-other-project"]
}

新版本创建部署提醒

错误

ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib/x86_64-linux-gnu/mariadb18/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory

mysql 5.7 到 mysql 8 不在默认使用 mysql_native_password

添加参数--default-authentication-plugin=mysql_native_password

test:
  stage: test
  services:
    - name: mysql:8
      command: ["mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci", "--default-authentication-plugin=mysql_native_password"]

知识点

  • schema
  • types
  • Queries
  • Mutations
  • Subscriptions

schema

Schema Definition Language (SDL)

type Query {
  hello: String
}

Types

比如 Posts, Users, Likes, Groups 类型有 fields,比如 User 类型有 username email age

type User {
  id: ID!
  name: String!
  email: String!
  age: Int
}

! 表示这个field是 non-nullable 表示不可以为空 User类型可以为空的只有age

  • queries
  • mutations
  • subscriptions

Queries

GraphQL如何知道从哪获取数据呢? resolvers.js 处理怎么获取数据的问题

import { users } from "./db";

const resolvers = {
  Query: {
    user: (parent, { id }, context, info) => {
      return users.find(user => user.id === id);
    },
    users: (parent, args, context, info) => {
      return users;
    }
  }
};

export default resolvers;

query

query {
  users {
    id
    name
    email
    age
  }
}

有参数 单个user


query {
  user(id: 1) {
    id
    name
    email
    age
  }
}

Mutations

用于修改数据

便写 mutations 类型

schema.graphql

type Mutation {
  createUser(id: ID!, name: String!, email: String!, age: Int): User!
  updateUser(id: ID!, name: String, email: String, age: Int): User!
  deleteUser(id: ID!): User!
}

schema 有点想路由

Mutation 定义

  Mutation: {
    createUser: (parent, { id, name, email, age }, context, info) => {
      const newUser = { id, name, email, age };

      users.push(newUser);

      return newUser;
    },
    updateUser: (parent, { id, name, email, age }, context, info) => {
      let newUser = users.find(user => user.id === id);

      newUser.name = name;
      newUser.email = email;
      newUser.age = age;

      return newUser;
    },
    deleteUser: (parent, { id }, context, info) => {
      const userIndex = users.findIndex(user => user.id === id);

      if (userIndex === -1) throw new Error("User not found.");

      const deletedUsers = users.splice(userIndex, 1);

      return deletedUsers[0];
    }
  }

操作

mutation {
  createUser(id: 3, name: "Robert", email: "robert@gmail.com", age: 21) {
    id
    name
    email
    age
  }
}
mutation {
  deleteUser(id: 3) {
    id
    name
  }
}

Subscriptions

As I said before, subscriptions are the way you’re going to maintain a real-time connection with a server

维护实时连接到服务器, 客户端获得实时的数据更新

subscription {
  users {
    id
    name
    email
    age
  }
}

more https://hackernoon.com/from-zero-to-graphql-subscriptions-416b9e0284f3

实在搞不懂 为啥 rvm 把我 shell 搞的这么慢

remove:

$ rvm implode

换成chruby + ruby-install 的方案

fish shell 配置 RUBIES

~/.config/fish/config.fish

set -x RUBIES $RUBIES ~/.rubies/*