Code Monkey home page Code Monkey logo

blog's Introduction

Ecss Coop

Issues 写博客挺不错。

新的博客地址(已运行一年,应该不会再动了):https://memos.ecss.dev

blog's People

Contributors

ecss11 avatar

Watchers

 avatar

blog's Issues

Node.js 的 log4js 笔记

前言

在安全和和开发领域,日志可以反映出持续可能存在的安全隐患,性能问题,以及各种事件,有利于程序的改进和测试。

通过日志,事后我们可以很轻松的发现问题的原因,并快速对问题源做出修改。

快速开始

log4js 的官方文档https://log4js-node.github.io/log4js-node/

基本使用方法,使用 logger 打印出一段字符串,调用 getLogger 获取 logger 的实例:

const log4js = require('log4js')
const logger = log4js.getLogger()
logger.debug('这是一个测试信息')

日志等级

日志有不同的等级,每个等级又有不同的比重, 从低到高为:

1: TRACE
2: DEBUG
3: INFO
4: WARN
5: ERROR
6: FATAL
7: MARK

类型

在 log4js 中有一个概念是 category(类型),通过类型可以查看日志来源哪个模块,或者自定义类型的配置。

const log4js = require('log4js')
const logger = log4js.getLogger('abc')
logger.debug('此时 logger 的类型是 abc')

Appender

如果你希望将日志输出到一个文件,或者自定义一些配置,你可以配置 Appender 完成。

下面是 log4js 默认的 Appender 配置,在默认的情况下,所有的日志都会输出到控制台:

defaultConfig = {
  appenders: [{
    type: "console"
  }]
}

你也可以创建自己的 Appender 配置,通过 log4js 的 configuration 方法:

log4js.configure({
    appenders: {
        out: {
            type: 'stdout'
        },
        info: {
            type: 'file',
            filename: 'logs/info.log',
            maxLogSize: 52428800
        }
    }
})

施工中。。。

在 Python 中测试 http 请求

描述

据需求不同,这里主要介绍通过 requests 库的 get 返回的状态代码,判断请求成功。

前置

  • requests

案例

假设有一个 url,需要使用测试检查 url 请求是否成功。

def test1():
  url = 'http://localhost:5000/'
  response = requests.get(url=url)
  # 请求是否成功,200 状态码(OK)
  self.assertEqual(200, response.status_code)

FIrewalld 使用手册

什么是 Firewalld:它是 Centos 或类似系统下默认的防火墙系统,类似于 Ubuntu 的 ufw 系统。

Firewalld 的优点

使用 Firewalld 添加的出入站规则可以直接在运行环境中启用,不需要重启服务本身。

使用 Firewalld 提供的接口可以为服务,应用,和用户轻松的配置任何规则。

通过分离永久和内存中的规则,可以使用户实时对添加的规则进行评估。任何非永久添加的规则都会在下一次的热加载或服务重启时消失。而任何永久的规则会在重载后得以保留。通过这种方式,用户可以添加一些临时的设置。而如果配置已被评估完毕,并且成功运行,那么这项规则便可以添加至永久的设置中。

Firewalld 下载安装

下载并安装 firewalld 包:

sudo yum update && sudo yum install firewalld

Firewalld 规则配置

开放状态获取

查看区域:获取当前激活的区域,区域在大部分情况默认为 public

firewall-cmd --get-active-zones

列出规则:获取当前区域已配置的规则

firewall-cmd --zone=public --list-all

端口添加和关闭

开放端口:在 public 区域永久允许 5000 端口的 TCP 流量传输

firewall-cmd --zone=public --add-port=5000/tcp --permanent

firewalld 服务也支持开放一个地址段,比如 --add-port=5000-5500/tcp 即开放从 5000 到 5500 的所有 TCP 端口。

关闭端口:在 public 区域永久关闭 5000 的 TCP 端口

firewall-cmd --zone=public --remove-port=5000/tcp --permanent

服务添加和关闭

你可以使用防火墙内置的服务,也可以在添加端口时,自定义服务名使用 --service= 选项,查看这个 文档 了解更多。

获取服务:使用 --get-services 获取所有可开放的服务规则。

firewall-cmd --get-services

添加服务:使用 --add-service 添加一个内置的服务。

firewall-cmd --zone=public --add-service=http

启用添加的规则

热加载:使用 reload 热加载规则

firewall-cmd --reload

冷加载:使用 complete-reload 冷加载规则

firewall-cmd --complete-reload

创建 systemctl 服务

描述

在某些情况下,如需要部署一个可持久运行的服务时,可以创建 systemctl 实现自动登录,和便捷的启动和关闭。

实现案例

首先找到服务文件的存储路径,并创建一个服务文件 [服务名称].service

systemd 服务文件可以保存到多个不同的目录,我个人偏向保存在 /usr/lib/systemd/system/ 目录中。

5/3/2022 修改:现在默认写到 /etc/systemmd/system/ 目录

[Unit]
Description=A simple program

[Service]
ExecStart=/PATH_TO_PROGRAM/example

待施工。。。

Crontab 使用手册

今天在 Linux 做定时任务的时候突然想起来可以使用 Crontab 快速配置。

准备工作

在正式开始前先安装一些需要的程序,包括 Crontab 主体和编辑器选择。

安装 Crontab

首先我们需要安装 Crontab,在 Ubuntu,Debian 下输入:

sudo apt install cron

对于 Fedora,Red Hat,或 CentOS 输入:

sudo yum install cronie

安装编辑器

还需要一个可用的文本编辑器,这里为了方便使用 Nano

使用 Debian, Ubuntu 安装:

sudo apt install nano

使用 Fedora,Red Hat,CentOS 安装:

sudo yum install nano

开始使用

下文是如何使用 Crontab 添加定时任务,以及给懒人推荐的工具。

人工配置

在命令行中输入如下指令:

EDITOR=nano crontab -e

打开 Crontab 的配置页面,此时便可以在最后一行添加需要定时执行的命令。

下方是 Crontab 的配置格式,此时的 * * * * * 对应每分钟执行一次命令。

# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │                                   7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * * <command to execute>

来自:https://en.wikipedia.org/wiki/Cron

自动生成

一些提供自动生成定时任务配置的网站:

在生成好相应的配置后参考人工配置步骤插入至 Crontab 配置文件中即可。

问题解答

Q1. 如何在特定目录下执行命令?

A1. 切换路径后执行命令:cd /你/的/目录/ && [命令]

初识 NodeJS 开发 Rest API

背景

这前端开发可真有意思 - Ecss 11

大概在 4 月份左右,我突然恍然大悟,决定换个正常点的方法写网站,所以我就随便找了个能用的框架,也就是 NodeJS。

在经过了长达 10 分钟的学习后,我开始逐步实践 NodeJS 的代码,途中也遇到了些许问题,不过影响不大。

过程

首先我需要知道,我需要哪些功能,并把功能再分解到不同的小功能,最后实现这个项目的目标。

所需功能

基本:在我正在做的项目目前只有需要一个功能,那就是读取数据库并直接返回数据,十分的简单,没有任何难度。

5/3/2002 添加

  • 使用反向代理转发 GET 请求的响应数据。

服务入口

首先需要告诉程序如何创建地址监听,这里我使用了 Express 开发网页。

const express = require('express')

...

// 实例化
const server = express()

...

server.listen(PORT, () => {
    console.log(`${pkg.name} listening on port ${PORT}`)
})

这段代码表示在指定的端口监听接收的请求,虽然目前并没有任何的数据()

服务路由

既然有了入口,并实现了最基本的端口监听,那么是时候开始创建不同地址的路由了。

通过创建路由,我们可以指定不同的路径应该返回什么数据,当然别忘了在服务入口处引用。

碎碎念:初始化到底要不要放在服务入口啊,太纠结了,我决定暂时不管,能 run 起来就是好代码。

module.exports = (server) => {
    server.use('/api', require('./api'))
}

这段代码在入口实现后,等同于在入口写了一个 server.use('/api', require('./api'))

与此同时,server.use() 参数中的 require 又引用了另一个路由(路由地狱路由套娃

服务模型

在?为什么不写控制器?为什么不写控制器!- Ecss 11

在有了路由帮助我们处理用户的请求后,我们需要有一个模型来处理这些请求的数据。

在这个案例中,用户通过 GET 请求,传入一或者两个 query 参数。

所以我们的模型将会使用用户传入的参数,并对数据库进行读取。

具体实现

首先要读取数据库我们需要建立一个数据库连接,所以我又又又创建了 lib 文件夹。

const config = require('config')
const {MongoClient} = require("mongodb")

const url = config.get('mongodb.url')

const client = new MongoClient(url)

有了这个文件夹后,在其中创建 mongo.js 并实现数据库的连接方法,顺便实现了 query 方法。

module.exports = {
    /**
     * Connect and query the database
     * @param agg - aggregate pipeline statement
     * @returns {Promise<Document[]>} - a list of documents include query result
     */
    query: async (agg) => {
        ...
    }
}

之后在模型中我们只需要给 query 方法传入查询条件,query 方法就返回我们需要的资料。

然后再将 query 返回的数据作为模型的数据返回,再由路由更新视图。

由此,我们成功的创建了一个完整的 GET 请求处理(好耶!)

感言

所以这个模型理论上应该是控制器,而这个 lib 理论上应该是才是真正的模型?(雾)

Nginx 启用文件浏览

文件浏览功能使用 ngx_http_autoindex_module 模块实现,可选配置项不多。

location / {
    root /path/to/folder/;  
    autoindex on | off;   #开启nginx目录浏览功能
    autoindex_exact_size on | off;   #文件大小的大小格式
    autoindex_localtime on | off;   #服务器是否使用本地时间
}

在实际使用中,建议使用 location 搭配路由访问。

SpringBoot 笔记

SpringBoot 基础

SpringBoot 可以直接创建一个轻量的,可部署于生产环境的应用,并可以直接运行。

它在原 Spring 的基础上优化的配置的步骤,使开发者可以更专注程序的开发。

功能

  • 创建独立应用
  • 直接嵌入 Tomcat, Jetty, 或 Undertow
  • 提供打包好的依赖坐标
  • 多种已配置好的 Spring 库
  • 完全无需 XML 配置

快速开始

创建配置

可以通过访问 https://start.spring.io/ 快速生成一个 SpringBoot 的项目,也可以选择第三方 IDE 工具如 IntelliJ 创建。

添加代码

假设您已经创建好了一个 SpringBoot 的项目,并已经安装了 Spring Web 的依赖,那么您可以通过以下代码创建你的第一个控制器。

SpringbootApplication:

package com.learn.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootApplication.class, args);
    }

}

HelloController:

package com.learn.springboot.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String hello() {
        return "Hello Spring!";
    }
}

运行 SpringbootApplication 启动应用,并访问 http://localhost:8080/hello 查看你的代码是否成功。

配置文件

依赖文件

在传统的依赖关系中,依赖导入是一件十分繁琐且复杂的事,但在 SpringBoot 中可以通过依赖关系解决。

SpringBoot 使用了一个类似于材料清单的方式,将不同的依赖整合,提供了一个稳定,测试,有效的依赖方案。

应用配置

SpringBoot 在初始构建的时候已经有了默认配置,但是开发者依旧可以通过修改 application.properties 覆盖这些设置。

application.properties 的后缀也可以是 yaml 或 yml,如果这些文件同时存在,配置将会通过优先级选择:properties > yml > yaml

Yaml 语法

Ymal 是一种容易被人类阅读,和电脑识别的配置类型,并被多种编程语言支持,可选的后缀有 yml 和 yaml。

优势

相比于 properties 或者 xml,yml 的数据结构更简洁,同时带有缩进,直观的显示了配置的关系。

基本语法

  • 大小写敏感
  • 数据值必须要有空格作分割
  • 使用缩进表示层级关系
  • 缩进只能使用空格,这是因为 Tab 对应的空格不一致
  • 缩进的空格数量并不重要,只要同层级元素对其即可
  • 使用 #(井号)表示注释

数据格式

  • 对象:使用键值
people:
  leader: xiaoming

# 行类写法
people: {leader: xiaoming}
  • 数组
people:
  - me
  - you

# 行类写法
people: [me, you]
  • 纯量:单个,不可分的值
msg1: '来做任务吗?\n' # 单引号忽略转义符号
msg2: '真的不来吗?\n' # 双引号识别转义符号
  • 参数引用
name: xiaoming

var: ${name} # ${ } 中的 name 表示引用 name 的值

SpringBoot 读取配置文件

在 SpringBoot 中,提供了三种读取配置文件的方式。

  1. @ Value
  2. Environment
  3. @ ConfigurationProperties

@ Value

使用 Value 注入变量 var 到字符串 name 中。

@Value("${var}")
private String name;

Environment

相比于使用 @Value,Environment 的好处是只需要注入一个对象。

@Autowired // 启动时自动初始化变量
private Environment var; // 注意是 spring 的 Environment

System.out.println(var.getProperty("name"))

@ ConfigurationProperties

使用教程,访问 https://www.baeldung.com/configuration-properties-in-spring-boot 查看

档案(Profile)

在 Spring 的开发过程中,通常会遇到对多种不同的环境如:开发,测试,和生产。如果每次打包的时候都要进行一次配置无疑会增加开发过程中的繁琐程度,而档案则通过动态地切换配置文件解决了这个问题。

档案配置

首先在 resources 文件中创建不同环境的配置文件,如 application-dev.yml 或 application-pro.yml。

档案激活

在默认的配置文件中,使用以下代码激活档案:

# 激活开发环境
spring.profiles.active=dev

档案合并

除了将不同环境分为不同的文件,Spring 也可以在同一个文件中使用分割的方式配置不同的环境。

# 使用 --- 包括代表一段配置
---

spring:
  profiles: dev
---

spring:
  profiles: pro
---

spring.profiles.active: dev

虚拟机参数

除了修改配置外,还可以通过虚拟机配置参数切换配置。(IDE 自带)

命令行参数

与虚拟机参数相似,开发者还可以通过命令行参数切换配置。(IDE 自带,但也可以在命令行中输入参数)

在实际生产环境中,一般通过打包后的 jar 包运行。

内部配置加载顺序

SpringBoot 程序启动时,会从以下几个目录读取文件:

  1. file/config/:当前项目下的 config 目录下
  2. file:当前项目的根目录下
  3. classpath/config/:classpath 的 config 目录下
  4. classpath:classpath 的根目录下

加载顺序从上到下,低优先不会覆盖高优先配置,但会补充未存在的配置。

外部配置加载顺序

访问 https://docs.spring.io/spring-boot/docs/2.1.8.RELEASE/reference/html/boot-features-external-config.html 查看顺序。

整合 Junit

以下为搭建步骤:

  1. 搭建 SpringBoot 工程
  2. 引入 starter-test 依赖坐标
  3. 编写相应测试类
  4. 添加测试类相关注解
  5. 编写测试方法

整合 Redis

以下为搭建步骤:

  1. 搭建 SpringBoot 工程
  2. 引入 redis 起步依赖
  3. 配置 redis 相关属性
  4. 注入 RedisTemplate 模板
  5. 编写测试方法

SpringBoot 高级

自动配置

条件(Condition)

Condition 是 Spring 在 4.0 版本后添加的一个条件判断功能,并通过它选择性的执行 Bean 操作。

满足则创建,不满足则不创建,识别配置文件并创建。

监听机制

启动流程

Linux 服务器启用 BBR

BBR 是一个新的 TCP 拥塞控制算法,常用于改善网络连接如代理。

前置环境

在 Linux Kernal 4.9 以及往上,BBR 会自动集成在系统中,无需用户手动安装。

输入以下命令查看可用的 TCP 控制算法:

sysctl net.ipv4.tcp_available_congestion_control

启用算法

使用任意编辑器打开 /etc/sysctl.conf 文件,添加以下两行:

net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr

部分云服务商,如 DMIT 在初始化服务器时以及配置好了 BBR 算法,可以使用以下指令查看:

sysctl net.ipv4.tcp_congestion_control

最后配上成功后的结果:

root@vmi819506:~# sysctl net.ipv4.tcp_congestion_control 
net.ipv4.tcp_congestion_control = bbr

使用 rsync 定时同步数据

首先我们需要知道 rsync 的基本使用方法,可以通过 man rsync 简单的了解一下。

本地:rsync [选项...] 源... [目标]

通过 SSH 远程连接:

拉取: rsync [选项...] [用户@]地址:源... [目标]

推送: rsync [选项...] 源... [用户@]地址:目标

通过 rsync 监听服务:

拉取: 

  rsync [选项...] [用户@]地址::源... [目标]
  rsync [选项...] rsync://[用户@]地址[:端口]/源... [目标]

推送: 

  rsync [选项...] 源... [用户@]地址::目标
  rsync [选项...] 源... rsync://[用户@]地址[:端口]/目标

只有提供 SRC 参数,而没有 DEST 参数将列出源文件而不是复制。

快速开始

使用平台:ubuntu 20

如何实现:通过在服务端配置 rsync 监听服务,并在客户端主动推送,并设置 crontab 定时任务。

配置 rsync 监听

在远程服务器,也就是希望同步文件保存的服务器中,依次执行命令进行判断:

root@ubuntu:~# sudo apt update
root@ubuntu:~# sudo apt install rsync

检查 rsync 环境是否已安装。

root@ubuntu:~# service rsync status

查看 rsync 服务信息。

● rsync.service - fast remote file copy program daemon
     Loaded: loaded (/lib/systemd/system/rsync.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2022-05-09 00:19:13 MSK; 29min ago
       Docs: man:rsync(1)
             man:rsyncd.conf(5)
   Main PID: 6216 (rsync)
      Tasks: 1 (limit: 2279)
     Memory: 13.0M
     CGroup: /system.slice/rsync.service
             └─6216 /usr/bin/rsync --daemon --no-detach

使用任意编辑器,或者 cat 打开 rsync.service 服务文件。

[Unit]
Description=fast remote file copy program daemon
Documentation=man:rsync(1) man:rsyncd.conf(5)
ConditionPathExists=/etc/rsyncd.conf
After=network.target

[Service]
ExecStart=/usr/bin/rsync --daemon --no-detach

[Install]
WantedBy=multi-user.target

通过 ConditionPathExists=/etc/rsyncd.conf 我们可以得知 rsync 读取 rsyncd.conf 读取配置文件。

root@ubuntu:~# vim /etc/rsyncd.conf

使用任意编辑器打开配置文件,如果不存在就创建一个,别问怎么创建,建议自行百度。

配置选项

[custom1]
pid file = /var/run/rsyncd1.pid
...

[custom2]
pid file = /var/run/rsyncd2.pid
...

[custom3]
pid file = /var/run/rsyncd3.pid
...

必须:创建自定义模块,之后连接时会用到。

uid = user1
gid = group1

必须:rsync 模块的用户,不推荐 root,建议使用 adduser --disabled-login [username] 创建一个。

path = /path/to/backup
use chroot = yes

必须:使用 path 定义这个模块的路径,并使用 use chroot 加强安全性。

read only = no
write only = no

可选:是否启用读取或写入,可自行按需求配置。

hosts allow = 154.53.59.237

# 最大连接数
max connections = 4

# 启用传输日志
transfer logging = yes

# 指定日志格式
log format = %t %a %m %f %b

list = no

额外:通过 hosts allow 限制 IP 访问,以及 list 隐藏使用的模块。

客户端连接

在客户端,同样下载 rsync,使用以下指令测试是否配置成功。

root@vmi819506:~# rsync -avzrn /tmp/test/ rsync://[用户]@[地址][:端口]/[模块]

排错方案

Q1:无法连接到服务端。
A1:可能是服务端的端口未开放,rsync 默认使用 873 端口监听。

设置定时

使用 crontab,时间到后自动运行,下面是一个例子(每 5 分钟运行一次 rsync):

5 * * * * [指令]

总结

那么这篇文章到这里就结束了,之后可能会对本文的一些内容进行补充或修改。

rsync 的配置写起来总感觉不够优雅,也没有 md 的高亮支持,寄

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.