Prisma的简介和使用

Prisma的简介和使用

什么是 Prisma

官网介绍

We simplify query caching,so you don’t have to know how it works

We simplify database subscriptions,so you don’t have to worry about them

We simplify databse migrations,so you don’t have to explain them

We simplify readable date models,so you don’t have to figure out how

We simplify database queries,so you don’t have to manage it

We simplify connecting pooling,so you don’t have to get a PhD in it

翻译过来就是:

我们简化了查询缓存,因此您不必了解它是如何工作的。

我们简化了数据库订阅,因此您不必担心它们。

我们简化了数据库迁移,因此您不必解释它们。

我们简化了可读的日期模型,因此您不必弄清楚如何实现。

我们简化了数据库查询,因此您不必管理它。

我们简化了连接池,因此您不必获得博士学位。

关于 ORM(Object/Relational Mapping),简单来说就是一个可以像操作对象一样操作数据库的工具

就好像 MongoDB 是数据库,Mongoose 是 MongoDB 的 ORM

Prisma 更加强大,它使用更加方便,又支持 PostgreSQL、MySQL、MongoDB、SQL Server和SQLite 等多个数据库

如果要学习 Prisma ,最简单的方法就是去官网看一下它的教学

我相信只要你看完以上几个视频,对 Prisma 的已经会用了,之后叠加 AI 辅助,就能写出你想要的增删改查了

Prisma 组成

Prisma 的产品有很多,其中 Prisms ORM 是我们使用的最最关注的

Prisma ORM是一个基于 Nodejs 和 TypeScript 的 ORM,由于其直观的数据模型、自动迁移、类型安全和自动完成功能,它在处理数据库时解锁了开发人员的新体验。

除此之外,还有 Prisma Optimize、Prisma Accelerate、Prisma Pules、以及新出的Prisma Postgres

  • Prisma Optimize:分析查询、生成见解并提供建议以加快数据库查询速度
  • Prisma Accelerate:全局数据库缓存,具有可扩展的连接池,可加快查询速度
  • Prisma Pules:允许使用类型安全的模型流实时响应数据库更改
  • Prisma Postgres:托管的 PostgreSQL 服务

其中我们最关注的 Prisms ORM 由以下工具组成:

  • Prisma Client:自动生成且类型安全的Node.js和TypeScript查询构建器
  • Prisma Migrate:声明式数据建模和迁移系统
  • Prisma Studio:用于查看和编辑数据库中的数据的可视化工具

Prisma 要学习的点

因为 Prisma 要做的是跨数据库,所以它分为两部分,一部分是对数据库的连接以及定义 Schema,二是由 Prisma Client 做的增删改查

第一部分做的是兼容各个数据库的不同,以 Prisma ORM 的标准来定义 Schema。简单说就是 数据类型的映射,例如 Prisma ORM 的 String 在 SQLite 里是 TEXT,在 PostgreSQL 就是text,而在 MySQL 里是VARCHAR(191)

而且定义 Schema 后的表的关系也是 Prisma 的自定义的标准

第二部分就是Prisma Client 做的增删改查,看文档一目了然

当你修改 Schema (就是你定义的表)后,你需要将其迁移到数据库中,命令为 prisma migrate dev --name xxx

Prisma 实操

第一步:下载 prisma

pnpm i prisma -D

使用 pnpm prisma 命令能获得 Prisma 的各种介绍以及命令行的使用

Prisma is a modern DB toolkit to query, migrate and model your database (https://www.prisma.io)

Usage

  $ prisma [command]

Commands

            init   Setup Prisma for your app
        generate   Generate artifacts (e.g. Prisma Client)
              db   Manage your database schema and lifecycle
         migrate   Migrate your database
          studio   Browse your data with Prisma Studio
        validate   Validate your Prisma schema
          format   Format your Prisma schema

Flags

     --preview-feature   Run Preview Prisma commands

Examples

  Setup a new Prisma project
  $ prisma init

  Generate artifacts (e.g. Prisma Client)
  $ prisma generate

  Browse your data
  $ prisma studio

  Create migrations from your Prisma schema, apply them to the database, generate artifacts (e.g. Prisma Client)
  $ prisma migrate dev

  Pull the schema from an existing database, updating the Prisma schema
  $ prisma db pull

  Push the Prisma schema state to the database
  $ prisma db push

第二步:初始化

pnpm prisma init

这一步会在根目录下创建 prisma 文件,并在其中创建 schema.prisma 文件

第三步:添加 schma.prisma 以及.env 中的数据库地址

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider  = "postgresql"
  url       = env("DATABASE_URL")
}
DATABASE_URL="postgresql://username:password@localhost:5432/mydb?schema=public"

第四步:下载@prisma/client 客户端、vscode 下载 prisma 插件

pnpm i @prisma/client

第五步:回到 schma.prisma 写 model

即定义 User 模型

model UserApiLimit {
  id        String      @id @default(cuid())
  userId    String   @unique
  count     Int      @default(0)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

第七步:同步数据库

将 prisma 模型同步到数据库

pnpm prisma db push

如果是一个已经有数据的项目,就不能使用这个命令,而是用 prisma migrate 迁移

第八步:生成 Prisma Client

前面同步数据库时,已经执行了 prisma generate。所以现在不需要再次执行了,但是一旦 Prisma Schema 文件发生了变动,比如修改了模型,就需要再来执行下这个命令,重新生成 Prisma Client。

pnpm prisma generate

第九步:在线查看数据库

pnpm prisma studio

第十步:@prisma/client 链接数据库

import { PrismaClient } from '@prisma/client'

declare global {
  var prisma: PrismaClient | undefined
}

const prisma = global.prisma || new PrismaClient()

if (process.env.NODE_ENV !== 'production') global.prisma = prisma

export default prisma

Prisma Schema

Prisma Schema 是在最大程序上贴近数据库结构描述的基础上,对关联关系进行进一步抽象

https://camo.githubusercontent.com/5dc1a4d1b53d9b73c71228619cb9cf8ec34dfeef0c2378c7700429e771d42c93/68747470733a2f2f7a332e617831782e636f6d2f323032312f31302f31372f3559775a6f462e706e67

字段由下面四种描述组成:

  • 字段名。
  • 字段类型。
  • 可选的类型修饰。
  • 可选的属性描述。
model Tag {
  name String? @id
}

在这个描述里,包含字段名 name、字段类型 String、类型修饰 ?、属性描述 @id

prisma Client CRUD

使用 create 创建一条记录:

const user = await prisma.user.create({
  data: {
    email: "elsa@prisma.io",
    name: "Elsa Prisma",
  },
});

使用 createMany 创建多条记录:

const createMany = await prisma.user.createMany({
  data: [
    { name: "Bob", email: "bob@prisma.io" },
    { name: "Bobo", email: "bob@prisma.io" }, // Duplicate unique key!
    { name: "Yewande", email: "yewande@prisma.io" },
    { name: "Angelique", email: "angelique@prisma.io" },
  ],
  skipDuplicates: true, // Skip 'Bobo'
});

使用 findUnique 查找单条记录:

const user = await prisma.user.findUnique({
  where: {
    email: "elsa@prisma.io",
  },
});

对于联合索引的情况:

model TimePeriod {
  year    Int
  quarter Int
  total   Decimal

  @@id([year, quarter])
}

需要再嵌套一层由 _ 拼接的 key:

const timePeriod = await prisma.timePeriod.findUnique({
  where: {
    year_quarter: {
      quarter: 4,
      year: 2020,
    },
  },
});

使用 findMany 查询多条记录:

const users = await prisma.user.findMany();

可以使用 SQL 中各种条件语句,语法如下:

const users = await prisma.user.findMany({
  where: {
    role: "ADMIN",
  },
  include: {
    posts: true,
  },
});

使用 update 更新记录:

const updateUser = await prisma.user.update({
  where: {
    email: "viola@prisma.io",
  },
  data: {
    name: "Viola the Magnificent",
  },
});

使用 updateMany 更新多条记录:

const updateUsers = await prisma.user.updateMany({
  where: {
    email: {
      contains: "prisma.io",
    },
  },
  data: {
    role: "ADMIN",
  },
});

使用 delete 删除记录:

const deleteUser = await prisma.user.delete({
  where: {
    email: "bert@prisma.io",
  },
});

使用 deleteMany 删除多条记录:

const deleteUsers = await prisma.user.deleteMany({
  where: {
    email: {
      contains: "prisma.io",
    },
  },
});

使用 include 表示关联查询是否生效,比如:

const getUser = await prisma.user.findUnique({
  where: {
    id: 19,
  },
  include: {
    posts: true,
  },
});

这样就会在查询 user 表时,顺带查询所有关联的 post 表。关联查询也支持嵌套:

const user = await prisma.user.findMany({
  include: {
    posts: {
      include: {
        categories: true,
      },
    },
  },
});

筛选条件支持 equalsnotinnotInltltegtgtecontainssearchmodestartsWithendsWithANDORNOT,一般用法如下:

const result = await prisma.user.findMany({
  where: {
    name: {
      equals: "Eleanor",
    },
  },
});

这个语句代替 sql 的 where name="Eleanor",即通过对象嵌套的方式表达语义。

Prisma 也可以直接写原生 SQL:

const email = "emelie@prisma.io";
const result = await prisma.$queryRaw(
  Prisma.sql`SELECT * FROM User WHERE email = ${email}`
);

参考资料

芝麻开门,显示全文!

字节前端面试题

字节前端面试题

国庆前夕面试了字节的前端,面试官很nice,在这次面试中也学到了不少知识点。那时候靠着记忆记下了这些题

一、name、setName编程题,考察箭头函数中this的指向;

二、https的工作原理;

三、组件库的 polyfill的处理;

四、promise打印顺序问题;

五、JS中的原始值为什么能调用方法

六、React 中的 加上 if 判断后的 useState;

七、编程题tree,name,家谱问题;

八、三个数组,求交集,要求函数能重载; 先记录下,回头把这些问题都攻克攻克

一、箭头函数 this 指向问题

let name = "x";

let people = {
  name: "y",
  setName: () => {
    return () => {
      console.log(this.name);
    };
  },
};

let getName = people.setName();

console.log(getName());
console.log(people.name);

答案: x、y

箭头函数中没有 this,它的 this 指向外部词法环境,与谁调用无关。而且词法环境是在初始化的时候就确定,也就是说当代码中有箭头函数时,代码一开始还没执行时就确定了它的 this

在这代题目中,people 中的 setName 是箭头函数,它的 this 永远绑定在 window 上,所以 getName 无论怎么执行,它的this 都指向 window,所以let getName = people.setName()console.log(getName()) 中的 this 都指向 window,people.name 的值是 y,window 的name 是 x,所以打印 x、y

所谓外部词法环境

如果再思考一下上述代码,会觉得奇怪,setName 不是在 people 对象中吗,为什么它的 this 不是 people。其实 people 是它当前的词法环境,而非外部词法环境,也就是说在它这层环境的外层,那外层就是 window 了

我们从 this关键字 中拿出箭头函数的例子再做说明

var people = {
  name: "eliane",
  age: 28,
  sayName: () => console.log(this.name, this),
  sayName2: function () {
    console.log(this.name, this);
  },
};
people.sayName(); //  '', Window
people.sayName2(); // elaine, {name: 'eliane', age: 28}

看到没,sayName是箭头函数,所以它的this 要从外部词法环境中找,而 sayName2 是普通函数,谁调用它,this 指向谁

至于外部词法环境,简单来说就是要形成作用域(全局作用域、函数作用域和块级作用域),以下例子也是个典型的寻找外部词法环境的例子

var foo = {
  bar: {
    a: () => console.log(this),
  },
};
foo.bar.a(); // window

foo 是对象,bar 也是对象,都没有形成作用域,所以箭头函数a 的 this 只能找全局的 window

三、组件库的 polyfill的处理

主要是对组件库的理解

组件库主题有哪些?

组件库给别人用的时候,输出的是编译后的文件还是编译前的文件

  • 用的是编译后的产物给消费者

  • 如果你们做的组件的兼容目标和使用方不一样怎么办,你们会把一些 polyfill 编译进去吗

    • 规定了浏览器的兼容目标
    • 包体积会变大吗
    • 组件引入 polyfill,业务又引入了 polyfill。这样就两份 polyfill
  • 实现的方式是什么

    • 我的回答:从依赖项的做处理
    • 编译时检测,写一个babel插件,检测如果依赖项中已经有了,就不注入,如果没有则注入
    • 还有别的思路吗?你的思路有一个怪的点,一般babel处理文件的时候不会处理 node_modules 下的文件,它只会对我开发的代码进行检测,你这种方法,不仅要对自己写的代码进行检测处理,还要对你引用的依赖性也就是 node_modules 处理,这样babel编译的时候时间就会超慢,一般默认情况下 babel 不会做相关的检测,思路是正确的,只是怪
    • 另一个回答,把 polyfill 进行拆包,单独引用
      • 方案也可以,但问题是 polyfill 是动态的
      • 如果是你这种情况下,就要规定语法检测,要约定俗成一下

四、Promise 的编程题

setTimeout(() => {
  console.log("a");
});

new Promise((resolve) => {
  console.log("b");
  for (let i = 0; i < 10000; i++) {
    if (i === 1) console.log("c");
    if (i === 9999) resolve();
  }
}).then(() => {
  console.log("d");
});

console.log("e");

答案: b、c、e、d、a

衍生

let p0 = new Promise((resolve) => {
  resolve();
})
  .then(() => {
    console.log("0");
  })
  .then(() => {
    console.log("1");
  });

let p1 = new Promise((resolve) => {
  resolve();
}).then(() => {
  console.log("2");
});

p0.then(() => {
  console.log("3");
});

答案: 0、2、1、3

分析:Promise 的事件机制分为注册函数和执行函数,当我们执行到第三行的时候,我们会把 console(‘0’) 注册,因为第二行已经 resolve 了,所以会把第四行中的回调函数放入微任务队列中,执行第五行的时候,是个同步任务,会注册 console.log(‘1’),但注册完了并不会扔到微任务队列上,因为 console.log(‘1’) 是否扔到微任务队列上,取决于 console.log(‘0’) 的执行结果,如果这里报错了,就会走到 catch 里

此时微任务队列中有 0,但没有 1,因为 console.log(0) 还没执行

相同的道理,执行到11行,我们是将console.log(2)扔到微任务队列里去

同样的道理,执行到15行,console.log(3) 取决于 console.log(1) 的结果,console.log(3)只是注册了但是没有扔到微任务队列上

同步任务执行完后,微任务队列上有两个回调函数(0和2),当console.log(0) 执行完后,再把 console.log(1) 扔到console.log(2) 的后面,当 console.log(1) 执行完了,再把console.log(3) 扔在console.log(1) 的后面

五、JS中的原始值为什么能调用方法

为什么 js 中的 原始值能调用方法,比如 str.split()

关键字:原始值包装对象(Primitive Wrapper Objects)

在调用方法的时候会把它包装成一个对象,之后把这个对象置成null。它一开始就是个原始值,就是简单类型的值,只是在运行时做某一些处理,这种设计允许开发者像使用对象一样使用原始值

总结

后续的问题我没有什么记忆了,只是能在面试中感受到这个面试官的友好

芝麻开门,显示全文!

2023年的加密货币操作

一年前,笔者写了一篇 加密货币预测记录 文章,因为去年的加密货币市场是暴跌行情,一整年都在跌啊跌,所以去年我没买,那篇文章贴了一张别人做的刻舟求剑的图:

加密货币未来预测

现在的价格走势是:

当前价格按上轮跌幅的价格
BTC2570511040
ETH1609293
ADA0.2480.14

之前的文章还贴出了一张“比特币四年一个周期”的预测图,现在可以填上第三轮历史最低时机、时间跨度和跌幅了

历年高点时机历年低点时机时间跨度跌幅
2013年11月:¥80002015年1月:¥90014个月88.75%
2017年12月:$200002018年11月:$320011个月84%
2021年11月:$689002022年11月:$15,60312个月77%

时间跨度上预测对了,但是低点价位没有在前两次范围内,我想,很大程度上是因为更多的购买者以及机构入场了,他们就持有不卖出,所以历来跌幅比例越来越小。如果这样,下一轮跌幅,大概70%就是极限了

去年的 ahr999 在十月份之后确实跌到了 0.45 以下,但是我没有入场,其原因是那个时候考虑买房了,短线我是不会做的,所以就一直没买。后来没了机会也一直没后悔,因为房子还没买

8月底签好了房子,月供做公积金对冲,这几年攒的公积金能顶个两三年,所以现在终于有机会入场了

回过头看如果去年五月份忍不住买币,到现在都是亏的,熊市周期太难熬了

这次的美元加息是否会复刻之前的形势,我不确定。按照笔者掌握的信息,美联储会维持加息力度好几年,如果这样的话现在入场就太早了,还是时机,手里还是要留有一定量的现金,等价格真正到了洼地,没钱买才是最痛苦的事情

笔者的遐想

按照笔者这一年看《杨世光在金钱爆》(+部分金铁杆内容)的心得,9月份大概率不会加息,而11月份大概会加息最后一次0.5%,如此一来就实现了两次会议加息一码(0.5%)的节奏,即每次会议加息0.25%的节奏。12道金牌下去(连续加息12次),美国再一次伟大。而连续的加息,让第四季度的全球资产行情很差,然后传导再传导,越来越多的人抛售加密货币,而那时,笔者就会入场,什么时候会入场,笔者就再写一篇文章进行说明

其实就是等,我拿着现金存银行,虽然跑不过通货膨胀,但是我能随时入场,而现在我觉得远没到低点,那就等呗,就这么简单

芝麻开门,显示全文!

局域网设备访问WSL项目

https://www.cnblogs.com/—ZHIYUAN/p/17230924.html

查找现有网络适配器及其名称

Get-NetAdapter

要创建外部虚拟交换机,请运行以下命令,将 <value> 占位符替换为你自己的值

New-VMSwitch -Name <switch-name>  -NetAdapterName <netadapter-name>

wsl --shutdown && wsl 重启 WSL2,搞定。

https://github.com/MicrosoftDocs/wsl/blob/main/WSL/wsl-config.md

https://www.bilibili.com/read/cv22613431?spm_id_from=333.999.0.0

https://space.bilibili.com/1434257

https://learn.microsoft.com/zh-cn/windows/wsl/networking#accessing-a-wsl-2-distribution-from-your-local-area-network-lan

芝麻开门,显示全文!

现代SEO该做些什么

最近一个月,除了忙公司的事情外,就在做两件事,一是我的婚礼H5,我找来了羡辙婚礼H5作模仿对象。因为老婆是平面设计师,所以让她设计(可后来她就找借口不想做了,所以换装那里就用的羡辙的素材。二是对我的 FE 进行了一个SEO优化,以前是没想搞,哥飞

哥飞做的网站:https://www.threadspage.com/

How to screen shot on windows:https://www.howtoscreenshotonwindows.net/

网友赖嘉伟Gray :https://threadvideodownloader.com/

网友phil502:https://downloader4threads.com/

Airyland 在群里分享 ai.sb

@AUDI 新站上线当天就拿到了 1000PV。

@DemoChen 花了两天时间做的 DocHub.wiki ,上线第二天就拿到了1000UV。

云志:threads2img.com

如何分析:爱站

similarweb :https://www.similarweb.com

以 tool.lu 为例子,查看它的百度权重

https://baidurank.aizhan.com/baidu/tool.lu/

再来回顾一下我们的整个过程,我们先在谷歌里随便输入一个“在线工具”关键字,得到了 tool.lu 网站,之后在 similarweb 和 aizhan 上,我们得到了 tool.lu 网站能够拿到排名的一些关键字,大概就是下面这些了:

时间戳、时间戳转换、ip地址查询、ip查询、ip、时间戳转换器、在线工具、整数分区、视频地址解析、下载地址转换、整数分区计算器、unix时间戳、timestamp、unixtimestamp、在线拆字

这里的每一个关键字,我们都可以用站长网的关键字优化分析工具查看SEO优化难度。打开 https://tool.chinaz.com/kwevaluate ,输入“时间戳”。

https://tool.chinaz.com/kwevaluate/时间戳

可以看到整体优化难度分为86分,不算太难,如果是90以上,那么趁早放弃,换下一个词。

而且实际查看列表发现,首页也只是子域名而已。

那么,“时间戳”这个词,如果我们注册一个域名,专门做“时间戳”相关工具的话,假以时日,是有可能上搜索引擎首页,甚至是排到前5前3的。

时间戳Timestamp在线工具网站

先从分析开始,谷歌搜索“timestamp”

接着,我们用关键字密度检测工具 https://tool.chinaz.com/tools/density.aspx ,查一下每个页面的 timestamp 这个关键字的密度。

然后看下这几个域名的注册时间:

unixtimestamp.com 注册于 2003年10月09日

epochconverter.com 注册于 2007年05月08日

techtarget.com 注册于 1999年09月15日

protobuf.dev 注册于 2020年07月02日

下面我们看下前两个站的反链数量,第一名 unixtimestamp.com ,反向链接400万,引荐域名4900多个

这里我们选择流量最高的美国来查看,都有哪些关键字。

可以看到有些关键字虽然搜索量比较大,但是这个网站并没有排到第一。

拿“utc time”这个词为例,第一名是 https://www.timeanddate.com/ 的内页,也就是我们文章开头的镇楼图对应的网站

我们先不管他,我们聚焦到 timestamp 这个词,找长尾词。

这些长尾词,就是我们需要抓住的,做到我们的网站里的。

同样的方法,我们找出第三名的长尾词,可以看到,第三名的 timestamp 相关长尾词,基本也是这些。

我们还可以去谷歌下拉找搜索需求词:

去谷歌相关搜索找:

把以上这些地方找到的长尾词都收集起来,按照出现次数排序,去重,我们就得到了我们网站能用的关键词列表。

然后我们去挑一个合适的域名,最好是com的,没有的话,其它后缀也行。或者加长,如 timestamptool.net 。

找到合适的域名之后,就要规划全站路径了。我们是后来者,是竞争者,最好的办法是每个语言用一个域名做一个站,那么多语言切换时,直接换不同的域名就行。所以就不需要考虑子域名形式或者子目录形式做多语言。

那么要做的就是

/ 首页,根目录,做工具

h1 是 timestamp把所有长尾词都变成 h2有层级关系的就变成h2下的h3

/{h2关键字}/ 内页,h2层级目录

/{h2关键字}/{h3关键字}/ 内页,h2下的h3层级目录

这样把所有url结构规划好之后,就可以开始做页面了。

以首页举例:

要有时间戳多种转换形式:

1、从数字时间戳转化为年月日时分秒形式;

2、从年月日时分秒形式转化为时间戳;

3、每分每秒显示当前时间戳。

把以上时间戳转化做成模块,在多个页面都可以使用。

接着首页还需要把所有的h2、h3列出来。

每一个h2、h3都需要用一两段文字解释一下。

什么叫都解释一下呢,拿“timestamp sql”为例,我们就需要去告诉用户,在sql中如何获取时间戳,如何转化时间戳,如何使用时间戳。

然后我们刚才说了,每个h2都需要做内页,还是以“timestamp sql”为例,在这个页面里,你就需要围绕“timestamp sql”去做更详细的解释。基于这个关键字,会有更多的长尾关键字,都要解释到位。

如果内页页面里需要用到时间戳转换工具,那就引用一下刚才在首页已经做好的模块。

首页需要有列出所有的内页链接,至少需要h2和h3的链接。

所有的内页也需要到上一层级,直到首页的链接。

如h3页面,需要有h2和首页的链接。

注意制作页面时,注意保持关键字密度,你需要让每个页面的关键字的密度在5%左右,也就是超过之前最大密度4.1%。

以“timestamp sql”页面为例,这个页面会有很多文字,但“timestamp sql”需要占所有字符的5%左右。

这里怎么计算呢?“timestamp sql”总共13个字符,5%就是乘以20,也就是你的网页内容至少需要260个字符才行。如果你的网页需要“timestamp sql”出现3次,那么网页总字符需要780个。注意,空格和换行也算字符。

基于以上方法,把所有页面都做好。然后做好sitemap,就可以提交到搜索引擎了。

但是,你会发现,以上页面都是静态页面,只要做好了,就几乎不会增加新页面,如果我想让搜索引擎爬虫经常来怎么办?

可以学下面这两个网站,做动态页面,每一些时间戳都收录进去。时间戳页面url举例 /timestamp/1672502400 。

可以做一些层级,按年,按月按日分组,每天挑选整点时刻生成页面,将来时刻的页面也可以先生成。

分组后,可以是这样 /timestamp/2023/01/01/{秒时间戳} 。

做好之后,就是和时间交朋友了。

不过,因为我们是挑战者,最好能够做得更漂亮,更好用,让用户能够自发传播。

另外,站长之家的这个时间戳工具页面 https://tool.chinaz.com/Tools/unixtime.aspx ,值得学习。

工具站又分为两种,一种是纯前端就能实现的,比如json相关的网站,如json.cn,bejson.com等,还有base64编码解码,或者MD5编码,这些都是前端js代码就能实现的,不需要后端。

还有比如我们可能用过的一些推特视频下载的网站,你在推特上看到一个视频很喜欢,你想下载怎么办?去搜索相关的网站,然后粘贴推特的链接就能下载。它其实是通过在后端服务器里解析推特的网页得到视频地址的,这个就需要后端支持。

比如,你可以让GPT为你生成一个base64编码、解码的前端代码,然后直接复制出来,部署起来就可以创建一个网站。

那么怎么找到这些需求呢?一种方法是你自己经常使用的工具,比如我之前在即刻举过的一个例子,就是字数统计的需求。这个需求可能大家很难想到,但实际上很多时候我们就会有这样的需求

我以前一直使用的是一个国内的设计工作室创建的字数统计网站 etest.com 。我不知道他们是怎么发现这个需求的,但他们很早就做了这个网站,我也用了很多年。我查了一下,他们每个月的访问量应该在30万左右,这对于国内的网站来说,已经算是不错了。

国外的字数统计工具网站,流量就很大了,比如 wordcounter.net 每个月有700多万访问量, wordcounter.icu 每个月有200多万访问量。所以,你需要自己有这样的需求,或者你知道别人有这个需求,然后你去创建这样的工具站。

另一种方法是去工具大全类网站看,有哪些工具大全网站。如果你不知道,没关系,直接在谷歌搜索工具大全,或者在线工具,就能找到很多。

比如说,大家可能比较熟悉的tool.lu网站,那里会列出很多不同的工具,虽然它没有显示每个工具的使用次数,但我们可以直接找他使用次数多的,或者他的热门的,这些都是用户需求比较大的工具,我们就可以模仿他们。

那么怎么模仿呢?我们刚刚说了,无论你是前端工具还是后端支持工具,一般一个工具,一个页面界面交互都不会特别复杂,一个页面就能完成。

但是我们创建工具站的话,我们不能只做一个页面,因为别人已经有先发优势了,我们现在的竞争者,他们已经做了好几年了,他们的权重比我们高,他们用内页,我们就不能用内页了。

我们需要用单独的域名,一个域名只做一个工具。比如说,时间转换,或者说base64编码,我刚才提到的那个不懂编程的朋友,他就做了一个base64编解码的纯前端工具,放在那里,前几年几乎没流量,然后最近几个月突然来了很多流量。

我们需要专门买一个域名,只做一个关键字。比如说base64编码,我就找一个跟base64相关的域名,比如直接base64.xxx,找一个非主流的后缀也好,或者你前面后面加一点其他单词也好,反正要有一个专门的域名。

既然我们用一个域名来做一个工具站,那就肯定不是只做一个页面了,而是去扩展关键词。关于扩展关键词的工具,可能大家都有自己喜欢的,这里就不详细介绍了。反正用关键词扩展的话,比如IP查询,你肯定可能关键字就有IP查询、IP转换或者说是IP位置查询这些所有相关的词。

每一个词做一个页面,因为每一个页面里面都有title,标题有h1,有h2,这些都能增强这个关键词的权重。如果你一个页面做多个关键词的话,那么你都拿不到权重,那么你就需要一个页面专门做一个关键词的权重,然后再把这个页面指向首页,这就相当于是一个网站的内页链接指向到首页,把这个权重再收回到首页里面来。

这就是我们的单域名单站做单关键词的策略。

我们需要注重内页的建设,找到更多的关键字,然后一个关键字做一个页面。网站首页,我们通常使用index.html,index是什么?就是索引的意思。

所以我们的首页需要把我们所有的关键词页面都索引进来。怎么索引?其实就是在首页添加所有内页的链接,然后每一个内页都要指向首页。指向首页的话,你需要用关键字去指向首页,比如说你某一个页面的关键字是IP查询,那么你在那个页面增加一个到首页的链接,一个a标签的链接,链接上面的开头以及链接里面的文字,你就用IP查询,这样权重就到了首页。

<a href="首页网址" title="关键字描述">关键字</a>

我们在做页面的时候,不能浪费每一个html标签,比如title,这个是最重要的,因为搜索引擎在索引我们页面的时候,最主要的就是看你这个title你写了什么,他就认为你这个页面的主要内容是关于什么的,所以title的权重很高。

这也是为什么我们不能只在首页做一个页面的原因,因为你这个关键词可能有很多,你不可能把所有的关键词都放到首页的title里面去,你只能抽取最重要的几个关键词放进去,其他关键词怎么办?放到别的页面,每一个页面一个title。

然后还有description,描述的话就是说用你的关键词去描述你的页面,因为我们在搜索引擎搜索的时候,每一个搜索结果基本上它就是三行,一行显示链接,一行显示标题,一行显示描述,所以描述很重要,你需要用关键词去描述你的页面。例如,如果你的网页是关于IP查询的,那么你的描述应该是关于IP查询的相关介绍,以吸引用户点击进入。

还有什么是非常重要的呢?H1、H2、H3标签。你的每个页面只应放置一个H1标签。H1标签与页面开头的权重几乎相同,也就是说,搜索引擎在查看你的页面主题时,除了查看标题外,更主要的是查看你的H1标签。然后,H2、H3等标签都是用来进一步解释H1标签的内容。

另外,为什么要在页面中放置图片呢?这个图片也非常重要。因为专门的搜索引擎都有一个图片搜索功能,你可以在那里专门搜索图片。假设你制作的工具或你的站点与图片有关,比如你的工具是生成水印,生成签名或者生成精美图片,生成海报等,那么用户可能会在图片搜索中专门去搜索相关图片。

因此,如果你的页面上,你所生成的每一个页面或者说每一个功能,每一个内页你都放一张大图,大图的尺寸一定要比A4纸更大,而不是那种200×300这种小图。

然后,每一个图片的alt和title都要写好。alt属性最早的作用是当你的页面链接有误,网址有问题的情况下,当图片不显示的时候,alt就是一个占位符,告诉用户和搜索引擎这个图片到底是什么。因此,我们也需要清楚地写出alt属性。那么,用户在图片搜索引擎里搜索的时候,alt的权重就会很高,你的图片就能排到前面了。

然后,我刚才提到,如果有一个内页的话,所有的内页都应该有一个指向首页的链接,怎么写呢?链接的开头一定要写清楚,不仅仅是我们这里的a标签不是自闭合的标签,a标签后面还有一个斜杠a来闭合,中间的内容就是我们的指向首页的关键字。在链接的开头里面,你也可以把关键字写上,或者稍微解释一下关键字都可以。这样,你就把内页的权重传递到了首页。同时,我们刚才说了,首页也要有到所有内页的链接,也要把链接的开头写上你内页的标题。

那么,网站做好了之后该怎么办呢?搜索引擎的收录是第一步,因为你只有先被搜索引擎收录,才有可能有排名,才有可能在用户搜索的时候被看到,从而带来流量。

我们需要做什么呢?我们需要尽快让搜索引擎收录我们的网站。如果我们只是把网站放在那里,可能因为搜索引擎很难发现我们的网站,可能需要一个月或两个月才能被收录。

那么,有没有更快的办法呢?有的,那就是可以找一个高权重的网站,比如说如果在国内,你可以选择知乎专栏,或者是掘金,或者是其他任何一个可以放链接的社区。然后在国外,你可以选择V2EX,或者其他一些高权重的网站。

同时还有另一种方法,那就是我们可以主动提交网站到搜索引擎的站长工具,如百度站长工具和谷歌的Search Console。

新上线的网站,如何快速让谷歌收录?做网站为什么要生成几十万个页面?

新上线的网站,如何快速让谷歌收录?

答案是去V2EX发帖介绍自己产品,然后留下网站链接。这个方法10年前就有用,现在更有用了,因为V站在谷歌的权重更高了。

那怎么让搜索引擎知道你有那么多页面呢?

答案就是内链和网站地图。

做好这两样,就能让搜索引擎发现你的所有内页。

又有人问,生成页面目的是什么?

我答,生成页面是为了给谷歌收录,谷歌收录之后,才有可能把你的页面放进搜索结果里,最终目的当然是为了从搜索引擎里获取流量。

至于获取到了流量了,怎么变现,就要看你做的是什么网站了。有些可能单纯赚广告费,有些赚会员费,有些赚交易佣金。

每一个页面,都对应一个关键字,生成几十万个页面的意思就是做了很多关键字页面。

用户搜索这些关键字时,如果谷歌把我们网站排到前面了,用户就有可能会点进进来。

一个页面可能一天只能带来10个访问,但如果你有10万个这样的页面,是不是每天就有100万个访问了。

赖嘉伟Gray

看完上文,你 Get 到了@赖嘉伟Gray 是怎么操作的吗?我总结一下:

1、在新鲜事物出现时,迅速抓住机会,分析可能产生的用户需求,分析用户可能会有哪些关键字在谷歌等搜索引擎搜索找到满足需求的网站;

2、基于关键字去注册域名,快速建站,快速上线,即使功能暂时还没开发出来也没关系,先把网站上线了,先让谷歌收录,尽快参与排名;

3、通过提交网址到 Google Search Console 中,以及在一些高权重网站留下外链形式,快速让谷歌收录;

4、当用户通过搜索引擎打开网站后,需要能够真的满足用户的需求,这样用户就会留下来使用,而不是立马关闭页面,去点击另一个搜索结果;

5、增加更多的真实的外部链接,进一步提升网站权重。

其实就8个字可以概括,“离钱越近,单价越高”,要说明这8个字,我就得给大家讲故事了。

如何做到通过小产品日入100美元

如果你想靠纯广告费赚这么多,按照海外 ecpm 3.3 美元计算,需要每天有 30 个 ecpm ,就是3万个广告曝光。

假设一个页面放3个广告位,每个pv平均能够产生 2 个广告曝光的话,需要1.5万日PV。

假设一个UV能够产生2个PV的话,需要7500日UV。

假设每个关键字每天能给你带来100UV的话,你需要找75个这样的关键字。

找75个关键字很难吗?的确有些难度,那就先找到1个,然后找到5个,然后慢慢越来越多。

新上线的网站,如何快速让谷歌收录?做网站为什么要生成几十万个页面

新上线的网站,如何快速让谷歌收录?

答案是去V2EX发帖介绍自己产品,然后留下网站链接。这个方法10年前就有用,现在更有用了,因为V站在谷歌的权重更高了

在一个名叫 MoneyHunter 的微信群里,群主说,买了一个老域名,昨天上线新网站,生成了几十万个,今天就被谷歌收录了两千多个页面。

有人就问,几十万个什么?

我帮群主回答,是几十万个页面。

举个例子,16进制的颜色代码 ff0066 这种,你如果给每个颜色生成一个页面,那么就总共可以生成一千六百多万个页面。

当然实际操作中,不是真的生成这么多个 html 文件。而是用动态页面,根据不同的url路径参数显示不同的页面。

那怎么让搜索引擎知道你有那么多页面呢?

答案就是内链和网站地图。

做好这两样,就能让搜索引擎发现你的所有内页。

又有人问,生成页面目的是什么?

我答,生成页面是为了给谷歌收录,谷歌收录之后,才有可能把你的页面放进搜索结果里,最终目的当然是为了从搜索引擎里获取流量。

然而并不是,打开 colorhexa.com 输入任意一个16进制颜色代码,看看页面显示了什么,再输入另一个颜色代码,看看页面又显示了什么,就知道了我说的生成具体指的是什么了。

再举一个例子,你做了一个查字典网站,输入任何一个中文汉字,能够给出这个字的解释、读音、组词等信息。

举例我昨天说的颜色代码网站 colorhexa.com ,每个月100万的访问量,有70万来自于搜索引擎。

还有 color-hex.com 这个网站每个月访问量在190万,其中有150万来自于搜索引擎。

为什么搜索引擎愿意给这么多流量给这些网站? 谷歌那么聪明,当然是识别到了,用户从搜索结果里点进去之后,真的觉得有用

![image-20230727145843622](D:\Documents\PicGo Files\image-20230727145843622.png)

但现在服务器已经白菜价了,几乎很少网站会采用静态页面,尤其是内容越多的站点,越不可能静态化。

善用大域名

不打开浏览器,猜一猜是否可以用 support(支持).qq.com 这个域名做自己产品的帮助文档域名? 答案当然是可以。 那么用这个域名有什么好处呢? 有没有发现这个域名很唬人? 如果你做的是微信相关的产品,用这个域名是不是看起来更权威一些呢?

关键字

https://web.okjike.com/originalPost/64ad16757b5daee5430e6f17

谷歌每天处理的搜索中有15%是从来没有被搜索过的词。 2016年,谷歌说每年处理2万亿次搜索,到2023年,应该要有3万亿次以上了。 15%就是4500亿,再除以365得到每天是12亿次左右。 即使其中有大部分是旧关键字的变种,也还是有很多全新的搜索。 这里具体多少比例不清楚,但即使打个1折,也有每天1.2亿次全新的搜索。 全新的搜索意味着什么? 意味着你只要做个网页上去,只要被收录了,你就能排名第一。 那么剩下的问题就是,如何找到每天出现的新词了。 考考大家,你会如何自动化的发现新词?

给大家看看什么是执行力,周末两天就把网站搞出来了。 而且做得还挺好。 threads2img.com 是一个生成精美 Threads 卡片的小工具。 图二就是生成好的一个例子。 (暂时第一版只做了pc端,所以手机端打开界面会乱)

模仿:https://poet.so/

产品

https://web.okjike.com/originalPost/649e3191bb0badadbdd517b8

分享个产品,书法字典,有网站和App,收费方式简单粗暴,免费查看小图,收费查看大图。 5月份流量暴涨,达到了150万访问量。 关键信息我都截图了,我给大家留作业,请根据这些截图和你自己查询到的信息回答以下几个问题: (哥飞首发于即刻,可加我微信 qiayue) 1、估算这个产品的月收入是多少? 2、5月份流量暴涨的原因是什么? 3、如果要增加收入,这个产品还有哪些优化空间?

之前建议大家出海,那有人会问,没有爱迪尔怎么办?

https://web.okjike.com/originalPost/649c087a0496a46ed6cd6717

之前建议大家出海,那有人会问,没有爱迪尔怎么办? 现在我给你一个有效办法,可以去 similarweb.com ,先随便扔进去一个你熟悉的网站的域名开始,去查看数据,去看热门受众兴趣点和竞对网站,通过一个域名你能找到10个以上的新域名,之后再点进这10个域名去,再发现10个新域名,不断点进去,看到流量不错的站点,打开网站看看别人到底提供什么服务的。 那些太复杂的网站先略过,只看简单的,能够快速实现的。 举例,下面我发现的这两个网站,功能都很简单,但是用户真的有需求,只要做好体验,做好SEO,流量就会越来越大。 shurt.pw 月访问量 300 万,解决生成密码的需求。 wordcounter.icu 月访问量 260 万,解决字数统计需求。 字数统计这个我常用的是国内一个开发者做的 eteste.com ,月访问量 30 万。

发3个站,感兴趣的即友可以研究下 rentry.org 月访问量 670 万,很简单的工具站,就 2 个页面。这个站还有个域名 rentry.co 月访问量 1040万。

chatgptfy.com 月访问量 170万,主要流量来自于搜索,你去仔细分析搜索词会有大发现。

chatgptdownload.org 月访问量 130万,我不提示了,请你去发掘发现。

我的产品思路:

https://tools.miku.ac/

https://tools.miku.ac/driver/

https://tools.miku.ac/china_colors/

https://tools.miku.ac/yi_ge_ding_lia/

芝麻开门,显示全文!

我的云服务器初始化做哪些(持续更新)

此地禁止大声喧哗

前言

三年之期已到,我的阿里云服务器也到期,我的服务要迁移了。思来想去,还是选择了腾讯云,只因我选择过阿里云

一个身份证可实名三个腾讯云账号,所以如果买三年的低配服务器部署应用,阿里云三个,腾讯云三个,华为云三个,ucloud 三个,共计 36 年,够程序员的职业生涯了(当然今年阿里、华为云没有三年服务器,三年后不知道还有没有三年服务期)

个人认证

省流

安装 oh-my-zsh 配置主题,安装自动补全、语法高亮插件

安装 docker、docker-compose 环境

iptables 除了 80 443 ssh 端口,其他全禁

安装 node 环境

安装 ruby 环境

正文

自从有了 vercel 后,我将大多数前端项目都放在那儿,包括五年前端三年面试,博客,个人网站。服务器除了 bilibili录播姬和几个小 node 、ruby on rails demo 外,就没怎么用过,这两年在 v2ex 上看到几篇讲拿到服务器后可以部署哪些服务的帖子

就想着也在我的服务器上部署一些服务,这里当作记录

初始化

进入腾讯云服务器控制台

![image-20230620143434808](D:\Documents\PicGo Files\image-20230620143434808.png)

点更多,重置密码,输入新密码

注意,腾讯云的轻量服务器的初始登录名是 ubuntu试了好几次 root 才发现这个坑)

![image-20230617084650969](D:\Documents\PicGo Files\image-20230617084650969.png)

复制该机器的公网 ip

在本地 hosts 文件里写下 公网ip server1 (比如 1.2.3.4 server1)保存即可。

同理,笔者有些项目在 wsl2 只开发,进入 wsl 中, vim /etc/hosts,将 公网ip server1 放入其中即可

这个步骤是为了设置别名,以后通过 ssh 登录服务器,只需要ssh 用户名@serve1 即可,但我们还需要登录密码,所以我们需要复制 ssh 密钥

复制SSH密钥到目标主机,开启无密码SSH登录

ssh-copy-id ubuntu@server1
# 回答 yes
# 输入密码

之后输入 ssh ubuntu@server1 ,就不需要登录密码了

![image-20230617084849141](D:\Documents\PicGo Files\image-20230617084849141.png)

安装软件

# 安装 Docker
apt install software-properties-common
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
# 安装 docker-compose
sudo apt install docker-compose

# 安装 oh-my-zsh 配置


# 安装 git vim
apt update
apt install -y git vim

# 安装 node 环境

# 安装 ruby 环境

Docker 加速

打开 阿里云容器镜像服务 网页,点击【镜像工具】-【镜像加速器】,然后根据提示加速即可(所有操作要在 root@server1 账户里运行)

前往 /etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件):

{ "registry-mirrors": ["填入以上链接"] }

放开防火墙

防火墙命令

https://blog.51cto.com/u_15057832/4537317

先下载 firewall-cmd

# 下载
sudo apt install firewalld

# 查看放开的端口
firewall-cmd --list-ports
# 开放的服务
firewall-cmd --list-services


关掉 firewall 服务

systemctl stop firewalld.service

添加指定端口

比如我们现在要打开对外2356/tcp端口,可以使用下面的命令

firewall-cmd --add-port=2356/tcp --permanent
firewall-cmd --reload
firewall-cmd --list-ports #2356/tcp

安装软件

数据统计和分析工具:matomo

生成短链并统计点击:polr

wechaty:聊天机器人

windmark.pro 编写

blog 挂了一个博客 rssant 订阅 rss 源每天摸鱼用的 syncthing 同步文件,家里和公司电脑的笔记等 frp 在公司远程自己电脑用的 rustdesk 远程连接,和朋友一起用的 memos 一个碎片化的备忘录 alist 聚合网盘用的 artalk 一个自部署的评论程序给博客用的 excalidraw 一个自部署的白板 portainer 在线管理 docker 程序 umami 监测网站访问数据用的 vocechat 一个仿 discord 的聊天室,偶尔交流信息会用到 包括放了图片和文件用来做 cdn

服务挂了报警

https://weibo.com/ttarticle/p/show?id=2309404669439416336911

https://github.com/easychen/windmark-practice

数据统计和分析工具:matomo

生成短链并统计点击:polr

wechaty:聊天机器人

windmark.pro 编写

内网穿透:

RSSHub:订阅 rss

参考资料

芝麻开门,显示全文!

我的 VScode 配置

这篇文章主要是为了记录自己的 VSCode 配置,万一哪一天电脑重置,方便自己配置

字体

JetBrains Mono,前往字体官网,下载并安装字体

进入 VSCode 中,ctrl + , 打开设置面板,在 Editor: Font Family 栏添加字体:JetBrains Mono, Fira Code, Consolas, 'Courier New

或者是打开 settings.json 中,在其中填入

{
	...
	"editor.fontFamily": "JetBrains Mono, Fira Code, Consolas, 'Courier New', monospace",
	...
}

推荐在 json 中配置(后续也会在这个json中配置)

主题

主题:Dark Molokai Theme

在插件市场中收缩Dark Molokai Theme,或者去官网 安装主题,并在 settings.json 中配置主题

{
  "workbench.colorTheme": "Dark (Molokai)",
  "editor.fontFamily": "JetBrains Mono, Fira Code, Consolas, 'Courier New', monospace"
}

界面布局

看到几个大佬的 activityBar 都放在屏幕右边,因为这样一来,编辑器就不会因为我们切换sidebar 的可见而左右跳动,同样在 settings.json 中配置屏幕位置

{
  "workbench.colorTheme": "Dark (Molokai)",
  "workbench.sideBar.location": "right",
  "editor.fontFamily": "JetBrains Mono, Fira Code, Consolas, 'Courier New', monospace"
}

在 VSCode 中集成 GitBash

同样,在 settings.json 中配置,将配置中的 bash.path 更换为自己的路径,window 中需要\\ 表示,配置如下:

{
  "workbench.colorTheme": "Dark (Molokai)",
  "workbench.sideBar.location": "right",
  "editor.fontFamily": "JetBrains Mono, Fira Code, Consolas, 'Courier New', monospace",
  "terminal.integrated.profiles.windows": {
    "bash": {
      "path": "D:\\Development\\Git\\bin\\bash.exe",
      "args": ["-i", "-l"]
    }
  },
  "terminal.integrated.defaultProfile.windows": "bash" // 默认打开 bash
}

改完重启后,再打开终端,你会看到

vscode in bash

插件

Prettier - Code formatter:代码格式化工具,安装好之后。在 settings.json 中配置

{
	...
	"editor.defaultFormatter": "esbenp.prettier-vscode",
 	"editor.formatOnSave": true,
    ...
}

EditorConfig for VS Code: EditorConfig

root = true

[*]
charset = utf-8
end_of_line = lf
max_line_length = 80
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true

GitHub Copilot: AI 机器人辅助写代码

Live Sass Compiler:将写好的 sass 文件转成 css 文件

VSCode Great Icons:可在文件管理的树目录显示图标

参考资料

芝麻开门,显示全文!

尝试用 WSL2 + Ubuntu 开发

目的

用 WSL2 模拟 Linux 开发环境,然后用 Linux 开发项目,熟悉各种 Linux 系统和命令,为以后成为大神埋下习惯的种子

前言

可不看

笔者是 Window 用户,去年真正学 Linux,以前也用过虚拟机开发,也有过各种尝试,但因为各种原因,还是回归 Window 开发

去年看到方应杭的直播开发,了解到 docker + VS code 的开发模式,而后就写了 手把手提高开发体验:dev-container,配置好后我没有继续研究,没有马上把环境切换成,直到最近,换电脑,才想着就用 Linux 开发吧

正文

什么是 WSL

Window 中的 Linux 系统,Window 提供的内置虚拟机

所以我们可以在 Window 中安装 Ubuntu、Centos 等 Linux 系统

但他的缺点是文件系统和 Window 不一致,但可以共享

说白了,如果你在 Linux 中操作 Window 中的文件,会卡顿。反之亦然

WSL、docker、Window 的虚拟机(Hyper-v)的关系相当于,Window 用 Hyper-v 实现了虚拟机,也就是 WSL,window 中的 docker 也是基于此技术来实现容器化的

省流版

修改默认安装目录到 D 盘

更换阿里云软件源

更新软件

安装 oh my zsh

配置 ssh

node 环境

ruby 环境

修改默认安装目录到 D 盘

wsl --help # 查看文档
wsl --list # 查看启动的 wsl 数量
wsl --list --verbose # 列出已安装的 Linux 发行版
wsl --set-default-version <Version> # 设置默认 WSL 版本
wsl --set-default <Distribution Name> # 设置默认 Linux 发行版
wsl --shutdown # 关闭 wsl
wsl --export <Distribution Name> <FileName> # 导出
wsl --unregister Unbuntu-18.04 # 注销当前分发版
wsl --import <Distribution Name> <InstallLocation> <FileName> # 导入
ubuntu1804 config --default-user johan # 设置默认登陆用户

同理,可以把 docker 也放到 D 盘中

更多命令可以前往官网查看

更换阿里云软件源

1.备份

sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak

2.修改

sudo vim /etc/apt/sources.list

将 source.list 文件内容替换成下面的

deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse

更新软件

sudo apt update && sudo apt upgrade -y

安装 oh my zsh

安装 zsh

sudo apt install zsh -y

安装 ohmyzsh

sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

安装 ohmyzsh 插件,按照自己的喜好

可以看看 antfu 的配置

git clone https://github.com/denysdovhan/spaceship-prompt.git "$ZSH_CUSTOM/themes/spaceship-prompt" --depth=1
ln -s "$ZSH_CUSTOM/themes/spaceship-prompt/spaceship.zsh-theme" "$ZSH_CUSTOM/themes/spaceship.zsh-theme"

进入 .zshrc 文件,并修改成ZSH_THEME="spaceship",并让配置立马生效 source ~/.zshrc

将 ohmyzsh 设置为默认编辑器

chsh -s $(which zsh)

配置 ssh

生成 github 公钥

ssh-keygen -t rsa -C "t511069160@qq.com" -f "~/.ssh/id_rsa_github"

生成 gitlab 公钥

ssh-keygen -t rsa -C "XX" -f "~/.ssh/id_rsa_gitlab"

配置 config 文件

Host github
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa_github

Host 10.110.119.233
HostName 10.110.119.233
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa_gitlab

测试是否配置成功

ssh -T git@github.com
ssh -T git@10.110.119.233

node 环境

使用 nvm 来控制 node 版本,因为有些老项目还在用 14 版本的

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash

如果说安装失败或者安装很慢,就在 /etc/hosts 中将 raw.githubusercontent.com 域名映射下,具体方法可看GitHub520

将配置写进 .nvm 中

export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

再让配置立即生效source ~/.zshrc

nvm --version # 0.39.3
nvm install 16.19.1 # 下载 16.19.1 版本的 node
nvm list # 查看 node 列表
nvm use 16.19.1 # 使用 16.19.1 版本的 node

nvm下载

ruby 环境

使用 rvm 来管理 ruby,安装文档参考官网

安装 GPG keys

gpg2 --keyserver keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB

报错:

没有gnupg2库

先下载 gnupg2

apt install grupg2 -y

grupg2 安装好了,就重新 GPG keys。再安装 rvm

curl -sSL https://get.rvm.io | bash -s stable

安装结果

安装好后,我们需要修改 ruby 安装源,来提高安装速度

 echo "ruby_url=https://cache.ruby-china.com/pub/ruby" > /usr/local/rvm/user/db

看截图中的绿色字,RVM 安装的路径

使 rvm 命令生效

source /usr/local/rvm/scripts/rvm

此时,rvm -v 就能看到 rvm 1.29.12(latest)...

安装 ruby

rvm install ruby-3.1.3
rvm list known:#查看
rvm list:#查看
rvm use 3.1.3 --default #使用 3.13 为默认版本的
ruby -v # ruby 3.1.3p185

安装 rails

gem install rails --verbose # --verbose 可以查看进度
rails -v # 7.0.4

遇到的问题(一)

之前用 curl -sSL https://get.rvm.io | bash -s stable 安装完后,使用gem install railscommand not found ubuntu,解决不了,后来尝试了各种方法安装,例如下载源码,例如用sudo apt-get install ruby-full,后来都不是很好使

可怪自己 linux 基础太差,英语又不好,下载完 rvm 后,它已经提示了,让我切换用户并重新登录

安装完rvm后的提示

而我第二次安装的契机是不死心,还是想用 rvm 安装,然后就想到先卸载,再重新安装

发现了 apt-get purge rvmapt-get remove rvm 等命令,第二次安装我用了 sudo 命令,安装地址改成了 /usr/shar/rvm

删除 rvm

sudo apt-get purge rvm

重新安装

curl -sSL https://get.rvm.io | sudo bash -s stable

第一步,将正在用的用户添加到 rvm 组中

sudo usermod -a -G rvm johan

第二步,注销-再次登录

我的办法比较土,先切换到 root,再切回来

su root
su johan

第三步,运行生效命令

source /etc/profile.d/rvm.sh

这样就安装成了

遇到的问题(二)

因为在 WSL 中开发,但是有时候要用手机来查看样式问题,所以需要在手机端访问,但是 WSL 启动的服务,手机端访问不了。笔者对网络方面的知识不了解,也不想了解。按照从局域网访问 WSL2 这篇文章的操作来做

先开启对应端口防火墙,再将 WSL 上的 ip 、端口映射到本地

后续

做事情都要有所目的,当初写 手把手提高开发体验:dev-container 时,想着把环境配置成一致,方便项目部署。但发现所占内存太大,笔记本(12G)带不动。现如今新电脑(32G)虽然可以用此方法来开发,但笔者的目的变了,笔者现如今想学的是 Linux 、bash,使用 WSL 能随时随地接触它,熟悉它,习惯它

开发还是用 WSL ,但是写东西,例如写博客之类的还是会依赖于 Windows,所以真不如别人说的还不如买一台 mac 呢

参考资料

芝麻开门,显示全文!

安装 docker 后无法启动

前言

好久没写文章了,一部分是忙了,另一部分是过年懒了,还有一部分是在学习 ruby,想搞个前端七天学 ruby 系列文章,敬请期待

正文

最近在部署 ruby 项目中,遇到了 docker 19 版本无法在两个容器中互联的问题,后升级 docker 至最新版本(23)解决,但升级完后之后,无法启动

可惜的很,没截图

当使用 docker --version 或者 docker ps 时,说没有启动

Failed to start Docker Application Container Engine.

通过systemctl status docker 启动 docker,报错

failed to start daemon: Error initializing network controller: Error creating default "bridge" network

没启动 bridge 网络

firewall-cmd --permanent --zone=docker --change-interface=docker0
# 防火墙加入 docker0
firewall-cmd --reload
# 重启防火墙

这样 docker 就正常运行了

参考资料

芝麻开门,显示全文!