把原knowledge中的文档转移过来,一部分做了重新编制

This commit is contained in:
wandoubaba 2024-11-04 19:15:05 +08:00
parent 57afa11d29
commit 070abbce73
82 changed files with 7776 additions and 181 deletions

8
.env
View File

@ -1,5 +1,5 @@
IMAGE_NAME=vitepressbook
IMAGE_NAME=wandoubabadocs
IMAGE_TAG=latest
CONTAINER_NAME=vitepressbook
CONTAINER_PORT=7001
HOST_PORT=7001
CONTAINER_NAME=wandoubabadocs
CONTAINER_PORT=80
HOST_PORT=7007

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
docs/.vitepress/dist
docs/.vitepress/cache
node_modules
!.gitignore

View File

@ -1,10 +1,6 @@
# 可以用docker一键启动的 VitePress 文档工程
# wandoubaba的技术文档
本项目提供了一种简单的方式来容器化 VitePress 文档网站。通过使用 Docker 和一些辅助脚本,您可以方便地构建、管理和部署您的文档项目。
## 介绍
本工程可以自动将VitePress生成的静态站点打包到docker镜像内包括自定义的nginx配置文件当镜像构建成功后可以直接分发到目标主机不需要携带任何额外的主机文件。
wandoubaba是一位很老的PHP程序员他不是大牛却很喜欢研究程序随着时间一点一点的积累了一些些技术资料包括PHP、Docker、Worker(Webman)、RabbitMQ、FreeSWITCH、GoLang、Kubernete(k8s)等等。
## 系统依赖

View File

@ -2,27 +2,69 @@ import { defineConfig } from 'vitepress'
// https://vitepress.dev/reference/site-config
export default defineConfig({
title: "VitePress Book",
description: "A VitePress Site",
title: "wandoubaba的技术收藏",
description: "wandoubaba是一位很老的PHP程序员他不是大牛却很喜欢研究程序随着时间一点一点的积累了一些些技术资料包括PHP、Docker、Worker(Webman)、RabbitMQ、FreeSWITCH、GoLang、Kubernete(k8s)等等。",
srcDir: 'src',
ignoreDeadLinks: true,
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
logo: '/wandoubaba.svg',
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2019-present wandoubaba'
},
nav: [
{ text: 'Home', link: '/' },
{ text: 'Examples', link: '/markdown-examples' }
{ text: '首页', link: '/' },
{ text: 'PHP', link: '/php/' },
{ text: 'Docker', link: '/docker/' },
{ text: 'Go', link: '/go/' },
{ text: '前端', link: '/frontend/' },
{ text: 'FreeSWITCH', link: '/freeswitch/' }
],
sidebar: [
{ text: '前言', link: '/start' },
{
text: 'Examples',
text: 'Docker',
items: [
{ text: 'Markdown Examples', link: '/markdown-examples' },
{ text: 'Runtime API Examples', link: '/api-examples' }
{ text: '不常用命令备忘', link: '/docker/command' },
{ text: '安装Dockerdebian包管理器', link: '/docker/install-apt' },
{ text: '安装Docker二进制文件', link: '/docker/install-binary' },
{ text: '配置国内镜像源', link: '/docker/mirrors' },
{ text: '制作Vue开发环境镜像', link: '/docker/vue' },
{ text: '制作集成ik中文分词器的elasticsearch镜像', link: '/docker/elasticsearch-ik' },
{ text: '制作支持stomp和延时队列的rabbitmq镜像', link: '/docker/rabbitmq-stomp' },
{ text: '部署单节点MinIO服务', link: '/docker/minio' },
{ text: '部署Posrgres服务', link: '/docker/postgres' },
{ text: '部署一个私有Gitea服务', link: '/docker/gitea' }
]
},
{
text: 'PHP',
items: [
// 'docker-phpfpm74',
// 'docker81',
// 'nginx',
// 'openresty',
// 'php82'
{ text: 'monolog保存日志到mongodb', link: '/php/monolog-mongo' },
{ text: '制作7.4的FPM环境镜像', link: '/php/docker-phpfpm74' },
{ text: '基于PHP8.x制作workman环境镜像', link: '/php/docker-php8' },
{ text: '源码编译安装PHP8.2环境', link: '/php/php82' }
]
},
{
text: '运维',
items: [
{ text: '用acme.sh自动部署和续签SSL证书', link: '/ops/acme' },
{ text: '源码编译安装Nginx', link: '/ops/nginx' },
{ text: '源码编译安装OpenResty', link: '/ops/openresty' },
{ text: 'Linux以二进制方式安装node环境', link: '/ops/node' }
]
}
],
socialLinks: [
{ icon: 'github', link: 'https://github.com/vuejs/vitepress' }
{ icon: 'github', link: 'https://git.wandoubaba.com/wandoubaba/docs.git' }
]
}
})

View File

@ -1,49 +0,0 @@
---
outline: deep
---
# Runtime API Examples
This page demonstrates usage of some of the runtime APIs provided by VitePress.
The main `useData()` API can be used to access site, theme, and page data for the current page. It works in both `.md` and `.vue` files:
```md
<script setup>
import { useData } from 'vitepress'
const { theme, page, frontmatter } = useData()
</script>
## Results
### Theme Data
<pre>{{ theme }}</pre>
### Page Data
<pre>{{ page }}</pre>
### Page Frontmatter
<pre>{{ frontmatter }}</pre>
```
<script setup>
import { useData } from 'vitepress'
const { site, theme, page, frontmatter } = useData()
</script>
## Results
### Theme Data
<pre>{{ theme }}</pre>
### Page Data
<pre>{{ page }}</pre>
### Page Frontmatter
<pre>{{ frontmatter }}</pre>
## More
Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata).

View File

@ -1,25 +0,0 @@
---
# https://vitepress.dev/reference/default-theme-home-page
layout: home
hero:
name: "VitePress Book"
text: "A VitePress Site"
tagline: My great project tagline
actions:
- theme: brand
text: Markdown Examples
link: /markdown-examples
- theme: alt
text: API Examples
link: /api-examples
features:
- title: Feature A
details: Lorem ipsum dolor sit amet, consectetur adipiscing elit
- title: Feature B
details: Lorem ipsum dolor sit amet, consectetur adipiscing elit
- title: Feature C
details: Lorem ipsum dolor sit amet, consectetur adipiscing elit
---

View File

@ -1,85 +0,0 @@
# Markdown Extension Examples
This page demonstrates some of the built-in markdown extensions provided by VitePress.
## Syntax Highlighting
VitePress provides Syntax Highlighting powered by [Shiki](https://github.com/shikijs/shiki), with additional features like line-highlighting:
**Input**
````md
```js{4}
export default {
data () {
return {
msg: 'Highlighted!'
}
}
}
```
````
**Output**
```js{4}
export default {
data () {
return {
msg: 'Highlighted!'
}
}
}
```
## Custom Containers
**Input**
```md
::: info
This is an info box.
:::
::: tip
This is a tip.
:::
::: warning
This is a warning.
:::
::: danger
This is a dangerous warning.
:::
::: details
This is a details block.
:::
```
**Output**
::: info
This is an info box.
:::
::: tip
This is a tip.
:::
::: warning
This is a warning.
:::
::: danger
This is a dangerous warning.
:::
::: details
This is a details block.
:::
## More
Check out the documentation for the [full list of markdown extensions](https://vitepress.dev/guide/markdown).

View File

@ -0,0 +1,40 @@
# docker不常用命令备忘
> wandoubaba / 2024-10-29
## 基础操作
### 查看磁盘占用
```sh
# 查看镜像、容器、卷的总磁盘占用情况
docker system df
# 查看每个image、container的详细空间占用情况
docker system df -v
```
## 清理操作
### 删除关闭的容器和未使用的镜像
```sh
docker system prune -a
```
## 镜像操作
### 把容器导出为镜像
```sh
docker commit <容器ID或容器名> <镜像名>:<镜像tag>
```
### 镜像导入导出save & load
```sh
docker save -o <要保存的文件名>.tar <本地镜像名>:<本地镜像tag>
```
```sh
docker load < <镜像文件名>
```

View File

@ -0,0 +1,55 @@
# 制作集成ik中文分词器的elasticsearch镜像
> wandoubaba / 2024-10-29
## 说明
按照本文过程制作后的镜像不是跨平台的在arm64平台制作的镜像只能用于arm64平台在amd64平台制作的镜像只能用于amd64平台。
## 制作过程
本文要制作一个整合了`analysis-ik`分词器的`elasticsearch`服务镜像。
注意`analysis-ik`和`elasticsearch`的版本要保持一致,本文选择版本`7.17.18`。
拉取基础镜像:
```sh
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.17.18
```
启动容器:
```sh
docker run -p 127.0.0.1:9200:9200 -p 127.0.0.1:9300:9300 -e "discovery.type=single-node" --name=es docker.elastic.co/elasticsearch/elasticsearch:7.17.18
```
进入容器安装`analysis-ik`插件:
```sh
docker exec -it es bash
```
```sh
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.17.18/elasticsearch-analysis-ik-7.17.18.zip
```
在容器内执行上面的命令后会自动下载并安装`elasticsearch-analysis-ik`插件(如果由于网络原因导致下载制作,请重试几次),下载后的问答请回答`y`。
安装成功后退出容器:
```sh
exit
```
导出镜像:
```sh
docker commit es <镜像名称>:<镜像tag>
```
## 一键启动
这个仓库已经利用本文制作的镜像实现了一个一键启动的服务。
<https://git.wandoubaba.com/wandoubaba/docker-elasticsearch-ik>

292
docs/src/docker/gitea.md Normal file
View File

@ -0,0 +1,292 @@
# Docker部署Gitea服务器完整过程
> wandoubaba / 2024-10-29
## 介绍
下面引用 [gitea官方文档](https://docs.gitea.cn/) 中的一段描述:
```
Gitea 是一个轻量级的 DevOps 平台软件。从开发计划到产品成型的整个软件生命周期,他都能够高效而轻松的帮助团队和开发者。包括 Git 托管、代码审查、团队协作、软件包注册和 CI/CD。它与 GitHub、Bitbucket 和 GitLab 等比较类似。 Gitea 最初是从 Gogs 分支而来,几乎所有代码都已更改。
```
## 本文目标
- 仓库、数据库等用户产生数据保存在数据盘中
- 使用postgresql数据库
- 数据库和gitea服务以docker方式启动
- 主机和容器使用22端口实现SSH直通
- 使用域名访问通过nginx反向代理实现通过80端口访问web UI
> 为了方便文档中的操作都是在root用户下执行建议在生产环境中使用普通用户执行操作在命令前加`sudo`。
## 准备域名
提前准备一个公网域名指向到下面即将要操作的服务器IP上后面的操作完成了域名解析也差不多该生效了。
> 假设我们用的是`gitea.wukezhenzhu.com`,后面配置是用以它为例。
## 准备服务器
本文中我使用了Debian 11既然是用docker方式部署的所以几乎不受操作系统限制。
> 接下来的操作是本人一步一步边操作加记录的。
### 挂载数据盘
通过`df -h`、`lsblk`、`fdisk -l`等命令确认当前磁盘和分区状态,下面是结果示例:
```sh
root@debian:~# df -h
Filesystem Size Used Avail Use% Mounted on
udev 2.0G 0 2.0G 0% /dev
tmpfs 394M 560K 393M 1% /run
/dev/sda1 491G 1.4G 464G 1% /
tmpfs 2.0G 0 2.0G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 394M 0 394M 0% /run/user/0
root@debian:~# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 500G 0 disk
├─sda1 8:1 0 499G 0 part /
├─sda2 8:2 0 1K 0 part
└─sda5 8:5 0 975M 0 part [SWAP]
sdb 8:16 0 4T 0 disk
sr0 11:0 1 1024M 0 rom
root@debian:~# fdisk -l
Disk /dev/sdb: 4 TiB, 4398046511104 bytes, 8589934592 sectors
Disk model: Virtual disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/sda: 500 GiB, 536870912000 bytes, 1048576000 sectors
Disk model: Virtual disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xac8bf5c9
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 1046575103 1046573056 499G 83 Linux
/dev/sda2 1046577150 1048573951 1996802 975M 5 Extended
/dev/sda5 1046577152 1048573951 1996800 975M 82 Linux swa
```
从上面的结果可以看到,系统中有一个名为`/dev/sdb`的4TB硬盘是空闲的下面我们要把它整个挂载到`/data`目录下:
```sh
root@debian:~# mkfs.ext4 /dev/sdb
mke2fs 1.46.2 (28-Feb-2021)
Creating filesystem with 1073741824 4k blocks and 134217728 inodes
Filesystem UUID: f081b706-f637-4b84-b70b-5521b7ad5b6b
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
102400000, 214990848, 512000000, 550731776, 644972544
Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done
root@debian:~# mkdir /data
root@debian:~# mount -t ext4 /dev/sdb /data
root@debian:~# df -h
Filesystem Size Used Avail Use% Mounted on
udev 2.0G 0 2.0G 0% /dev
tmpfs 394M 560K 393M 1% /run
/dev/sda1 491G 1.4G 464G 1% /
tmpfs 2.0G 0 2.0G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 394M 0 394M 0% /run/user/0
/dev/sdb 4.0T 28K 3.8T 1% /data
```
经过上面的操作,已经把磁盘`/dev/sdb`格式化为ext4文件系统并成功挂载下`/data`目录下,但是如果现在重启系统后,数据盘还不能自动完成挂载,需要执行下面的操作:
```sh
root@debian:~# ll /dev/disk/by-uuid/
total 0
lrwxrwxrwx 1 root root 10 Apr 21 14:22 0bc1a76e-3457-4e2c-b708-a201e510f343 -> ../../sda1
lrwxrwxrwx 1 root root 9 Apr 21 14:30 f081b706-f637-4b84-b70b-5521b7ad5b6b -> ../../sdb
lrwxrwxrwx 1 root root 10 Apr 21 14:22 ff162b2a-5e9e-4661-854a-64ad11f22fa5 -> ../../sda5
root@debian:~# echo "UUID=f081b706-f637-4b84-b70b-5521b7ad5b6b /data ext4 defaults 0 0" >> /etc/fstab
```
> 上面写入`/etc/fstab`文件中的UUID是在`/dev/disk/by-uuid/`中查到的`sdb`对应的UUID。
可以试着`reboot`一下,重启后数据盘会自动完成挂载。
> 操作系统的准备工作已经完成,但是我们建议中国大陆用户要为系统配置一组高速的软件源,配置文件位置`/etc/apt/sources.list`,本文不对展开讲解。
### 准备docker环境
> 按照docker官方文档安装[Docker Engine](https://docs.docker.com/engine/install/debian/)和[Docker Compose](https://docs.docker.com/compose/install/other/)。
```sh
# 卸载原有旧版本的docker新系统可以跳过
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
# 安装ca支持
sudo apt-get update && sudo apt-get install ca-certificates curl gnupg
# 配置docker官方GPG密钥
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# 配置docker官方软件源
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装docker engine
sudo apt-get update && sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 单独安装docker-compose不执行后面这步使用docker compose [command]也是可以的)
curl -SL https://github.com/docker/compose/releases/download/v2.17.2/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
# 查看docker版本
docker version
# 查看docker-compose版本
docker-compose version
```
对于国内服务器给docker hub配置几个加速源是必要的操作[阿里云容器镜像服务-镜像加速器](https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors)。
除了阿里云,也可以试试下面的加速源:
- https://registry.docker-cn.com
- https://hub-mirror.c.163.com
### 部署gitea和postgresql服务
#### 配置nginx实现反向代理
我们希望实现的是通过网址http://gitea.wukezhenzhu.com直接访问gitea的web UI而gitea服务默认使用的http端口是3000为了不过多更改服务配置我们只要用nginx做一层指向127.0.0.1:3000端口的反向代理即可具体如何操作本文不展开。
#### 创建git专用的系统账号和分组
```sh
# 创建git分组和git用户
adduser --system --shell /bin/bash --gecos 'Git Version Control' --group --disabled-password --home /home/git git
# 记录下返回结果中的UID和GID
Adding system user `git' (UID 112) ...
Adding new group `git' (GID 117) ...
Adding new user `git' (UID 112) with group `git' ...
# 为git用户生成ssh-key
sudo -u git ssh-keygen -t rsa -b 4096 -C "Gitea Host Key"
```
#### 为主机和容器建立SSH直通
创建名为`/usr/local/bin/gitea`的可执行文件,文件内容:
```shell
ssh -p 2222 -o StrictHostKeyChecking=no git@127.0.0.1 "SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $0 $@"
```
为`/usr/local/bin/gitea`文件添加可执行权限:
```sh
chmod +x /usr/local/bin/gitea
```
把git用户的ssh公钥添加到`/home/git/.ssh/authorized_keys`中(因为主机的`/home/git/.ssh/`会映射到容器中)
```sh
echo "$(cat /home/git/.ssh/id_rsa.pub)" >> /home/git/.ssh/authorized_keys
```
#### 准备docker-compose.yml文件
创建`/data/docker-compose.yml`文件,内容如下(随着时间推移,可以试着改变镜像的版本),注意修改`USER_UID`和`USER_GID`为实际值:
```yml
version: "3"
networks:
gitea:
external: false
services:
gitea:
image: gitea/gitea:1.19
container_name: gitea
environment:
- USER_UID=112
- USER_GID=117
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=gitea_db:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=gitea
restart: always
networks:
- gitea
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
- /home/git/.ssh/:/data/git/.ssh
ports:
- "3000:3000"
- "127.0.0.1:2222:22"
depends_on:
- gitea_db
gitea_db:
image: postgres:14
container_name: gitea_db
restart: always
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=gitea
- POSTGRES_DB=gitea
networks:
- gitea
volumes:
- ./postgres:/var/lib/postgresql/data
```
在/data目录下执行
```sh
docker compose up
```
如果在编排期间没有提示错误的话说明我们在服务器端的部署工作基本完成了下面进入web安装与配置阶段。
#### 通过Web UI完成服务安装与配置
假设最开始做的域名解析已经生效了接下来打开浏览器访问gitea.wukezhenzhu.com如果打不开页面检查检查域名解析、服务器防火墙、nginx代理
```
http://gitea.wukezhenzhu.com
```
- 数据库设置都使用默认值就行因为我们没有把pg的5432端口映射给主机所以基本也不需要给数据库设置强口令
- 站点名称会显示在Web首页和浏览器标题栏
- 仓库根目录:默认
- LFS根目录默认
- 以用户名运行默认git
- 服务器域名就是刚才解析的域名文本中是gitea.wukezhenzhu.com
- SSH服务端口22
- HTTP服务端口3000
- 基础URL如果这里是带:3000端口号的url我们就把端口号去掉就是http://gitea.wukezhenzhu.com/。
- 日志路径:默认
- 启用更新检查不勾选因为我们用的是docker即使在线更新了容器重启后也会把程序重置。
- 电子邮箱设置:建议配置并开启邮件确认注册和邮件通知提醒
- 第三方服务设置:根据情况
- 管理账号设置:根据情况
完成以上配置后直接点“立即安装”然后等待一小会页面会自动以管理员登录如果创建了管理员或者进入到gitea的登录页。
#### 以daemon方式重新启动服务
在服务器上按ctrl+c停止docker服务再重启执行一遍docker-compose命令这次后面加上-d。
```sh
docker compose up -d
```
好了,大功告成!

3
docs/src/docker/index.md Normal file
View File

@ -0,0 +1,3 @@
# Docker
记录了一些与docker相关的内容。

View File

@ -0,0 +1,41 @@
# Debian11中安装Docker
> wandoubaba / 2024-10-29
本文参考docker官方文档
- <https://docs.docker.com/engine/install/debian/>
## 联网环境安装
依次执行下面的命令就可以。
> 如果root账号下提示没有`sudo`命令的话,使用`apt-get install sudo -y`安装一下就可以了。
```sh
# 卸载旧版本(可省略)
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
# 安装新版本
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```
> 可以把上面的过程制作一个`docker.sh`脚本里,直接执行脚本就能完成安装了。
## 验证安装
```sh
# 查看docker版本
docker version
# 查看docker compose版本
docker compose version
```

View File

@ -0,0 +1,319 @@
# 用二进制文件安装Docker
> wandoubaba / 2024-11-04
## 说明
本文在Debian12系统上直接通过二进制包安装docker服务适用于离线场景。
## 系统依赖
- 64位环境
- Linux kernel版本3.10以上
- iptables版本1.4以上
- git版本1.7以上
- ps
- xz-utils版本4.9以上
- 正确的cgroupfs层次结构
## 准备二进制文件
先在可以连接互联网的环境下载安装包截至文本发布时docker的最新版本是27.3.1
```sh
# docker、containerd等
curl -L -O https://download.docker.com/linux/static/stable/x86_64/docker-27.3.1.tgz
# docker compose
curl -L -O https://github.com/docker/compose/releases/download/v2.30.1/docker-compose-linux-x86_64
# docker buildx
curl -L -O https://github.com/docker/buildx/releases/download/v0.18.0/buildx-v0.18.0.linux-amd64
```
然后以各种各样的方式把二进制安装包复制到目标环境中。
## 安装过程
### 复制docker文件
```sh
tar zxvf docker-27.3.1.tgz
sudo cp docker/* /usr/bin/
```
### 创建用户组
```sh
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker
```
### 注册系统服务
#### containerd.service
```sh
vim /usr/lib/systemd/system/containerd.service
```
内容如下:
```sh
# Copyright The containerd Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target
[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/bin/containerd
Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=infinity
# Comment TasksMax if your systemd version does not supports it.
# Only systemd 226 and above support this version.
TasksMax=infinity
OOMScoreAdjust=-999
[Install]
WantedBy=multi-user.target
```
#### docker.socket
```sh
vim /usr/lib/systemd/system/docker.socket
```
内容
```sh
[Unit]
Description=Docker Socket for the API
[Socket]
# If /var/run is not implemented as a symlink to /run, you may need to
# specify ListenStream=/var/run/docker.sock instead.
ListenStream=/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=sockets.target
```
#### docker.service
```sh
vim /usr/lib/systemd/system/docker.service
```
内容
```sh
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target docker.socket firewalld.service containerd.service time-set.target
Wants=network-online.target containerd.service
Requires=docker.socket
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutStartSec=0
RestartSec=2
Restart=always
# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
# to make them work for either version of systemd.
StartLimitBurst=3
# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
# this option work for either version of systemd.
StartLimitInterval=60s
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Comment TasksMax if your systemd version does not support it.
# Only systemd 226 and above support this option.
TasksMax=infinity
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
OOMScoreAdjust=-500
[Install]
WantedBy=multi-user.target
```
#### 启动服务并设置开机自启
```sh
systemctl enable --now containerd
systemctl enable --now docker
```
### 安装docker compose
截至本文发布时docker compose的最新版本是2.30.1以下命令适用于amd64平台其他平台请到<https://github.com/docker/compose/releases>去找对应的二进制包。
```sh
cp docker-compose-linux-x86_64 /usr/local/lib/docker/cli-plugins/docker-compose
chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
```
### 安装docker buildx
截至本文发布时docker buildx的最新版本是0.18.0以下命令适用于amd64平台其他平台请到<https://github.com/docker/buildx/releases>对找对应的二进制包。
```sh
cp buildx-v0.18.0.linux-amd64 /usr/local/lib/docker/cli-plugins/docker-buildx
chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx
docker buildx install
```
### 配置网络
```sh
modprobe br_netfilter
sudo bash -c 'echo -e "net.bridge.bridge-nf-call-iptables = 1\nnet.bridge.bridge-nf-call-ip6tables = 1" > /etc/sysctl.d/bridge.conf && modprobe br_netfilter'
sudo sysctl -p /etc/sysctl.d/bridge.conf
systemctl restart docker
```
### 配置镜像仓库地址
> 纯离线环境又没有私有仓库的话,这一步做不做没什么区别。
```sh
mkdir /etc/docker
vim /etc/docker/daemon.json
```
文件内容:
```json
{
"registry-mirrors": [
"https://registry.docker-cn.com",
"https://docker.mirrors.ustc.edu.cn",
"https://dockerhub.azk8s.cn",
"http://hub-mirror.c.163.com"
]
}
```
生效
```sh
systemctl daemon-reload
systemctl restart docker
```
## 结果确认
执行`docker info`后应该可以看到下面的结果:
```sh
Client:
Version: 27.3.1
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.18.0
Path: /usr/local/lib/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.30.1
Path: /usr/local/lib/docker/cli-plugins/docker-compose
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 27.3.1
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: systemd
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 7f7fdf5fed64eb6a7caf99b3e12efcf9d60e311c
runc version: v1.1.14-0-g2c9f560
init version: de40ad0
Security Options:
apparmor
seccomp
Profile: builtin
cgroupns
Kernel Version: 6.1.0-23-amd64
Operating System: Debian GNU/Linux 12 (bookworm)
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 3.698GiB
Name: ten01
ID: f3c00e60-7eee-4b53-97a6-b1937701c3b1
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://registry.docker-cn.com/
https://docker.mirrors.ustc.edu.cn/
https://dockerhub.azk8s.cn/
http://hub-mirror.c.163.com/
Live Restore Enabled: false
Product License: Community Engine
```

62
docs/src/docker/minio.md Normal file
View File

@ -0,0 +1,62 @@
# Docker部署MinIO服务
> wandoubaba / 2024-10-29
## 介绍
下面是[MinIO官网](https://www.minio.org.cn/)的一段介绍:
```
MinIO 是一种高性能、S3 兼容的对象存储。
它专为大规模 AI/ML、数据湖和数据库工作负载而构建并且它是由软件定义的存储。
不需要购买任何专有硬件,就可以在云上和普通硬件上拥有分布式对象存储。
MinIO拥有开源 GNU AGPL v3 和商业企业许可证的双重许可。
```
简单来说MinIO 是一个被广泛用使用的开源对象存储服务组件,可以用它轻松搭建私有的对象存储服务。
## 操作过程
本文只是简单启动一个单节点单硬盘服务,更复杂的场景可以参考[MinIO对象存储Container官方文档](https://www.minio.org.cn/docs/minio/container/index.html)。
### 创建存储目录
比如创建`/app/minio/`目录,准备用其中的`/app/minio/data`保存所有存储桶bucket和其中的对象。
```sh
mkdir /app/minio/data -p
```
### 创建docker-compose.yml文件
创建文件`/app/minio/docker-compose.yml`,内容如下(注意自己改管理员账号密码):
```yml
services:
minio:
image: quay.io/minio/minio:latest
hostname: "minio"
restart: always
environment:
MINIO_ROOT_USER: ROOTNAME
MINIO_ROOT_PASSWORD: CHANGEME123
MINIO_VOLUMES: /data
ports:
- 9001:9001
- 9000:9000
volumes:
- ./data:/data
command: server --console-address ':9001'
```
### 启动容器
在`/app/minio`目录下执行下面的命令:
```sh
docker compose up -d
```
### 验证安装
服务器防火墙要放行 9000 和 9001端口假设我的服务器的IP是 192.168.0.8 那么在web浏览器上打开 `http://192.168.0.8:9001` ,应该可以看到登录页,填入`MINIO_ROOT_USER`和`MINIO_ROOT_PASSWORD`对应的值应该可以登录minio的web控制台。

View File

@ -0,0 +1,27 @@
# 配置Docker Hub国内镜像加速
本文以以下操作系统适用Ubuntu 16.04+, Debian 8+, CentOS 7+
创建或者修改`/etc/docker/daemon.json`文件:
```json
{
"registry-mirrors": [
"https://registry.docker-cn.com",
"https://docker.mirrors.ustc.edu.cn",
"https://dockerhub.azk8s.cn",
"http://hub-mirror.c.163.com"
]
}
```
> 也可以去阿里云镜像加速服务中获取账号专用的阿里云加速链接,添加到`registry-mirrors`数组中。
重启服务:
```sh
sudo systemctl daemon-reload
sudo systemctl restart docker
```
用命令`docker info`可以查看配置是否生效。

View File

@ -0,0 +1,86 @@
# Docker部署Postgres数据库服务
> wandoubaba / 2024-10-29
## 创建存储目录
比如创建`/app/postgres/`目录。
```sh
mkdir /app/postgres -p
```
## 创建docker-compose.yml文件
创建文件`/app/postgres/docker-compose.yml`内容如下注意自己改postgres用户的密码
以host网络启动
```yml
services:
db:
image: postgres:14
container_name: postgres
restart: always
environment:
POSTGRES_PASSWORD: PASSWORD
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- ./data:/var/lib/postgresql/data
network_mode:
host
```
以bridge网络启动推荐
```yml
services:
db:
image: postgres:14
container_name: postgres
restart: always
environment:
POSTGRES_PASSWORD: PASSWORD
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- ./data:/var/lib/postgresql/data
ports:
- 5432:5432
```
## 启动容器
在`/app/postgres`目录下执行下面的命令:
```sh
docker compose up -d
```
## 查看当前postgres版本
### 方法一 - 进入容器使用命令
```sh
docker exec -it postgres /bin/bash
# 进入容器后执行下面命令
psql --version
# psql (PostgreSQL) 14.1 (Debian 14.1-1.pgdg110+1)
postgres --version
# postgres (PostgreSQL) 14.1 (Debian 14.1-1.pgdg110+1)
pg_config | grep VERSION
# VERSION = PostgreSQL 14.1 (Debian 14.1-1.pgdg110+1)
```
### 方法二 - 连接数据库使用查询命令
```sql
show server_version;
```
结果如下:
```txt
server_version |
------------------------------+
14.1 (Debian 14.1-1.pgdg110+1)|
```

View File

@ -0,0 +1,104 @@
# rabbitmq启用stomp和延时队列(rabbitmq_delayed_message_exchange插件)构建多平台镜像
> wandoubaba / 2024-10-29
## 下载对应版本的插件安装包
本文使用的rabbitmq版本是3.13.4,用下面的命令可以下载对应的延时队列插件安装包
```sh
curl -L -O https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/download/v3.13.0/rabbitmq_delayed_message_exchange-3.13.0.ez
```
> 如果要使用其他版本的rabbitmq可以到 <https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases> 去找对应的安装包。
## Dockerfile文件
```dockerfile
# 使用 RabbitMQ 3.13.4 管理镜像作为基础镜像
FROM rabbitmq:3.13.4-management
# 设置工作目录
WORKDIR /
# 将本地的插件文件复制到容器内
COPY rabbitmq_delayed_message_exchange-3.13.0.ez .
# 启用插件
RUN rabbitmq-plugins enable rabbitmq_delayed_message_exchange rabbitmq_stomp rabbitmq_web_stomp rabbitmq_web_stomp_examples
# 持久化数据目录
VOLUME ["/var/lib/rabbitmq/mnesia"]
# 将容器的启动命令更改为默认命令
CMD ["rabbitmq-server"]
```
> `Dockerfile`文件应该与`rabbitmq_delayed_message_exchange-3.13.0.ez`文件在同一个目录下。
## 构建多平台镜像
### 确认`docker buildx`环境
```sh
docker info
```
执行以上命令可以看到类似下面的信息:
```txt
Client: Docker Engine - Community
Version: 27.0.3
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.15.1
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.28.1
Path: /usr/libexec/docker/cli-plugins/docker-compose
...
```
一般情况下如果是通过包管理器安装的docker engine或者docker desktop的话默认就已经安装好了buildx和compose插件了。
### 跨平台构建并发布
接下来我们的目标是用上面的Dockerfile构建多平台的`rabbitmq:3.13.4`镜像并直接推送到`quay.io`平台上:
> 为什么是`quay.io`因为有一段时间全国封锁docker-hub时`quay.io`是可以推拉镜像的,仅此而已。
```sh
docker login quay.io
docker buildx create --use
docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64 --push -t quay.io/wandoubaba517/rabbitmq:3.13.4 .
```
执行上面的命令执行过程中会自动从docker hub上拉取名为`moby/buildkit:buildx-stable-1`的镜像并启动容器开始自动构建和推送整个过程在我的2核4G服务器上执行了好几个小时所以建议使用`tmux`等工具,任务执行起来就可以关闭终端了。
## 使用镜像
```sh
docker run -d \
-p 5672:5672 \
-p 15672:15672 \
-p 61613:61613 \
-v ./data:/var/lib/rabbitmq/mnesia \
-v ./conf/conf.d:/etc/rabbitmq/conf.d \
--hostname rabbitmq \
--name rabbitmq \
quay.io/wandoubaba517/rabbitmq:3.13.4
```
## 工程示例
<https://git.wandoubaba.com/wandoubaba/docker-rabbitmq>
```sh
git clone git@git.wandoubaba.com:wandoubaba/docker-rabbitmq.git
cd docker-rabbitmq
# 先在conf/conf.d/10-defaults.conf文件中设置首次启动创建的默认用户名和密码
# 然后再执行启动脚本
./start
```

126
docs/src/docker/vue.md Normal file
View File

@ -0,0 +1,126 @@
# 制作vue开发环境镜像(node18.18.2+openresty1.21.4.2)
> wandoubaba / 2024-10-29
## 说明
按照本文过程制作后的镜像不是跨平台的在arm64平台制作的镜像只能用于arm64平台在amd64平台制作的镜像只能用于amd64平台。
## 系统环境
- docker engine
- docker compose
## 制作过程
### 拉取node18.18.2镜像
```sh
docker pull node:18-bullseye
```
### 准备openresty源码
```sh
curl -O https://openresty.org/download/openresty-1.21.4.2.tar.gz
tar zxvf openresty-1.21.4.2.tar.gz
```
### 启动node容器
```sh
docker run -itd --name=node-resty node:18-bullseye
```
### 容器内环境
如果宿主系统是deiban11就直接把sources.list复制到容器内如果不是就单独制作一个deiban11的sources.list文件复制到容器内
```sh
docker cp /etc/apt/sources.list node-resty:/etc/apt/
docker cp openresty-1.21.4.2 node-resty:/
docker exec -it node-resty bash
```
在容器内进行下面的操作
```sh
apt update
cd openresty-1.21.4.2
./configure -j2
gmake
gmake install
ln -sf /usr/local/openresty/bin/openresty /usr/local/bin/nginx
cd /
mkdir /app/web -p
exit
```
### 宿主机操作
```sh
# 创建一个开发目录
mkdir web
# 把nginx.conf文件复制到宿主
docker cp node-resty:/usr/local/openresty/nginx/conf/nginx.conf ./
# 把docker-entrypoint.sh复制到宿主
docker cp node-resty:/usr/local/bin/docker-entrypoint.sh ./
```
修改docker-entrypoint.sh文件在`exec "$@"`一句之前加上`nginx`一行。
```sh
docker cp ./docker-entrypoint.sh node-resty:/usr/local/bin/
```
### 生成镜像
```sh
docker commit node-resty node-resty:18.18.2
```
### 提交到docker hub
```sh
docker login --username=<hub.docker.com的用户名>
docker tag node-resty:18.18.2 <docker仓库>/node-resty:18.18.2
docker push <docker仓库>/node-resty:18.18.2
```
### 使用方法
假设在某一个vue项目目录下。
```sh
docker pull <docker仓库>/node-resty:18.18.2
# npm install
docker run -it --rm --name=node-resty -w /app/web -v ./:/app/web <docker仓库>/node-resty:18.18.2 npm install
# npm run build
docker run -it --name=node-resty -w /app/web -v ./:/app/web -v ./dist:/usr/local/openresty/nginx/html -p 80:80 <docker仓库>/node-resty:18.18.2 npm run build
```
可以看到上面的操作明显太麻烦了。我们可以试着写一个docker-compose.yml文件
```yml
version: "3.1"
services:
node-resty:
image: <docker仓库>/node-resty:18.18.2
container_name: node-resty
ports:
- 80:80
restart: always
volumes:
- ./docker-entrypoint.sh:/usr/local/bin/docker-entrypoint.sh
- ./:/app/web
- ./nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf
- ./dist:/usr/local/openresty/nginx/html
working_dir: /app/web
stdin_open: true
command: ["npm", "run", "build"]
```
还可以通过编写shell脚本的方式解锁更多开发和发布姿势。
参照<https://git.wandoubaba.com/wandoubaba/docker-vue3>可以把镜像用于实际开发和生产。

View File

@ -0,0 +1,387 @@
## CentOS7.9(2009)安装freeswitch1.10
---
> 2022年6月这个文档已经失效按照这个文档操作将不会成功转至Debian11编译安装FreeSWITCH1.10,亲测成功。
### 安装centos7.9(2009)操作系统
### 系统更新和安装依赖
```bash
yum update -y
# 安装fs依赖
yum install -y http://files.freeswitch.org/freeswitch-release-1-6.noarch.rpm epel-release
# 安装ffmpeg需要
rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-1.el7.nux.noarch.rpm
yum install -y yum-utils git gcc gcc-c++ automake autoconf libtool libtiff-devel libjpeg-devel openssl-devel vim
yum install -y alsa-lib-devel bison broadvoice-devel bzip2 curl-devel libdb4-devel e2fsprogs-devel erlang flite-devel g722_1-devel gdbm-devel gnutls-devel ilbc2-devel ldns-devel libcodec2-devel libcurl-devel libedit-devel libidn-devel libmemcached-devel libogg-devel libsilk-devel libsndfile-devel libtheora-devel libuuid-devel libvorbis-devel libxml2-devel lua-devel lzo-devel ncurses-devel net-snmp-devel opus-devel pcre-devel perl perl-ExtUtils-Embed pkgconfig portaudio-devel postgresql-devel python-devel python-devel soundtouch-devel speex-devel sqlite-devel unbound-devel unixODBC-devel which yasm zlib-devel libshout-devel libmpg123-devel lame-devel rpm-build libX11-devel libyuv-devel swig wget ffmpeg ffmpeg-devel
# 单独下载spandsp源码
cd /usr/local/src
git clone https://github.com/freeswitch/spandsp.git
cd spandsp
./bootstrap.sh
./configure
make
make install
ldconfig
# 单独下载sofia-sipSIP协议栈源码
cd /usr/local/src
git clone https://github.com/freeswitch/sofia-sip.git
cd sofia-sip
./bootstrap.sh
./configure
make
make install
ldconfig
cd ..
# 编译安装cmake 3.7.2
cd /usr/local/src
wget https://cmake.org/files/v3.7/cmake-3.7.2.tar.gz
tar zxvf cmake-3.7.2.tar.gz
cd cmake-3.7.2
./bootstrap
gmake
gmake install
# 安装libatomic
yum install -y libatomic uuid-devel libuuid-devel
# 单独下载libks源码需要cmake 3.7.2以上版本)
cd /usr/local/src
git clone https://github.com/signalwire/libks.git
cd libks
cmake .
make
make install
# 单独安装opus-dev否则在freeswitch里make时可能会报You must install libopus-dev to build mod_opus
cd /usr/local/src
wget https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz
tar zxvf opus-1.3.1.tar.gz
cd opus-1.3.1
./configure
make
make install
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
# 安装python组件
curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip-2.7.py
python get-pip-2.7.py -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
#这两个命令用完之后使用pip install 后面要加上
-i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
# 验证pip是否安装成功可以用 `pip --version`
# pip安装python组件
pip install pydub -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
pip install python-ESL -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
pip install pika -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
pip install DBUtils==2.0.3 -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
# pip install dbutils python 2.7 is not support dbutils炸裂
```
### 开始安装
```bash
cd /usr/local/src
git clone -b v1.10 https://github.com/signalwire/freeswitch.git freeswitch
# 如果github连接不顺畅的话可以试试码云镜像仓库更新慢1天
# git clone -b v1.10 https://gitee.com/mirrors/FreeSWITCH.git freeswitch
cd freeswitch
./bootstrap.sh -j
```
- 编辑modules.conf文件
```bash
vim modules
```
根据需要打开或关闭注释
```
formats/mod_shout
languages/mod_python
#event_handlers/mod_cdr_pg_csv
asr_tts/mod_unimrcp
#开启freeswitch自带的http状态界面
xml_int/mod_xml_rpc
```
如果需要使用mod_xml_curl的话
```
xml_int/mod_xml_curl
```
给不需要的模块加上注释
```
#applications/mod_av
#applications/mod_signalwire
```
然后保存退出
- 开始编译安装
```bash
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
./configure --with-python=/usr/bin/python2.7 --with-lua=/usr/bin/lua --enable-core-pgsql-support
# 如果在spandsp位置报错可能是忘export那一句
make
#make mod_cdr_pg_csv-install
make mod_unimrcp-install
# 如果需要xml_curl模块的话
make mod_xml_curl-install
make mod_xml_rpc-install
make install
```
- 安装音频文件(英文)
```bash
make cd-sounds-install
make cd-moh-install
make uhd-sounds-install
make uhd-moh-install
make hd-sounds-install
make hd-moh-install
make sounds-install
make moh-install
# make moh-install && make sounds-install && make hd-moh-install && make hd-sounds-install && make uhd-moh-install && make uhd-sounds-install && make cd-moh-install && make cd-sounds-install
```
- 建立软连接
```bash
sudo ln -sf /usr/local/freeswitch/bin/freeswitch /usr/local/bin/
sudo ln -sf /usr/local/freeswitch/bin/fs_cli /usr/local/bin/
```
- 配置mod
```bash
sudo vim /usr/local/freeswitch/conf/autoload_configs/modules.conf.xml
```
在前3行开启
```xml
<load module="mod_console"/>
<load module="mod_logfile"/>
<load module="mod_xml_curl"/>
```
打开注释
```xml
<load module="mod_python"/>
<load module="mod_shout"/>
<load module="mod_xml_rpc"/>
```
添加配置
```xml
<!-- <load module="mod_cdr_pg_csv"/> -->
<load module="mod_unimrcp"/>
<!--<load module="mod_vad"/>-->
```
注释掉其他不需要的模块
```xml
<!-- <load module="mod_av"/> -->
<!-- <load module="mod_signalwire"/> -->
```
- 配置acl白名单
```bash
vim /usr/local/freeswitch/conf/autoload_configs/acl.conf.xml
```
根据自己网络的实际情况进行配置(照抄大概率无效)
```xml
<list name="domains" default="deny">
<!-- domain= is special it scans the domain from the directory to build t$ -->
<node type="allow" domain="$${domain}"/>
<!-- use cidr= if you wish to allow ip ranges to this domains acl. -->
<!-- <node type="allow" cidr="192.168.0.0/24"/> -->
<node type="allow" cidr="192.168.0.112/24"/>
<node type="allow" cidr="192.168.0.50/24"/>
<!-- ==================这里添加 本机ip 127.0.0.1 ======================== -->
<!-- ==================这里添加 本机内网ip ======================== -->
<!-- ==================这里添加 本机外网ip ======================== -->
<!-- ==================这里添加 web内网ip 192.168.2.173======================== -->
<!-- ==================这里添加 web外网ip 39.107.68.127======================== -->
<!-- ==================这里添加 runcall 内外网Ip======================== -->
<node type="allow" cidr="192.168.2.178/24"/>
<node type="allow" cidr="39.107.70.84/24"/>
</list>
```
- 配置ESL
```bash
vim /usr/local/freeswitch/conf/autoload_configs/event_socket.conf.xml
```
```xml
<configuration name="event_socket.conf" description="Socket Client">
<settings>
<param name="nat-map" value="false"/>
<!--ip 统一为0.0.0.0-->
<param name="listen-ip" value="0.0.0.0"/>
<!-- 端口号 默认8021 -->
<param name="listen-port" value="8021"/>
<!-- 密码统一Aicyber -->
<param name="password" value="Aicyber"/>
<!-- 允许acl白名单内的IP 访问 -->
<param name="apply-inbound-acl" value="domains"/>
<!--<param name="apply-inbound-acl" value="loopback.auto"/>-->
<!--<param name="stop-on-bind-error" value="true"/>-->
</settings>
</configuration>
```
- 适配WebRTCJSSIP/SIPJS
在`/usr/local/freeswitch/conf/sip_profiles/internal.xml`中添加或修改下面这些配置
```xml
<param name="apply-candidate-acl" value="rfc1918.auto"/>
<param name="apply-candidate-acl" value="localnet.auto"/>
<param name="apply-candidate-acl" value="candidate"/>
```
```xml
<!-- 取消注释这一行(让前端可以得到早期媒体) -->
<param name="enable-100rel" value="true"/>
```
- 适配特定终端以云翌通安卓SDK为例
在`/usr/local/freeswitch/conf/sip_profiles/internal.xml`中添加下面这些配置
```xml
<param name="user-agent-string" value="YunEasy"/>
```
- 拨号计划规则
在`/usr/local/freeswitch/conf/sip_profiles/internal.xml`中修改下面这些配置
```xml
<!-- 默认是public -->
<param name="context" value="default"/>
```
### 安全配置
- 配置端口
在`/usr/local/freeswitch/conf/vars.xml`文件中:
```xml
<!-- sip端口终端通过tcp协议连接到这个端口默认5060 -->
<X-PRE-PROCESS cmd="set" data="internal_sip_port=5060"/>
<!-- tls端口终端通过tls协议连接到这个端口默认5061 -->
<X-PRE-PROCESS cmd="set" data="internal_tls_port=5061"/>
```
```xml
<!-- 把原来的stun协议的地址改成下面的内容 -->
<X-PRE-PROCESS cmd="stun-set" data="external_rtp_ip=xxx.xxx.xxx.xxx"/>
<X-PRE-PROCESS cmd="stun-set" data="external_sip_ip=*.*.*.*"/>
```
在`/usr/local/freeswitch/conf/sip_profiles/internal.xml`文件中:
```xml
<!-- ws端口通过ws协议使用webrtc时需要连接到这个端口默认5066 -->
<param name="ws-binding" value=":5066"/>
<!-- wss端口通过wss协议使用webrtc时需要连接到这个端口默认7443 -->
<param name="wss-binding" value=":7443"/>
```
- 默认密码
在`/usr/local/freeswitch/conf/vars.xml`文件中:
```xml
<!-- 初始的1000~1019分机使用的默认密码建议修改 -->
<X-PRE-PROCESS cmd="set" data="default_password=1234"/>
```
- 配置防火墙
```bash
# 开放sip端口tcp协议
sudo firewall-cmd --permanent --add-port=5060/tcp
# 开放sip端口udp协议
sudo firewall-cmd --permanent --add-port=5060/udp
# 开放ws端口
sudo firewall-cmd --permanent --add-port=5066/tcp
# 开放wss端口
sudo firewall-cmd --permanent --add-port=7443/tcp
# 开放rtp端口范围
sudo firewall-cmd --permanent --add-port=16384-32768/udp
# 让防火墙配置生效
sudo firewall-cmd --reload
```
- 参考资料
|FireWall Ports|Network Protocol|Application Protocol|Description|
|---|---|---|---|
|1719|UDP|H.323|Gatekeeper RAS port|
|1720|TCP|H.323|Call Signaling|
|3478|UDP|STUN service|Used for NAT traversal|
|3479|UDP|STUN service|Used for NAT traversal|
|5002|TCP|MLP|protocol server|
|5003|UDP| |Neighborhood service|
|5060|UDP & TCP|SIP UAS|Used for SIP signaling (Standard SIP Port, for default Internal Profile)|
|5070|UDP & TCP|SIP UAS|Used for SIP signaling (For default "NAT" Profile)|
|5080|UDP & TCP|SIP UAS|Used for SIP signaling (For default "External" Profile)|
|8021|TCP|ESL|Used for mod_event_socket *|
|16384-32768|UDP|RTP/ RTCP multimedia streaming|Used for audio/video data in SIP and other protocols|
|5066|TCP|Websocket|Used for WebRTC|
|7443|TCP|Websocket|Used for WebRTC|
### 效率
- 关闭ipv6
在`/usr/local/freeswitch/conf/sip_profiles/`目录下
```bash
cd /usr/local/freeswitch/conf/sip_profiles
mv internal-ipv6.xml internal-ipv6.xml.removed
mv external-ipv6.xml external-ipv6.xml.removed
```
### 启动
- 后台快速启动
```bash
freeswitch -nc -nonat
```
- 控制台启动(退出即关闭服务)
```bash
freeswitch
```

View File

@ -0,0 +1,551 @@
# Debian11安装FreeSWITCH1.10_参照ClueCon官方文档
[[toc]]
## 安装操作系统
### 更换软件源
> 在有些地方可能Debian10/11使用网易源速度较好
```shell
vi /etc/apt/sources.list
```
```text
deb http://mirrors.163.com/debian/ buster main non-free contrib
deb http://mirrors.163.com/debian/ buster-updates main non-free contrib
deb http://mirrors.163.com/debian/ buster-backports main non-free contrib
deb http://mirrors.163.com/debian-security/ buster/updates main non-free contrib
deb-src http://mirrors.163.com/debian/ buster main non-free contrib
deb-src http://mirrors.163.com/debian/ buster-updates main non-free contrib
deb-src http://mirrors.163.com/debian/ buster-backports main non-free contrib
deb-src http://mirrors.163.com/debian-security/ buster/updates main non-free contrib
```
### 系统安装完成后可以进行系统升级并安装一些基础软件
```shell
apt update && apt upgrade -y
apt install -y wget git vim lrzsz net-tools
```
### 在Debian系统里想要SSH登录root账号
```shell
vim /etc/ssh/sshd_conf
```
修改内容如下:
```ini
#PermitRootLogin prohibit-password
PermitRootLogin yes
#PasswordAuthentication yes
PasswordAuthentication yes
```
修改后重启一下ssh服务
```shell
/etc/init.d/ssh restart
```
### 在Debian系统里启用ll命令
```shell
vim ~/.bashrc
```
解除alias ll行的注释或者添加一行
```ini
alias ll='ls $LS_OPTIONS -l --color=auto'
```
退出终端重新进入或者使用下面命令生效:
```shell
source ~/.bashrc
```
> 命令`echo "alias ll='ls $LS_OPTIONS -l --color=auto'" >> ~/.bashrc && source ~/.bashrc && ll`
## 安装lua和luarocks环境
### 安装lua
> lua安装包的下载地址<http://www.lua.org/ftp/>
```shell
apt install -y build-essential libreadline-dev unzip
cd /usr/src
wget http://www.lua.org/ftp/lua-5.2.4.tar.gz
tar zxvf lua-5.2.4.tar.gz
cd lua-5.2.4
make linux test
make install
```
> 合并命令:`cd /usr/src && wget http://www.lua.org/ftp/lua-5.2.4.tar.gz`,下载成功后再执行`tar zxvf lua-5.2.4.tar.gz && cd lua-5.2.4 && make linux test && make install && cd ..`
### 安装luarocks3.9.0
> luarocks安装包的下载地址<https://luarocks.github.io/luarocks/releases/>
```shell
cd /usr/src
wget https://luarocks.github.io/luarocks/releases/luarocks-3.9.0.tar.gz
tar zxfv luarocks-3.9.0.tar.gz
cd luarocks-3.9.0
./configure
make
make install
```
> 合并命令:`cd /usr/src && wget https://luarocks.github.io/luarocks/releases/luarocks-3.9.0.tar.gz`,下载成功后再执行`tar zxfv luarocks-3.9.0.tar.gz && cd luarocks-3.9.0 && ./configure && make && make install && cd ..`
## 安装python2.7和对应的pip非必要
```shell
apt install python
cd /usr/src
wget https://bootstrap.pypa.io/pip/2.7/get-pip.py
python get-pip.py
# 下面的命令可以查看各种版本
python --version # 查看python2的版本
python3 --version # 查看python3的版本
pip --version # 查看pip2的版本
```
## 编译安装FreeSWITCH
### 安装FreeSWITCH
> 不知道后来从什么时间点开始通过signalwire的源去安装FreeSWITCH所需依赖包时需要使用向Signalwire平台申请的Access Token临时提供一个`pat_jMxihv2uTh3ivpPdSqUMffB3`
```shell
# 这个token不要照抄要替换成自己的
TOKEN=pat_jMxihv2uTh3ivpPdSqUMffB3
apt update && apt install -yq gnupg2 wget lsb-release
wget --http-user=signalwire --http-password=$TOKEN -O /usr/share/keyrings/signalwire-freeswitch-repo.gpg https://freeswitch.signalwire.com/repo/deb/debian-release/signalwire-freeswitch-repo.gpg
echo "machine freeswitch.signalwire.com login signalwire password $TOKEN" > /etc/apt/auth.conf
echo "deb [signed-by=/usr/share/keyrings/signalwire-freeswitch-repo.gpg] https://freeswitch.signalwire.com/repo/deb/debian-release/ `lsb_release -sc` main" > /etc/apt/sources.list.d/freeswitch.list
echo "deb-src [signed-by=/usr/share/keyrings/signalwire-freeswitch-repo.gpg] https://freeswitch.signalwire.com/repo/deb/debian-release/ `lsb_release -sc` main" >> /etc/apt/sources.list.d/freeswitch.list
apt update && apt upgrade -y
# Install dependencies required for the build
apt build-dep freeswitch -y
```
> 命令```TOKEN=pat_jMxihv2uTh3ivpPdSqUMffB3 && apt update && apt install -yq gnupg2 wget lsb-release &&wget --http-user=signalwire --http-password=$TOKEN -O /usr/share/keyrings/signalwire-freeswitch-repo.gpg https://freeswitch.signalwire.com/repo/deb/debian-release/signalwire-freeswitch-repo.gpg && echo "machine freeswitch.signalwire.com login signalwire password $TOKEN" > /etc/apt/auth.conf && echo "deb [signed-by=/usr/share/keyrings/signalwire-freeswitch-repo.gpg] https://freeswitch.signalwire.com/repo/deb/debian-release/ `lsb_release -sc` main" > /etc/apt/sources.list.d/freeswitch.list && echo "deb-src [signed-by=/usr/share/keyrings/signalwire-freeswitch-repo.gpg] https://freeswitch.signalwire.com/repo/deb/debian-release/ `lsb_release -sc` main" >> /etc/apt/sources.list.d/freeswitch.list && apt update && apt upgrade -y && apt build-dep freeswitch -y```
```shell
# then let's get the source. Use the -b flag to get a specific branch
cd /usr/src/
git clone https://github.com/signalwire/freeswitch.git -b v1.10 freeswitch
cd freeswitch
# Because we're in a branch that will go through many rebases, it's
# better to set this one, or you'll get CONFLICTS when pulling (update).
git config pull.rebase true
# ... and do the build
./bootstrap.sh -j
./configure
make
make install
```
### 安装音频文件(英文)
```shell
cd /usr/src/freeswitch
make cd-sounds-install
make cd-moh-install
make uhd-sounds-install
make uhd-moh-install
make hd-sounds-install
make hd-moh-install
make sounds-install
make moh-install
```
> 合并成一条命令`cd /usr/src/freeswitch && make moh-install && make sounds-install && make hd-moh-install && make hd-sounds-install && make uhd-moh-install && make uhd-sounds-install && make cd-moh-install && make cd-sounds-install && cd ..`
## 配置FreeSWITCH
### conf/vars.xml中的配置项
> 主要是sip用户默认密码、stun地址、sip端口号等配置
```shell
vim /usr/local/freeswitch/conf/vars.xml
```
```xml
<!-- 改成其他密码 -->
<X-PRE-PROCESS cmd="set" data="default_password=654654321"/>
<!-- <X-PRE-PROCESS cmd="stun-set" data="external_rtp_ip=stun:stun.freeswitch.org"/> -->
<X-PRE-PROCESS cmd="stun-set" data="external_rtp_ip=$${local_ip_v4}"/>
<!-- <X-PRE-PROCESS cmd="stun-set" data="external_sip_ip=stun:stun.freeswitch.org"/> -->
<X-PRE-PROCESS cmd="stun-set" data="external_sip_ip=$${local_ip_v4}"/>
<!--根据实际需要改成需要的端口号 -->
<X-PRE-PROCESS cmd="set" data="internal_sip_port=5060"/>
<X-PRE-PROCESS cmd="set" data="internal_tls_port=5061"/>
<X-PRE-PROCESS cmd="set" data="external_sip_port=5080"/>
<X-PRE-PROCESS cmd="set" data="external_tls_port=5081"/>
```
### conf/sip_profiles/internal.xml中的配置项
> 主要是与内部sip账号相关的配置
```shell
vim /usr/local/freeswitch/conf/sip_profiles/internal.xml
```
```xml
<!-- 默认是public要改成default -->
<param name="context" value="default"/>
<!-- 如果要在WebRTC场景中听到早期媒体回铃音就要解除这一行的注释 -->
<param name="enable-100rel" value="true"/>
<!-- 如果需要WebRTC场景中使用需要在末尾加上后面这几个配置项 -->
<param name="apply-candidate-acl" value="rfc1918.auto"/>
<param name="apply-candidate-acl" value="localnet.auto"/>
<param name="apply-candidate-acl" value="candidate"/>
```
### conf/autoload_configs/acl.conf.xml中的配置项
> 主要用来制定可通过ESL连接FreeSWITCH的IP规则
```shell
vim /usr/local/freeswitch/conf/autoload_configs/acl.conf.xml
```
下面的文件内容要根据实际情况配置,不能照抄。
```xml
<list name="lan" default="allow">
<!-- 拒绝来自内网的特定网断连接 -->
<node type="deny" cidr="192.168.42.0/24"/>
<!-- 允许来自内网的特定IP连接 -->
<node type="allow" cidr="192.168.42.42/32"/>
</list>
<list name="domains" default="deny">
<node type="allow" domain="$${domain}"/>
<!-- 允许本机连接 -->
<node type="allow" cidr="127.0.0.1/32"/>
<!-- 允许特定IP地址连接 -->
<node type="allow" cidr="183.211.245.0/25"/>
<node type="allow" cidr="112.4.97.0/25"/>
</list>
```
### conf/autoload_configs/switch.conf.xml中的配置项
> 主要配置并发数
```shell
vim /usr/local/freeswitch/conf/autoload_configs/switch.conf.xml
```
```xml
<!-- 根据实际环境配置 -->
<param name="max-sessions" value="2000"/>
<param name="sessions-per-second" value="2000"/>
```
### conf/autoload_configs/event_socket.conf.xml中的配置项
> 用于配置ESL相关参数
```shell
vim /usr/local/freeswitch/conf/autoload_configs/event_socket.conf.xml
```
```xml
<configuration name="event_socket.conf" description="Socket Client">
<settings>
<param name="nat-map" value="false"/>
<!-- listen-ip改成0.0.0.0 -->
<param name="listen-ip" value="0.0.0.0"/>
<!-- 端口号根据实际需要修改默认8021 -->
<param name="listen-port" value="8021"/>
<!-- 密码一定要改默认是ClueCon -->
<param name="password" value="ClueConAAAA"/>
<!-- 允许acl白名单内的IP 访问 -->
<param name="apply-inbound-acl" value="domains"/>
<!--<param name="apply-inbound-acl" value="loopback.auto"/>-->
<!--<param name="stop-on-bind-error" value="true"/>-->
</settings>
</configuration>
```
### conf/autoload_configs/modules.conf.xml中的配置
> 负责开启或关闭一些模块,开启模块时需要确定模块已经被正确安装
```shell
vim /usr/local/freeswitch/conf/autoload_configs/modules.conf.xml
```
```xml
<!-- av模块一般用不上注释掉 -->
<!-- <load module="mod_av"/> -->
<!-- signalwire模块一般也用不上注释掉 -->
<!-- <load module="mod_signalwire"/> -->
<!-- 语音信箱基本也没什么用,注释掉 -->
<!-- <load module="mod_voicemail"/> -->
```
### 关闭ipv6配置
> 为了提高一点启动效率而已如果需要IPV6就跳过这一步
```shell
cd /usr/local/freeswitch/conf/sip_profiles/
mv external-ipv6.xml external-ipv6.xml.removed
mv internal-ipv6.xml internal-ipv6.xml.removed
```
### 做freeswitch和fs_cli的软连接
```shell
ln -sf /usr/local/freeswitch/bin/freeswitch /usr/local/bin/
ln -sf /usr/local/freeswitch/bin/fs_cli /usr/local/bin/
```
## 配置ufw防火墙
```shell
apt install -y ufw
# 基础规则
ufw default allow outgoing && ufw default deny incoming && ufw allow ssh
# FS-SIP
ufw allow 5060
# FS-SIP-EXTERNAL
ufw allow 5080
# FS-WS
ufw allow 5066/tcp
# FS-WSS
ufw allow 7443/tcp
# Event Socket
ufw allow 8021/tcp
# FS-RTP
ufw allow 16384:32768/udp
# FS-MRCP-RTP
ufw allow 4000:5000/udp
# ufw开机自启
systemctl enable ufw
# 启动ufw
ufw enable
# 检查ufw开机项
systemctl list-unit-files | grep ufw
```
## 启动FreeSWITCH
```shell
# 控制台启动,退出即关闭服务
freeswitch -nonat
# 也可以后台启动启动后需要使用fs_cli查看控制台需要用shutdown命令关闭服务
freeswitch -nc -nonat
```
## fs_cli连接
```shell
vim ~/.fs_cli_conf
```
```ini
[default]
host => 127.0.0.1
port => 8021
password => ClueConAAAA
debug => 6
```
做了以上配置后,直接`fs_cli`就能查看控制台,`...`退出控制台
## SIP终端注册测试
> 假设这个FreeSWITCH服务器和SIP终端的网络是互通的
**注册信息:**
|项|值|
|---|---|
|服务器IP|FreeSWITCH服务器的IP或域名|
|SIP端口号|5060或是在vars.xml中配置的其他端口号|
|用户名|1001~1019中的任意一个分机号都行|
|密码|654654321或是在vars.xml中配置的其他默认密码|
|网络协议|TCP或UDP都可以|
> 如果终端分机注册成功,用分机呼叫`9664`可以听到通话保持音乐,呼叫`9196`可以听到`echo`效果你说什么他回什么如果以上结果正常说明本次FreeSWITCH服务器安装成功可以开始后面的具体的开发和配置了。
## 向已安装的FreeSWITCH添加模块
### 添加mod_shout模块
> mod_shout模块可以将通话录音保存为mp3文件
先进入FreeSWITCH的源码目录
```shell
cd /usr/src/freeswitch
vim modules.conf
```
修改如下内容
```ini
# 找到mod_shout一行解除行首的注释
formats/mod_shout
```
保存退出后,再执行下面的命令
```shell
make mod_shout-install
```
待编译安装完成后在FreeSWITCH的安装目录`/usr/local/freeswitch`中的`mod`目录下就已经存在`mod_shout.so`这个文件了。
接下来要回到FreeSWITCH的安装目录
```shell
cd /usr/local/freeswitch
vim conf/autoload_configs/modules.conf.xml
```
编辑文件内容
```xml
<!-- 找到这一行,解除注释,如果没有就直接在后面添加 -->
<load module="mod_shout"/>
```
最后进入FreeSWITCH控制台`fs_cli`,在控制台中执行命令`load mod_shout`到此mod_shout模块已经安装完成并在FreeSWITCH服务器生效。
### 添加mod_unimrcp模块
> mod_unimrcp模块可以通过mrcp协议实现实时语音识别和语音合成能力
先进入FreeSWITCH的源码目录
```shell
cd /usr/src/freeswitch
vim modules.conf
```
修改如下内容
```ini
# 找到mod_unimrcp一行解除行首的注释
asr_tts/mod_unimrcp
```
保存退出后,再执行下面的命令
```shell
make mod_unimrcp-install
```
待编译安装完成后在FreeSWITCH的安装目录`/usr/local/freeswitch`中的`mod`目录下就已经存在`mod_unimrcp.so`这个文件了。
接下来要回到FreeSWITCH的安装目录
```shell
cd /usr/local/freeswitch
vim conf/autoload_configs/modules.conf.xml
```
编辑文件内容
```xml
<!-- 找到这一行,解除注释,如果没有就直接在后面添加 -->
<load module="mod_unimrcp"/>
```
最后进入FreeSWITCH控制台`fs_cli`,在控制台中执行命令`load mod_unimrcp`到此mod_unimrcp模块已经安装完成并在FreeSWITCH服务器生效。
> 以上方法只适用于FreeSWITCH1.10.7及之前的版本1.10.8开始mod_unimrcp被从核心代码中移除转移为独立项目详见另外一份文档
### 添加mod_python模块
> mod_python模块可以支持用python脚本制作ivr支持的python版本为2.7如果需要python3的支持需要安装mod_python3
先进入FreeSWITCH的源码目录
```shell
cd /usr/src/freeswitch
vim modules.conf
```
修改如下内容
```ini
# 找到mod_python一行解除行首的注释
languages/mod_python
```
保存退出后,再执行下面的命令
```shell
make mod_python-install
```
待编译安装完成后在FreeSWITCH的安装目录`/usr/local/freeswitch`中的`mod`目录下就已经存在`mod_python.so`这个文件了。
接下来要回到FreeSWITCH的安装目录
```shell
cd /usr/local/freeswitch
vim conf/autoload_configs/modules.conf.xml
```
编辑文件内容
```xml
<!-- 找到这一行,解除注释,如果没有就直接在后面添加 -->
<load module="mod_python"/>
```
最后进入FreeSWITCH控制台`fs_cli`,在控制台中执行命令`load mod_python`到此mod_unimrcp模块已经安装完成并在FreeSWITCH服务器生效。
### 添加mod_g729模块
> FreeSWITCH源码中的G729模块只能用在透传模式下如果想要在非透传模式下使用G729编码就需要手动安装第三方模块
通过git克隆源码编译安装
```bash
cd /usr/src
git clone https://github.com/abaci64/mod_g729.git
cd mod_g729
make
make install
```
进入FreeSWITCH配置文件修改modules.conf.xml配置
```xml
<!--把mod_g729一行取消注释-->
<load module="mod_g729"/>
```
然后重新启动FreeSWITCH服务即可以使用g729编码。
```shell
bgapi originate {ignore_early_media=true,absolute_codec_string=g729\,PCMA}sofia/gateway/[YOUR_GATEWAY]/[TARGET_PHONE] &echo
```

View File

@ -0,0 +1,34 @@
## Debian11安装lua和luarocks
> wandoubaba / 2023-01-18
严格来说这个内容并不只针对FreeSWITCH不过打造一个合适的lua的编写和运行环境也是玩转FreeSWITCH的一个前提而且笔者是通过FreeSWITCH才认识lua的所以把搭建lua环境也当作是FreeSWITCH的一个案例看待。
### 安装lua
> 后面的操作过程中如果使用root账号的话就不需要加`sudo`了
```sh
sudo apt-get install -y lua5.1
```
### 安装luarocks
```sh
sudo apt-get install -y unzip
cd /opt
wget https://luarocks.org/releases/luarocks-3.9.2.tar.gz
tar zxpf luarocks-3.9.2.tar.gz
cd luarocks-3.9.2
./configure && make
sudo make install
```
### 验证
```sh
# 查看lua版本号
lua -v
# 查看luarocks版本号
luarocks --version
```

View File

@ -0,0 +1,124 @@
## Docker部署阿里云的MRCP服务版权
> wandoubaba / 2023-02-21
在阿里云的的智能语音服务中除了提供常规的ASR、TTS等能力外也有完整的MRCP服务阿里名称SDM不但可以对接私有化的智能语音能力同时还可以对接公有云的ASR和TTS。
引用阿里云《SDM(MRCP-SERVER)公共镜像使用》文档中的一段话:
> SDM(MRCP-SERVER)目前在公共云上有对应的镜像仓库,用户可以直接拉取公共云镜像到本地,然后部署使用,一定程度上简化了部署和接入的成本。
### 环境依赖
机器需求4C8G
操作系统CentOS7.2及以上其他支持Docker环境的较新版本的Linux发行版
软件环境要求Docker环境
### 安装过程
安装部署主要包括两个过程到阿里云开通公共云语音服务、部署SDM镜像。
#### 开通阿里云智能语音服务
> 下面这些操作都是在阿里云的控制台里完成的。
- 注册阿里云账号,这里省略具体步骤。
- 登录阿里云控制台到“智能语音交互服务”页面开通ASR、TTS相关服务
- 阿里云的语音服务都支持试用版免费使用,只不过并发路数有限,开发测试可以用。
- 到阿里云的“Access Key管理页面”创建并获取一组供SDM使用的具有调用智能语音服务能力的“Access Key ID”和“Access Key Secret”注意妥善保存
- 到阿里云“智能语音交互”控制台->“全部项目”,如果没有项目创建一个项目,项目类型选择“语音识别+语音合成+语音分析“主要是要拿到项目的“AppKey”。
- 注意“AppKey”对应项目的“项目功能配置”中要选择8K模型。
经过以上操作在云端的基础能力就已经配置好了一共得到了3个变量“Access Key ID”、“Access Key Secret”、“AppKey”后面部署SDM时会用到这几个变量。
#### 部署SDM镜像
> 下面的操作是在要部署SDM的服务器上进行的如果是以root登录的话就自行忽略`sudo`假设Linux系统上已经安装好了docker服务。
开始操作之前最好事先在主机上为SDM规划一个目录用于保存配置文件和日志等运行时文件本文假设这个目录是`/data/sdm`,下面的操作都默认在`/data/sdm`目录下进行。
##### 初始化配置
```sh
# 进入主机准备的sdm文件目录
cd /data/sdm
# 拉取镜像
sudo docker pull registry.cn-shanghai.aliyuncs.com/nls-cloud/sdm:latest
# 确认本地已拉取的镜像
sudo docker images | grep sdm
# 初始化本地环境
sudo docker run -d --privileged --net=host --name nls-cloud-sdm -v `pwd`/logs:/home/admin/logs -v `pwd`/data:/home/admin/disk registry.cn-shanghai.aliyuncs.com/nls-cloud/sdm:latest standalone
```
到这里只是用到初始化环境将容器中的SDM目录映射到宿主机上由于相关配置参数还没有修改所以容器最终不会运行起来如果真运行起来了也请用`docker stop`命令将它停了吧),下面需要进行相关配置操作。
##### 配置
首次启动后,容器内的配置文件在宿主机`/data/sdm/data/nls-cloud-sdm/conf`目录下一般来说只需要修改其中的3个配置文件nlstoken.json、service-asr.json、service-tts.json。
- nlstoken.json配置AccessKeyId和AccessKeySecret
```json
{
"AccessKeyId": "前面得到的AccessKeyId",
"AccessKeySecret": "前面得到的AccessKeySecret",
"DefaultToken": ""
}
```
说明对接公有云时DefaultToken的值要是空白。
- service-asr.json主要配置url和AppKey
```json
{
"url": "wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1",
"appkey": "前面得到的项目AppKey",
}
```
- service-tts.json主要配置url和AppKey
```json
{
"url": "wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1",
"appkey": "前面得到的项目AppKey",
}
```
其他asr和tts的配置一般不用修改如果有特殊需求的话就按需配置好了。
##### 启动
```sh
sudo docker start nls-cloud-sdm
# 查看是否启动成功
sudo docker ps
# 查看服务进程是否已拉起
ps -ef | grep alimrcp-server
# 查看端口是否监听
sudo lsof -i:7010
# 查看日志中有没有ERROR信息
cat logs/nls-cloud-sdm/alimrcp-server.log | grep ERROR
# 设置容器自启动
sudo docker update --restart=always nls-cloud-sdm
```
##### 端口
默认情况下SDM使用以下端口与客户端如FreeSWITCH通信与服务端阿里云不需要开放端口只需要能连接阿里云公有云服务即可。
- 7010TCP&UDPSIP端口。
- 1544、1554TCPMRCP协议端口。
- 10000-20000UDPRTP协议端口用来传输语音流。
##### 并发
SDM单机资源默认支持100路ASR+100路TTS这个并发指的是SDM与客户端如FreeSWITCH的资源处理能力与公有云的ASR、TTS并发能力无关。

View File

@ -0,0 +1,117 @@
# FreeSWITCH常用的命令
---
## 启动freeswitch
```bash
freeswitch -nc # 后台启动
freeswitch -nc -nonat # 后台启动且关闭自动nat有独立公网IP时不需要开启nat功能能明显提高启动速度
```
## fs_cli中使用的命令
- **shutdown**
> 关闭freeswitch服务
- **reloadxml**
> 重载配置(如拨号计划)
- **reloadacl**
> 重载acl
- **sofia profile internal restart**
> 重启internal服务
- **sofia profile external restart**
> 重启external服务
- **sofia status profile internal**
> 查看服务端口等信息
结果示例:
```text
=================================================================================================
Name internal
Domain Name N/A
Auto-NAT false
DBName sofia_reg_internal
Pres Hosts 183.211.245.46,183.211.245.46
Dialplan XML
Context public
Challenge Realm auto_from
RTP-IP 183.211.245.46
SIP-IP 183.211.245.46
URL sip:mod_sofia@183.211.245.46:5060
BIND-URL sip:mod_sofia@183.211.245.46:5060;transport=udp,tcp
WS-BIND-URL sip:mod_sofia@183.211.245.46:5066;transport=ws
WSS-BIND-URL sips:mod_sofia@183.211.245.46:7443;transport=wss
HOLD-MUSIC local_stream://moh
OUTBOUND-PROXY N/A
CODECS IN OPUS,G722,PCMU,PCMA,VP8
CODECS OUT OPUS,G722,PCMU,PCMA,VP8
TEL-EVENT 101
DTMF-MODE rfc2833
CNG 13
SESSION-TO 0
MAX-DIALOG 0
NOMEDIA false
LATE-NEG true
PROXY-MEDIA false
ZRTP-PASSTHRU true
AGGRESSIVENAT false
CALLS-IN 8
FAILED-CALLS-IN 0
CALLS-OUT 2
FAILED-CALLS-OUT 0
REGISTRATIONS 2
```
- **sofia status profile internal reg**
> 查看注册用户
结果示例:
```text
Registrations:
=================================================================================================
Call-ID: G7ZfP264pLJawfNLKuFg1A..
User: 1002@183.211.245.46
Contact: "" <sip:1002@39.152.207.190:43502;transport=TCP;rinstance=c8aef170677f30f6>
Agent: Zoiper rv2.10.6.2
Status: Registered(TCP)(unknown) EXP(2021-09-14 13:42:51) EXPSECS(359)
Ping-Status: Reachable
Ping-Time: 0.00
Host: fstesting
IP: 39.152.207.190
Port: 43502
Auth-User: 1002
Auth-Realm: 183.211.245.46
MWI-Account: 1002@183.211.245.46
Call-ID: JRlQZx3SoV0ElHunKRrQNg..
User: 1001@183.211.245.46
Contact: "" <sip:1001@39.152.207.190:41043;transport=UDP;rinstance=eaf774985a9b3b03>
Agent: Zoiper rv2.10.6.2
Status: Registered(UDP)(unknown) EXP(2021-09-14 13:38:15) EXPSECS(83)
Ping-Status: Reachable
Ping-Time: 0.00
Host: fstesting
IP: 39.152.207.190
Port: 41043
Auth-User: 1001
Auth-Realm: 183.211.245.46
MWI-Account: 1001@183.211.245.46
Total items returned: 2
=================================================================================================
```

View File

@ -0,0 +1,170 @@
# Freeswitch通过mod_unimrcp与百度mrcp-server对接lua版
---
## 参考链接
[https://freeswitch.org/confluence/display/FREESWITCH/mod_unimrcp]
[https://ptorch.com/news/206.html]
[https://ptorch.com/news/207.html]
## 安装并加载mod_unimrcp模块
```bash
# 在freeswitch源码目录不是安装目录
make mod_unimrcp-install
# 在freeswitch安装目录中编译modules.conf.xml文件
cd /usr/local/freeswitch
vim conf/autoload_configs/modules.conf.xml
```
```xml
<!-- 添加如下配置 -->
<load module="mod_unimrcp"/>
```
## 设置profile文件和conf文件
```bash
vim /usr/local/freeswitch/conf/mrcp_profiles/unimrcpserver-mrcp-v2.xml
```
输入以下内容:
```xml
<include>
<!-- UniMRCP Server MRCPv2 -->
<!-- 后面我们使用该配置文件,均使用 name 作为唯一标识,而不是文件名 -->
<profile name="unimrcpserver-mrcp2" version="2">
<!-- MRCP 服务器地址和SIP端口号 -->
<param name="server-ip" value="192.168.16.4"/>
<!-- mrcp服务器的sip-port -->
<param name="server-port" value="15060"/>
<param name="resource-location" value=""/>
<!-- FreeSWITCH IP、端口以及 SIP 传输方式 -->
<param name="client-ip" value="192.168.16.4" />
<!-- freeswitch的sip-port -->
<param name="client-port" value="5069"/>
<param name="sip-transport" value="udp"/>
<param name="speechsynth" value="speechsynthesizer"/>
<param name="speechrecog" value="speechrecognizer"/>
<!--param name="rtp-ext-ip" value="auto"/-->
<!-- 也是freeswitch的ip和rtp端口范围不是mrcp里配置的rtp范围 -->
<param name="rtp-ip" value="192.168.16.4"/>
<param name="rtp-port-min" value="4000"/>
<param name="rtp-port-max" value="5000"/>
<param name="codecs" value="PCMU PCMA L16/96/8000"/>
<!-- Add any default MRCP params for SPEAK requests here -->
<synthparams>
</synthparams>
<!-- Add any default MRCP params for RECOGNIZE requests here -->
<recogparams>
<!--param name="start-input-timers" value="false"/-->
</recogparams>
</profile>
</include>
```
编辑`unimrcp.conf.xml`文件改`default-tts-profile`和`default-asr-profile`
```bash
vim /usr/local/freeswitch/conf/autoload_configs/unimrcp.conf.xml
```
```xml
<!-- UniMRCP profile to use for TTS -->
<param name="default-tts-profile" value="unimrcpserver-mrcp2"/>
<!-- UniMRCP profile to use for ASR -->
<param name="default-asr-profile" value="unimrcpserver-mrcp2"/>
```
## 设置dialplan
```bash
vim /usr/local/freeswitch/conf/dialplan/default.xml
```
添加一个extension
```xml
<extension name="unimrcp">
<condition field="destination_number" expression="^5001$">
<action application="answer"/>
<!-- 对应scripts/baidu.lua文件 -->
<action application="lua" data="baidu.lua"/>
</condition>
</extension>
```
在`/usr/local/freeswitch/scripts`目录下创建`baidu.lua`文件:
```bash
touch /usr/local/freeswitch/scripts/baidu.lua
vim /usr/local/freeswitch/scripts/baidu.lua
```
文件内容如下:
```lua
session:answer()
--freeswitch.consoleLog("INFO", "Called extension is '".. argv[1]"'\n")
welcome = "/usr/local/freeswitch/sounds/en/us/callie/ivr/8000/ivr-welcome_to_freeswitch.wav"
--
grammar = "baidu"
no_input_timeout = 80000
recognition_timeout = 80000
--
tryagain = 1
while (tryagain == 1) do
--
session:execute("play_and_detect_speech", welcome .. " detect:unimrcp {start-input-timers=false,no-input-timeout=" .. no_input_timeout .. ",recognition-timeout=" .. recognition_timeout .. "} " .. grammar)
xml = session:getVariable('detect_speech_result')
--
if (xml == nil) then
freeswitch.consoleLog("CRIT","Result is 'nil'\n")
tryagain = 0
else
freeswitch.consoleLog("CRIT","Result is '" .. xml .. "'\n")
tryagain = 0
end
end
--
-- put logic to forward call here
--
session:sleep(250)
session:hangup()
```
> 以上脚本实现当分机用户拨打5001时freeswitch会自动播放一段录音并接收用户发出的声音同时把声音传给mrcp服务器并接收返回结果
在`/usr/local/freeswitch/grammar`目录新增`hello.gram`语法文件内容为百度mrcp程序句中的语法文件内容
```xml
<?xml version="1.0"?>
<grammar xmlns="http://www.w3.org/2001/06/grammar" xml:lang="en-US" version="1.0" mode="voice" root="digit">
<rule id="digit">
<one-of>
<item>one</item>
<item>two</item>
<item>three</item>
</one-of>
</rule>
</grammar>
```
## 让配置生效并测试
```bash
fs_cli
reloadxml
```
## 防火墙
在freeswitch服务器和mrcp服务器都不需要额外开放端口。

View File

@ -0,0 +1,142 @@
## FreeSWITCH对接阿里云MRCP服务SDM
> wandoubaba / 2023-02-21
在阿里云的的智能语音服务中除了提供常规的ASR、TTS等能力外也有完整的MRCP服务阿里名称SDM不但可以对接私有化的智能语音能力同时还可以对接公有云的ASR和TTS。
### 网络规划
- MRCP服务器
|配置项|配置值|
|---|---|
|IP| 192.168.0.10|
|SIP端口|7010TCP&UDP|
|MRCP端口|1544、1554TCP|
|RTP端口|10000-20000UDP|
- FreeSWITCH服务器
|配置项|配置值|
|---|---|
|IP|192.168.0.60|
|SIP端口|5060TCP&UDP|
|RTP端口与MRCP通信|40000-50000UDP|
### 部署SDM
目前阿里云并没有开放SDM服务通过阿里云智能语音服务的客户经理可以得以《SDM(MRCP-SERVER)公共镜像使用》文档,按照文档部署,比较容易。
摘抄阿里云《SDM(MRCP-SERVER)公共镜像使用》文档中的一段话:
> SDM(MRCP-SERVER)目前在公共云上有对应的镜像仓库,用户可以直接拉取公共云镜像到本地,然后部署使用,一定程度上简化了部署和接入的成本。
### 安装mod_unimrcp模块
详见《为FreeSWITCH安装mod_unimrcp模块》。
### 配置mod_unimrcp
在FreeSWITCH的安装目录修改`conf/autoload_configs/modules.conf.xml`文件:
```xml
<!-- 添加一行 -->
<load module="mod_unimrcp"/>
```
在FreeSWITCH的安装目录下创建`conf/mrcp_profiles/aliyun-mrcpserver.xml`文件:
```xml
<include>
<profile name="aliyun-mrcpserver" version="2">
<param name="client-ip" value="$${local_ip_v4}"/>
<param name="client-port" value="5060"/>
<param name="server-ip" value="192.168.0.10"/>
<param name="server-port" value="7010"/>
<param name="resource-location" value=""/>
<param name="sip-transport" value="tcp"/>
<param name="sdp-origin" value="Freeswitch"/>
<param name="rtp-ip" value="$${local_ip_v4}"/>
<param name="rtp-port-min" value="40000"/>
<param name="rtp-port-max" value="50000"/>
<param name="speechsynth" value="speechsynthesizer"/>
<param name="speechrecog" value="speechrecognizer"/>
<param name="codecs" value="PCMU PCMA L16/96/8000"/>
</profile>
</include>
```
创建或修改`conf/autoload_configs/unimrcp.conf.xml`文件:
```xml
<configuration name="unimrcp.conf" description="UniMRCP Client">
<settings>
<!-- UniMRCP profile to use for TTS -->
<!-- value对应aliyun-mrcpserver.xml中profile的name -->
<param name="default-tts-profile" value="aliyun-mrcpserver"/>
<!-- UniMRCP profile to use for ASR -->
<!-- value对应aliyun-mrcpserver.xml中profile的name -->
<param name="default-asr-profile" value="aliyun-mrcpserver"/>
<!-- UniMRCP logging level to appear in freeswitch.log. Options are:
EMERGENCY|ALERT|CRITICAL|ERROR|WARNING|NOTICE|INFO|DEBUG -->
<param name="log-level" value="DEBUG"/>
<!-- Enable events for profile creation, open, and close -->
<param name="enable-profile-events" value="false"/>
<param name="max-connection-count" value="100"/>
<param name="offer-new-connection" value="1"/>
<param name="request-timeout" value="3000"/>
</settings>
<profiles>
<X-PRE-PROCESS cmd="include" data="../mrcp_profiles/*.xml"/>
</profiles>
</configuration>
```
在`grammar`目录下创建`alimrcp.gram`文件:
```js
#JSGF V1.0;
/** JSGF Grammar for example */
grammar example;
public <results> = [];
```
修改unimrcp配置后需要重启FreeSWITCH服务。
### 通过dialplan测试
在FreeSWITCH安装目录里创建`conf/dialplan/default/mrcp.xml`文件:
```xml
<include>
<!-- 一个简单实现echo的脚本用于测试lua模块是否好用 -->
<extension name="to_asr">
<condition field="destination_number" expression="^(001)$">
<action application="detect_speech" data="unimrcp:aliyun-mrcpserver alimrcp default"/>
<action application="echo"/>
</condition>
</extension>
</include>
```
在fs_cli中执行`reloadxml`然后盯着控制台用分机呼叫001接通后说一句话应该会在控制台看到识别结果类似
```xml
<?xml version="1.0" encoding="utf-8"?>
<result>
<interpretation grammar="session:default" confidence="1">
<instance>
<result>中午吃什么?</result>
<beginTime>730</beginTime>
<endTime>2220</endTime>
<taskId>511ba061b8a54d7b93e0f5675534febd</taskId>
<waveformUri>5d27104393eb4dbe-1.wav</waveformUri>
</instance>
<input mode="speech">中午吃什么?</input>
</interpretation>
</result>
```
恭喜到这里你的FreeSWITCH已经可以“听”和“说”了。

View File

@ -0,0 +1,40 @@
# FreeSWITCH配置SSL证书
---
## 申请证书
向域名提供商申请SSL证书然后下载证书文件应该会得到2个文件分别是`xxx.key`和`xxx.pem`。
## 上传证书至freeswitch目录
把`xxx.key`文件和`xxx.pem`文件上传到freeswitch安装目录的`certs`目录下,如`/usr/local/freeswitch/certs`。
## 合成wss.pem文件
> 先备份原有的wss.pem文件
```bash
cat xxx.pem xxx.key > wss.pem
```
## 配置wss端口
```bash
vim /usr/local/freeswitch/conf/sip_profiles/internal.xml
```
```xml
<param name="wss-binding" value=":7443"/>
```
## 重启freeswitch服务
```bash
freeswitch -stop
freeswitch -nc -nonat
```
## 客户端配置
在sip.js或jssip或其他webrtc客户端配置服务器访问地址为`wss://域名:7443`

View File

@ -0,0 +1,11 @@
# FreeSWITCH问题和解决
[[toc]]
## 网内通话在conf/dialplan/default.xml中设置的拨号计划不生效只走public.xml
在`conf/sip_profiles/internal.xml`文件中:
把`<param name="context" value="public"/>`改成`<param name="context" value="default"/>`
> 它默认是public

View File

@ -0,0 +1,70 @@
# Debian11中注册FreeSWITCH为系统服务
Debian 11使用了systemd作为启动管理器而不再使用sysvinit所以我们不去`/etc/init.d/`目录中去搞,而是在`/etc/systemd/system/`里面搞。
假设FreeSWITCH的安装目录是`/usr/local/freeswitch`。
## 创建freeswitch.service文件
```sh
touch /etc/systemd/system/freeswitch.service
vim /etc/systemd/system/freeswitch.service
```
文件内容参考如下:
```ini
[Unit]
Description=FreeSWITCH
After=network.target network-online.target
Wants=network-online.target
[Service]
User=freeswitch
Group=freeswitch
WorkingDirectory=/usr/local/freeswitch
ExecStart=/usr/local/freeswitch/bin/freeswitch
ExecStop=/usr/local/freeswitch/bin/freeswitch -stop
ExecStartPre=/bin/sleep 3
Restart=always
[Install]
WantedBy=default.target
```
其中`[Service]`段的`ExecStartPre=/bin/sleep 3`表示在启动FreeSWITCH前先等待3秒这一句可根据实际环境酌情使用。
保存`freeswitch.service`文件并退出。
## 创建freeswitch启动用户和组
```sh
## 创建freeswith用户组
groupadd -r freeswitch
## 创建freeswitch用户
useradd -r -g freeswitch -s /bin/false -d /usr/local/freeswitch -c "FreeSWITCH" freeswitch
## 更改freeswitch程序目录的权限
sudo chown -R freeswitch:freeswitch /usr/local/freeswitch
```
## 注册系统服务并实现开机自启
```sh
## 注册freeswitch服务
sudo systemctl daemon-reload
## 让freeswitch随系统自动启动
sudo systemctl enable freeswitch
```
现在名为freeswitch的系统服务已经注册完成可以使用下面的系统命令管理freeswitch的启动与停止了
```sh
## 启动服务
sudo systemctl start freeswitch
## 重新启动服务(停止再启动)
sudo systemctl restart freeswitch
## 停止服务
sudo systemctl stop freeswitch
## 查看服务状态
sudo systemctl status freeswitch
```

View File

@ -0,0 +1,137 @@
# Debian12编译安装FreeSWITCH1.10
> wandoubaba / 2024-08-19
本文以Debian12和FreeSWITCH1.10.12为例介绍一步一步编译安装FreeSWITCH的方法。
## 先下载/克隆各种资源
```shell
# 假设所有资源都下载到/opt/目录下
cd /opt
# 下载FreeSWITCH源码
git clone -b v1.10 https://github.com/signalwire/freeswitch freeswitch
# 下载libks源码
git clone https://github.com/signalwire/libks
# 下载sofia-sip源码
git clone https://github.com/freeswitch/sofia-sip
# 下载spandsp源码
git clone -b fs https://github.com/freeswitch/spandsp
# 下载signalwire-c源码
git clone https://github.com/signalwire/signalwire-c
```
> 国内连接github很累另外不保证各资源仓库以后更新后对应的操作方法是否会变建议资源下载成功后自己留一份备份
## 一步一步安装
> 如果后面的操作是在root账号下就不需要再用sudo了
先安装必要的依赖程序。
```shell
# 安装FreeSWITCH需要的依赖
sudo apt-get install -y \
build-essential cmake automake autoconf 'libtool-bin|libtool' pkg-config \
libssl-dev zlib1g-dev libdb-dev unixodbc-dev libncurses5-dev \
libexpat1-dev libgdbm-dev bison erlang-dev libtpl-dev libtiff5-dev uuid-dev \
libpcre3-dev libedit-dev libsqlite3-dev libcurl4-openssl-dev nasm \
libogg-dev libspeex-dev libspeexdsp-dev \
libldns-dev \
python3-dev \
libavformat-dev libswscale-dev 'libswresample-dev|libavresample-dev' \
liblua5.3-dev \
libopus-dev \
libpq-dev \
libsndfile1-dev libflac-dev libogg-dev libvorbis-dev \
libshout3-dev libmpg123-dev libmp3lame-dev \
lsb-release
# 安装libks
cd libks
cmake . -DCMAKE_INSTALL_PREFIX=/usr -DWITH_LIBBACKTRACE=1
sudo make install
cd ..
# 安装sofia-sip
cd sofia-sip
./bootstrap.sh
./configure CFLAGS="-g -ggdb" --with-pic --with-glib=no --without-doxygen --disable-stun --prefix=/usr
make -j`nproc --all`
sudo make install
cd ..
# 安装spandsp
cd spandsp
./bootstrap.sh
./configure CFLAGS="-g -ggdb" --with-pic --prefix=/usr
make -j`nproc --all`
sudo make install
cd ..
# 安装signalwire-c
cd signalwire-c
PKG_CONFIG_PATH=/usr/lib/pkgconfig cmake . -DCMAKE_INSTALL_PREFIX=/usr
sudo make install
cd ..
```
可以开始安装FreeSWITCH了
```shell
# 编译安装FreeSWITCH
cd freeswitch
sed -i 's|#formats/mod_shout|formats/mod_shout|' build/modules.conf.in
./bootstrap.sh -j
./configure
make -j`nproc`
sudo make install
# 安装英文声音资源(可选)
make cd-sounds-install && \
make cd-moh-install && \
make uhd-sounds-install && \
make uhd-moh-install && \
make hd-sounds-install && \
make hd-moh-install && \
make sounds-install && \
make moh-install
cd ..
```
## 启动FreeSWITCH服务
执行以上步骤后FreeSWITCH已经被安装到/usr/local/freeswitch目录下了。
```shell
cd /usr/local/freeswitch
# 前台启动服务
bin/freeswitch
```
等待一段时间后FreeSWITCH服务就已经成功启动了在当前控制台输入命令`sofia status`可以看到一点配置信息。前台启动方式非常简单,但是一旦执行`...`命令退出控制台后对应的FreeSWITCH服务也就退出了。如果想在后台启动服务在执行`bin/freeswitch`时后面加上`-nc`命令参数就可以了。
## 做freeswitch和fs_cli的软连接
```shell
ln -sf /usr/local/freeswitch/bin/freeswitch /usr/local/bin/
ln -sf /usr/local/freeswitch/bin/fs_cli /usr/local/bin/
```
做完这一步操作后就可以在任意目录下执行freeswitch地fs_cli命令了但是要注意freeswitch的运行目录的相对路径问题
## 配置.fs_cli_conf文件
fs_cli的本质也是通过esl连接去控制FreeSWITCH所以如果对FreeSWITCH做配置时更改了event_socket的端口号、密码等内容时再使用fs_cli工具时就需要在后面加上各种复杂的参数为了简化操作我们可以配置一个名为.fs_cli_conf的文件在里面写好FreeSWITCH的esl相关参数以后就可以直接执行fs_cli命令进入到FreeSWITCH控制台了。
```shell
vim ~/.fs_cli_conf
```
文件内容参数:
```ini
[default]
host => 127.0.0.1
port => 8021
password => ClueConAAAA
debug => 6
```
做了以上配置后,直接`fs_cli`就能查看控制台,`...`退出控制台。

View File

@ -0,0 +1,95 @@
# 制作FreeSWITCH镜像的Dockerfile
> wandoubaba / 2024-08-19
下面是基于`debian:bookworm`镜像制作FreeSWITCH1.10.12版服务镜像,同时安装`mod_unimrcp`模块并开启`mod_shout`模块。
```dockerfile
FROM debian:bookworm
RUN apt-get update && apt-get upgrade -y && \
apt-get install -y wget tar git \
build-essential cmake automake autoconf 'libtool-bin|libtool' pkg-config \
libssl-dev zlib1g-dev libdb-dev \
unixodbc-dev libncurses5-dev \
libexpat1-dev libgdbm-dev bison erlang-dev \
libtpl-dev libtiff5-dev uuid-dev \
libpcre3-dev libedit-dev libsqlite3-dev \
libcurl4-openssl-dev nasm \
libogg-dev libspeex-dev libspeexdsp-dev \
libldns-dev \
python3-dev \
libavformat-dev libswscale-dev 'libswresample-dev|libavresample-dev' \
liblua5.3-dev \
libopus-dev \
libpq-dev \
libsndfile1-dev libflac-dev libogg-dev libvorbis-dev \
libshout3-dev libmpg123-dev libmp3lame-dev \
lsb-release
RUN mkdir /install && cd /install && \
git clone -b v1.10 https://github.com/signalwire/freeswitch freeswitch && \
git clone https://github.com/signalwire/libks && \
git clone https://github.com/freeswitch/sofia-sip && \
git clone -b fs https://github.com/freeswitch/spandsp && \
git clone https://github.com/signalwire/signalwire-c && \
git clone https://github.com/unispeech/unimrcp.git && \
git clone https://github.com/freeswitch/mod_unimrcp.git && \
wget https://www.unimrcp.org/project/component-view/unimrcp-deps-1-6-0-tar-gz/download -O unimrcp-deps-1.6.0.tar.gz && \
tar xvzf unimrcp-deps-1.6.0.tar.gz
RUN cd /install/libks && \
cmake . -DCMAKE_INSTALL_PREFIX=/usr -DWITH_LIBBACKTRACE=1 && \
make install
RUN cd /install/sofia-sip && \
./bootstrap.sh && \
./configure CFLAGS="-g -ggdb" --with-pic --with-glib=no --without-doxygen --disable-stun --prefix=/usr && \
make -j`nproc --all` && \
make install
RUN cd /install/spandsp && \
./bootstrap.sh && \
./configure CFLAGS="-g -ggdb" --with-pic --prefix=/usr && \
make -j`nproc --all` && \
make install
RUN cd /install/signalwire-c && \
PKG_CONFIG_PATH=/usr/lib/pkgconfig cmake . -DCMAKE_INSTALL_PREFIX=/usr && \
make install
RUN cd /install/freeswitch && \
sed -i 's|#formats/mod_shout|formats/mod_shout|' build/modules.conf.in && \
./bootstrap.sh -j && \
./configure && \
make -j`nproc` && \
make install && \
make cd-sounds-install && \
make cd-moh-install && \
make uhd-sounds-install && \
make uhd-moh-install && \
make hd-sounds-install && \
make hd-moh-install && \
make sounds-install && \
make moh-install && \
ln -sf /usr/local/freeswitch/bin/freeswitch /usr/local/bin/ && \
ln -sf /usr/local/freeswitch/bin/fs_cli /usr/local/bin/
RUN cd /install/unimrcp-deps-1.6.0/libs/apr && \
./configure --prefix=/usr/local/apr && \
make && make install && \
cd ../apr-util && \
./configure --prefix=/usr/local/apr --with-apr=/usr/local/apr && \
make && make install && \
cd ../../../unimrcp && \
./bootstrap && \
./configure --with-sofia-sip=/usr && \
make && make install && \
cd ../mod_unimrcp && \
export PKG_CONFIG_PATH=/usr/local/freeswitch/lib/pkgconfig:/usr/local/unimrcp/lib/pkgconfig && \
./bootstrap.sh && \
./configure && \
make && make install
RUN apt-get clean
```

View File

@ -0,0 +1,240 @@
# 使用fail2ban自动拦截恶意注册
> wandoubaba / 2023-07-10
通常情况下如果我们的FreeSWITCH应用是面向互联网开放的话就要对互联网开放SIP端口那么就避免不了来自一些“不友善”的IP发来的尝试SIP注册的请求我们往往会在FreeSWITCH的日志中看到类似这下面这样的信息
```log
2023-07-10 19:12:35.902557 98.23% [WARNING] sofia_reg.c:3211 Can't find user [8001@192.168.0.112] from 194.61.28.102
You must define a domain called '192.168.0.112' in your directory and add a user with the id="8001" attribute
and you must configure your device to use the proper domain in its authentication credentials.
2023-07-10 19:13:38.522558 98.27% [WARNING] sofia_reg.c:3211 Can't find user [80018001@192.168.0.112] from 194.61.28.102
You must define a domain called '192.168.0.112' in your directory and add a user with the id="80018001" attribute
and you must configure your device to use the proper domain in its authentication credentials.
2023-07-10 19:14:42.342569 98.10% [WARNING] sofia_reg.c:3211 Can't find user [80018001@192.168.0.112] from 194.61.28.102
You must define a domain called '192.168.0.112' in your directory and add a user with the id="80018001" attribute
and you must configure your device to use the proper domain in its authentication credentials.
```
> 自从1.10.7开始FreeSWITCH的日志中都会在时间戳的后面加上空闲CPU百分比这里的FreeSWITCH版本是1.10.8。
从上面这些内容我们不难看出,有个主机一直从`194.61.28.102`这个IP在向我们的FreeSWITCH发直SIP注册请求想要注册分机号`8001`或者`80018001`去网上查询一下可以看到这个IP的地理位置位于美国的加里福尼亚洲笔者可以肯定两点
1. 我们的业务没有美国的客户。
2. 我们的SIP账号中没有8001或者80018001这样的账号。
因此我们可以非常肯定,这种注册行为完全是我们所不欢迎的。
通常情况下我们可以通过将这个IP添加到系统防火墙的黑名单来拒绝来自这种恶意IP的请求但是完全靠这种手动操作是治标不治本的因为过不了多久就会有来自其他IP的恶意注册请求出现靠手动处理完全是禁不绝的。
那么,能不能有一种自动化的工具能够代替人工来做这种自动捕捉和禁止的动作呢?
答案就是:**fail2ban**
## fail2ban简介
fail2ban是一款入侵防御软件通过监控指定日志文件中的文本行可以自动捕获到尝试操作失败的事件进而得到入侵来源地址并自动将地址加入系统防火墙黑名单中从而实现对系统自动入侵防御的目的。
## 用fail2ban防止FreeSWITCH被恶意注册
本文假设系统中已经正确安装、配置并运行了FreeSWITCH。
### 针对Debian上的FreeSWITCH1.10.8
版本信息
|软件/组件|版本|
|---|---|
|操作系统|Debian10.2.1-6(bullseye)|
|FreeSWITCH|1.10.8|
|fail2ban|0.11.2|
#### 安装fail2ban
```sh
sudo apt-get install fail2ban
```
#### 配置fail2ban
fail2ban默认已经内置了针对多种常见服务的入侵防御配置但是默认都不是开启的状态默认情况下fail2ban只是开启了针对`sshd`服务的防御下面我们就一步一步开始打开针对FreeSWITCH的恶意注册防御。
##### 目录结构
|目录或文件|作用|说明|
|---|---|---|
|/etc/fail2ban/fail2ban.conf|fail2ban的主配置文件|一般情况下不需要修改这里|
|/etc/fail2ban/jail.conf|fail2ban的默认拦截配置文件|官方建议不要修改这个文件|
|/etc/fail2ban/filter.d/|fail2ban的默认捕获规则目录|这里包含各种服务的规则文件,如果需要修改,建议在这里基于.conf文件创建.local文件|
|/etc/fail2ban/jail.d/|fail2ban的具体拦截规则目录|在这里创建.local文件来配置拦截规则如freeswitch.local|
|/etc/fail2ban/action.d/|fail2ban执行拦截的执行动作配置|一般情况下不需要修改这里的文件|
##### 创建拦截规则
在`/etc/fail2ban/jail.d/`目录下创建名为`freeswitch.local`的文件:
```sh
touch /etc/fail2ban/jail.d/freeswitch.local
```
编辑`/etc/fail2ban/jail.d/freeswitch.local`文件
```ini
[freeswitch]
enabled = true
filter = %(known/filter)s[_pref_line='(?: [\d\.]+%%%%)?']
banaction = ufw
maxretry = 5
findtime = 3600
bantime = 259200
ignoreip = 127.0.0.1/32
port = 5060,5061
logpath = /usr/local/freeswitch/log/freeswitch.log
```
规则说明:
- `enabled = true` 表示开启这个规则。
- `filter = %(known/filter)s[_pref_line='(?: [\d\.]+%%%%)?']` 是针对FS版本1.10.7之后版本的日志文件中在每行时间戳后面会加下空间CPU百分比加上这行就可以正常识别到事件如果不加上这行就无法正确识别到事件参考<https://github.com/fail2ban/fail2ban/issues/3143>)。
- `banaction = ufw` 表示拦截时使用ufw命令如果不加这句则默认在拦截时会使用iptables命令如果系统中使用了ufw来管理防火墙建议加上这句否则有可能拦截无效
- `maxretry = 5` 表示相同事件连续发生的次数这里设置为5表示连续尝试5次就被视为恶意行为
- `findtime = 3600` 表示监控的周期配合maxretry使用这里的配置表示“3600秒内发生5次尝试即被视为恶意行为”。
- `bantime = 259200` 表示拦截时间这里设置为259200秒就是72小时也就是3天
- `ignoreip = 127.0.0.1/32` 表示不拦截的IP地址。
- `port = 5060,5061` 是SIP服务的端口号包括TLS
- `logpath = /usr/local/freeswitch/log/freeswitch.log` 是FreeSWITCH是实时日志文件的绝对路径。
上面这个拦截规则实现的效果就是在1小时之内如果来自同一个IP的SIP注册失败次数达到5次就认为这个IP发起了恶意注册请求3天内自动拒绝来自这个IP的所有请求。
##### 检查事件匹配规则
```sh
cat /etc/fail2ban/filter.d/freeswitch.conf
```
可以看到类似下面的内容
```ini
# Fail2Ban configuration file
#
# Enable "log-auth-failures" on each Sofia profile to monitor
# <param name="log-auth-failures" value="true"/>
# -- this requires a high enough loglevel on your logs to save these messages.
#
# In the fail2ban jail.local file for this filter set ignoreip to the internal
# IP addresses on your LAN.
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf
[Definition]
_daemon = freeswitch
# Parameter "mode": normal, ddos or extra (default, combines all)
# Usage example (for jail.local):
# [freeswitch]
# mode = normal
# # or with rewrite filter parameters of jail:
# [freeswitch-ddos]
# filter = freeswitch[mode=ddos]
#
mode = extra
# Prefix contains common prefix line (server, daemon, etc.) and 2 datetimes if used systemd backend
_pref_line = ^%(__prefix_line)s(?:(?:\d+-)?\d+-\d+ \d+:\d+:\d+\.\d+)?
prefregex = ^%(_pref_line)s \[WARN(?:ING)?\](?: \[SOFIA\])? \[?sofia_reg\.c:\d+\]? <F-CONTENT>.+</F-CONTENT>$
cmnfailre = ^Can't find user \[[^@]+@[^\]]+\] from <HOST>$
mdre-normal = %(cmnfailre)s
^SIP auth failure \((REGISTER|INVITE)\) on sofia profile \'[^']+\' for \[[^\]]*\] from ip <HOST>$
mdre-ddos = ^SIP auth (?:failure|challenge) \((REGISTER|INVITE)\) on sofia profile \'[^']+\' for \[[^\]]*\] from ip <HOST>$
mdre-extra = %(cmnfailre)s
<mdre-ddos>
failregex = <mdre-<mode>>
ignoreregex =
datepattern = ^(?:%%Y-)?%%m-%%d[ T]%%H:%%M:%%S(?:\.%%f)?
{^LN-BEG}
# Author: Rupa SChomaker, soapee01, Daniel Black, Sergey Brester aka sebres
# https://freeswitch.org/confluence/display/FREESWITCH/Fail2Ban
# Thanks to Jim on mailing list of samples and guidance
#
# No need to match the following. Its a duplicate of the SIP auth regex.
# ^\.\d+ \[DEBUG\] sofia\.c:\d+ IP <HOST> Rejected by acl "\S+"\. Falling back to Digest auth\.$
```
这是fail2ban官方内容的事件匹配规则针对本文档所使用各组件版本这里的规则不需要修改。
##### fail2ban命令
```sh
## 启动系统服务
systemctl start fail2ban
## 重启系统服务(修改配置生效)
systemctl restart fail2ban
## 停止系统服务
systemctl stop fail2ban
## 用fail2ban-client命令启动服务
fail2ban-client start
## 用fail2ban-client命令重载全部配置修改配置生效
fail2ban-client reload
## 用fail2ban-client命令重载指定监禁配置<JAIL>换成具体的名称)
fail2ban-client reload <JAIL>
## 用fail2ban-client命令停止服务
fail2ban-client stop
## 查看当前保护状态
fail2ban-client status
## 查看当前保护的具体服务状态(把<JAIL>换成具体的名称)
fail2ban-client status <JAIL>
## 查看版本
fail2ban-client version
## 手动监禁一个IP<JAIL>换成具体名称,把<xx.xx.xx.xx>换成具体IP
fail2ban-client set <JAIL> banip <xx.xx.xx.xx>
## 手动将一个IP解除监禁<JAIL>换成具体名称,把<xx.xx.xx.xx>换成具体IP
fail2ban-client set <JAIL> unbanip <xx.xx.xx.xx>
```
##### fail2ban日志
位置 `/var/log/fail2ban.log`
##### 查看拦截是否生效
在本文的示例环境中,使用了`ufw`做为系统防火墙管理工具所以我们使用ufw命令可以看到拦截是否生效
```sh
ufw status
```
结果可能类似下面:
```sh
Status: active
To Action From
-- ------ ----
Anywhere REJECT 194.61.28.102
Anywhere REJECT 193.107.216.55
Anywhere REJECT 193.107.216.29
Anywhere REJECT 193.107.216.143
22/tcp ALLOW Anywhere
80/tcp ALLOW Anywhere
443/tcp ALLOW Anywhere
....
```
上面被REJECT的这几个IP就是被fail2ban监禁的IP。
关于fail2ban的更多玩法可以到fail2ban的官方github上去了解<https://github.com/fail2ban/fail2ban>

View File

@ -0,0 +1 @@
# FreeSWITCH相关

View File

@ -0,0 +1,74 @@
# FreeSWITCH安装mod_unimrcp模块
> wandoubaba / 2023-01-18
本文操作过程基于Debian11操作系统。自FreeSWITCH1.10.8开始mod_unimrcp已经从FreeSWITCH主库分离成为独立项目因此不能再用`make mod_unimrcp-install`命令安装模块了。
## 确保FreeSWITCH已经安装成功
安装过程请参见[Debian编译安装FreeSWITCH](debian.html)。
## 安装unimrcp和依赖
下面的操作如果在root账号下请省略`sudo`前缀。
```sh
sudo apt-get install wget tar
wget https://www.unimrcp.org/project/component-view/unimrcp-deps-1-6-0-tar-gz/download -O unimrcp-deps-1.6.0.tar.gz
tar xvzf unimrcp-deps-1.6.0.tar.gz
cd unimrcp-deps-1.6.0
# 安装apr
cd libs/apr
./configure --prefix=/usr/local/apr
make
sudo make install
cd ..
# 安装apr-util
cd apr-util
./configure --prefix=/usr/local/apr --with-apr=/usr/local/apr
make
sudo make install
cd ../../..
# 安装unimrcp
git clone https://github.com/unispeech/unimrcp.git
cd unimrcp
./bootstrap
./configure --with-sofia-sip=/usr
make
sudo make install
cd ..
```
## 安装mod_unimrcp
按照下面的程序清单执行完毕后在FreeSWITCH的安装目录下的mod目录中会出现`mod_unimrcp.so`文件,如`/usr/local/freeswitch/mod/mod_unimrcp.so`。
```sh
cd /opt
git clone https://github.com/freeswitch/mod_unimrcp.git
cd mod_unimrcp
export PKG_CONFIG_PATH=/usr/local/freeswitch/lib/pkgconfig:/usr/local/unimrcp/lib/pkgconfig
./bootstrap.sh
./configure
make
sudo make install
```
如果在执行./bootstrap.sh后遇到`required file './ltmain.sh' not found`错误的话,通过以下方法或许可以解决:
```sh
libtoolize --version
libtoolize --automake --copy --debug --force
```
## 在FreeSWITCH配置中启用mod_unimrcp
编辑配置文件`/usr/local/freeswitch/conf/autoload_configs/modules.conf.xml`,在`configuration->modules`节点下,追加下面一行配置:
```xml
<load module="mod_unimrcp"/>
```
如果FreeSWITCH是已启动状态在fs控制台执行load mod_unimrcp即可加载模块。
此时执行`load mod_unimrcp`后,有可能会看到`mod_unimrcp.c:3893 Could not open unimrcp.conf`之类的报错那是因为我们还没有对unimrcp模块做具体配置后面会有专门的文档介绍unimrcp模块的具体使用。

View File

@ -0,0 +1,213 @@
# Ubuntu16.04安装freeswitch1.6
## 操作系统和软件版本
ubuntu16.04
freeswitch v1.6
python2.7
lua5.1
## 准备工作
### 安装系统
最小安装ubuntu16.04系统安装ssh server
### 安装依赖
```sh
sudo apt-get install -y \
python-dev swig ffmpeg \
yasm unixodbc-dev \
libshout3-dev libmpg123-dev \
libmp3lame-dev libsndfile-dev \
autoconf automake devscripts \
libopus-dev libvorbis0a \
libogg0 libogg-dev \
libvorbis-dev gawk \
g++ git-core libjpeg-dev \
libncurses5-dev libtool-bin \
pkg-config libtiff5-dev \
libperl-dev libgdbm-dev \
libdb-dev gettext libssl-dev \
libcurl4-openssl-dev \
libpcre3-dev libspeex-dev \
libspeexdsp-dev libsqlite3-dev \
libedit-dev libldns-dev \
libpq-dev
```
如果需要开启mod_lua模块还需要安装lua
```sh
sudo apt-get install -y lua5.1 liblua5.1-dev
```
- 安装一些python依赖
安装dbutils可能会失败是因为python和pip的版本太老了。
这一步不是必须的只有在你需要用python2为FreeSWITCH写脚本时才会用到。
```sh
wget https://bootstrap.pypa.io/pip/2.7/get-pip.py
python get-pip.py
pip install pydub
pip install python-ESL
pip install pika
pip install dbutils
```
### 下载源码
```sh
git clone https://github.com/signalwire/freeswitch.git
cd freeswitch
git checkout v1.6
git remote rm origin
```
> 最后一句是断开本地目录和远程代码库的关联
## 安装freeswitch
- 配置lua
```bash
cp /usr/include/lua5.1/*.h src/mod/languages/mod_lua/
```
```bash
sudo ln -s /usr/lib/x86_64-linux-gnu/liblua5.1.so /usr/lib/x86_64-linux-gnu/liblua.so
```
- 预处理
```bash
sudo ./bootstrap.sh -j
```
- 预配置模块
```bash
vim modules.conf
```
打开注释
```
formats/mod_shout
languages/mod_python
event_handlers/mod_cdr_pg_csv
asr_tts/mod_unimrcp
```
如果不需要使用lua语言模块则将下面内容加注释
```
#languages/mod_lua
```
- 编译安装
```bash
./configure --with-python=/usr/bin/python2.7 --with-lua=/usr/bin/lua5.1 --enable-core-pgsql-support
sudo make
sudo make mod_cdr_pg_csv-install
sudo make mod_unimrcp-install
sudo make install
```
- 安装声音包
```bash
sudo make sounds-install
sudo make moh-install
sudo make cd-sounds-install
sudo make cd-moh-install
sudo make uhd-sounds-install
sudo make uhd-moh-install
```
- 全局命令
```bash
sudo ln -sf /usr/local/freeswitch/bin/freeswitch /usr/local/bin/
sudo ln -sf /usr/local/freeswitch/bin/fs_cli /usr/local/bin/
```
- 配置模块
```bash
vim /usr/local/freeswitch/conf/autoload_configs/modules.conf.xml
```
打开注释
```xml
<load module="mod_python"/>
<load module="mod_shout"/>
```
添加配置
```xml
<load module="mod_cdr_pg_csv"/>
<load module="mod_unimrcp"/>
```
- 配置acl白名单
```bash
vim /usr/local/freeswitch/conf/autoload_configs/acl.conf.xml
```
根据自己网络的实际情况进行配置(照抄大概率无效)
```xml
<list name="domains" default="deny">
<!-- domain= is special it scans the domain from the directory to build t$ -->
<node type="allow" domain="$${domain}"/>
<!-- use cidr= if you wish to allow ip ranges to this domains acl. -->
<node type="allow" cidr="127.0.0.1/32"/>
</list>
```
- 配置ESL
```bash
vim /usr/local/freeswitch/conf/autoload_configs/event_socket.conf.xml
```
```xml
<configuration name="event_socket.conf" description="Socket Client">
<settings>
<param name="nat-map" value="false"/>
<!--ip 统一为0.0.0.0-->
<param name="listen-ip" value="0.0.0.0"/>
<!-- 端口号 默认8021 -->
<param name="listen-port" value="8021"/>
<!-- 密码统一ClueCon -->
<param name="password" value="ClueCon"/>
<!-- 允许acl白名单内的IP 访问 -->
<param name="apply-inbound-acl" value="domains"/>
<!--<param name="apply-inbound-acl" value="loopback.auto"/>-->
<!--<param name="stop-on-bind-error" value="true"/>-->
</settings>
</configuration>
```
## 4. 启动freeswitch
```bash
freeswitch -nc
```
通过fs_cli可以进入freeswitch控制台freeswitch服务启动需要等一段时间而且可能会很长
```bash
fs_cli --password=ClueCon
```

View File

@ -0,0 +1,90 @@
# 恶意SIP行为IP黑名单持续更新
> 更新时间: 2023年7月4日
```text
103.145.13.152
103.145.13.249
13.64.199.47
13.71.209.198
134.119.178.63
134.119.223.166
141.94.119.172
141.98.10.20
141.98.11.91
143.244.57.69
143.244.57.86
146.0.32.162
151.106.27.151
151.106.34.153
162.244.32.51
162.244.33.16
172.107.196.242
178.239.21.117
178.239.21.140
178.239.21.66
178.239.21.79
185.159.82.22
185.167.96.138
185.209.162.207
185.209.162.21
185.246.211.81
185.53.90.125
185.53.90.166
192.99.232.191
193.107.216.135
193.107.216.141
193.107.216.147
193.107.216.232
193.107.216.62
193.46.255.163
193.46.255.253
20.106.123.29
20.106.171.142
20.206.66.152
20.213.250.164
20.216.2.135
20.227.142.53
212.83.145.185
222.79.56.89
23.148.145.240
23.148.145.54
23.148.145.83
23.148.145.94
23.254.36.131
37.19.217.75
37.221.123.90
45.134.144.10
45.134.144.169
45.134.144.254
45.134.144.47
45.134.144.57
45.134.144.86
45.159.188.57
45.93.16.61
45.95.147.9
51.103.210.57
51.12.91.47
51.132.241.252
51.142.145.184
51.142.145.87
77.247.108.35
80.94.93.88
84.247.51.246
85.114.130.103
87.119.220.202
87.119.220.250
92.118.39.12
92.118.39.59
92.204.134.78
103.145.13.47
77.247.108.248
77.247.108.56
77.247.108.31
149.7.16.224
103.145.13.74
103.145.13.47
77.247.108.248
77.247.108.56
77.247.108.31
```

View File

@ -0,0 +1,100 @@
# 搭建STUN服务
---
> 以centos7为例
* github地址
```
https://github.com/jselbie/stunserver
```
* STUNServer官网
```
http://www.stunprotocol.org/
```
## 部署过程推荐Docker
> 确保已有docke环境
```bash
# 下载安装包
wget http://www.stunprotocol.org/stunserver-1.2.16.tgz
# 解压
tar xvf stunserver-1.2.16.tgz
# 转移目录
mv stunserver /usr/local/
cd /usr/local/stunserver
docker image build -t=stun-server-image .
docker run -d -p 3478:3478/tcp -p 3478:3478/udp --name=stun-server stun-server-image
```
## 部署过程(编译安装)
* 如果是centos系统
```bash
# 安装依赖
yum install -y gcc gcc-c++ make boost-devel openssl-devel
cd /usr/local/src
```
* 如果是debian系统
```bash
apt install -y libboost1.74-all-dev
cd /usr/src
```
```bash
# 下载安装包
wget http://www.stunprotocol.org/stunserver-1.2.16.tgz
# 解压
tar xvf stunserver-1.2.16.tgz
# 转移目录
mv stunserver /usr/local/
cd /usr/local/stunserver
# 安装
make
# 校验
./stuntestcode
# 启动服务
./stunserver &
```
## 防火墙
```bash
firewall-cmd --permanent --add-port=3478/udp
firewall-cmd --reload
```
## 开机启动stun服务
```bash
vim /etc/rc.local
```
在最后添加一行
```bash
/usr/local/stunserver/stunserver &
```
对rc.local添加执行权限
```bash
chmod +x /etc/rc.d/rc.local
```
## 配置freeswitch
```bash
cd /usr/local/freeswitch/conf
vim vars.xml
```
把stun-set中的服务地址换成刚配置好的stun服务器地址

View File

@ -0,0 +1,265 @@
# 部署百度智能呼叫中心的MRCPServer
---
## 官方链接
<https://cloud.baidu.com/doc/SPEECH/s/8kay0g6pq>
## 系统要求
centos7+
## 操作系统 & 必要配置
- 最小安装centos7+系统比如7.9
- 网卡名称配置为eth0
- 配置服务器IP
- 安装必要软件
```bash
yum install -y net-tools telnet git vim wget
```
## 部署MRCPServer
### 下载sdk
```bash
curl https://ai.baidu.com/download?sdkId=111 -L -o mrcpserver.tar.gz
```
### 解压
```bash
tar zxvf mrcpserver.tar.gz
```
### 部署配置
- 预处理
```bash
cd MRCPServer
./bootstrap.sh
```
- 配置IP和端口
```bash
cd mrcp-server
vim conf/unimrcpserver.xml
```
定位到`unimrcpserver->properties->ip`节点对绑定IP进行配置可以有多种配置方式
```xml
<!-- 可以直接设置IP地址(客户端无论在远程还是本地都只能通过这个ip来调用) -->
<ip>183.211.245.48</ip>
<!-- 可以设置成type="auto"由程序自动获取机器IP默认只支持本机127.0.0.1 -->
<ip type="auto">
<!-- 可以填写网卡名称自动获取网口的IP少用客户端无论在远程还是本地都只能通过这个网口的ip来调用 -->
<ip type="iface">eth0</ip>
<!-- 同时支持127.0.0.1调用和公网IP调用 -->
<ip>0.0.0.0</ip>
```
定位到`unimrcpserver->components->sip-uas->sip-port`节点可以配置SIP端口
```xml
<!-- 软件默认SIP端口是5060可以自定义如8060不要与其他服务冲突udp和tcp -->
<sip-port>5060</sip-port>
```
定位到`unimrcpserver->components->rtsp-uas->rtsp-port`节点可以配置RTSP端口
```xml
<!-- 软件默认RTSP端口是1554可以自定义如8554不要与其他服务冲突TCP -->
<rtsp-port>1554</rtsp-port>
```
定位到`unimrcpserver->components->mrcpv2-uas->mrcp-port`节点可以配置mrcp端口
```xml
<!-- 软件默认MRCP端口是1544可以自定义如8544不要与其他服务冲突TCP -->
<mrcp-port>1544</mrcp-port>
```
定位到`unimrcpserver->components->rtp-factory`节点可以配置rtp端口范围
```xml
<!-- 软件默认是50006000可以自定义注意不要和其他服务冲突TCP -->
<rtp-port-min>5000</rtp-port-min>
<rtp-port-max>6000</rtp-port-max>
```
- 配置asr
```
vim conf/mrcp-asr.conf
```
定位到`AUTH_APPID`和`AUTH_APPKEY`这两个值分别对应百度控制台语音技术应用的AppID和API Key网址<https://console.bce.baidu.com/ai/#/ai/speech/app/list>
```
# AppID照抄无效
AUTH_APPID : 2400000
# API Key照抄无效
AUTH_APPKEY : "FfMfDOdAdjBqCaLKAmNfqquW"
```
- 配置tts
```bash
vim conf/mrcp-proxy.conf
```
定位到`AUTH_APPID`和`AUTH_APPKEY`这两个值分别对应百度控制台语音技术应用的AppID和API Key网址<https://console.bce.baidu.com/ai/#/ai/speech/app/list>
```
# AppID照抄无效
AUTH_APPID : 2400000
# API Key照抄无效
AUTH_APPKEY : "FfMfDOdAdjBqCaLKAmNfqquW"
```
- 配置启动控制文件
```bash
vim conf/unimrcpserver_control.conf
```
定位到`_check_cmd_pro="./bin/check 127.0.0.1 1544"`把127.0.0.1替换成unimrcpserver.xml配置的ip如果auto这里就不用换了把1544替换成在unimrcpserver.xml配置的mrcp-port
## 启动服务
### 以调试模式启动系统
做好配置后首次启动服务建议以调试模式启动以便可以在console里看到启动过程。
```bash
# 根据sdk保存位置不同你的具体路径不一定跟这里一样
cd /root/MRCPServer/mrcp-server
./bin/unimrcpserver -r . &
```
正常情况下,应该会看到类似下面的输出
```console
Version: mrcp-asr | v2.0.0 | 20200609-175030 | 0e285e16 | mrcp-asr-ctrip-1.5
Version: mrcp-tts | v2.0.0 | 20200601-212708 | 24a1c9b1 | dev-liantong.mrcp1.5.0
```
> 调试模式启动后,如果想要关闭服务,需要用`ps -aux | grep mrcp`查看相关进程的PID然后用`kill -9 PID`杀掉进程
### 以启护进程方式启动服务
在生产环境时,建使用启动脚本,以守护进程方式启动服务。
执行`${SERVER_ROOT}/mrcp-server/bin/`下的`unimrcpserver_control`并带上控制参数:
```bash
cd /root/MRCPServer/mrcp-server/bin
#启动
./unimrcpserver_control start
#停止
./unimrcpserver_control stop
#重启
./unimrcpserver_control restart
```
> restart指令必须在start状态下才可以使用修改配置文件后需要restart才能生效但是如果修改的是ip或者端口restart会出错这时就只能`ps -aux | grep mrcp`然后再`kill -9 PID`杀掉相关进程后再发重新start
### 安全设置
MRCPServer对于客户端没有安全校验机制如果不启用防火墙或者中是单纯的开放端口结果可能会被任意freeswitch接入为了避免这种情况发生应该对MRCPServer开启防火墙并采用指定IP机制具体操作如下
```txt
MRCPServer服务器
IP183.211.245.48
SIP-PORT8060/udp, 8060/tcp
RTSP-PORT1554/tcp
MRCP-PORT1544/tcp
RTP5000-6000/udp
freeswitch服务器
IP112.4.97.6
```
在MRCP服务端配置防火墙规则如下
```bash
# 向112.4.97.6开放sip端口8060/tcp
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="112.4.97.6" port protocol="tcp" port="8060" accept'
# 向112.4.97.6开放sip端口8060/udp
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="112.4.97.6" port protocol="udp" port="8060" accept'
# 向112.4.97.6开放rtsp端口1554/tcp
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="112.4.97.6" port protocol="tcp" port="1554" accept'
# 向112.4.97.6开放mrcp端口1544/tcp
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="112.4.97.6" port protocol="tcp" port="1544" accept'
# 向112.4.97.6开放rtp范围5000-6000/udp
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="112.4.97.6" port protocol="udp" port="5000-6000" accept'
```
### 用sdk中的客户端进行asr测试
#### 在本机测试
- 保证${SERVER_ROOT}/mrcp-server/conf/mrcp-asr.conf文件中的相关配置填写正确
```text
* AUDIO_CONTROLLER_ADDR百度上游服务地址(默认值当前有效)
* AUTH_APPID和AUTH_APPKEY从百度官网中获取的APPID和API Key的值。
* NEED_SAVE_AUDIO是否保存语音识别时用户语音默认1为保存
* AUDIO_SPLIT_TIME是VAD判断的间隔时间单位毫秒
```
- 配置LD_LIBRARY_PATH变量
```bash
# 注意把${SERVER_ROOT}替换成真实路径
export LD_LIBRARY_PATH=${SERVER_ROOT}/mrcp-server/lib:$LD_LIBRARY_PATH
```
- 修改测试程序配置文件
conf/client-profiles/unimrcp.xml 是测试工具的配置文件需要将其中的unimrcpclient->settings->sip-settings->server-ip的值修改为本机IP端口设置为主程序端口如5060。
- 执行测试程序
- 切换到 ${SERVER_ROOT}/mrcp-server/bin 目录下
- 执行 ./asrclient
- 待测试程序启动后,在控制台输入 run grammar.xml xeq.pcm
- 在控制台会显示识别结果在log目录下的mrcp_debug.log中也可以看到整个识别过程
> 更多信息可参考<https://ai.baidu.com/ai-doc/SPEECH/Ekaxz1mkz>
### 用sdk中的客户端进行tts测试
待完善
### 服务开机自启动
待完善
### 配置文件说明
#### vad配置文件conf/vad.conf
```
sp_threshold : 0.2 # 有效声音的音量阈值(多少以上有效)
sil_threshold : 0.1 # 被认为无效声音的音量阈值(多少以下无效)
max_wait_duration : 150 # 最大等待时长
max_sp_duration : 24000 # 最长说话时间
max_sp_pause : 150 # 最大说话暂停时长
head_sil_duration : 18000 # 开头允许的最大静音时长
start_back_frame : 40
end_back_frame : 40
debug_log : 0
sample_rate : 8000
cmvnfile : global.cmvn
dnnfile : vad.dnn
package_len : 1600
vad_num : 10
```

View File

@ -0,0 +1 @@
# 前端相关

View File

@ -0,0 +1,33 @@
# npm切换源
---
## 查看源来的镜像地址
```bash
npm get registry
```
## 设置成淘宝源
```bash
npm config set registry http://registry.npm.taobao.org
```
## 设置成初始的源
```bash
npm config set registry https://registry.npmjs.org/
```
## 将npm替换成cnpm
```bash
npm install -g cnpm --registry=https://registry.npm.taobao.org
```
## 全局安装yarn
```bash
cnpm install yarn -g
```

View File

@ -0,0 +1,88 @@
# 在VuePress项目中添加百度统计代码
## 背景
VuePress是Vue驱动的静态网站生成器如果想知道VuePress生成的网站每天的访问情况而又不想为它开发后台最好就是引用外部统计脚本本文选择百度统计平台。
## 获取统计代码
百度统计平台地址: <https://tongji.baidu.com>
登录后先创建站点,然后就可以获取统计代码,得到的统计代码示例:
```html
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?1eb7f71a234c2320xxxxxxxxxxxxxxxx";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
```
同时,在百度统计的代码获取页中还有一段说明,原文如下:
```text
代码安装说明
1. 请将代码添加到网站全部页面的</head>标签前。
2. 建议在header.htm类似的页头模板页面中安装以达到一处安装全站皆有的效果。
3. 如需在JS文件中调用统计分析代码请直接去掉以下代码首尾的<script type="text/javascript"></script>放入JS文件中即可。
如果代码安装正确一般20分钟后可以查看网站分析数据。
```
可我们的VuePress项目中生成的html文件都是由Vue编译出来的实际源代码中都是Markdown文档和js文件所以我们无法按照百度统计平台中的方法去安装代码。
## 安装代码
具体只需要处理2个文件分别是`.vuepress/config.js`和`.vuepress/enhanceApp.js`(如果不存在就自己创建)。
### 编辑config.js
```js
module.exports = {
/// ...其他配置项
head: [
/// ...其他head项
// 百度统计代码
[
"script",
{},
`var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?1eb7f71a234c2320xxxxxxxxxxxxxxxx";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();`,
],
],
/// ...其他配置项
};
```
### 编辑enhanceApp.js
主要是用来让统计代码可以捕捉到Vue的路由变化。
```js
export default ({ router }) => {
// 路由切换事件处理
router.beforeEach((to, from, next) => {
//触发百度的pv统计
if (typeof _hmt != "undefined") {
if (to.path) {
_hmt.push(["_trackPageview", to.fullPath]);
}
}
next();
});
};
```
## 安装检查
完成上面操作后,将项目重新编辑打包并发布到服务器上,试着浏览网站,打开`F12`,在`Network`中查看有没有`hm.js`,如果有,就说明统计代码安装成功了,按照百度统计的说法,多等些时候就能看到统计结果了。

View File

@ -0,0 +1,42 @@
## 在linux中安装node二进制文件
### 下载二进制文件
下载网址 <https://nodejs.org/zh-cn/download/>
备用中文网址 <https://nodejs.cn/download/>
以18.16.1版本为例
```sh
wget https://npmmirror.com/mirrors/node/v18.16.1/node-v18.16.1-linux-x64.tar.xz
```
### 安装
先创建安装目录并解压文件
```sh
sudo mkdir -p /usr/local/lib/nodejs
tar xJvf node-v18.16.1-linux-x64.tar.xz -C /usr/local/lib/nodejs
```
再将node执行目录写入/etc/profile在`export PATH`的上一行添加:
```
PATH=/usr/local/lib/nodejs/node-v18.16.1-linux-x64/bin:$PATH
```
重新加载profile
```sh
source /etc/profile
```
安装完成!
查看版本
```sh
node -v
npm -v
```

View File

@ -0,0 +1,59 @@
# 在vscode里配置vetur符合eslint
## 默认格式化程序
| 配置项 | 值 |
|---|---|
|vetur.format.defaultFormatter.html|prettier|
|vetur.format.defaultFormatter.js|vscode-typescript|
|vetur.format.defaultFormatter.css|prettier|
|vetur.format.defaultFormatter.less|prettier|
|vetur.format.defaultFormatter.scss|prettier|
|vetur.format.defaultFormatter.postcss|prettier|
|vetur.format.defaultFormatter.sass|sass-formatter|
## js函数名与括号之间添加一个空格
| 配置项 | 值 |
|---|---|
|javascript.format.insertSpaceBeforeFunctionParenthesis|true|
> 这个选项只在`vetur.format.defaultFormatter.js`值为`vscode-typescript`时有效。
## 配置缩进
| 配置项 | 值 | 说明 |
|---|---|---|
|vetur.format.scriptInitialIndent|false|&lt;script&gt;内代码初始缩进为0|
|vetur.format.styleInitialIndent|false|&lt;style&gt;内代码初始缩进为0|
|vetur.format.options.tabSize|2|代码缩进单位为2个空格|
|vetur.format.options.useTabs|false|使用空格代替tab|
## js中的字符串使用单引号而不是双引号
只要`vetur.format.defaultFormatter.js`值为`vscode-typescript`就已经可以了。
| 配置项 | 值 |
|---|---|
|vetur.format.defaultFormatter.js|vscode-typescript|
## 取消行尾分号(如果有分号会在格式时自动删除)
| 配置项 | 值 |
|---|---|
|javascript.format.semicolons|remove|
> 这个不是只针对vue的而是对所有js生效。
## 避免脚本中因使用别名被报错
| 配置项 | 值 |
|---|---|
|vetur.validation.script|false|
## 避免其他过于严格的报错(可选)
| 配置项 | 值 |
|---|---|
|vetur.validation.style|false|
|vetur.validation.template|false|

View File

@ -0,0 +1,18 @@
## 解决create-vue创建的项目运行后提示Network: use --host to expose的问题
### 修改vite.config.js文件
```js
import vue from '@vitejs/plugin-vue'
/**
* https://vitejs.dev/config/
* @type {import('vite').UserConfig}
*/
export default {
plugins: [vue()],
server: {
host: '0.0.0.0' // 新增内容
}
}
```

View File

@ -0,0 +1,98 @@
# 常用git命令
> git官方中文文档 <https://www.git-scm.com/book/zh/v2> 中包含更多的信息
---
## 从远程克隆一个仓库
```bash
# 通过SSH连接克隆一个仓库可能需要事先配置SSH公钥
# 执行成功后会在当前路径创建一个名为fsdoc的目录进入目录后即可以用git命令操作仓库了
git clone git@gitee.com:wandoubaba517/fsdoc.git
# 通过HTTP连接克隆一个仓库有时可能会需要用户名和密码
# 执行成功后会在当前路径创建一个名为callapp_mrcp的目录
git clone https://gitee.com/polaris-arvin_admin/callapp_mrcp.git
```
> 除了`git clone`命令外其他git命令都需要在仓库目录下进行操作
## 分支操作
> 别忘了在仓库目录下操作
```bash
# 查看所有分支(本地和远程)
git branch -a
# 切换分支
git checkout develop
# 创建一个名为iss053的分支同时切换到这个新分支
git checkout -b iss053
# 在iss053分支提交修改
git commit -a -m "添加一些git分支操作"
# 将iss053分支的变更合并到master分支
git checkout master
git merge iss053
# 合并后可以删iss053分支
git branch -d iss053
# 如果合并时发现冲突,需要手动处理一下
# 刷新远端分支列表
git remote update origin -p
# 在没有使用git add之前放弃当前全部操作
git checkout .
# 在使用了git add后但还没有git commit之前放弃当前全部操作
git reset HEAD .
git checkout .
# 在使用了git commit后回滚操作
git reset --hard HEAD^ # 回滚到上一次commit状态
git reset --hard <commitid> # 回滚到指定的任意一次提交
# 查看commitid
git log # 退出请按q键
```
## 代码推拉
> 别忘了在仓库目录下操作
```bash
# 从远程分支拉取代码到本地
git pull # 会提取默认关联的远程分支
# 添加本次要跟踪的代码(全部)
git add .
# 提交变更(在本地)
git commit -m "本次提交说明内容"
# 把变更推送到远程服务器
git push # 推送到默认关联的远程分支
git push origin # 有些时候当关联有问题时可能需要手写origin
git push origin bob # 可以指定目标远程分支
```
## 给本地的一个文件夹添加git管理并关联远程仓库
```bash
# 在这个文件夹内执行
git init
# 给本地的一个git文件夹关联一个远程服务器
git remote add origin git@gitee.com:wandoubaba517/ps.git
# 对目录内所有文件建立跟踪
git add .
# 提交本次跟踪
git commit -m "这次提交的说明"
# 推送当前分支并建立与远程上游的跟踪
git push --set-upstream origin master
# 把本地当前分支与远端指定分支关联关联后在本地这个分支下直接git pull和git push就行了不需要再加origin
git branch --set-upstream-to=origin/<branch>
```
## 在一个本地目录上添加多个远程仓库
```bash
# 关联另一个远程仓库
git remote set-url --add origin git@gitee.com:wandoubaba517/personal.git
# 推送当前分支并建立与远程上游的跟踪
git push --set-upstream origin master
# 以后再推送时直接push就行了
git push
```

View File

@ -0,0 +1,90 @@
# 各操作系统生成sshkey的方法
---
---
## Windows 10
> 其他版本系统类似
### 1. 先得安装git
> 如果电脑里已经有git bash就跳过这一步
- 上git官网 `https://git-scm.com/` 去下载最新版,注意对应操作系统。
- 安装git按照向导操作明白选项意思的就根据自己实际情况配置不明白的就留下默认值。
### 2. 检查系统内是否已经有sshkey文件
```cmd
cd ~/.ssh
dir
```
> 如果~/.ssh目录下已经存有id_rsa和id_rsa.pub文件的话那就不需要执行 `3`
### 3. 在git bash中创建sshkey
先打开git bash是git带的命令行工具
```bash
ssh-keygen -t rsa -C "yourname@yourpc"
```
> 一路回车如果希望以后操作git每次push时都输入密码的话那这里可以设置一个密码
以上操作完成后,默认会在~/.ssh/目录下生成名为id_rsa和id_rsa.pub的文件。
### 4. 给自己的公钥文件起一个个性化的名字
> 还是在git bash中操作
```bash
cd ~/.ssh
cp id_rsa.pub yourname_yourpc.pub
```
### 5. 完成
在需要用到sshkey的地方比如git服务器把你的pub文件部署上去就可以了。
---
## MAC
### 1. 先检查系统内是否已经有sshkey文件
```bash
cd ~/.ssh
ls
```
> 如果~/.ssh目录下已经存有id_rsa和id_rsa.pub文件的话那就不需要执行 `2`
### 2. 创建sshkey
```bash
ssh-keygen -t rsa -C "yourname@yourpc"
```
> 一路回车如果希望以后操作git每次push时都输入密码的话那这里可以设置一个密码
以上操作完成后,默认会在~/.ssh/目录下生成名为id_rsa和id_rsa.pub的文件。
### 3. 给自己的公钥文件起一个个性化的名字
```bash
cd ~/.ssh
cp id_rsa.pub yourname_yourpc.pub
```
### 4. 完成
在需要用到sshkey的地方比如git服务器把你的pub文件部署上去就可以了。
---
## linux
> linux下的操作方式与mac非常非常类似。

1
docs/src/go/index.md Normal file
View File

@ -0,0 +1 @@
# go相关

92
docs/src/go/install.md Normal file
View File

@ -0,0 +1,92 @@
# 安装Go环境
> wandoubaba / 2024-08-29
截止本文发布时go的最新版本是`1.23.0`。
## linux
### 下载
```sh
wget https://go.dev/dl/go1.23.0.linux-amd64.tar.gz
```
### 删除旧版本
```sh
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.23.0.linux-amd64.tar.gz
```
### 解压安装
```sh
tar zxvf go1.23.0.linux-amd64.tar.gz -C /usr/local/
```
修改环境变量
```sh
touch /etc/profile.d/go.sh
vim /etc/profile.d/go.sh
```
文件内容如下,然后保存退出
```sh
export PATH=$PATH:/usr/local/go/bin
```
使环境变量立即生效
```sh
source /etc/profile.d/go.sh
```
### 验证安装
```sh
go version
```
结果应该是
```txt
go version go1.23.0 linux/amd64
```
## mac
### 下载
Intel平台
```sh
wget https://go.dev/dl/go1.23.0.darwin-amd64.pkg
```
Arm平台
```sh
wget https://go.dev/dl/go1.23.0.darwin-arm64.pkg
```
### 安装
直接在Finder中执行pkg文件或者在终端中用命令
```sh
sudo installer -pkg go1.23.0.darwin-amd64.pkg -target /usr/local/
```
### 验证安装
```sh
go version
```
结果应该是
```txt
go version go1.23.0 linux/amd64
```

13
docs/src/go/proxy.md Normal file
View File

@ -0,0 +1,13 @@
# 解决`go mod tidy`加载模块超时的问题
## 查看go环境相关信息
```sh
go env
```
## 修改`GOPROXY`配置
```sh
go env -w GOPROXY=https://goproxy.cn
```

28
docs/src/index.md Normal file
View File

@ -0,0 +1,28 @@
---
# https://vitepress.dev/reference/default-theme-home-page
layout: home
hero:
name: "个人技术收藏"
text: "wandoubaba的经验"
tagline: 关于PHP、GoLang、Vue、Git、Docker、MQ、FreeSWITCH……
image:
src: /wandoubaba.png
alt: cover pic
actions:
- theme: brand
text: 打开资料
link: /start
features:
- title: PHP
details: 号称“世界上最好的语言”,又有人说它“已经没落”,不管怎样,用它确实能做很多事情。
- title: Docker
details: 真是一种很有用的技术,至少它打破了“环境死一半”的魔咒。
- title: GoLang
details: 被认为是“Google版的C++”也被认为是“PHP的完美补充”用它可以实现一些PHP做不到的特性。
- title: FreeSWITCH
details: 与PHP没什么关系是一个电话的软交换解决方案做音视频实时通信项目时大概率会用到它。
---

View File

@ -0,0 +1 @@
# kubernetes(k8s)相关内容

View File

@ -0,0 +1,605 @@
# K8s安装过程Debian12+Kubernetes1.28+Containerd+Calico用apt-get在线搭建1master+2node的K8s集群
> wandoubaba / 2024-10-21
截止本文发布时kubernetes最新版本是`v1.31`,而补丁已经全部打完的最新稳定版本是`v1.28`,本文基于后者。
## 安装准备
### 资源准备
|准备项|内容|
|---|---|
|操作系统|Debian 12(bookworm)|
|系统内核|6.1.0-23-amd64|
|容器运行时|containerd CRI|
### 主机清单
|IP假设|主机名|CPU|内存|
|---|---|---|---|
|172.31.0.11|k8s-master01|8c|8G|
|172.31.0.14|k8s-master04|8c|16G|
|172.31.0.15|k8s-master05|8c|16G|
## 过程
### 确认主机基本信息(每台主机)
```sh
# 查看IP地址确认设置为静态地址
ip addr | awk '/inet /{split($2, ip, "/"); print ip[1]}'
# 查看MAC地址确保每台主机的MAC唯一
ip link | awk '/state UP/ {getline; print $2}'
# 查看主机的UUID确保product_uuid的唯一性
sudo cat /sys/class/dmi/id/product_uuid
# 查看内核版本
uname -r
# 查看操作系统发行版本信息
cat /etc/os-release
# 确认cpu核心数量
lscpu -p | grep -v "^#" | wc -l
# 确认内存容量
free -h | awk '/Mem/{print $2}'
# 确认磁盘空间
lsblk
```
### 设置主机名并更新/etc/hosts文件每台主机
#### 设置主机名
```sh
# 在主控制节点k8s-master01上执行
sudo hostnamectl set-hostname k8s-master01
# 在工作节点k8s-node01、k8s-node02上执行
sudo hostnamectl set-hostname k8s-node01
sudo hostnamectl set-hostname k8s-node02
```
主机名设置成功后可以`exit`退出终端再重新连接,或者直接执行`bash`,都可以看到修改后的效果
#### 修改/etc/hosts文件
要根据自己的真实IP进行修改
```sh
sudo bash -c 'cat <<EOF >> /etc/hosts
172.31.0.11 k8s-master01
172.31.0.14 k8s-node01
172.31.0.15 k8s-node02
EOF'
```
### 设置时区并安装时间服务(每台主机)
```sh
sudo timedatectl set-timezone Asia/Shanghai
sudo apt-get update && sudo apt-get install -y chrony
```
#### 配置阿里云时间服务器(可选)
```
pool ntp1.aliyun.com iburst maxsources 4
```
提示:在/etc/chrony/chrony.conf中加入上述配置将其他pool开头的配置注释掉
重启chrony,并验证
```sh
sudo systemctl restart chrony
sudo systemctl status chrony
sudo chronyc sources
```
### 禁用swap每台主机
```sh
sudo swapoff -a
```
还要在`/etc/fstab`文件中注释关于swapr挂载的行。
### 禁用防火墙(每台主机)
```sh
sudo ufw disable
sudo apt-get remove ufw
```
### 优化内核参数
```sh
sudo bash -c 'cat > /etc/sysctl.d/kubernetes.conf <<EOF
# 允许 IPv6 转发请求通过iptables进行处理如果禁用防火墙或不是iptables则该配置无效
net.bridge.bridge-nf-call-ip6tables = 1
# 允许 IPv4 转发请求通过iptables进行处理如果禁用防火墙或不是iptables则该配置无效
net.bridge.bridge-nf-call-iptables = 1
# 启用IPv4数据包的转发功能
net.ipv4.ip_forward = 1
# 禁用发送 ICMP 重定向消息
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
# 提高 TCP 连接跟踪的最大数量
net.netfilter.nf_conntrack_max = 1000000
# 提高连接追踪表的超时时间
net.netfilter.nf_conntrack_tcp_timeout_established = 86400
# 提高监听队列大小
net.core.somaxconn = 1024
# 防止 SYN 攻击
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
# 提高文件描述符限制
fs.file-max = 65536
# 设置虚拟内存交换swap的使用策略为0减少对磁盘的频繁读写
vm.swappiness = 0
EOF'
# 加载或启动内核模块 br_netfilter该模块提供了网络桥接所需的网络过滤功能
sudo modprobe br_netfilter
# 查看是否已成功加载模块
lsmod | grep br_netfilter
# 将读取该文件中的参数设置,并将其应用到系统的当前运行状态中
sudo sysctl -p /etc/sysctl.d/kubernetes.conf
```
### 安装ipset和ipvsadm每台主机
- `ipset`主要用于支持`Service`的负载均衡和网络策略。它可以帮助实现高性能的数据包过滤和转发以及对IP地址和端口进行快速匹配。
- `ipvsadm`主要用于配置和管理`IPVS`负载均衡器,以实现`Service`的负载均衡。
```sh
sudo apt-get install -y ipset ipvsadm
# 检查是否安装
dpkg -l ipset ipvsadm
```
### 内核模块配置(每台主机)
```sh
sudo bash -c 'cat > /etc/modules-load.d/kubernetes.conf << EOF
# /etc/modules-load.d/kubernetes.conf
# Linux 网桥支持
br_netfilter
# IPVS 加载均衡器
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
# IPv4 连接跟踪
nf_conntrack_ipv4
# IP 表规则
ip_tables
EOF'
# 添加可执行权限
sudo chmod a+x /etc/modules-load.d/kubernetes.conf
```
### 关闭安全策略服务(每台主机)
```sh
# 停止 AppArmor 服务
sudo systemctl stop apparmor.service
# 禁用 AppArmor 服务
sudo systemctl disable apparmor.service
```
### 关闭防火墙(每台主机)
```sh
# 禁用ufw
sudo ufw disable
sudo systemctl stop ufw.service
sudo systemctl disable ufw.service
```
### 安装容器运行时(每台主机)
#### 下载
<https://github.com/containerd/containerd/releases>查看最新版本,然后选择对应的`cri-containerd-x.x.x-linux-platform`文件下载:
```sh
curl -L -O https://github.com/containerd/containerd/releases/download/v1.7.23/cri-containerd-1.7.23-linux-amd64.tar.gz
```
#### 安装
```sh
sudo tar xf cri-containerd-1.7.23-linux-amd64.tar.gz -C /
```
#### 配置
```sh
sudo mkdir /etc/containerd
sudo bash -c 'containerd config default > /etc/containerd/config.toml'
sudo sed -i '/sandbox_image/s/3.8/3.9/' /etc/containerd/config.toml
sudo sed -i '/SystemdCgroup/s/false/true/' /etc/containerd/config.toml
```
#### 启动
```sh
# 启用并立即启动containerd服务
sudo systemctl enable --now containerd.service
# 检查containerd服务的当前状态
sudo systemctl status containerd.service
```
#### 验证
```sh
# 检查containerd的版本
containerd --version
# 与CRIContainer Runtime Interface兼容的容器运行时交互的命令行工具
crictl --version
# 运行符合 OCIOpen Container Initiative标准的容器
sudo runc --version
```
### 安装docker每个主机在k8s中可选仅用于构建镜像
```sh
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli docker-buildx-plugin docker-compose-plugin
```
### 安装k8s组件每个主机
指的是安装`kubelet`、`kubeadm`、`kubectl`
```sh
sudo apt-get update
# apt-transport-https may be a dummy package; if so, you can skip that package
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
# If the directory `/etc/apt/keyrings` does not exist, it should be created before the curl command, read the note below.
# sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# This overwrites any existing configuration in /etc/apt/sources.list.d/kubernetes.list
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
sudo systemctl enable --now kubelet
```
#### 配置kubelet
```sh
sudo bash -c 'cat > /etc/default/kubelet << EOF
# 该参数指定了 kubelet 使用 systemd 作为容器运行时的 cgroup 驱动程序
KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"
EOF'
# 这里先设置kubelet为开机自启
sudo systemctl enable kubelet
```
### 初始化master01主机
#### 查看k82镜像可选
```sh
sudo kubeadm config images list
```
应该能列出以下信息:
```sh
registry.k8s.io/kube-apiserver:v1.31.1
registry.k8s.io/kube-controller-manager:v1.31.1
registry.k8s.io/kube-scheduler:v1.31.1
registry.k8s.io/kube-proxy:v1.31.1
registry.k8s.io/coredns/coredns:v1.11.3
registry.k8s.io/pause:3.10
registry.k8s.io/etcd:3.5.15-0
```
> 如果看到类似`remote version is much newer: v1.31.1; falling back to: stable-1.28`的提示说版本低,忽略它就行了。
> k8s的镜像默认是谷歌仓库地址需要代理才可以正常访问如果你没有代理请使用阿里云仓库也是可以的用--image-repository="registry.aliyuncs.com/google_containers"来指定使用阿里云镜像仓库中的镜像部署k8s集群。
#### 下载镜像(可选)
```sh
sudo kubeadm config images pull
```
#### 创建k8s集群
##### 初始化master01节点
- 要把下面的`--apiserver-advertise-address`参数换成实际的`k8s-master01`主机IP地址.
- `--pod-network-cidr`参数指的是本k8s集群中要让pod使用的网段。
```sh
sudo kubeadm init --control-plane-endpoint=k8s-master01 --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=172.31.0.11 --cri-socket unix:///run/containerd/containerd.sock
```
如果执行顺利的话,应该会看到下面的信息(每次的具体参数应该不同)
```sh
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join k8s-master01:6443 --token 1ahq7i.sv3pqgcss8v5oecj \
--discovery-token-ca-cert-hash sha256:8bea18bff8c86d0bc23214974d6b2045c90760448cd4731c94546a9ae836e9ca \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join k8s-master01:6443 --token 1ahq7i.sv3pqgcss8v5oecj \
--discovery-token-ca-cert-hash sha256:8bea18bff8c86d0bc23214974d6b2045c90760448cd4731c94546a9ae836e9ca
```
接下来我们就先配置一下kubectl的配置文件
```sh
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
```
接下来可以查看节点状态:
```sh
kubectl get nodes -o wide
```
应该能看到类似下面的结果:
```sh
# 查看节点状态
kubectl get nodes -o wide
# 结果类似
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-master01 NotReady control-plane 25m v1.28.14 172.31.0.11 <none> Debian GNU/Linux 12 (bookworm) 6.1.0-23-cloud-amd64 containerd://1.7.23
# 查看集群信息
kubectl cluster-info
# 结果类似
Kubernetes control plane is running at https://k8s-master01:6443
CoreDNS is running at https://k8s-master01:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
# 列出所有CRI容器列表
sudo crictl ps -a
# 结果类似其中STATE一列应该都是Running
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID POD
6177ae20a68e6 6a89d0ef825cb 29 minutes ago Running kube-proxy 0 e8d15cb2bcd1a kube-proxy-jlndc
a1a43a29df5c2 6cbf215f8d44e 30 minutes ago Running kube-scheduler 1 3163922b00a0e kube-scheduler-k8s-master01
19dfb26520340 7abec2d806048 30 minutes ago Running kube-controller-manager 1 f6df8f333fcf0 kube-controller-manager-k8s-master01
b4c7a5f9c967f 3438637c2f3ae 30 minutes ago Running kube-apiserver 0 b05316fac4cad kube-apiserver-k8s-master01
8a4c587d9b8d9 2e96e5913fc06 30 minutes ago Running etcd 0 9a8c10ea30b80 etcd-k8s-master01
```
### 添加worker节点把k8s-node01和k8s-node02添加到集群
先在`k8s-master01`上得到添加节点命令(添加`k8s-node01`和`k8s-node02`之前分别是在`k8s-master01`上执行一次)
```sh
sudo kubeadm token create --print-join-command
# 结果与下面的类似每一次的token应该都是不一样的把下面的结果复制下来准备到worker节点上去执行
kubeadm join k8s-master01:6443 --token epvxya.fh4qmay5uwc8628a --discovery-token-ca-cert-hash sha256:8bea18bff8c86d0bc23214974d6b2045c90760448cd4731c94546a9ae836e9ca
```
下面的操作主要在`k8s-node01`和`k8s-node02`上分别执行
```sh
# 安装nmap用于在worker节点上验证master节点上的api-server服务端口的连通性
sudo apt-get install nmap -y
# 把下面的ip地址换成实际master节点主机ip
nmap -p 6443 -Pn 10.31.0.11
# 结果
Starting Nmap 7.93 ( https://nmap.org ) at 2024-10-21 18:50 CST
Nmap scan report for k8s-master01 (172.31.0.11)
Host is up (0.00081s latency).
PORT STATE SERVICE
6443/tcp open sun-sr-https
Nmap done: 1 IP address (1 host up) scanned in 0.03 seconds
# 把刚才在master节得得到的join命令粘贴过来执行建议用非root用户在前面加上sudo
sudo kubeadm join k8s-master01:6443 --token epvxya.fh4qmay5uwc8628a --discovery-token-ca-cert-hash sha256:8bea18bff8c86d0bc23214974d6b2045c90760448cd4731c94546a9ae836e9ca
# 结果类似下面
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
```
再到`k8s-master01`上验证一下
```sh
kubectl get nodes
# 结果类似
NAME STATUS ROLES AGE VERSION
k8s-master01 NotReady control-plane 41m v1.28.14
k8s-node01 NotReady <none> 2m6s v1.28.14
```
然后在master节点上再执行一次`sudo kubeadm token create --print-join-command`,在`k8s-node02`上重复上面的过程。
最后在`k8s-master01`上查看节点信息
```sh
kubectl get nodes
# 结果类似下面
NAME STATUS ROLES AGE VERSION
k8s-master01 NotReady control-plane 43m v1.28.14
k8s-node01 NotReady <none> 4m26s v1.28.14
k8s-node02 NotReady <none> 40s v1.28.14
# 查看k8s的pod信息
kubectl get pods -n kube-system
# 结果类似
NAME READY STATUS RESTARTS AGE
coredns-5dd5756b68-4btx5 0/1 Pending 0 45m
coredns-5dd5756b68-8v2z8 0/1 Pending 0 45m
etcd-k8s-master01 1/1 Running 0 45m
kube-apiserver-k8s-master01 1/1 Running 0 45m
kube-controller-manager-k8s-master01 1/1 Running 1 45m
kube-proxy-5tqw2 1/1 Running 0 6m33s
kube-proxy-864zg 1/1 Running 0 2m47s
kube-proxy-jlndc 1/1 Running 0 45m
kube-scheduler-k8s-master01 1/1 Running 1 45m
```
注意到每一个node的`STATUS`列都是`NotReady`这是因为还没有安装配置网络插件pod间的通信有问题。
### 安装calico网络插件master节点
参考文档<https://docs.tigera.io/calico/latest/getting-started/kubernetes/quickstart>
#### 安装Tigera Calico operator
```sh
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.2/manifests/tigera-operator.yaml
# 结果类似下面
serviceaccount/tigera-operator created
clusterrole.rbac.authorization.k8s.io/tigera-operator created
clusterrolebinding.rbac.authorization.k8s.io/tigera-operator created
deployment.apps/tigera-operator created
# 查看集群命名空间
kubectl get ns
# 结果类似下面
NAME STATUS AGE
default Active 63m
kube-node-lease Active 63m
kube-public Active 63m
kube-system Active 63m
tigera-operator Active 13s
# 查看tigera-operator下的pod
kubectl get pods -n tigera-operator
# 结果
NAME READY STATUS RESTARTS AGE
tigera-operator-5cfff76b77-tdswm 1/1 Running 0 3m46s
```
#### 安装Calico
```sh
curl -L -O https://raw.githubusercontent.com/projectcalico/calico/v3.26.3/manifests/custom-resources.yaml
# 修改ip池需与初始化时一致
sed -i 's/192.168.0.0/10.244.0.0/' custom-resources.yaml
# 安装calico
kubectl create -f custom-resources.yaml
# 结果
installation.operator.tigera.io/default created
apiserver.operator.tigera.io/default created
```
再执行`watch`命令等到所有pod的`STATUS`都变成`Running`
```sh
watch kubectl get pods -n calico-system
# 结果
Every 2.0s: kubectl get pods -n calico-system k8s-master01: Mon Oct 21 19:22:54 2024
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-5846f6d55d-87n88 1/1 Running 0 85s
calico-node-4mhxj 1/1 Running 0 85s
calico-node-6c64k 1/1 Running 0 85s
calico-node-sbzwz 1/1 Running 0 85s
calico-typha-6c76968df6-lcjm6 1/1 Running 0 84s
calico-typha-6c76968df6-xbnk5 1/1 Running 0 85s
csi-node-driver-2vrg7 2/2 Running 0 85s
csi-node-driver-gmb7m 2/2 Running 0 85s
csi-node-driver-mnqvx 2/2 Running 0 85s
```
确认pod运行状态直到所有的pod状态都是`Running`
```sh
watch kubectl get pods -n calico-system
# 结果类似
Every 2.0s: kubectl get pods -n calico-system k8s-master01: Mon Oct 21 19:23:47 2024
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-5846f6d55d-87n88 1/1 Running 0 2m18s
calico-node-4mhxj 1/1 Running 0 2m18s
calico-node-6c64k 1/1 Running 0 2m18s
calico-node-sbzwz 1/1 Running 0 2m18s
calico-typha-6c76968df6-lcjm6 1/1 Running 0 2m17s
calico-typha-6c76968df6-xbnk5 1/1 Running 0 2m18s
csi-node-driver-2vrg7 2/2 Running 0 2m18s
csi-node-driver-gmb7m 2/2 Running 0 2m18s
csi-node-driver-mnqvx 2/2 Running 0 2m18s
```
用`ctrl+c`退出`watch`状态再查看k8s系统的pod状态
```sh
kubectl get pods -n kube-system -o wide
# 结果类似
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
coredns-5dd5756b68-4btx5 1/1 Running 0 72m 10.244.58.196 k8s-node02 <none> <none>
coredns-5dd5756b68-8v2z8 1/1 Running 0 72m 10.244.58.193 k8s-node02 <none> <none>
etcd-k8s-master01 1/1 Running 0 72m 172.31.0.11 k8s-master01 <none> <none>
kube-apiserver-k8s-master01 1/1 Running 0 72m 172.31.0.11 k8s-master01 <none> <none>
kube-controller-manager-k8s-master01 1/1 Running 1 72m 172.31.0.11 k8s-master01 <none> <none>
kube-proxy-5tqw2 1/1 Running 0 33m 172.31.0.14 k8s-node01 <none> <none>
kube-proxy-864zg 1/1 Running 0 29m 172.31.0.15 k8s-node02 <none> <none>
kube-proxy-jlndc 1/1 Running 0 72m 172.31.0.11 k8s-master01 <none> <none>
kube-scheduler-k8s-master01 1/1 Running 1 72m 172.31.0.11 k8s-master01 <none> <none>
```
清理taints污点
```sh
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
```
再次确认集群节点
```sh
kubectl get nodes -o wide
# 结果类似
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-master01 Ready control-plane 75m v1.28.14 172.31.0.11 <none> Debian GNU/Linux 12 (bookworm) 6.1.0-23-cloud-amd64 containerd://1.7.23
k8s-node01 Ready <none> 35m v1.28.14 172.31.0.14 <none> Debian GNU/Linux 12 (bookworm) 6.1.0-23-cloud-amd64 containerd://1.7.23
k8s-node02 Ready <none> 32m v1.28.14 172.31.0.15 <none> Debian GNU/Linux 12 (bookworm) 6.1.0-23-cloud-amd64 containerd://1.7.23
```

View File

@ -0,0 +1,84 @@
# centos7防火墙操作
---
centos7默认使用firewall作为防火墙iptables仍然有效
## 查看防火墙服务状态
```bash
firewall-cmd --state
```
## 启动、关闭、状态
```bash
# 查看状态
systemctl status firewalld
# 启动
systemctl start firewalld
# 停止
systemctl stop firewalld
# 重启
systemctl restart firewalld
# 禁卡开机启动
systemctl disable firewalld
# 开机启动
systemctl enable firewalld
```
## 端口操作
```bash
# 查看已经打开的端口
firewall-cmd --list-ports
# 查看当前所有配置(包括端口、服务等所有)
firewall-cmd --list-all
# 查看firewall所有可识别的服务
firewall-cmd --get-service
# 查看端口是否开通如果开的是服务直接查端口有可能会是no
firewall-cmd --query-port=22/tcp
# 查看服务是否开通
firewall-cmd --query-service=ssh
# 开放某个端口(permanent是永久生效)
firewall-cmd --permanent --add-port=80/tcp
# 开放某段端口范围
firewall-cmd --permanent --add-port=5000-6000/tcp
# 关闭某个端口
firewall-cmd --permanent --remove-port=80/tcp
# 开放某个服务(的默认端口)
firewall-cmd --permanent --add-service=http
# 关闭某个服务(的默认端口)
firewall-cmd --permanent --remove-service=http
# 对指定IP开放相当于白名单
firewall-cmd --permanent --add-source=192.168.1.100
# 对指定IP段开放相当于白名单
firewall-cmd --permanent --add-source=192.168.1.0/24
# 移除某IP
firewall-cmd --permanent --remove-source=192.168.1.100
```
## 复杂操作
```bash
# 允许指定IP访问本机指定端口
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="80" accept'
# 允许指定IP段访问本机端口范围
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="8080-8090" accept'
# 禁止指定IP访问本机指定端口
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="80" reject'
# 屏蔽某个IP的所有请求
firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=103.145.13.92 reject'
```
## 配置生效
任何操作执行完成后,都需要重新装载或重启服务以使其生效:
```bash
firewall-cmd --reload
# 或
service firewalld restart
# 或
systemctl restart firewalld
```

View File

@ -0,0 +1,31 @@
# docker操作
---
## docker容器设置开机自启动
> 前提是docker服务先被设置成开机自启
- 新建容器时配置自启参数
```bash
docker run --restart=always <容器id><容器名称>
```
- 已经存在的容器配置自启
```bash
docker update --restart=always <容器id><容器名称>
```
- 取消容器自启
```bash
docker update --restart=no <容器id><容器名称>
```
- 批量设置所有容器自启
```bash
docker update --restart=always $(docker ps -aq)
```

View File

@ -0,0 +1,60 @@
# linux常用命令和操作技巧
---
## 查看linux发行版本
- centos
```bash
rpm -q centos-release
```
结果大概如下:
centos-release-7-9.2009.1.el7.centos.x86_64
- ubuntu
```bash
lsb_release -a
```
## 查看本机的公网IP
```bash
curl cip.cc
```
## 用curl下载文件不需要单独安装wget
```bash
curl http://domain/path -L -O
```
将会在path的最后一段作为文件名来保存文件
```bash
curl http://domain/path -L -o filename
```
将会以filename为文件名保存文件
## centos系统临时切换成英文/中文
```bash
export LANG=en_US.UTF-8
```
```bash
export LANG=zh_CN.UTF-8
```
## ll按时间或大小排序
```bash
# 按时间降序(最新的在最后)
ll -rt
# 按大小降序(最小的在最后)
ll -Sh
```

View File

@ -0,0 +1,138 @@
# 在ubuntu系统里把网卡名称改为eth0
---
## 在ubuntu16.04系统
> 非root用户需要在命令前加sudo
### 1. 修改grub文件
```bash
vim /etc/default/grub
```
原文
```
GRUB_CMDLINE_LINUX=""
```
改为
```
GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0"
```
保存退出
### 2. grub生效
```bash
grub-mkconfig -o /boot/grub/grub.cfg
```
### 3. 改网络配置
> 适用于ubuntu16.04,其他版本不一定有效
```bash
vim /etc/network/interfaces
```
原文(类似)
```txt
auto ens160
iface ens160 inet static
```
改为
```txt
auto eth0
iface eth0 inet static
```
### 4. 网卡开机自启(大部分情况可省略)
```bash
systemctl enable networking.service
```
### 5. 重启
```bash
reboot
```
```bash
init 6
```
### 6. 查看网络信息
```bash
ip addr
```
---
## 在centos7系统
### 1. 先确定当前网卡名
```bash
ip addr
```
### 2. 改网卡配置文件
> 原网卡名称有可能不一样
```bash
vim /etc/sysconfig/network-scripts/ifcfg-ens192
```
把`DEVICE=ens192`改为`DEVICE=eth0`
把`NAME=ens192`改为`NAME=eth0`
保存退出
再把网卡配置文件的文件名改了
```bash
cd /etc/sysconfig/network-scripts
mv ifcfg-ens192 ifcfg-eth0
```
### 3. 修改grub
```bash
vim /etc/default/grub
```
往`GRUB_COMLINE_LINUX`里面加上`net.ifnames=0 biosdevname=0`
保存退出
执行命令
```bash
grub2-mkconfig -o /boot/grub2/grub.cfg
```
### 4. 重启系统并校验效果
```bash
init 6
```
```bash
ip a
```

View File

@ -0,0 +1,40 @@
# SSH免密码连接服务器
> 前提:服务器已经部署了你的私钥对应的公钥文件
---
## 使用默认密钥文件连接服务器
```bash
ssh username@server
```
例:
```bash
ssh root@192.168.0.8
```
> 使用`~/.ssh/id_rsa`文件以root身份登录192.168.0.8主机
## 使用指定密钥文件连接服务
```bash
ssh -i keyfile username@server
```
例:
```bash
ssh -i ~/.ssh/bob root@192.168.0.8
```
> 使用`~/.ssh/bob`私钥文件以root身份登录192.168.0.8主机
## 指定密钥文件并且服务器ssh端口不是默认的22
```bash
ssh -i ~/.ssh/bob root@192.168.0.8 -p 22222
```
> 服务器把ssh端口设置成22222需要凭`~/.ssh/bob`文件登录

View File

@ -0,0 +1,12 @@
# SSH客户端保持连接的方法
---
在客户端电脑的`~/.ssh/config`文件开头做如下配置:
```
Host *
ServerAliveInterval 30
```
> 表示每隔30秒自动向服务端发送一个no-op包

View File

@ -0,0 +1,33 @@
# tmux操作
```bash
ctrl+b s 退出 tmux 到列表
```
```bash
ctrl+b d 退出到root
```
```bash
tmux ls 查看所有窗口
```
```bash
tmux kill-window -t 2 杀掉编号为2的窗口
```
```bash
tumx a 上一次进入的窗口
```
```bash
tmux new -s py 新建窗口
```
```bash
cd /usr/local/freeswitch/scripts/call_outivr python listen_event_process.py 启动esl监听程序
```
```bash
cd /usr/local/freeswitch ./freeswitch 启动freeswitch 如果发现已经启动 则退出到root界面杀掉进程pid
```

View File

@ -0,0 +1,114 @@
# ubuntu系统配置NFS服务端及客户端
## 配置nfs服务端与客户端
> nfs的作用是实现各主机间的共享存储空间`切记不要在公网环境中使用nfs`
### 1. NFS服务端安装与配置
- 安装nfs服务需要先安装
```shell
sudo apt install nfs-kernel-server nfs-common
```
- 配置nfs共享目录
```bash
vim /etc/exports
```
- 添加如下两行:
```ini
/storage 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash,fsid=0)
/storage 127.0.0.1/24(rw,sync,no_subtree_check,no_root_squash,fsid=0)
```
> 其中`/storage`为需要共享的路径,`Tab`键后的ip地址是允许访问的网段根据实际情况修改括号内则是一些权限不建议改动
- 重启nfs服务并刷新共享配置
```bash
/etc/init.d/nfs-kernel-server restart
exportfs -rv
```
### 2. NFS服务端的端口处理
> NFS服务是基于RPC协议的服务通过`rpcinfo -p`命令会发现除了`111`和`2049`端口外,其`mountd`和`nlockmgr`以及`status`对应的端口是随机分配的这样几乎无法搞防火墙和端口映射了为了不让服务器裸奔需要对nfs-kernel-server主机做一些配置以固定其端口。
- 修改`/etc/default/nfs-common`文件,配置`status`服务端口为`40001`
```ini
STATDOPTS="--port 40001"
```
- 修改`/etc/default/nfs-kernel-server`文件,配置`mountd`服务端口为`40002`
```ini
RPCMOUNTDOPTS="--manage-gids -p 40002"
```
- 创建`/etc/modprobe.d/options.conf`文件,添加如下内容,配置`nlockmgr`端口为`40003`
```ini
options lockd nlm_udpport=40003 nlm_tcpport=40003
```
- 在`/etc/modules`文件中添加`lockd`
```ini
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
lockd
```
- 重启服务器(`reboot`),然后再运行`rpcinfo -p localhost`,就会看到,各种端口都已经被固定了。
### 3. NFS客户端安装与配置
- 安装nfs客户端以ubuntu为例
```shell
sudo apt install nfs-common -y
```
- 确保客户端与服务端的网络连接正常,在客户端主机上执行以下操作:
```shell
showmount -e 192.168.1.68
```
> 正常情况下会命令执行后会返回服务器开放出来的共享目录路径,包含类似`/storage 192.168.1.0/24`的信息。
- 打开`/etc/fstab`文件:
```shell
vim /etc/fstab
```
- 在文件末尾所加行(`tab`键间隔)后保存并退出编辑器:
```ini
192.168.1.68:/storage /storage nfs defaults 0 0
```
> 其中第1段IP为本机IP地址第2段为要挂载到`/storage`目录,后面几段原样照抄。
> 如果在nfs服务端本机内配置可将ip地址改为127.0.0.1。
- 创建挂载点目录:
```shell
mkdir /storage
```
> 完成以上操作后,就会在系统启动时自动将服务器的/storage目录挂载到本机的/storage目录。
- 以下命令可实现一次性的手动挂载如果未在fstab中配置的话重启服务器将失效
```shell
sudo mount -t nfs -o nolock 192.168.1.68:/storage /storage
```

View File

@ -0,0 +1,30 @@
# 为ubuntu系统配置静态ip地址
---
> 如果使用非root用户需要在命令前加sudo
## ubuntu 16.04
```bash
vim /etc/network/interfaces
```
只修改eth0部分或者是别的网卡名
```
auto eth0
iface eth0 inet static
address 183.211.245.49
netmask 255.255.255.128
broadcast 183.211.245.127
gateway 183.211.245.1
dns-nameservers 221.131.143.69
```
如果想用dhcp自动获取ip的话照下面改
```
auto eth0
iface eth0 inet dhcp
```

View File

@ -0,0 +1,40 @@
# vim快捷操作
---
## 定义tab键为4个空格
```bash
# ubuntu
vim /etc/vim/vimrc
# centos
vim /etc/vimrc
```
在最后添加如下配置
```text
set ts=4
set sw=4
set expandtab
```
## 查找替换
把每一行中的所有fromstring替换为tostring
```txt
:%s/fromstring/tostring/g
```
把每一行中的第一个fromstring替换为tostring
```txt
:%s/fromstring/tostring
```
## 粘贴时缩进错乱
```txt
:set paste
```

View File

@ -0,0 +1,12 @@
# 删除.user.ini文件
用宝塔创建站点后在站点根目录会有.user.ini文件等一系列的默认文件其他文件都可以正常被删除只有这个.user.ini文件无法用`rm -rf .user.ini`命令删除,原因是它被锁定了,需要先解锁再删除。
```sh
# 解除 user.ini 文件锁定
chattr -i .user.ini
# 删除 .user.ini 文件
rm -rf .user.ini
```
可以了。

View File

@ -0,0 +1,19 @@
# 删除某时间前的文件或文件夹(比如录音文件)
## 命令示例
```bash
find /usr/local/freeswitch/log/freeswitch.log.*.1 -mtime +5 -exec rm -rf {} \;
```
解读:
删除5天前的freeswitch日志
```bash
find /usr/local/freeswitch/recordings/ -type d -mtime +10 -exec rm -rf {} \;
```
解读:
删除10天前的freeswitch录音

View File

@ -0,0 +1,47 @@
# 阿里云CentOS7磁盘扩容
## 场景
在阿里云控制台对主机云盘成功完成磁盘扩容操作。
## centos系统内操作
查看磁盘和分区
```bash
fdisk -l
```
结果有可能会看到有一个名为/dev/vda的磁盘同时有一个名为/dev/vda1的分区而且/dev/vda的磁盘容量已经是扩容后的容量了。
查看分区大小
```bash
df -h
```
结果可以看到分区大小还是扩容前的大小。
为分区扩容
```bash
growpart /dev/vda 1
```
语法
```sh
growpart [DeviceName] [PartionNumber]
```
扩容文件系统
```bash
resize2fs /dev/vda1
```
语法
```sh
resize2fs [PartitionName]
```

View File

@ -0,0 +1 @@
## luasocket示例

209
docs/src/ops/acme.md Normal file
View File

@ -0,0 +1,209 @@
# 用acme.sh实现ssl证书部署及自动续签
> wandoubaba / 2024-11-04
## 介绍
`acme.sh`是一个实现了 `acme` 协议的客户端工作,使用它可以申请`Let's Encrpypt`、`TrustAsia`等机构的免费SSL证书并可以实现自动部署与自动续签。
项目地址:<https://github.com/acmesh-official/acme.sh>
本文主要介绍如何使用 `acme.sh` 为域名申请免费的90天证书并实现Nginx自动部署和自动续签。
> 本文的操作环境是 Debian 11/12 系统域名从腾讯云注册DNSPod提供解析
## 安装acme.sh客户端
使用发下命令安装email可以换成自己的
```sh
curl https://get.acme.sh | sh -s email=my@example.com
```
如果上面的命令安装失败,可以换下面这种方式:
```sh
git clone https://gitee.com/neilpang/acme.sh.git
cd acme.sh
./acme.sh --install -m my@example.com
. ~/.bashrc
```
整个安装过程只会把工具安装到`~/.acme.sh/`目录下,只是在`~/.bashrc`中添加了一句`. "/root/.acme.sh/acme.sh.env"`,看一眼`acme.sh.env`内容,是这样的:
```sh
cat /root/.acme.sh/acme.sh.env
# 结果
export LE_WORKING_DIR="/root/.acme.sh"
alias acme.sh="/root/.acme.sh/acme.sh"
```
建议再安装个`socat`它本身功能也十分强大是linux网络运维的瑞士军刀可以用于以`standalone mode`申请证书时临时“伪装”一个服务器出来。
```sh
apt-get install socat
```
## 确认证书申请方式
在`acme.sh`的官方文档中可以看到分发证书的方式有很多种比如文件验证、独立模式、手动DNS、自动DNS等等我们为了实现全自动化和未来的自动续签所以我们选择“自动DNS解析方式”。
我的域名注册商是腾讯云解析服务由DNSPod提供幸运的是`acme.sh`支持DNSPod平台的API密钥所以我先到DNSPod平台上去创建一组密钥
- 登录网址:<https://www.dnspod.cn/>
- 登录控制台
- 我的账号 - API密钥
- 切换到`DNSPod Token`不要用腾讯云API密钥
- 记录`ID`和`Token`(页面关闭后就再也看不见了)
执行下面命令:
```sh
export DP_Id=<Id>
export DP_Key=<Token>
```
## 申请证书
```sh
acme.sh --issue --dns dns_dp -d example.com
```
如果执行成功,最后可以看到类似下面的结果,说明已经将证书文件安装到了本地:
```sh
[Mon Nov 4 01:12:52 PM CST 2024] Your cert is in: /root/.acme.sh/example.com/example.com.cer
[Mon Nov 4 01:12:52 PM CST 2024] Your cert key is in: /root/.acme.sh/example.com/example.com.key
[Mon Nov 4 01:12:52 PM CST 2024] The intermediate CA cert is in: /root/.acme.sh/example.com/ca.cer
[Mon Nov 4 01:12:52 PM CST 2024] And the full chain certs is there: /root/.acme.sh/example.com/fullchain.cer
[Mon Nov 4 01:12:52 PM CST 2024] _on_issue_success
```
## 部署证书
下面分别是在apache上和在nginx上部署证书的示例需要替换的内容是`example.com`和相`关文件的绝对路径`,以及服务`重新加载配置的命令`。
### Apache示例:
```sh
acme.sh --install-cert -d example.com \
--cert-file /path/to/certfile/in/apache/cert.pem \
--key-file /path/to/keyfile/in/apache/key.pem \
--fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \
--reloadcmd "service apache2 force-reload"
```
### Nginx示例:
```sh
acme.sh --install-cert -d example.com \
--key-file /path/to/keyfile/in/nginx/key.pem \
--fullchain-file /path/to/fullchain/nginx/cert.pem \
--reloadcmd "service nginx force-reload"
```
### 修改配置文件
acme.sh只会重新部署证书文件不会去更改任何其他配置文件为了安全考虑所以要让web服务器应用证书还需要手动去修改相关的配置文件。
我们以nginx为例提供一个web站点加载ssl证书并提供https服务开443端口的示例
```nginx
server {
listen 80;
listen [::]:80;
server_name localhost;
# ssl
listen 443 ssl;
server_name localhost;
ssl_certificate /etc/nginx/certs/cert.pem; # 证书文件路径
ssl_certificate_key /etc/nginx/certs/key.pem; # 私钥文件路径
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
```
如果我们希望所有的http请求80都可以自动转到https443可以对上面的配置文件做一些修改
```nginx
server {
listen 80;
listen [::]:80;
server_name localhost;
# 重定向所有 HTTP 请求到 HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name localhost;
ssl_certificate /etc/nginx/certs/cert.pem; # 证书文件路径
ssl_certificate_key /etc/nginx/certs/key.pem; # 私钥文件路径
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
```
修改完配置文件后,再要重新启动服务或者重新加载一下配置,才会生效。
## 验证自动续签机制
```sh
crontab -l
```
如果看到有下面这样的定时任务说明acme.sh的自动续签机制是生效的
```sh
43 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
```

3
docs/src/ops/index.md Normal file
View File

@ -0,0 +1,3 @@
# 其他技术资料
一些不便分类又有必要记录的内容

154
docs/src/ops/nginx.md Normal file
View File

@ -0,0 +1,154 @@
# 编译安装nginx
> wandoubaba / 2023-07-21
## 系统环境
以Debian11为例
## 下载源码
以1.24.0版本为例下载nginx
```sh
wget https://nginx.org/download/nginx-1.24.0.tar.gz
```
如果提示`wget: command not found`就先安装wget执行`sudo apt-get install wget`就行。
解压:
```sh
tar zxvf nginx-1.24.0.tar.gz
```
## 安装依赖
```sh
sudo apt-get install libgd-dev build-essential zlib1g-dev libpcre3-dev libssl-dev lsb-release
```
## 创建www用户和组
查看www用户是否存在
```sh
id www
```
创建www分组和www用户并且不允许登录系统
```sh
groupadd www
useradd -g www -s /sbin/nologin www
```
再查看www用户
```sh
id www
```
## 编译安装
```sh
cd nginx-1.24.0
```
带参数执行编译
```sh
./configure --user=www --group=www \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_image_filter_module \
--with-http_addition_module \
--with-http_stub_status_module \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-http_gzip_static_module \
--with-http_gunzip_module \
--with-http_sub_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_dav_module \
--with-openssl-opt=-g \
--with-pcre-opt=-g \
--with-pcre
```
安装:
```sh
make
sudo make install
```
经过以上步骤nginx已经被安装到`/usr/local/nginx`目录下,程序文件位于`/usr/local/nginx/sbin/nginx`。
## 启动服务
可以先把nginx程序路径写到系统环境中可以把这条命令加到`~/.bashrc`文件中)
```sh
export PATH=/usr/local/nginx/sbin/:$PATH
```
执行直接执行`nginx`即可启动服务。
在浏览器访问`http://ip`把IP换成你的nginx主机地址如果防火墙和安全组都放行了80端口我们现在应该能看到`Welcome to nginx`页面了。
用下面的命令可以控制服务的启停:
```sh
## 重启服务
nginx -s reopen
## 停止服务
nginx -s stop
nginx -s quit
## 重载配置
nginx -s reload
```
## 注册系统服务
注意:操作系统不同,下面的方法可能不一样。
创建`/etc/systemd/system/nginx.service`文件:
```ini
[Unit]
Description=Nginx Service
After=syslog.target network.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
PrivateTmp=true
[Install]
WantedBy=multi-user.target
```
执行下面的命令使服务生效并实现随系统启动:
```sh
sudo systemctl daemon-reload
sudo systemctl enable nginx
```
用下面的命令控制服务:
```sh
sudo systemctl start nginx
sudo systemctl restart nginx
sudo systemctl stop nginx
sudo systemctl reload nginx
sudo systemctl status nginx
```

101
docs/src/ops/node.md Normal file
View File

@ -0,0 +1,101 @@
# Linux安装node二进制
> wandoubaba / 2024-08-29
## 下载
<https://nodejs.org/download/release> 中可以下载到需要的版本和对应平台的安装包。本文写作时的最新版本是`v22.7.0`。
```sh
wget https://nodejs.org/download/release/v22.7.0/node-v22.7.0-linux-x64.tar.xz
```
## 解压安装
```sh
tar xvf node-v22.7.0-linux-x64.tar.xz
mv node-v22.7.0-linux-x64 /usr/local/node
ln -s /usr/local/node/bin/node /usr/local/bin/node
ln -s /usr/local/node/bin/npm /usr/local/bin/npm
```
验证安装
```sh
node --version
npm --version
```
## 配置npm源
淘宝镜像
```sh
npm config set registry https://registry.npmmirror.com
```
阿里云
```sh
npm config set registry https://npm.aliyun.com
```
腾讯云
```sh
npm config set registry http://mirrors.cloud.tencent.com/npm/
```
华为云
```sh
npm config set registry https://mirrors.huaweicloud.com/repository/npm/
```
官方
```sh
npm config set registry https://registry.npmjs.org/
```
## 安装yarn
Yarn 是一个由 Facebook 贡献的 Javascript 包管理器
```sh
npm install -g yarn
ln -s /usr/local/node/bin/yarn /usr/local/bin/yarn
```
验证安装
```sh
yarn --version
```
## 安装nrm
nrm 是一个 npm 源管理器,允许你快速地在 npm 源间切换。
```sh
npm install -g nrm
ln -s /usr/local/node/bin/nrm /usr/local/bin/nrm
```
查看可选的源
```sh
nrm ls
```
使用taobao源
```sh
nrm use taobao
```
测试速度
```sh
nrm test
```

140
docs/src/ops/openresty.md Normal file
View File

@ -0,0 +1,140 @@
# 编译安装OpenResty
> wandoubaba / 2023-07-21
## 系统环境
以Debian11为例
## 安装依赖
```sh
apt-get install wget libpcre3-dev libssl-dev perl make build-essential curl libgd-dev lsb-release
```
## 安装postgres模块依赖
我们这要安装驱动而不是安装一个pg数据库服务所以只需要安装一个`libpq-dev`就够了。
```sh
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt-get update
sudo apt-get -y install libpq-dev
```
## 创建www用户和组
查看www用户是否存在
```sh
id www
```
创建www分组和www用户并且不允许登录系统
```sh
groupadd www
useradd -g www -s /sbin/nologin www
```
再查看www用户
```sh
id www
```
## 下载源码包
```sh
wget https://openresty.org/download/openresty-1.21.4.2.tar.gz
```
## 解压&编译&安装
```sh
tar zxvf openresty-1.21.4.2.tar.gz
cd openresty-1.21.4.2
./configure \
--prefix=/www/server/openresty \
--with-pcre-jit \
--with-http_iconv_module \
--with-http_postgres_module \
--user=www --group=www \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_image_filter_module \
--with-http_addition_module \
--with-http_stub_status_module \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-http_gzip_static_module \
--with-http_gunzip_module \
--with-http_sub_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_dav_module \
--with-openssl-opt=-g \
--with-pcre-opt=-g \
--with-pcre
gmake
gmake install
```
## 注册系统服务和开机自启
在`/etc/systemd/system/`目录下创建`nginx.service`文件,内容如下:
```ini
[Unit]
Description=Nginx HTTP Server
After=network.target
[Service]
Type=forking
PIDFile=/www/server/openresty/nginx/logs/nginx.pid
ExecStartPre=/www/server/openresty/nginx/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/www/server/openresty/nginx/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/www/server/openresty/nginx/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=/www/server/openresty/nginx/sbin/nginx -g 'daemon on; master_process on;' -s quit
PrivateTmp=true
Restart=always
[Install]
WantedBy=multi-user.target
```
保存文件并退出后,执行下面命令:
```sh
systemctl daemon-reload
systemctl enable nginx
```
现在已完成系统服务注册和开机自启,下面是服务控制命令:
```sh
systemctl start nginx # 启动nginx服务
systemctl stop nginx # 停止nginx服务
systemctl restart nginx # 重启nginx服务
systemctl reload nginx # 重新加载nginx配置文件
systemctl status nginx # 检查nginx服务状态
```
## 测试
正确启动服务后,使用`ps`命令可以查看nginx服务进程
```sh
ps aux | grep nginx
```
使用`ss`命令可以查看端口监听情况
```sh
ss -tnlp | grep 80
```
在浏览器中访问`http://ip`应该可以看到OpenResty的默认欢迎页`Welcom to OpenResty`。

259
docs/src/php/docker-php8.md Normal file
View File

@ -0,0 +1,259 @@
# 基于php8.x制作跨平台的workerman环境Docker镜像
> wandoubaba / 2024-10-29
## 说明
本方法基于PHP官方`8.1.30-cli`版本的镜像制作安装好workerman开发常用的依赖和扩展并通过`docker buildx`构建多平台的Docker镜像。
## Dockerfile文件
```dockerfile
# 拉基础镜像
FROM php:8.1.30-cli
# 替换源本文操作时使用的是aws主机所以用的是国外源国内操作可以换成阿里、中科大等国内源
RUN rm /etc/apt/sources.list.d/debian.sources && \
echo 'deb http://mirror.us.oneandone.net/debian bookworm main' > /etc/apt/sources.list && \
echo 'deb-src http://mirror.us.oneandone.net/debian bookworm main' >> /etc/apt/sources.list && \
echo 'deb http://mirror.us.oneandone.net/debian-security bookworm-security main' >> /etc/apt/sources.list && \
echo 'deb-src http://mirror.us.oneandone.net/debian-security bookworm-security main' >> /etc/apt/sources.list && \
echo 'deb http://mirror.us.oneandone.net/debian bookworm-updates main' >> /etc/apt/sources.list && \
echo 'deb-src http://mirror.us.oneandone.net/debian bookworm-updates main' >> /etc/apt/sources.list && \
echo 'deb http://mirror.us.oneandone.net/debian bookworm-backports main' >> /etc/apt/sources.list && \
echo 'deb-src http://mirror.us.oneandone.net/debian bookworm-backports main' >> /etc/apt/sources.list
# 安装一些依赖
RUN apt-get update && apt-get install -y \
libfreetype6-dev libjpeg62-turbo-dev \
libpng-dev libwebp-dev zlib1g-dev \
libzip-dev zip \
libevent-dev libssl-dev \
lsb-release libpq-dev \
libgmp-dev \
libmagickwand-dev \
libzookeeper-mt-dev \
librdkafka-dev
# 安装扩展
RUN docker-php-ext-configure gd --enable-gd --with-freetype --with-jpeg --with-webp \
&& docker-php-ext-install -j$(nproc) gd \
&& docker-php-ext-install exif \
&& docker-php-ext-install opcache \
&& docker-php-ext-install pdo_mysql \
&& docker-php-ext-install mysqli \
&& docker-php-ext-install zip \
&& docker-php-ext-install pcntl \
&& docker-php-ext-install fileinfo \
&& pecl install https://pecl.php.net/get/redis-6.1.0.tgz \
&& docker-php-ext-enable redis \
&& docker-php-ext-install sockets \
&& pecl install https://pecl.php.net/get/event-3.1.4.tgz \
&& docker-php-ext-enable event \
&& cat /usr/local/etc/php/conf.d/docker-php-ext-event.ini >> /usr/local/etc/php/conf.d/docker-php-ext-sockets.ini \
&& mv /usr/local/etc/php/conf.d/docker-php-ext-sockets.ini /usr/local/etc/php/conf.d/docker-php-ext-event.ini \
&& docker-php-ext-install -j$(nproc) pgsql pdo_pgsql \
&& pecl install https://pecl.php.net/get/mongodb-1.19.3.tgz \
&& docker-php-ext-enable mongodb \
&& docker-php-ext-install -j$(nproc) gmp \
&& pecl install https://pecl.php.net/get/imagick-3.7.0.tgz \
&& docker-php-ext-enable imagick \
&& docker-php-ext-install bcmath \
&& docker-php-ext-enable bcmath \
&& pecl install https://pecl.php.net/get/xlswriter-1.5.5.tgz \
&& docker-php-ext-enable xlswriter \
&& pecl install https://pecl.php.net/get/zookeeper-1.2.1.tgz \
&& docker-php-ext-enable zookeeper \
&& pecl install https://pecl.php.net/get/rdkafka-6.0.3.tgz \
&& docker-php-ext-enable rdkafka
# 安装Composer
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
&& php composer-setup.php \
&& php -r "unlink('composer-setup.php');" \
&& mv composer.phar /usr/local/bin/composer \
&& composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
# 安装swow扩展
# RUN composer require swow/swow && ./vendor/bin/swow-builder --install
# 创建应用目录
RUN mkdir -p /app
# 设置工作目录
WORKDIR /app
```
> 在`替换源`那一段中,应该把其中的源地址替换成你的主机可以快速访问的源地址,不建议直接使用本文的源。
## 用`docker buildx`构建
将上面的Dockerfile脚本直接保存为`Dockerfile`文件。
### 检查`docker buildx`环境
```sh
docker info
```
执行以上命令可以看到类似下面的信息:
```txt
Client: Docker Engine - Community
Version: 27.0.3
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.15.1
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.28.1
Path: /usr/libexec/docker/cli-plugins/docker-compose
...
```
一般情况下如果是通过包管理器安装的docker engine或者docker desktop的话默认就已经安装好了buildx和compose插件了。
### 跨平台构建并发布
接下来我们的目标是用上面的Dockerfile构建跨平台的`php:8.1-workerman`镜像并直接推送到`quay.io`平台上:
本文中我的quay.io账号是wandoubaba517你要替换成你自己的账号。
```sh
docker login quay.io
docker buildx create --use
docker buildx build --platform linux/386,linux/s390x,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8 --push -t quay.io/wandoubaba517/php:8.1-workerman .
```
执行上面的命令执行过程中会自动从docker hub上拉取名为`moby/buildkit:buildx-stable-1`的镜像并启动容器开始自动构建和推送整个过程在我的2核4G服务器上会执行数小时可以使用`tmux`等终端工具异步执行。
## 使用镜像
```sh
docker pull quay.io/wandoubaba517/php:8.1-workerman
docker run -itd -p 8787:8787 -v ./:/app -w /app quay.io/wandoubaba517/php:8.1-workerman
```
### docker-compose.yml
```yml
services:
workerman:
image: quay.io/wandoubaba517/php:8.1-workerman
container_name: workerman
restart: always
volumes:
- ./:/app
working_dir: /app
stdin_open: true
ports:
- 8787:8787
ommand: ['php', 'start.php', 'start']
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8787/"]
interval: 5s
retries: 3
start_period: 5s
timeout: 10s
```
### composer命令脚本
> 仅适用于linux系统
```sh
#!/bin/bash
# 使用heredoc构建docker run命令
read -r -d '' DOCKER_COMMAND <<'EOF'
docker run --rm \
-v "$(pwd)":/app \
-w /app \
quay.io/wandoubaba517/php:8.1-workerman \
composer
EOF
# 检查是否有传递参数,并将它们附加到命令的末尾
if [ $# -gt 0 ]; then
DOCKER_COMMAND+=" $@"
fi
# 执行docker run命令
eval "$DOCKER_COMMAND"
```
把上面的脚本保存为`compose`文件,设置可执行权限:
```sh
chmod +x ./composer
```
然后就可以用`./composer`代替composer命令了。
也可以直接把这个composer脚本复制到/usr/bin/目录下以供全局使用(不建议这样,失去了多版本共存的意义)。
### php命令脚本
```sh
#!/bin/bash
# 获取脚本所在目录的绝对路径
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
# 切换工作目录到脚本所在目录
cd "$SCRIPT_DIR" || exit 1
# 使用heredoc构建docker run命令
read -r -d '' DOCKER_COMMAND <<'EOF'
docker run --rm \
--network host \
-v "$(pwd)":/app \
-v "$(pwd)/php.ini":/usr/local/etc/php/php.ini \
-w /app \
quay.io/wandoubaba517/php:8.1-workerman \
php
EOF
# 检查是否有传递参数,并将它们附加到命令的末尾
if [ $# -gt 0 ]; then
DOCKER_COMMAND+=" $@"
fi
# 执行docker run命令
eval "$DOCKER_COMMAND"
```
同样要为`php`脚本赋予可执行权限
```sh
chmod +x ./php
```
然后就可以执行`./php`代替php命令了。
### 最佳实践
建议把composer脚本和php脚本都保存在项目工程目录下另外再把容器内`/usr/local/etc/php/php-production.ini`文件也复制到工程目录下并命名为`php.ini`,在`docker-compose.yml`文件中配置卷映射
```yml
volumes:
- ./:/app
- ./php.ini:/usr/local/etc/php/php.ini
```
## 其他版本
用本文中的方法可以同样制作`8.0`和`8.2`版本做镜像,但是`8.3`不行,因为`zookeeper`扩展只支持php版本`不高于8.2.999`,一般项目可能也用不上这个扩展,在`Dockerfile`中把这个扩展和相关的依赖删掉,也可以制作出`8.3`版本的镜像。
### 工程示例
<https://git.wandoubaba.com/wandoubaba/docker-webman>
```sh
git clone git@git.wandoubaba.com:wandoubaba/docker-webman.git
cd docker-webman
./composer install
./php start.php start
```

View File

@ -0,0 +1,376 @@
# 基于docker的phpfpm+nginx环境
## 简介
本文以php7.4为例介绍在具有docker环境的系统上不安装任何php相关服务完全利用docker容器来实现运行环境的搭建最后还会以ThinkPHP6.0为例演示真实项目的运行,本文中的环境可在生产环境使用。
## 准备工作
在本地创建一个工作目录,笔者的宿主机上它的位置就是`/app/dev/phpfpm-demo`。
```sh
mkdir -p /app/dev/phpfpm-demo
cd /app/dev/phpfpm-demo
```
## 制作过程
### 基础镜像
```sh
docker pull nginx:1.24
docker pull php:7.4.33-fpm-bullseye
```
其中nginx镜像不需要做更改可以直接使用而php镜像则要在基础镜像的基础上安装一些必要的依赖和扩展。
### 制作PHP镜像
#### 为PHP安装扩展
```sh
docker run --rm --name php-fpm -it -d php:7.4.33-fpm-bullseye
docker exec -it php-fpm
```
在容器内安装依赖前最好先更换一下软件源,否则可能会很慢。
```sh
cp /etc/apt/sources.list /etc/apt/sources.list.bak && echo "deb http://mirrors.aliyun.com/debian/ bullseye main non-free contrib
deb-src http://mirrors.aliyun.com/debian/ bullseye main non-free contrib
deb http://mirrors.aliyun.com/debian-security/ bullseye-security main
deb-src http://mirrors.aliyun.com/debian-security/ bullseye-security main
deb http://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib
deb-src http://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib
deb http://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib
deb-src http://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib" | tee /etc/apt/sources.list >/dev/null
```
基础php镜像中没有`redis`、`mysql`等扩展,我们要自己安装一下。在容器内可以随时用`php -m`命令查看当前已经生效的扩展
```sh
apt update && apt install -y \
# gd扩展依赖
libzip-dev libpng-dev \
ibwebp-dev libjpeg-dev \
libfreetype6-dev \
# pgsql扩展依赖
libpq-dev \
# gmp扩展依赖
libgmp-dev \
# composer需要
git
# redis扩展
pecl install redis && docker-php-ext-enable redis
# mysql扩展
docker-php-ext-install pdo_mysql && docker-php-ext-enable pdo_mysql
# opcache扩展
docker-php-ext-install opcache && docker-php-ext-enable opcache
# zip扩展
docker-php-ext-install zip && docker-php-ext-enable zip
# xlswriter扩展超高速读写excel文件
pecl install xlswriter && docker-php-ext-enable xlswriter
# pgsql扩展连接postgres数据库
docker-php-ext-install pdo_pgsql && docker-php-ext-enable pdo_pgsql
# gmp扩展
docker-php-ext-install gmp && docker-php-ext-enable gmp
# gd扩展直接使用docker-php-ext-install gd虽然也能安装成功但是不支持freetype的话tp的验证码会出错
docker-php-source extract
cd /usr/src/php/ext/gd
docker-php-ext-configure gd --with-webp=/usr/include/webp --with-jpeg=/usr/include --with-freetype=/usr/include/freetype2
make && make install
docker-php-ext-install gd && docker-php-ext-enable gd
# 安装composer
php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');" && php composer-setup.php && php -r "unlink('composer-setup.php');" && mv composer.phar /usr/local/bin/composer
```
以上是笔者经历过的项目中比较常用的扩展,如果还有其他需要,可以按照类似的方式安装。
最后一切完毕后就可以离开容器了:
```sh
exit
```
另外,我们需要知道几个关键路径:
- php.ini文件所有路径`/usr/local/etc/php/php.ini`
- 应用路径:`/var/www/html`
这两个路径我们未来要采用映射的方式从项目目录映射到容器内,因此不需要在容器内做什么动作了。
如果在自己的宿主机中没有现成的`php.ini`文件,可以从容器内复制出来一份:
```sh
# 开发环境建议
docker cp php-fpm:/usr/local/etc/php/php.ini-development ./php.ini
# 生产环境建议
docker cp php-fpm:/usr/local/etc/php/php.ini-production ./php.ini
```
#### 保存PHP镜像
```sh
docker commit php-fpm php-fpm:7.4
```
以后我们要使用的就是这个新创建的镜像,如果有`hub.docker.com`网站的账号,可以使用`docker push`命令把这个镜像上传到自己的docker hub上方便以后在其他地方使用。
现在我们刚才启动的镜像已经不再需要了,直接删除就行。
```sh
# 启动时已经使用了--rm参数所以容器被关闭就会自动删除
docker stop php-fpm
```
### 准备nginx配置文件
我们直接启动nginx容器然后从容器是把配置文件复制到宿主机上。
```sh
# 当前目录是宿主机上的工作目录
mkdir nginx
docker run --rm --name php-fpm-nginx -it -d nginx:1.24
docker cp php-fpm-nginx:/etc/nginx/nginx.conf ./nginx/
docker cp php-fpm-nginx:/etc/nginx/conf.d ./nginx/
dorker stop php-fpm-nginx
```
现在我们已经准备好了`nginx:1.24`镜像和`php-fpm:7.4`镜像,已经具备工作条件,下面就开始使用。
## 环境与配置
到目前为止,我们已经有两个镜像:`nginx:1.24`和`php-fpm:7.4`,同时工作目录`/app/dev/phpfpm-demo`中的目录结构如下:
|目录或文件|说明|
|---|---|
|php.ini|PHP环境的配置文件|
|nginx|Nginx的配置文件目录|
|nginx/nginx.conf|nginx的主配置文件|
|nginx/conf.d|nginx下的站点配置目录|
现在我们已经把环境准备好了,接下来准备一个可以一键启动的`docker-compose.yml`文件再修改一些nginx的配置就可以了。
`docker-compose.yml`文件:
```yml
version: "3.1"
services:
php:
image: php-fpm:7.4
container_name: php74
restart: always
volumes:
- ./php.ini:/usr/local/etc/php/php.ini
- ./:/var/www/html
stdin_open: true
nginx:
image: nginx:1.24
container_name: phpnginx
restart: always
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf.d:/etc/nginx/conf.d
- ./:/usr/share/nginx/html
stdin_open: true
ports:
- 8008:80
depends_on:
- php
```
简单解读一下:
- 把当前工作目录中的`php.ini`文件映射到php容器对应的路径上。
- 把当前上作目录映射到php容器中的默认站点根目录上。
- 把当前工作目录中的nginx配置文件映射到nginx容器对应的路径上。
- 把当前工作目录映射到nginx容器中的默认站点根目录上。
- 把nginx容器的80端口映射到宿主机上的8008端口上可以自己改
- nginx容器和php容器都不使用host网络而是自己组成一个私有网络。
接下来我们去修改nginx的配置文件只需要修改`nginx/conf.d/default.conf`这一个文件即可,在里面加入下面这一段:
在`location /`段中添加`index.php`
```
location / {
root /usr/share/nginx/html;
index index.html index.htm index.php;
}
```
然后再添加下面一段:
```
location ~ \.php$ {
fastcgi_pass phpfpm74:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
include fastcgi_params;
}
```
接下来,我们在站点根目录上创建一个`index.html`文件:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>欢迎</title>
</head>
<body>
<h1>Hello, web</h1>
</body>
</html>
```
再创建一个`phpinfo.php`文件:
```php
<?php
phpinfo();
```
接下来,在工作目录上,直接运行下面的命令:
```sh
docker compose up -d
```
看到容器启动成功。
- 用浏览器访问`http://ip:8008`应该可以看到我们刚才创建的`index.html`中的内容。
- 用浏览器访问`http://ip:8008/phpinfo.php`应该可以看到我们刚才创建的`phpinfo.php`中的内容也就是php服务的参数页。
现在一个基于docker的nginx+php-fpm环境已经制作好了任何支持docker的环境都可以直接使用。
## 高级应用
### 在宿主机使用composer命令
目前假设我们的宿主机没有php环境那么如果我们执行`composer create-project topthink/think:6.0.* tp`时,那自然会得到`composer: command not found`的结果这不是我们想要的结果解决办法也很简单——做个直接进入容器执行composer命令的脚本就行了。
> 下面的操作只适用于linux系统如果是windows系统的话可以按照这个思路做`composer.bat`批处理文件。
```sh
touch composer
```
编辑`composer`脚本内容如下:
```shell
#!/bin/bash
docker compose run --rm webman-jsonrpc composer $@
```
给文件添加执行权限:
```sh
chmod +x composer
```
现在就可以使用这个`composer`脚本了:
```sh
./composer create-project topthink/think:6.0.* think
```
网络正常的情况下,我们应该会看到工作目录下已经出现的`tp`文件夹打开就会看到完整的thinkphp项目目录。
### 开发ThinkPHP项目
下面我们整理一下工作目录结构:
```sh
mv tp/* .
mv tp/.* .
rm -rf tp
```
接下来我们再修改一下nginx配置文件来支持thinkphp的伪静态再把nginx站点目录和php站点目录指向到工作路径的pulic目录下。
编辑`nginx/conf.d/default.conf`文件如下:
```
location / {
root /usr/share/nginx/html/public/;
index index.html index.htm index.php;
try_files $uri $uri/ /index.html last;
if (!-e $request_filename){
rewrite ^(.*)$ /index.php?s=$1 last; break;
}
}
location ~* (runtime|app)/{
return 403;
}
location ~ \.php$ {
fastcgi_pass phpfpm74:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/html/public/$fastcgi_script_name;
include fastcgi_params;
}
```
现在再次在工作目录中用docker compose启动容器就可以启动这个tp项目了
```sh
docker compose up -d
```
再次在浏览器中打开`http://ip:8008`可以看到tp的欢迎页面了。
最后别忘了给`runtime`目录修改一个所有者,否则项目运行还是会出问题:
```sh
chown www-data:www-data -R runtime
```
### 在宿主机使用php命令
和制作`composer`脚本一样,我们同样可以通过制作名为`php`的脚本来实现在工作目录中使用`./php`命令来代替`php`命令:
```sh
touch php
```
编辑`php`脚本内容:
```shell
#!/bin/bash
docker compose run --rm php php "$@"
```
给脚本执行权限:
```sh
chmod +x php
```
使用脚本:
```sh
./php think make:controller Test
```
看到`Controller:app\controller\Test created successfully.`结果后,就可以看到工作目录下的`app\controller`目录中已经出现`Test.php`文件了。
## 一键完成
以上是搭建这样一套环境的整个过程,按照以上过程,已经做好了现成的一套代码库,可以直接使用:
```sh
git clone https://git.wandoubaba.com/wandoubaba/docker-tp6-php74.git tp-project
cd tp-project
git remote remove origin
./composer install
chown www-data:www-data -R runtime
docker compose up -d
```

1
docs/src/php/index.md Normal file
View File

@ -0,0 +1 @@
# PHP相关

View File

@ -0,0 +1,165 @@
# PHP实现把日志保存到mongodb中
`monolog`可以说是PHP中应用最为广泛的日志组件使用它可以方便的实现多种日志记录需求本文主要利用`monolog`的`MongoDBHandler`类,将日志保存至`mongodb`中。
## 环境
本文使用`webman`框架,用法基本与`laravel`大同小异。
## 准备工作
### 需要为php安装mongodb扩展
```sh
pecl install mongodb
```
> 也可以使用已经做好环境的docker镜像`docker pull wandoubaba517/workerman:8.1`
### monolog版本要在3.0以上
先创建一个全新的`webman`项目:
```sh
composer create-project workerman/webman
cd webman
```
`webman`中默认已经内置了`monolog`,不过我们要确保`monolog`的版本要在3.0以上:
```sh
compose require monolog/monolog:^3.0
```
### 用docker快速启动一下mongodb服务
```sh
mkdir -p log/db
touch mongod.conf
```
`mongod.conf`文件中的内容类似下面的样子:
```yml
storage:
dbPath: /data/db
net:
port: 27017
bindIp: 0.0.0.0
```
`docker-compose.yml`文件中添加`log`服务类似下面的样子把root和password换成你自己想要设置的
```yml
version: "3.1"
services:
log:
image: mongo:7.0
container_name: mongodb-log
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: password
MONGO_INITDB_DATABASE: log
volumes:
- ./log/db:/data/db
- ./log/mongod.conf:/etc/mongod.conf
network_mode: host
command: ['mongod', '--config', '/etc/mongod.conf']
```
执行`docker compose up -d`就可以启动mongodb服务了。
### 引入`mongodb/laravel-mongodb`组件
```sh
composer require mongodb/laravel-mongodb
```
## 实现代码
### `config/database.php`文件中配置mongodb连接
```php
return [
'default' => 'pgsql',
'connections' => [
'pgsql' => [
/// ...
],
'mongo' => [
'driver' => 'mongodb',
'host' => '127.0.0.1',
'port' => 27017,
'database' => 'log',
'username' => 'root',
'password' => 'password',
'options' => [
'appname' => 'homestead'
],
],
/// ...
]
];
```
### `config/log.php`文件中配置日志通道
```php
return [
'mongo' => [
'handlers' => [
[
'class' => Monolog\Handler\MongoDBHandler::class,
'constructor' => [
new Mongodb\Client('mongodb://root:password@localhost:27017'),
'log', // 数据库名
'default', // 集合名(相当于表名)
Monolog\Level::Debug, // 最低日志等级默认就是Debug
],
],
],
],
/// ...
];
```
### 业务代码中应用
以`app/controller/IndexController.php`中的`log`方法为例:
```php
<?php
namespace app\controller;
use support\Request;
use support\Db;
use support\Log;
class IndexController
{
public function log(Request $request)
{
// 随便记录点什么日志
Log::channel('mongo')->info(__CLASS__ . DIRECTORY_SEPARATOR . __FUNCTION__, $request->all());
$logs = Db::connection('mongo')->collection('default')->get();
return json($logs);
}
}
```
### 运行测试
启动服务,然后用浏览器或者接口调试工具访问`http://IP:port/index/log`,控制器方法会先记录一条日志,然后再把整所有已经保存的日志全部都输出回来。
## 与文本日志对比
主要优势方便查询文本日志文件的最小粒度是一天一个文件当日志量具大时在几百M或者几个G甚至更大的一个文本文件中定位某行记录简直就是灾难
主要劣势:需要自行处理过期记录(文本日志可以自动删除过期的文件)。
## 推荐
本文作者建好了一个开箱即用的webman+mongodb代码仓库<https://git.wandoubaba.com/wandoubaba/docker-webman-mongolog>

View File

@ -0,0 +1,53 @@
# 为PHP7.4安装pgsql和pdo_pgsql扩展
## 环境与版本
操作系统CentOS7.9 / Debian11
> 在Debian上操作相对简单所以本文以Centos7.9为例
软件版本PHP7.4, postgresql15
## 操作过程
假设基本的LNMP环境都已经安装好了但是没有安装pgsql扩展。
首先要先安装postgresql才可以安装pgsql扩展其实不需要安装数据库的服务端安装devel包就行了。
> postgresql官方下载安装网址<https://www.postgresql.org/download/>
```sh
# Install the repository RPM:
sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# Install PostgreSQL:
# 这句和官网的不一样官网让安装postgresql15-server而我们只需要支持扩展所以只安装postgresql15-devel
sudo yum install -y postgresql15-devel
```
以上任务执行完毕后postgresql15的开发包被安装到了`/usr/pgsql-15/`中,后面我们会用到`/usr/pgsql-15/bin`这个路径。
下面需要找到我们PHP7.4的源码目录(没有的话就临时下载一份),进入源码目录`src/ext/pgsql`,执行以下操作:
```sh
phpize
# 注意替换下面的PATH/TO/php-config为真实的php-config路径用find / -name "php-config"可以找到
./configure --with-pgsql=/usr/pgsql-15/bin/ --with-php-config=PATH/TO/php-config
make
make install
```
正常情况下名为pgsql.so的文件将会出现在`PATH/TO/PHP/lib/php/extensions/no-debug-non-zts-20190902/`目录中,记住这个路径。
用php --ini命令找到php.ini和php-cli.ini文件分别编辑这两个文件在最后面添加以下内容
```ini
[pgsql]
extension=PATH/TO/PHP/lib/php/extensions/no-debug-non-zts-20190902/pgsql.so
```
> 再次提醒,别忘了把`PATH/TO/PHP`替换成你的环境中的实际路径。
执行`php -m | grep pgsql`应该可以看到pgsql扩展已经安装好了。
PHP7.4源码目录中的`src/ext/pdo_pgsql`是pdo_pgsql扩展的源码安装过程与pgsql扩展是相同的这里就不说了。

394
docs/src/php/php82.md Normal file
View File

@ -0,0 +1,394 @@
# 编译安装PHP8.2
> wandoubaba / 2023-07-21
以Debian11操作系统为例。
本文目标在纯净的操作系统上安装PHP8.2环境同时安装composer和pecl并通过pecl安装一些常用的扩展最终实现在环境中运行基于Workerman的项目。
## 安装依赖
```sh
sudo apt-get install -y \
wget make gcc curl \
libxml2 libxml2-dev \
libsqlite3-dev \
libwebp-dev libonig-dev \
libsodium-dev pkg-config \
libssl-dev openssl \
libgd-dev build-essential \
zlib1g-dev libpcre3-dev \
lsb-release autoconf \
libzip-dev unzip
```
安装`libcurl`
```sh
wget https://curl.se/download/curl-8.2.0.tar.gz
tar zxvf curl-8.2.0.tar.gz
cd curl-8.2.0
./configure --with-openssl
make
make install
```
## 创建安装目录
为了让多个版本的PHP可以共存我们不准备把PHP安装到默认目录内而是为每个版本设置一个目录。
```sh
mkdir -p /www/server/php/82/etc
```
## 创建www用户和组
查看www用户是否存在
```sh
id www
```
创建www分组和www用户并且不允许登录系统
```sh
groupadd www
useradd -g www -s /sbin/nologin www
```
再查看www用户
```sh
id www
```
为www用户创建home目录composer会用到。
```sh
mkdir /home/www
chown www:www -R /home/www
usermod -d /home/www www
```
## 下载PHP
```sh
wget https://www.php.net/distributions/php-8.2.8.tar.gz
```
## 解压&编译&安装
```sh
tar zxvf php-8.2.8.tar.gz
cd php-8.2.8
./configure \
--prefix=/www/server/php/82 \
--with-config-file-path=/www/server/php/82/etc \
--enable-fpm \
--with-fpm-user=www \
--with-fpm-group=www \
--enable-mysqlnd \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-freetype \
--with-jpeg \
--with-zlib \
--enable-xml \
--disable-rpath \
--enable-bcmath \
--enable-shmop \
--enable-sysvsem \
--with-curl \
--enable-mbregex \
--enable-mbstring \
--enable-intl \
--enable-ftp \
--enable-gd \
--with-openssl \
--with-mhash \
--enable-pcntl \
--enable-sockets \
--enable-soap \
--with-gettext \
--disable-fileinfo \
--enable-opcache \
--with-sodium=/usr/local/libsodium \
--with-webp
make
sudo make install
```
## 创建全局命令
```sh
ln -s /www/server/php/82/bin/php /usr/local/bin/php
ln -s /www/server/php/82/bin/phpize /usr/local/bin/phpize
```
## 创建php.ini
在PHP的源码目录下有`php.ini-development`和`php.ini-production`两个文件,分别表示“开发环境配置”和“生产环境配置”,这里我们直接使用生产环境的。
```sh
cp php.ini-production /www/server/php/82/etc/php.ini
```
## 安装composer
```sh
cd /www/server/php/82/bin
php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');"
php composer-setup.php
ln -s /www/server/php/82/bin/composer.phar /usr/local/bin/composer
composer selfupdate
composer --version
```
把composer源改成国内镜像
```sh
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
```
## 安装pecl
pecl是可以方便为PHP安装扩展的工具。
```sh
cd /www/server/php/82/bin
wget http://pear.php.net/go-pear.phar
php go-pear.phar
ln -s /www/server/php/82/bin/pecl /usr/local/bin/pecl
```
## 安装扩展
- event扩展
event扩展可以使基于Workerman的项目发挥更高的性能。
注意提示Include libevent OpenSSL support [yes] : 时输入no回车其它直接敲回车就行。
```sh
apt-get install libevent-dev -y
pecl install event
```
安装成功后,命令行会提示编译后的库文件所在的位置,如`/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/event.so`。
在`php.ini`文件的最后添加下面的内容:
```ini
[event]
extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/event.so"
```
再执行`php -m`命令后会看到`event`扩展出现在了已安装的扩展列表中,说明扩展安装成功。
- zip扩展
```sh
pecl install zip
```
在`php.ini`文件的最后添加:
```ini
[zip]
extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/zip.so"
```
- redis扩展
```sh
pecl install redis
```
在`php.ini`文件的最后添加:
```ini
[redis]
extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/redis.so"
```
- swoole扩展
```sh
pecl install swoole
```
在`php.ini`文件的最后添加:
```ini
[swoole]
extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/swoole.so"
```
- protobuf扩展
如果项目中需要使用到gRPC服务端或客户端就要安装protobuf扩展
```sh
pecl install protobuf
```
在`php.ini`文件的最后添加:
```ini
[protobuf]
extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/protobuf.so"
```
- xlswriter扩展
如果项目中需要读或写excel文件可以尝试一下这个扩展它的最大特点的就解析速度无论读还是写但是并不具备phpoffice/phpspreadsheet的所有功能
```sh
pecl install xlswriter
```
在`php.ini`文件的最后添加:
```ini
[xlswriter]
extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/xlswriter.so"
```
- pdo_pgsql扩展
如果项目中需要使用postgresql数据库就需要安装这个扩展。
先安装pg数据库的驱动库libpg
```sh
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt-get update
sudo apt-get -y install libpq-dev
```
然后进入PHP源代码目录中的`ext/pdo_pgsql`目录下
```sh
## 注意要把下面的path/to换成实际路径
cd path/to/php-8.2.8/ext/pdo_pgsql
phpize
./configure --with-php-config=/www/server/php/82/bin/php-config
make
make install
```
在`php.ini`文件的最后添加:
```ini
[pdo_pgsql]
extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/pdo_pgsql.so"
```
- fileinfo扩展
fileinfo通过在文件的给定位置查找特定的魔术字节序列,来获取文件的MIME信息。laravel框架依赖这个扩展。
进入PHP源代码目录中的`ext/fileinfo`目录下
```sh
## 注意要把下面的path/to换成实际路径
cd path/to/php-8.2.8/ext/fileinfo
phpize
./configure --with-php-config=/www/server/php/82/bin/php-config
make
make install
```
在`php.ini`文件的最后添加:
```ini
[fileinfo]
extension="/www/server/php/82/lib/php/extensions/no-debug-non-zts-20220829/fileinfo.so"
```
## 测试
独立的php-cli环境已经安装完成了下面我们可以用简单的HTTP服务框架`webman`测试一下。
```sh
mkdir /www/wwwroot
cd /www/wwwroot
composer create-project workerman/webman
cd webman
php start.php start
```
一切顺利的话,应该可以在命令行中看到已经启动了名为`webman`的服务进程,默认监听端口`8787`
```sh
Workerman[start.php] start in DEBUG mode
------------------------------------------- WORKERMAN -------------------------------------------
Workerman version:4.1.11 PHP version:8.2.8 Event-Loop:\Workerman\Events\Event
-------------------------------------------- WORKERS --------------------------------------------
proto user worker listen processes status
tcp root webman http://0.0.0.0:8787 16 [OK]
tcp root monitor none 1 [OK]
-------------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.
```
这个时候使用浏览器访问`http://ip:8787`就可以看到webman框架的欢迎页了。
## 启用php-fpm
为了与nginx整合以支持类似laravel或tp这样的fpm框架我们还需要启动php-fpm服务。
```sh
ln -s /www/server/php/82/sbin/php-fpm /usr/local/bin/php-fpm
cd /www/server/php/82/etc/php-fpm.d
cp www.conf.default www.conf
php-fpm
```
要实现多版本PHP环境共存主要是解决不同版本的php-fpm服务监听端口冲突的问题我们可以做个约定规则就是让各个版本的php-fpm都监听`90xx`端口比如我们现在安装的是8.2版本那就让它的php-fpm监听`9082`端口。
修改`www.conf`文件,找到`listen = 127.0.0.1:9000`一行,把它改为`listen = 127.0.0.1:9082`,保存退出即可。
下面要把php-fpm注册为系统服务。
```sh
touch /etc/systemd/system/php-fpm.service
vim /etc/systemd/system/php-fpm.service
```
文件内容:
```ini
[Unit]
Description=The PHP 8.2 FastCGI Process Manager
After=network.target
[Service]
Type=simple
PIDFile=/run/php-fpm.pid
ExecStart=/www/server/php/82/sbin/php-fpm --nodaemonize --fpm-config /www/server/php/82/etc/php-fpm.conf
ExecReload=/bin/kill -USR2 MAINPID
ExecStop=/bin/kill SIGINT MAINPID
Restart=always
[Install]
WantedBy=multi-user.target
```
保存退出后执行下面的命令:
```sh
sudo systemctl daemon-reload
sudo systemctl enable php-fpm
```
服务控制命令:
```sh
sudo systemctl start php-fpm
sudo systemctl restart php-fpm
sudo systemctl stop php-fpm
sudo systemctl reload php-fpm
sudo systemctl status php-fpm
```

BIN
docs/src/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 22 KiB

11
docs/src/start.md Normal file
View File

@ -0,0 +1,11 @@
# 前言
这里包含了由 PHP 程序员创建的技术文档,主要记录在做与 FreeSWITCH 相关的开发过程中所遇到的问题、技能、知识、方法等内容也包括学习Go、Docker相关的技术。
如果这里的内容能帮到您,作者感到很荣幸。
如果你发现这里的内容有问题,欢迎你来指正。
源代码地址: <https://git.wandoubaba.com/wandoubaba/knowledge>
作者邮箱:<wandoubaba517@gmail.com>

View File

@ -2,8 +2,8 @@ server {
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
listen 7001;
listen [::]:7001;
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;

2
package-lock.json generated
View File

@ -1,5 +1,5 @@
{
"name": "book",
"name": "docs.wandoubaba.com",
"lockfileVersion": 3,
"requires": true,
"packages": {