NestJS 6.x折騰記- (0) 開胃菜, TypeORM 鏈接遠程的MySQL(ssh tunnel)及Linux信息過濾裁切基礎

前言

昨天發現的框架,看了下官方文檔,號稱Nodejs版本的spring(java)java

開發模式有ng6既視感,這對有ng經驗的小夥伴來講,莫名的親切..mysql

適合嚐嚐鮮,目前有1W+ star, 上正式線我以爲等version 6會穩定些,git

這個系列我會以一個真實項目的開發進展做爲基礎,一邊爬坑一邊水文;github

官網 | NestJS迭代計劃(roadmap)spring

  • 2018-12-7: mysql 8 連接報認證問題sql

    遠程數據庫是5.7, 備份下來切換到本地的mysql8,由於mysql 8升級了安全機制,無法相似之前那樣直連.typescript

    咱們須要修改下,使其支持shell

    # 登陸/切換數據庫/用新的機制更新咱們的密碼/ 刷新權限
    -> mysql -u root
    -> use mysql
    -> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456';
    -> flush privileges;
    
    複製代碼

效果圖

失敗

失敗的緣由有那麼幾個;數據庫

  • 數據庫的配置信息跟實際要連接的數據庫數據不一致(好比數據庫名字,好比用戶名密碼)
  • 隧道轉發的端口給本地其餘服務佔用了,好比mysql本地啓動的(默認3306)
    • 這時候要麼改端口映射,要麼關閉本地數據庫
  • mysql 8+須要修改特權認證
  • ts語法錯誤

成功

代碼

db.ts(src/config)

舒適提示: 如果要用__dirname,確保配置文件在根目錄,不然請改用相對路徑,否則會找不到實體npm

synchronize是同步,會自動同步到數據庫,好比建表什麼的(根據實體)

import { join } from 'path';
const EntityRecursivePath = join('..', '/**/*.entity{.ts,.js}');
export const MySqlConfig: any = {
  type: 'mysql',
  host: 'localhost',
  port: 3306,
  username: 'root',
  password: '!=basestagging**',
  database: 'shengxi_v2',
  entities: [EntityRecursivePath],
  synchronize: true,
};


複製代碼

app.module.ts

UsersModule 裏面寫了對應的服務,實體的關聯

import { Module, NestModule, MiddlewareFunction } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

// 用戶模塊,註冊,登陸,更新我的信息
import { UsersModule } from './modules/users/users.module';

// 數據庫ORM
import { TypeOrmModule } from '@nestjs/typeorm';
import { MySqlConfig } from './config/db';

@Module({
  imports: [TypeOrmModule.forRoot(MySqlConfig), UsersModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule implements NestModule {
  // consumer 這裏能夠掛在中間件什麼的
  configure(consumer: MiddlewareFunction): void {
    consumer
      .apply(null)
      .with('AppModule')
      .forRoutes('/');
  }
}

複製代碼

users.entity.ts

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

// entity裝飾器提供一個options能夠配置關聯的表名,引擎等等,具體看她的interface
// 不提供name的話,,類名就是表名了

@Entity({
  name: 'sx_admin',
})
export class Users {
  @PrimaryGeneratedColumn() id: number;

  // 用戶名
  @Column('varchar', { length: 100 })
  admin_name: string;

  // 用戶密碼
  @Column('varchar', { length: 255 }) admin_passwd: string;

  // 建立時間
  @Column('timestamp') created_at: number;
  // 更新時間
  @Column('timestamp') updated_at: number;
  // 是否啓用
  @Column('int') admin_status: number;
}


複製代碼

剩下的姿式,就在services裏面注入實體和ormRepository;

再到controller注入服務調用便可...返回的是Promise

要點提示及舒適提示

SSH隧道轉發(SSH Tunnel)

遠程數據庫咱們通常不暴露外接端口直連,安全隱患過高;

通常選擇走ssh 隧道(很經常使用的接入方式),

經過ssh登陸認證服務器,再轉發本地的端口到遠程端口,達到數據打通的姿式

  • ssh命令轉發

ssh的命令解釋(官方手冊): 英文,寫的很詳細;

咱們主要用瞭如下幾個參數

-L: 端口轉發

-C: 壓縮傳送數據

-f: 後臺運行

-N: 不執行遠程命令

常規alias

# 這條命令會在後臺運行
alias mstunnel=ssh -L 3306:localhost:3306  root@xxx.xx.xx.xx -NCf

# 如果遠程轉遠程 用-R 替換-L
複製代碼

傳遞參數的alias

shellalias不支持參數的傳遞,要傳遞只能寫成function再賦值到alias

能夠設置多個佔位符,依次遞增(好比端口,域名都變成外部傳入什麼的,看本身喜愛了)

# ssh tunnel
function sst(){
  ssh -L 3306:localhost:3306  root@$1 -NCf
}
alias sst=sst

複製代碼

關閉會話(ssh tunnel)

分步進行的依賴lsof,kill

  • 找到對應的進程PID ,lsof -i tcp:22(查詢誰用着22的端口,ssh tunnel默認走tcp)
  • kill -9 pid , -9 是終止進程

如果要一步到位的,就要藉助幾個命令一塊兒了,awk,xargs以及管道(|)

# 意思就是
# 查詢TCP且端口22的進程
# 輸出第二行的第二列(第一行是列名)
# stdin 轉爲arguments 給kill 
lsof -i tcp:22 | awk 'NR==2 { print $2}' |xargs   kill -9

# 固然也能夠當作一個表達式來寫
kill -9 $(lsof -i tcp:22 | awk 'NR==2 { print $2}')


# 如果要同時關閉多個引用該端口的進程 , NR!=1 便可 , kill 支持殺多進程
# 有傳遞參數的alias記得用function 來實現!!!


複製代碼

如果ssh沒有配置定時發送信號,一段時間後會自動中止會話(packet_write_wait:);

此時要麼去配置,要麼咱們改寫下alias , 用-o ServerAliveInterval=60 來保持鏈接的鏈接這

ssh -o ServerAliveInterval=60 -L  3306:localhost:3306  root@xxxx.xxx.xxx -NCf
複製代碼

IPV6就帶上 -6

  • npm模塊的姿式

能夠經過安裝ssh2,Promise成功後再去連接數據庫;

不考慮用這種,由於實際服務器都是內部直連的,隧道咱們也在開發過程用的比較多

總結

語法轉義

  • 如果使用js文件

目前的版本,仍是要考慮commonjs的寫法,爲何這樣說,

我把數據庫連接的配置文件分離出來,不能用export default

導入的時候也不能用...(rest)解耦的方式. 否則會報語法錯誤

  • ts文件

能夠任性使用ES6+語法

有不對之處請留言,會及時修正,謝謝閱讀

相關文章
相關標籤/搜索