Linux 实践
Unix 特点:多用户多任务;命令行界面;简单、通用、高效; Linux 是一个多用户多任务的操作系统,也是一款自由软件,拥有良好的用户界面, 支持多种处理器架构,移植方便。 严格的来讲,Linux 并不算是一个操作系统,只是一个 Linux 系统中的内核,即计算 机软件与硬件通讯之间的平台; Linux的全称是GNU/Linux,这才算是一个真正意义上的Linux系统。 设计原则:1)所有的东西都是文件,所以管理简单 2)所有操作系统配置数据都存储在正文文件中 3)每个操作系统命令或应用程序很小,只完成单一功能 4)避免使用俘获用户的接口,很少交互命令,应用程序由vi编辑器等完成交互 5)多个程序串接在一起完成复杂任务
- Error: ENOSPC: System limit for number of file watchers reached
- 使用Nginx转发TCP/UDP
- Linux系统编写Systemd Service实践
- Linux安装rinetd实现TCP/UDP端口转发
- 使用Nginx进行TCP/UDP端口转发
- linux系统中rsync+inotify实现服务器之间文件实时同步
- rsync 用法教程
- Centos 6无法使用yum解决办法(centos6停止更新)
- Nginx配置中不同请求匹配不同请求
- 使用 flock 文件锁解决 crontab 冲突问题
- Ubuntu扩展 /dev/mapper/ubuntu--vg-ubuntu--lv空间
- 搭建RTMP直播流服务器实现直播
- FRP使用
Error: ENOSPC: System limit for number of file watchers reached
在使用Ubuntu进行开发时,会遇到这个错误!
Error: ENOSPC: System limit for number of file watchers reached,
这个错误的意思时系统对文件监控的数量已经到达限制数量了!!
造成的结果: 执行的命令失败!或抛出警告(比如执行 react-native start 或者打开 vsocde)
解决方法:
修改系统监控文件数量
Ubuntu
sudo vim /etc/sysctl.conf
添加一行在最下面
fs.inotify.max_user_watches = 524288
执行
sudo sysctl -p
参考:
https://blog.csdn.net/weixin_30640291/article/details/94920800
https://www.cnblogs.com/or2-/p/10461045.html
https://www.jianshu.com/p/4d2edd55b471
https://blog.csdn.net/weixin_43760383/article/details/84326032
使用Nginx转发TCP/UDP
使用Nginx转发TCP/UDP
环境
- CentOS Linux release 7.7.1908 (Core)
- Nginx: 1.19.2
编译安装Nginx
从1.9.0开始,nginx就支持对TCP的转发,而到了1.9.13时,UDP转发也支持了。提供此功能的模块为ngx_stream_core。不过Nginx默认没有开启此模块,所以需要手动安装。
# http://nginx.org/download/
cd /usr/local/src
wget http://nginx.org/download/nginx-1.19.2.tar.gz
tar zxf nginx-1.19.2.tar.gz
cd nginx-1.19.2
./configure --prefix=/usr/local/nginx --with-stream --without-http
make && make install
Note:由于是传输层转发,本着最小化原则,就关闭了http功能。
配置Nginx
TCP转发
目标:通过3000端口访问本机Mysql(其中mysql使用yum安装,默认配置文件)
/usr/local/nginx/conf/nginx.conf配置如下:
user nobody;
worker_processes auto;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
use epoll;
worker_connections 1024;
}
stream {
server {
listen 3000;
proxy_pass 127.0.0.1:3306;
# 也支持socket
# proxy_pass unix:/var/lib/mysql/mysql.socket;
}
}
首先,先通过3306端口访问mysql:
然后,启动Nginx:
最后使用3000端口访问mysql:
UDP转发
目标: 发送UDP数据到3000端口,3001端口可以接收
/usr/local/nginx/conf/nginx.conf配置如下:
user nobody;
worker_processes auto;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
use epoll;
worker_connections 1024;
}
stream {
server {
listen 3000 udp;
proxy_pass 127.0.0.1:3001;
}
}
这里写一个my_socket_server.py
侦听在3001端口,用于接收UDP数据:
# coding=utf-8
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('127.0.0.1', 3001))
print ('start server on [%s]:%s' % ('127.0.0.1', 3001))
while True:
data, addr = sock.recvfrom(1024)
print ('Received from %s:%s' % (addr,data))
sock.sendto(b'Hello, %s!' % data, addr)
再写一个my_socket_client.py
用于向Nginx侦听的3000端口发送数据:
# coding=utf-8
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
data = raw_input('Input msg: ')
if len(data) == 0:
continue
s.sendto(data.encode(), ('127.0.0.1', 3000))
print (s.recv(1024).decode('utf-8'))
同时运行两个脚本,在client端发送数据:
UDP转发遇到的一个坑
修改下client脚本,改为连续发送2000个数据包:
# coding=utf-8
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for data in range(2000):
s.sendto(str(data).encode(), ('127.0.0.1', 3000))
print (s.recv(1024).decode('utf-8'))
然后运行client脚本,发现经常会遇到如下情况:
由图可知只成功了511个。
查看文档得知listen
指令有个backlog
参数,此参数在Linux系统中默认为511:
悲剧的是backlog参数和udp参数不能同时使用。
Linux系统编写Systemd Service实践
Linux系统编写Systemd Service实践
Systemd 服务是一种以 .service 结尾的单元(unit)配置文件,用于控制由Systemd 控制或监视的进程。简单说,用于后台以守护精灵(daemon)的形式运行程序。Systemd 广泛应用于新版本的RHEL、SUSE Linux Enterprise、CentOS、Fedora和openSUSE中,用于替代旧有的服务管理器service。
开始
Systemd 服务的内容主要分为三个部分,控制单元(unit)的定义、服务(service)的定义、以及安装部分。服务的路径位于/etc/systemd/system
目录(系统的服务位于/usr/lib/systemd/system
),以 .service
结尾的单元(unit)配置文件,这篇文章以创建nginx service为例,这里假设您已经自行编译安装好了nginx,下面我们来创建一个nginx service
#创建一个nginx.service文件
vi /etc/systemd/system/nginx.service
内容如下:
[Unit]
Description=Nginx - high performance web server
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
[Install]
WantedBy=multi-user.target
输入命令systemctl daemon-reload
来加载刚刚创建的nginx服务,这样我们就可以用Systemd的方式来管理nginx了,命令如下:
#启动nginx
systemctl start nginx
#重载nginx
systemctl reload nginx
#停止nginx
systemctl stop nginx
#重启nginx
systemctl restart nginx
#如果需要开机启动
systemctl enable nginx
#如果需要取消开机启动
systemctl disable nginx
定义控制单元 [Unit]
从上面的例子中我们看到Unit内容如下:
[Unit]
Description=Nginx - high performance web server
After=network.target
- Description:代表整个单元的描述,可根据需要任意填写。
- Before/After:指定启动顺序。
- network.target代表有网路,network-online.target代表一个连通着的网络。
定义服务本体 [service]
上面的Service中服务本体内容为:
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
-
Type:服务的类型,各种类型的区别如下所示
- simple:默认,这是最简单的服务类型。意思就是说启动的程序就是主体程序,这个程序要是退出那么一切皆休。
- forking:标准 Unix Daemon 使用的启动方式。启动程序后会调用 fork() 函数,把必要的通信频道都设置好之后父进程退出,留下守护精灵的子进程。
- oneshot:适用于那些被一次性执行的任务或者命令,它运行完成后便了无痕迹。因为这类服务运行完就没有任何痕迹,我们经常会需要使用 RemainAfterExit=yes。意思是说,即使没有进程存在,Systemd 也认为该服务启动成功了。同时只有这种类型支持多条命令,命令之间用;分割,如需换行可以用\。
- dbus:这个程序启动时需要获取一块 DBus 空间,所以需要和 BusName= 一起用。只有它成功获得了 DBus 空间,依赖它的程序才会被启动。
-
ExecStart:在输入的命令是start时候执行的命令,这里的命令启动的程序必须使用绝对路径,比如你必须用/sbin/arp而不能简单的以环境变量直接使用arp。
-
ExecStop:在输入的命令是stop时候执行的命令,要求同上。
-
ExecReload:这个不是必需,如果不写则你的service就不支持restart命令。ExecStart和ExecStop是必须要有的。
其实服务本体中还有更多的参数,这里在额外列举一些常用的参数:
- User:指定用户运行
- Group:指定用户组运行
- WorkingDirectory:进程工作目录,也就是说在执行前会先切换到这个目录
安装服务 [install]
上面例子中安装服务内容为:
[Install]
WantedBy=multi-user.target
- WantedBy:设置服务被谁装载,一般设置为multi-user.target
总结
Systemd Service 是一种替代/etc/init.d/下脚本的更好方式,它可以灵活的控制你什么时候要启动服务,一般情况下也不会造成系统无法启动进入紧急模式。所以如果想设置一些开机启动的东西,可以试着写 Systemd Service。当然了,前提是你使用的Linux发行版是支持它的才行。
Linux安装rinetd实现TCP/UDP端口转发
Linux安装rinetd实现TCP/UDP端口转发
在Linux系统中大多数情况选择用iptables来实现端口转发,iptables虽然强大,但配置不便,而且新手容易出错。在此分享另一个TCP/UDP端口转发工具rinetd,rinetd体积小巧,配置也很简单。
安装rinetd
这篇文章以CentOS 7为例,复制下面的命令输入,一行一个:
#安装依赖
yum -y install gcc gcc-c++ make
#下载rinetd
wget https://github.com/samhocevar/rinetd/releases/download/v0.70/rinetd-0.70.tar.gz
#解压
tar -zxvf rinetd-0.70.tar.gz
#进入目录
cd rinetd-0.70
#编译安装
./bootstrap
./configure
make && make install
安装后,可以输入rinetd -v
查看当前版本。
[root@kryptcn2 rinetd-0.70]# rinetd -v
rinetd 0.70
随着时间推移,上面下载地址不一定是最新的,大家可前往Github:https://github.com/samhocevar/rinetd/releases下载最新版本。
设置TCP端口转发
#新建rinetd配置文件
vi /etc/rinetd.conf
#填写如下内容
0.0.0.0 2018 103.74.192.160 2019
#启动rinetd
rinetd -c /etc/rinetd.conf
rinetd配置文件的格式如下:
0.0.0.0
:源IP2018
:源端口103.74.192.160
:目标IP2019
:目标端口
上面配置的意思是将本地2018端口转发到103.74.192.160
的2019端口,启动后可以输入netstat -apn|grep 'rinetd'
查看是否运行正常,注意还需要在自己服务器防火墙放行对应的源端口,否则无法正常使用用。
从0.70
版本开始rinetd已经支持UDP转发,写法如下:
127.0.0.1 8000/udp 192.168.1.2 8000/udp
创建systemd服务
为了方便管理,我们可以为rinetd编写一个systemd服务,有兴趣的同学可参考《Linux系统编写Systemd Service实践》,xiaoz已经编写好了,直接复制下面的内容即可:
#创建rinetd服务
vi /etc/systemd/system/rinetd.service
复制下面的内容进行保存:
[Unit]
Description=rinetd
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/sbin/rinetd -c /etc/rinetd.conf
[Install]
WantedBy=multi-user.target
输入命令:systemctl daemon-reload
重载daemon使其生效,然后就可以使用下面的命令来管理rinetd了。
#启动rinetd
systemctl start rinetd
#设置开机启动
systemctl enable rinetd
#停止rinetd
systemctl stop rinetd
#重启
systemctl restart rinetd
rinetd的一些问题
rinetd支持转发到域名,rinetd会提前解析域名,并将解析出的IP缓存到内存中,如果您的域名解析IP发生了变化必须重启rinetd才会生效,所以rinetd并不适合转发到域名IP经常发生变化的情况,而socat则不存在此问题。
其它转发工具
总结
rinetd安装和配置都非常简单,并且从0.70
版本开始已经支持UDP转发,但rinetd具体性能如何xiaoz并未进一步测试,不知道高并发的情况下能否扛得住。
使用Nginx进行TCP/UDP端口转发
使用Nginx进行TCP/UDP端口转发
Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。在1.9.13版本后,Nginx已经支持端口转发。之前分享过《Linux安装rinetd实现TCP端口转发》,rinetd配置简单,使用方便,但遗憾的是不支持UDP转发。如果需要同时支持TCP/UDP端口转发可以使用Nginx
安装Nginx
可以自行去官方http://nginx.org/下载最新版本Nginx编译安装,注意版本一定要大于1.9.1,编译的时候需要--with-stream
这个模块支持。
编译方法这里就不介绍了,这篇文章直接使用xiaoz写好的一键脚本安装Nginx,省时、省力,直接执行下面的命令即可。
#执行下面的命令,根据提示完成安装
wget https://raw.githubusercontent.com/helloxz/nginx-cdn/master/nginx.sh && bash nginx.sh
#安装完成后执行下面的命令让环境变量生效
source /etc/profile
#执行下面的命令查看nginx信息
nginx -V
端口转发
在nginx.conf
添加如下配置,并使用nginx -s reload
重载nginx使其生效,同时注意防火墙/安全组放行对应的端口。
stream {
#将12345端口转发到192.168.1.23的3306端口
server {
listen 12345;
proxy_connect_timeout 5s;
proxy_timeout 20s;
proxy_pass 192.168.1.23:3306;
}
#将udp 53端口转发到192.168.1.23 53端口
server {
listen 53 udp reuseport;
proxy_timeout 20s;
proxy_pass 192.168.1.23:53;
}
#ipv4转发到ipv6
server {
listen 9135;
proxy_connect_timeout 10s;
proxy_timeout 30s;
proxy_pass [2607:fcd0:107:3cc::1]:9135;
}
}
- listen:后面填写源端口(也就是当前服务器端口),默认协议为TCP,可以指定为UDP协议
- proxy_connect_timeout:连接超时时间
- proxy_timeout:超时时间
- proxy_pass:填写转发目标的IP及端口号
注意:nginx可以将IPV4的数据包转发到IPV6,IPV6的IP需要使用[]
括起来。
总结
目前能实现端口转发的工具大致有:rinetd、SSH、iptables、nginx、haproxy,其中rinetd配置最为简单,但不支持UDP转发,并且该软件已经好几年未更新,如果您服务器上已经安装了nginx,不妨用nginx做端口转发。
此文部分内容参考了:
其它nginx相关文章
linux系统中rsync+inotify实现服务器之间文件实时同步
linux系统中rsync+inotify实现服务器之间文件实时同步
- rsync
与传统的cp、tar备份方式相比,rsync具有安全性高、备份迅速、支持增量备份等优点,通过rsync可以解决对实时性要求不高的数据备份需求,例如定期的备份文件服务器数据到远端服务器,对本地磁盘定期做数据镜像等。 随着应用系统规模的不断扩大,对数据的安全性和可靠性也提出的更好的要求,rsync在高端业务系统中也逐渐暴露出了很多不足,首先,rsync同步数据时,需要扫描所有文件后进行比对,进行差量传输。如果文件数量达到了百万甚至千万量级,扫描所有文件将是非常耗时的。而且正在发生变化的往往是其中很少的一部分,这是非常低效的方式。其次,rsync不能实时的去监测、同步数据,虽然它可以通过linux守护进程的方式进行触发同步,但是两次触发动作一定会有时间差,这样就导致了服务端和客户端数据可能出现不一致,无法在应用故障时完全的恢复数据。基于以上原因,rsync+inotify组合出现了!
1. rsync ---- remote synchronize ,是一款实现远程同步功能的软件;
2. rsync使用“Rsync算法”来同步文件,该算法只传送两个文件的不同部分,因此速度相当快;
3. 同步文件的同时,可以保持原来文件的权限、时间 和目录结构;
4. 对于多个文件来说,内部流水线减少文件等待的延时;
5. rsync默认监听TCP 873端口,通过远程shell如rsh和ssh复制文件。同时要求必须在远程和本地系统上都安装sync.
- inotify
Inotify 是一种强大的、细粒度的、异步的文件系统事件监控机制,linux内核从2.6.13起,加入了Inotify支持,通过Inotify可以监控文件系统中添加、删除,修改、移动等各种细微事件,利用这个内核接口,第三方软件就可以监控文件系统下文件的各种变化情况,而 inotify-tools
就是这样的一个第三方软件。
在上面章节中,我们讲到,rsync可以实现触发式的文件同步,但是通过 crontab
守护进程方式进行触发,同步的数据和实际数据会有差异,而inotify可以监控文件系统的各种变化,当文件有任何变动时,就触发rsync同步,这样刚好解决了同步数据的实时性问题。
具体大家可以参照http://www.ibm.com/developerworks/cn/linux/l-ubuntu-inotify/index.html
来进行学习。
接下面我们来开始进行rsync与inotify的安装、配置、测试。
下面是2个服务器的结构,分别为主机名、ip、同步的目录,并将2台服务器均是CentOS 6.5发行版本。
Host | IP | Docoment |
---|---|---|
Server | 192.168.1.21 | /tmp |
Client | 192.168.1.22 | /tmp |
主服务器(Server)
其中主服务器需要安装rsync与inotify,主服务器作为server,向备份服务器client传输文件
1、安装rsync
该版本的已安装rsync,如果没有,可使用yum安装(也可以使用源码安装,这里就不多做介绍了):
#安装rsync和xinetd,并创建目录:
yum install rsync xinetd
#配置xinetd:
vi /etc/xinetd.d/rsync
#disable = yes修改为
disable = no
启动xinetd服务:
service xinetd start
2、建立密码认证文件
代码如下:
[root@Server ]# echo "rsync-pwd" >/etc/rsync.passwd
#其中rsync-pwd可以自己设置密码,rsync.passwd名字也可以自己设置
[root@Server]# chmod 600 /etc/rsync.passwd
#无论是为了安全,还是为了避免出现以下错误,密码文件都需要给600权限
- 配置 Rsync
- 配置文件
rsync的主要有以下三个配置文件:
rsyncd.conf ----主配置文件,需要手动生成
rsyncd.secrets ----密码文件
rsyncd.motd ----rysnc服务器信息
3、安装inotify
[root@Server]# cd /usr/src/
[root@Server src]# wget http://cloud.github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz
[root@Server src]# tar zxvf inotify-tools-3.14.tar.gz
[root@Server src]# cd inotify-tools-3.14
[root@Server inotify-tools-3.14]# ./configure --prefix=/usr/local/inotify
[root@Server inotify-tools-3.14]# make
[root@Server inotify-tools-3.14]# make install
4、创建rsync复制脚本
此项功能主要是将server端的目录/tmp里的内容,如果修改了(无论是添加、修改、删除文件)能够通过inotify监控到,并通过rsync实时的同步给client的/tmp里,下面是通过shell脚本实现的。
#!/bin/bash
host=192.168.1.22
src=/tmp/
des=web
user=webuser
/usr/local/inotify/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e modify,delete,create,attrib $src \
| while read files
do
/usr/bin/rsync -vzrtopg --delete --progress --password-file=/usr/local/rsync/rsync.passwd $src $user@$host::$des
echo "${files} was rsynced" >>/tmp/rsync.log 2>&1
done
注意:建议各位吧rsync的日志放到其他的目录下(非备份目录)。 其中host是client的ip,src是server端要实时监控的目录,des是认证的模块名,需要与client一致,user是建立密码文件里的认证用户。 把这个脚本命名为rsync.sh,放到监控的目录里,比如我的就放到/tmp下面,并给予764权限
[root@Server tmp]# chmod 764 rsync.sh
然后运行这个脚本
[root@Server tmp]# sh /tmp/rsync.sh &
请记住,只有在备份服务器client端的rsync安装并启动rsync之后,在启动rsync.sh脚本,否则有时候会满屏出现:
rsync: failed to connect to 192.168.1.22: Connection refused (111)
rsync error: error in socket IO (code 10) at clientserver.c(107) [sender=2.6.8]
我们还可以把rsync.sh脚本加入到开机启动项里
[root@Server tmp]# echo "/tmp/rsync.sh" >> /etc/rc.local
备份服务器(Client)
1、安装rsync(备份服务器只安装rsync)
#安装rsync和xinetd,并创建目录:
yum install rsync xinetd
#配置xinetd:
vi /etc/xinetd.d/rsync
#disable = yes修改为
disable = no
启动xinetd服务:
service xinetd start
2、建立用户与密码认证文件
[root@Client]# echo "webuser:rsync-pwd" > /etc/rsync.passwd
#请记住,在server端建立的密码文件,只有密码,没有用户名;而在备份服务端client里建立的密码文件,用户名与密码都有。
[root@Client]# chmod 600 /etc/rsync.passwd
#需要给密码文件600权限
3、建立rsync配置文件
vim /etc/rsyncd.conf
uid = root
gid = root
use chroot = no
max connections = 10
strict modes = yes
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsyncd.log
[web]
path = /tmp/
comment = web file
ignore errors
read only = no
write only = no
hosts allow = 192.168.10.220
hosts deny = *
list = false
uid = root
gid = root
auth users = webuser
secrets file = /usr/local/rsync/rsync.passwd
其中web是server服务端里的认证模块名称,需要与主服务器里的一致,以上的配置我的自己服务器里的配置,以供参考。
4、启动rsync
service xinetd start
chkconfig xinetd on #设置开机自启动
测试
现在rsync与inotify在server端安装完成,rsync在备份服务器client端也安装完成。接下来就可以来测试一下:
在server里创建个test-rsync文件,看看client是否能收到
[root@Server tmp]# touch test-rsync
再看client端是否有test-rsync文件,同时client端的tmp目录文件是否与server端的文件完全一致。如果一致,则表示已经设置成功。
附
配置文件详细说明:
注释:
uid = nobody
进行同步或者备份的用户,nobody 为任何用户
gid = nobody
进行备份的组,nobody为任意组
use chroot = no
如果"use chroot"指定为true,那么rsync在传输文件以前首先chroot到path参数所指定的目录下。这样做的原因是实现额外的安全防护,但是缺点是需要以root权限,并且不能备份指向外部的符号连接所指向的目录文件。默认情况下chroot值为true.但是一般不需要,选择no或false
list = no
不允许列清单
max connections = 10
最大连接数
timeout = 600
覆盖客户指定的IP超时时间,也就是说rsync服务器不会永远等待一个崩溃的客户端。
pidfile = /var/run/rsyncd.pid
pid文件的存放位置
lock file = /var/run/rsync.lock
锁文件的存放位置
log file = /var/log/rsyncd.log
日志文件的存放位置
[data]
这里是认证模块名,即跟samba语法一样,是对外公布的名字
path = /home/backup
这里是参与同步的目录
ignore errors
可以忽略一些无关的IO错误
read only = no
允许可读可写
list = no
不允许列清单
hosts allow = 192.168.1.0/255.255.255.0
这里可以指定单个IP,也可以指定整个网段,能提高安全性。格式是ip 与ip 之间、ip和网段之间、网段和网段之间要用空格隔开
auth users = test
认证的用户名
secrets file = /etc/rsyncd.password
密码文件存放地址
注意:
1、[backup] 认证模块名和 path = /www/backup/ 参与同步的目录
这里的path 大家要记好了,这里不要随便的一设置就直接完事,要知道这里是认证模块的,以后从客户机备份的数据会存储在这里。
2、auth users = redhat 认证的用户名 这个名字是服务器端实实在在存在用户,大家不要直接跟步骤走却忽略了这点。如果服务器端少了这个的话我估计你的数据同步就实现不了,大家要谨记。
rsync 用法教程
rsync 用法教程
简介
rsync 是一个常用的 Linux 应用程序,用于文件同步。
它可以在本地计算机与远程计算机之间,或者两个本地目录之间同步文件(但不支持两台远程计算机之间的同步)。它也可以当作文件复制工具,替代 cp
和 mv
命令。
它名称里面的 r
指的是 remote,rsync 其实就是"远程同步"(remote sync)的意思。与其他文件传输工具(如 FTP 或 scp)不同,rsync 的最大特点是会检查发送方和接收方已有的文件,仅传输有变动的部分(默认规则是文件大小或修改时间有变动)。
安装
如果本机或者远程计算机没有安装 rsync,可以用下面的命令安装。
# Debian
$ sudo apt-get install rsync
# Red Hat
$ sudo yum install rsync
# Arch Linux
$ sudo pacman -S rsync
注意,传输的双方都必须安装 rsync。
基本用法
-r 参数
本机使用 rsync 命令时,可以作为 cp
和 mv
命令的替代方法,将源目录同步到目标目录。
$ rsync -r source destination
上面命令中, -r
表示递归,即包含子目录。注意, -r
是必须的,否则 rsync
运行不会成功。 source
目录表示源目录, destination
表示目标目录。
如果有多个文件或目录需要同步,可以写成下面这样。
$ rsync -r source1 source2 destination
上面命令中, source1
、 source2
都会被同步到 destination
目录。
-a 参数
-a
参数可以替代 -r
,除了可以递归同步以外,还可以同步元信息(比如修改时间、权限等)。由于 rsync
默认使用文件大小和修改时间决定文件是否需要更新,所以 -a
比 -r
更有用。下面的用法才是常见的写法。
$ rsync -a source destination
目标目录 destination
如果不存在,rsync
会自动创建。执行上面的命令后,源目录 source
被完整地复制到了目标目录 destination
下面,即形成了 destination/source
的目录结构。
如果只想同步源目录 source
里面的内容到目标目录 destination
,则需要在源目录后面加上斜杠。
$ rsync -a source/ destination
上面命令执行后, source
目录里面的内容,就都被复制到了 destination
目录里面,并不会在 destination
下面创建一个 source
子目录。
-n 参数
如果不确定 rsync
执行后会产生什么结果,可以先用 -n
或 --dry-run
参数模拟执行的结果。
$ rsync -anv source/ destination
上面命令中, -n
参数模拟命令执行的结果,并不真的执行命令。 -v
参数则是将结果输出到终端,这样就可以看到哪些内容会被同步。
--delete 参数
默认情况下,rsync 只确保源目录的所有内容(明确排除的文件除外)都复制到目标目录。它不会使两个目录保持相同,并且不会删除文件。如果要使得目标目录成为源目录的镜像副本,则必须使用 --delete
参数,这将删除只存在于目标目录、不存在于源目录的文件。
$ rsync -av --delete source/ destination
上面命令中, --delete
参数会使得 destination
成为 source
的一个镜像。
排除文件
--exclude 参数
有时,我们希望同步时排除某些文件或目录,这时可以用 --exclude
参数指定排除模式。
$ rsync -av --exclude='*.txt' source/ destination
# 或者
$ rsync -av --exclude '*.txt' source/ destination
上面命令排除了所有 TXT 文件。
注意,rsync 会同步以"点"开头的隐藏文件,如果要排除隐藏文件,可以这样写 --exclude=".*"
。
如果要排除某个目录里面的所有文件,但不希望排除目录本身,可以写成下面这样。
$ rsync -av --exclude 'dir1/*' source/ destination
多个排除模式,可以用多个 --exclude
参数。
$ rsync -av --exclude 'file1.txt' --exclude 'dir1/*' source/ destination
多个排除模式也可以利用 Bash 的大扩号的扩展功能,只用一个 --exclude
参数。
$ rsync -av --exclude={'file1.txt','dir1/*'} source/ destination
如果排除模式很多,可以将它们写入一个文件,每个模式一行,然后用 --exclude-from
参数指定这个文件。
$ rsync -av --exclude-from='exclude-file.txt' source/ destination
--include 参数
--include
参数用来指定必须同步的文件模式,往往与 --exclude
结合使用。
$ rsync -av --include="*.txt" --exclude='*' source/ destination
上面命令指定同步时,排除所有文件,但是会包括 TXT 文件。
远程同步
SSH 协议
rsync 除了支持本地两个目录之间的同步,也支持远程同步。它可以将本地内容,同步到远程服务器。
$ rsync -av source/ username@remote_host:destination
也可以将远程内容同步到本地。
$ rsync -av username@remote_host:source/ destination
rsync 默认使用 SSH 进行远程登录和数据传输。
由于早期 rsync 不使用 SSH 协议,需要用 -e
参数指定协议,后来才改的。所以,下面 -e ssh
可以省略。
$ rsync -av -e ssh source/ user@remote_host:/destination
但是,如果 ssh 命令有附加的参数,则必须使用 -e
参数指定所要执行的 SSH 命令。
$ rsync -av -e 'ssh -p 2234' source/ user@remote_host:/destination
上面命令中,-e参数指定 SSH 使用2234端口。
rsync 协议
除了使用 SSH,如果另一台服务器安装并运行了 rsync 守护程序,则也可以用 rsync://
协议(默认端口873)进行传输。具体写法是服务器与目标目录之间使用双冒号分隔 ::
。
$ rsync -av source/ 192.168.122.32::module/destination
注意,上面地址中的 module
并不是实际路径名,而是 rsync 守护程序指定的一个资源名,由管理员分配。
如果想知道 rsync 守护程序分配的所有 module 列表,可以执行下面命令。
$ rsync rsync://192.168.122.32
rsync 协议除了使用双冒号,也可以直接用 rsync://
协议指定地址。
$ rsync -av source/ rsync://192.168.122.32/module/destination
增量备份
rsync 的最大特点就是它可以完成增量备份,也就是默认只复制有变动的文件。
除了源目录与目标目录直接比较,rsync 还支持使用基准目录,即将源目录与基准目录之间变动的部分,同步到目标目录。
具体做法是,第一次同步是全量备份,所有文件在基准目录里面同步一份。以后每一次同步都是增量备份,只同步源目录与基准目录之间有变动的部分,将这部分保存在一个新的目标目录。这个新的目标目录之中,也是包含所有文件,但实际上,只有那些变动过的文件是存在于该目录,其他没有变动的文件都是指向基准目录文件的硬链接。
--link-dest
参数用来指定同步时的基准目录。
$ rsync -a --delete --link-dest /compare/path /source/path /target/path
上面命令中,--link-dest
参数指定基准目录 /compare/path
,然后源目录 /source/path
跟基准目录进行比较,找出变动的文件,将它们拷贝到目标目录 /target/path
。那些没变动的文件则会生成硬链接。这个命令的第一次备份时是全量备份,后面就都是增量备份了。
下面是一个脚本示例,备份用户的主目录。
#!/bin/bash
# A script to perform incremental backups using rsync
set -o errexit
set -o nounset
set -o pipefail
readonly SOURCE_DIR="${HOME}"
readonly BACKUP_DIR="/mnt/data/backups"
readonly DATETIME="$(date '+%Y-%m-%d_%H:%M:%S')"
readonly BACKUP_PATH="${BACKUP_DIR}/${DATETIME}"
readonly LATEST_LINK="${BACKUP_DIR}/latest"
mkdir -p "${BACKUP_DIR}"
rsync -av --delete \
"${SOURCE_DIR}/" \
--link-dest "${LATEST_LINK}" \
--exclude=".cache" \
"${BACKUP_PATH}"
rm -rf "${LATEST_LINK}"
ln -s "${BACKUP_PATH}" "${LATEST_LINK}"
上面脚本中,每一次同步都会生成一个新目录 ${BACKUP_DIR}/${DATETIME}
,并将软链接 ${BACKUP_DIR}/latest
指向这个目录。下一次备份时,就将 ${BACKUP_DIR}/latest
作为基准目录,生成新的备份目录。最后,再将软链接 ${BACKUP_DIR}/latest
指向新的备份目录。
配置项
-a
、 --archive
参数表示存档模式,保存所有的元数据,比如修改时间(modification time)、权限、所有者等,并且软链接也会同步过去。
--append
参数指定文件接着上次中断的地方,继续传输。
--append-verify
参数跟 --append
参数类似,但会对传输完成后的文件进行一次校验。如果校验失败,将重新发送整个文件。
-b
、--backup
参数指定在删除或更新目标目录已经存在的文件时,将该文件更名后进行备份,默认行为是删除。更名规则是添加由 --suffix
参数指定的文件后缀名,默认是~。
--backup-dir
参数指定文件备份时存放的目录,比如 --backup-dir=/path/to/backups
。
--bwlimit
参数指定带宽限制,默认单位是 KB/s
,比如 --bwlimit=100
。
-c
、 --checksum
参数改变 rsync
的校验方式。默认情况下,rsync
只检查文件的大小和最后修改日期是否发生变化,如果发生变化,就重新传输;使用这个参数以后,则通过判断文件内容的校验和,决定是否重新传输。
--delete
参数删除只存在于目标目录、不存在于源目标的文件,即保证目标目录是源目标的镜像。
-e
参数指定使用 SSH 协议传输数据。
--exclude
参数指定排除不进行同步的文件,比如 --exclude="*.iso"
。
--exclude-from
参数指定一个本地文件,里面是需要排除的文件模式,每个模式一行。
--existing
、 --ignore-non-existing
参数表示不同步目标目录中不存在的文件和目录。
-h
参数表示以人类可读的格式输出。
-h
、--help
参数返回帮助信息。
-i
参数表示输出源目录与目标目录之间文件差异的详细情况。
--ignore-existing
参数表示只要该文件在目标目录中已经存在,就跳过去,不再同步这些文件。
--include
参数指定同步时要包括的文件,一般与 --exclude
结合使用。
--link-dest
参数指定增量备份的基准目录。
-m
参数指定不同步空目录。
--max-size
参数设置传输的最大文件的大小限制,比如不超过 200KB(--max-size='200k')
。
--min-size
参数设置传输的最小文件的大小限制,比如不小于 10KB(--min-size=10k)
。
-n
参数或 --dry-run
参数模拟将要执行的操作,而并不真的执行。配合 -v
参数使用,可以看到哪些内容会被同步过去。
-P
参数是 --progress
和 --partial
这两个参数的结合。
--partial
参数允许恢复中断的传输。不使用该参数时, rsync
会删除传输到一半被打断的文件;使用该参数后,传输到一半的文件也会同步到目标目录,下次同步时再恢复中断的传输。一般需要与 --append
或 --append-verify
配合使用。
--partial-dir
参数指定将传输到一半的文件保存到一个临时目录,比如 --partial-dir=.rsync-partial
。一般需要与 --append
或 --append-verify
配合使用。
--progress
参数表示显示进展。
-r
参数表示递归,即包含子目录。
--remove-source-files
参数表示传输成功后,删除发送方的文件。
--size-only
参数表示只同步大小有变化的文件,不考虑文件修改时间的差异。
--suffix
参数指定文件名备份时,对文件名添加的后缀,默认是 ~
。
-u
、 --update
参数表示同步时跳过目标目录中修改时间更新的文件,即不同步这些有更新的时间戳的文件。
-v
参数表示输出细节。 -vv
表示输出更详细的信息, -vvv
表示输出最详细的信息。
--version
参数返回 rsync
的版本。
-z
参数指定同步时压缩数据。
参考链接
How To Use Rsync to Sync Local and Remote Directories on a VPS, Justin Ellingwood
Mirror Your Web Site With rsync, Falko Timme
Examples on how to use Rsync, Egidio Docile
How to create incremental backups using rsync on Linux, Egidio Docile
(完)
Centos 6无法使用yum解决办法(centos6停止更新)
Centos 6无法使用yum解决办法(centos6停止更新)
12月后Centos 6 系统无法使用yum出现错误
相信已经有一部分朋友今天连接到CentOS 6的服务器后执行yum后发现报错,那么发生了什么?
CentOS 6已经随着2020年11月的结束进入了EOL(Reaches End of Life),不过有一些老设备依然需要支持,CentOS官方也给这些还不想把CentOS 6扔进垃圾堆的用户保留了最后一个版本的镜像,只是这个镜像不会再有更新了
官方便在12月2日正式将CentOS 6相关的软件源移出了官方源,随之而来逐级镜像也会陆续将其删除。
不过有一些老设备依然需要维持在当前系统,CentOS官方也给这些还不想把CentOS 6扔进垃圾堆的用户保留了各个版本软件源的镜像,只是这个软件源不会再有更新了。
一键修复
sed -i "s|enabled=1|enabled=0|g" /etc/yum/pluginconf.d/fastestmirror.conf
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
curl -o /etc/yum.repos.d/CentOS-Base.repo https://www.xmpan.com/Centos-6-Vault-Aliyun.repo
yum clean all
yum makecache
手动修复教程:
首先把fastestmirrors关了
#编辑
vi /etc/yum/pluginconf.d/fastestmirror.conf
#修改
enable=0
#或者执行以下命令
sed -i "s|enabled=1|enabled=0|g" /etc/yum/pluginconf.d/fastestmirror.conf
先把之前的repo挪到备份,然后下面两个二选一
- 备份
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak
- 替换为官方Vault源(海外服务器用)
curl -o /etc/yum.repos.d/CentOS-Base.repo https://www.xmpan.com/Centos-6-Vault-Official.repo
或者替换为阿里云Vault镜像(国内服务器用)
curl -o /etc/yum.repos.d/CentOS-Base.repo https://www.xmpan.com/Centos-6-Vault-Aliyun.repo
Nginx配置中不同请求匹配不同请求
Nginx配置中不同请求匹配不同请求
一、正则匹配
- ~ 为区分大小写匹配
- ~* 为不区分大小写匹配
- !和!*分别为区分大小写不匹配及不区分大小写不匹配
二、文件及目录匹配
- -f和!-f用来判断是否存在文件
- -d和!-d用来判断是否存在目录
- -e和!-e用来判断是否存在文件或目录
- -x和!-x用来判断文件是否可执行
三.rewrite指令的最后一项参数为flag标记,flag标记有:
- last 相当于apache里面的[L]标记,表示rewrite。
- break本条规则匹配完成后,终止匹配,不再匹配后面的规则。
- redirect 返回302临时重定向,浏览器地址会显示跳转后的URL地址。
- permanent 返回301永久重定向,浏览器地址会显示跳转后的URL地址。
使用last和break实现URI重写,浏览器地址栏不变。而且两者有细微差别,使用alias指令必须用last标记;使用proxy_pass指令时,需要使用break标记。Last标记在本条rewrite规则执行完毕后,会对其所在server{…}标签重新发起请求,而break标记则在本条规则匹配完成后,终止匹配。
四.NginxRewrite 规则相关指令
1.break指令
使用环境:server,location,if;
该指令的作用是完成当前的规则集,不再处理rewrite指令。
2.if指令
使用环境:server,location
该指令用于检查一个条件是否符合,如果条件符合,则执行大括号内的语句。If指令不支持嵌套,不支持多个条件&&和||处理。
location /CMS/ {##请求以CMS开头的走此location
if ($request_uri ~ "CMS/was") { ##内容包含 CMS/was 的转发至以下请求(区分大小写)
proxy_pass http://10.1.1.247;
break; ##break表示
}
if ($request_uri ~ "CMS/Evaluate.action") { ##同上
proxy_pass http://10.1.1.247;
break;
}
rewrite ^ http://www.baidu.com/;##CMS后其余的请求统一重定向至百度
}
3.return指令
语法:returncode ;
使用环境:server,location,if;
该指令用于结束规则的执行并返回状态码给客户端。
location ~ .*\.(sh|bash)?$ {
return 403;
}
4.rewrite 指令
语法:rewriteregex replacement flag
使用环境:server,location,if
该指令根据表达式来重定向URI,或者修改字符串。指令根据配置文件中的顺序来执行。注意重写表达式只对相对路径有效。如果你想配对主机名,你应该使用if语句,示例如下:
if( $host ~* www\.(.*) ) {
set $host_without_www $1;
rewrite ^(.*)$ http://$host_without_www$1permanent;
}
5.Set指令
语法:setvariable value ; 默认值:none; 使用环境:server,location,if;
该指令用于定义一个变量,并给变量赋值。变量的值可以为文本、变量以及文本变量的联合。
set$varname "hello world";
6.Uninitialized_variable_warn指令
语法:uninitialized_variable_warnon|off
使用环境:http,server,location,if
该指令用于开启和关闭未初始化变量的警告信息,默认值为开启。
五.Nginx的Rewrite规则编写实例
1.当访问的文件和目录不存在时,重定向到某个html文件
if( !-e $request_filename )
{
rewrite ^/(.*)$ index.htmllast;
}
2.目录对换 /123456/xxxx ====> /xxxx?id=123456
rewrite ^/(\d+)/(.+)/ /$2?id=$1 last;
3.如果客户端使用的是IE浏览器,则重定向到/ie目录下
if( $http_user_agent ~ MSIE)
{
rewrite ^(.*)$ /ie/$1 break;
}
4.禁止访问多个目录
location ~ ^/(cron|templates)/
{
deny all;
break;
}
5.禁止访问以/data开头的文件
location ~ ^/data
{
deny all;
}
6.禁止访问以.sh,.flv,.mp3为文件后缀名的文件
location ~ .*\.(sh|flv|mp3)$
{
return 403;
}
7.设置某些类型文件的浏览器缓存时间
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}
location ~ .*\.(js|css)$
{
expires 1h;
}
8.给favicon.ico和robots.txt设置过期时间;
这里为favicon.ico为99天,robots.txt为7天并不记录404错误日志
location ~(favicon.ico) {
log_not_found off;
expires 99d;
break;
}
location ~(robots.txt) {
log_not_found off;
expires 7d;
break;
}
9.设定某个文件的过期时间;这里为600秒,并不记录访问日志
location ^~ /html/scripts/loadhead_1.js {
access_log off;
root /opt/lampp/htdocs/web;
expires 600;
break;
}
10.文件反盗链并设置过期时间
这里的return412 为自定义的http状态码,默认为403,方便找出正确的盗链的请求
rewrite ^/ http: //img.linuxidc.net/leech.gif;//显示一张防盗链图片
access_log off; //不记录访问日志,减轻压力
expires 3d //所有文件3天的浏览器缓存
location ~*^.+\.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$ {
valid_referers none blocked *.linuxidc.com*.linuxidc.net localhost 208.97.167.194;
if ($invalid_referer) {
rewrite ^/ http://img.linuxidc.net/leech.gif;
return 412;
break;
}
access_log off;
root /opt/lampp/htdocs/web;
expires 3d;
break;
}
11.只允许固定ip访问网站,并加上密码
root /opt/htdocs/www;
allow 208.97.167.194;
allow 222.33.1.2;
allow 231.152.49.4;
deny all;
auth_basic “C1G_ADMIN”;
auth_basic_user_file htpasswd;
12.将多级目录下的文件转成一个文件,增强seo效果
/job-123-456-789.html 指向/job/123/456/789.html
rewrite^/job-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /job/$1/$2/jobshow_$3.html last;
14.将根目录下某个文件夹指向2级目录
如/shanghaijob/ 指向 /area/shanghai/
如果你将last改成permanent,那么浏览器地址栏显是/location/shanghai/
rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2last;
上面例子有个问题是访问/shanghai时将不会匹配
rewrite ^/([0-9a-z]+)job$ /area/$1/ last;
rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2last;
这样/shanghai 也可以访问了,但页面中的相对链接无法使用,
如./list_1.html真实地址是/area/shanghia/list_1.html会变成/list_1.html,导至无法访问。
那我加上自动跳转也是不行咯
(-d $request_filename)它有个条件是必需为真实目录,而我的rewrite不是的,所以没有效果
if (-d $request_filename){
rewrite ^/(.*)([^/])$ http://$host/$1$2/permanent;
}
知道原因后就好办了,让我手动跳转吧
rewrite ^/([0-9a-z]+)job$ /$1job/permanent;
rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2last;
15.域名跳转
server{
listen 80;
server_name jump.linuxidc.com;
index index.html index.htm index.php;
root /opt/lampp/htdocs/www;
rewrite ^/ http://www.linuxidc.com/;
access_log off;
}
16.多域名转向
server_name www.linuxidc.com www.linuxidc.net;
index index.html index.htm index.php;
root /opt/lampp/htdocs;
if ($host ~ "linuxidc\.net") {
rewrite ^(.*) http://www.linuxidc.com$1permanent;
}
六.nginx全局变量
arg_PARAMETER #这个变量包含GET请求中,如果有变量PARAMETER时的值。
args #这个变量等于请求行中(GET请求)的参数,如:foo=123&bar=blahblah;
binary_remote_addr #二进制的客户地址。
body_bytes_sent #响应时送出的body字节数数量。即使连接中断,这个数据也是精确的。
content_length #请求头中的Content-length字段。
content_type #请求头中的Content-Type字段。
cookie_COOKIE #cookie COOKIE变量的值
document_root #当前请求在root指令中指定的值。
document_uri #与uri相同。
host #请求主机头字段,否则为服务器名称。
hostname #Set to themachine’s hostname as returned by gethostname
http_HEADER
is_args #如果有args参数,这个变量等于”?”,否则等于”",空值。
http_user_agent #客户端agent信息
http_cookie #客户端cookie信息
limit_rate #这个变量可以限制连接速率。
query_string #与args相同。
request_body_file #客户端请求主体信息的临时文件名。
request_method #客户端请求的动作,通常为GET或POST。
remote_addr #客户端的IP地址。
remote_port #客户端的端口。
remote_user #已经经过Auth Basic Module验证的用户名。
request_completion #如果请求结束,设置为OK. 当请求未结束或如果该请求不是请求链串的最后一个时,为空(Empty)。
request_method #GET或POST
request_filename #当前请求的文件路径,由root或alias指令与URI请求生成。
request_uri #包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。不能修改。
scheme #HTTP方法(如http,https)。
server_protocol #请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
server_addr #服务器地址,在完成一次系统调用后可以确定这个值。
server_name #服务器名称。
server_port #请求到达服务器的端口号。
七.Apache和Nginx规则的对应关系
Apache的RewriteCond对应Nginx的if
Apache的RewriteRule对应Nginx的rewrite
Apache的[R]对应Nginx的redirect
Apache的[P]对应Nginx的last
Apache的[R,L]对应Nginx的redirect
Apache的[P,L]对应Nginx的last
Apache的[PT,L]对应Nginx的last
例如:允许指定的域名访问本站,其他的域名一律转向www.linuxidc.net
Apache:
RewriteCond %{HTTP_HOST} !^(.*?)\.aaa\.com$[NC]
RewriteCond %{HTTP_HOST} !^localhost$
RewriteCond %{HTTP_HOST}!^192\.168\.0\.(.*?)$
RewriteRule ^/(.*)$ http://www.linuxidc.net[R,L]
Nginx过滤示例:
if( $host ~* ^(.*)\.aaa\.com$ )
{
set $allowHost ‘1’;
}
if( $host ~* ^localhost )
{
set $allowHost ‘1’;
}
if( $host ~* ^192\.168\.1\.(.*?)$ )
{
set $allowHost ‘1’;
}
if( $allowHost !~ ‘1’ )
{
rewrite ^/(.*)$ http://www.linuxidc.netredirect ;
}
使用 flock 文件锁解决 crontab 冲突问题
使用 flock 文件锁解决 crontab 冲突问题
linux 的 crontab 命令,可以定时执行操作,最小周期是每分钟执行一次。但是如果在这一分钟之内,之前的命令并没有执行完成,就会产生冲突。接下来介绍解决冲突的办法,那就是 linux 的 flock 文件锁。
关于crontab实现每秒执行可参考《linux crontab 实现每秒执行》
格式:
flock [-sxun][-w #] fd#
flock [-sxon][-w #] file [-c] command
参数是:
-s, --shared: 获得一个共享锁
-x, --exclusive: 获得一个独占锁
-u, --unlock: 移除一个锁,通常是不需要的,脚本执行完会自动丢弃锁
-n, --nonblock: 如果没有立即获得锁,直接失败而不是等待
-w, --timeout: 如果没有立即获得锁,等待指定时间
-o, --close: 在运行命令前关闭文件的描述符号。用于如果命令产生子进程时会不受锁的管控
-c, --command: 在shell中运行一个单独的命令
-h, --help 显示帮助
-V, --version: 显示版本
继续用回第一个 test.php
,文件锁使用独占锁,如果锁定则失败不等待。参数为 -xn
下面是在 crontab
中的使用:
# -xn 文件锁使用独占锁,如果锁定则失败不等待。
* * * * * flock -xn /tmp/test.lock -c 'php /home/develop/test.php >> /home/develop/test.log'
这样当任务未执行完成,下一任务判断到 /tmp/test.lock
被锁定,则结束当前的任务,下一周期再判断。
Ubuntu扩展 /dev/mapper/ubuntu--vg-ubuntu--lv空间
Ubuntu扩展 /dev/mapper/ubuntu--vg-ubuntu--lv空间
1. 查看磁盘空间
root@root:~# df -h
Filesystem Size Used Avail Use% Mounted on
udev 1.9G 0 1.9G 0% /dev
tmpfs 393M 2.1M 391M 1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv 14G 4.4G 8.8G 34% /
tmpfs 2.0G 0 2.0G 0% /dev/shm
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup
/dev/loop0 90M 90M 0 100% /snap/core/8268
/dev/sda2 976M 82M 828M 9% /boot
tmpfs 393M 20K 393M 1% /run/user/125
tmpfs 393M 56K 393M 1% /run/user/1000
查看vg
root@root:~# vgdisplay
--- Volume group ---
VG Name ubuntu-vg
System ID
Format lvm2
Metadata Areas 1
Metadata Sequence No 3
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 1
Open LV 1
Max PV 0
Cur PV 1
Act PV 1
VG Size <79.00 GiB
PE Size 4.00 MiB
Total PE 20223
Alloc PE / Size 3584 / 14.00 GiB
Free PE / Size 16639 / <65.00 GiB
VG UUID mg1Zau-atla-jy56-ycyN-e6dS-UJC9-1ErQU7
扩展
lvextend -L 120G /dev/mapper/ubuntu--vg-ubuntu--lv //增大至120G
lvextend -L +20G /dev/mapper/ubuntu--vg-ubuntu--lv //增加20G
lvreduce -L 50G /dev/mapper/ubuntu--vg-ubuntu--lv //减小至50G
lvreduce -L -8G /dev/mapper/ubuntu--vg-ubuntu--lv //减小8G
lvresize -L 30G /dev/mapper/ubuntu--vg-ubuntu--lv //调整为30G
调整
resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv //执行调整
搭建RTMP直播流服务器实现直播
搭建RTMP直播流服务器实现直播
服务介绍
RTMP流媒体服务器,现成的开源方案有很多,有SRS,Red5,wowoza,FMS等,我这里使用的是Nginx的rtmp插件实现实时流转发。
先在 Nginx官网 下载源码包,然后在 github 下载插件包。
为了简化安装过程,网上有很多现成的 nginx + rtmp
docker 镜像。下面以 alqutami/rtmp-hls 为例来讲解 rtmp
流媒体服务器的部署。
此 Docker 映像可用于创建开箱即用的支持RTMP、HLS、DASH的视频流服务器。它还允许视频流的自适应流媒体和自定义转码。所有模块都是在 Debian 和 Alpine Linux 基础映像上从源代码构建的。
- 后端是带有nginx-rtmp-module 的 Nginx。
- FFmpeg 用于转码和自适应流媒体。
- 默认设置:
- RTMP 开启
- HLS 开启(自适应,5 个变体)
- DASH 开启
- 还提供了其他 Nginx 配置文件以允许仅 RTMP 流或无 FFmpeg 转码。
- .RTMP 流的统计页面
http://<server ip>:<server port>/stats
。 - 可用的网络视频播放器(基于video.js和hls.js)位于
/usr/local/nginx/html/players
.
当前图像是使用以下方法构建的:
- Nginx 1.17.5(从源代码编译)
- Nginx-rtmp-module 1.2.1(从源码编译)
- FFmpeg 4.2.1(从源代码编译)
部署服务
下载
通过 docker 方式的部署无需安装服务器依赖环境,也不用关心服务器系统发行版。主要需要安装 docker
,然后执行以下命令获取镜像:
# pull rtmp-hls image
docker pull alqutami/rtmp-hls
# see rtmp-hls image
docker image ls
# save image
docker image save alqutami/rtmp-hls:latest > alqutami_rtmp-hls_latest.tar.gz
# load image
docker image load < alqutami_rtmp-hls_latest.tar.gz
安装
镜像下载安装之后,即可直接安装运行 rtmp 的 docker container
# base buid
docker run -d --name rtmp -p 1935:1935 -p 8080:8080 alqutami/rtmp-hls:latest
# see container
docker container exec -it rtmp bash
# delete container
docker container rm -f rtmp
附件:
调试
流式传输到服务器
- 将实时 RTMP 内容流式传输到:
-
rtmp://<server ip>:1935/live/<stream_key>
-
<stream_key>
您指定的任何流密钥在哪里。
-
- 配置 OBS 以流式传输内容:
- 转到设置 > 流式传输,选择以下设置:
- 服务:自定义流媒体服务器。
- 服务器:
rtmp://<server ip>:1935/live
。 - 流密钥:您想要的任何东西,但前提是视频播放器假定流密钥是
test
查看流
-
使用 VLC:
-
转至媒体 > 打开网络流。
-
输入流 URL:
rtmp://<server ip>:1935/live/<stream-key>
替换<server ip>
为运行服务器的 IP,以及<stream-key>
您在设置流时使用的流密钥。 -
对于 HLS 和 DASH,URL 的形式分别为:
http://<server ip>:8080/hls/<stream-key>.m3u8
和http://<server ip>:8080/dash/<stream-key>_src.mpd
。 -
单击播放。
-
-
使用提供的网络播放器:
-
提供的演示播放器假设调用了流密钥test并且播放器在本地主机中打开。
-
播放 RTMP 内容(需要 Flash):
http://localhost:8080/players/rtmp.html
-
播放 HLS 内容:
http://localhost:8080/players/hls.html
-
使用 hls.js 库播放 HLS 内容:
http://localhost:8080/players/hls_hlsjs.html
-
播放 DASH 内容:
http://localhost:8080/players/dash.html
-
在同一页面上播放 RTMP 和 HLS 内容:
http://localhost:8080/players/rtmp_hls.html
-
笔记:*
-
这些网络播放器被硬编码为在本地主机上播放流密钥
test
。 -
更改这些播放器的流源。下载html文件,修改html文件src中video标签中的属性。然后,您可以将修改后的文件挂载到容器中,如下所示:
# conf buid
docker run -d \
--name rtmp \
-p 1935:1935 \
-p 8080:8080 \
-v /data/rtmp/nginx.conf:/etc/nginx/nginx.conf \
-v /data/rtmp/html:/usr/local/nginx/html \
alqutami/rtmp-hls:latest
# order conf copy
mkdir -p html/players
docker container cp rtmp:/usr/local/nginx/html/50x.html html/
docker container cp rtmp:/usr/local/nginx/html/index.html html/
docker container cp rtmp:/usr/local/nginx/html/players/dash.html html/players/
docker container cp rtmp:/usr/local/nginx/html/players/hls.html html/players/
docker container cp rtmp:/usr/local/nginx/html/players/hls_hlsjs.html html/players/
docker container cp rtmp:/usr/local/nginx/html/players/rtmp.html html/players/
docker container cp rtmp:/usr/local/nginx/html/players/rtmp_hls.html html/players/
docker container cp rtmp:/usr/local/nginx/html/stat.xsl html/
rtmp
保存修改后的 html 文件的目录 在哪里。
页面调试
# stat page
http://rtmp.wzhz.xyz/stat
# players page
http://rtmp.wzhz.xyz/players/dash.html
http://rtmp.wzhz.xyz/players/hls.html
http://rtmp.wzhz.xyz/players/rtmp.html
http://rtmp.wzhz.xyz/players/rtmp_hls.html
http://rtmp.wzhz.xyz/players/hls_hlsjs.html
FRP使用
概览
frp 是什么?
frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。
为什么使用 frp?
通过在具有公网 IP 的节点上部署 frp 服务端,可以轻松地将内网服务穿透到公网,同时提供诸多专业的功能特性,这包括:
- 客户端服务端通信支持 TCP、KCP 以及 Websocket 等多种协议。
- 采用 TCP 连接流式复用,在单个连接间承载更多请求,节省连接建立时间。
- 代理组间的负载均衡。
- 端口复用,多个服务通过同一个服务端端口暴露。
- 多个原生支持的客户端插件(静态文件查看,HTTP、SOCK5 代理等),便于独立使用 frp 客户端完成某些工作。
- 高度扩展性的服务端插件系统,方便结合自身需求进行功能扩展。
- 服务端和客户端 UI 页面。
安装
关于如何安装 frp 的说明。
frp 采用 Golang 编写,支持跨平台,仅需下载对应平台的二进制文件即可执行,没有额外依赖。
系统需求
由于采用 Golang 编写,所以系统需求和最新的 Golang 对系统和平台的要求一致,具体可以参考 Golang System requirements。
下载
目前可以在 Github 的 Release 页面中下载到最新版本的客户端和服务端二进制文件,所有文件被打包在一个压缩包中。
部署
解压缩下载的压缩包,将其中的 frpc 拷贝到内网服务所在的机器上,将 frps 拷贝到具有公网 IP 的机器上,放置在任意目录。
开始使用!
编写配置文件,先通过 ./frps -c ./frps.ini
启动服务端,再通过 ./frpc -c ./frpc.ini
启动客户端。如果需要在后台长期运行,建议结合其他工具使用,例如 systemd
和 supervisor
。
如果是 Windows 用户,需要在 cmd 终端中执行命令。
概念
一些概念,理解它们有助于您更好地了解和使用 frp。
原理
frp 主要由 客户端(frpc) 和 服务端(frps) 组成,服务端通常部署在具有公网 IP 的机器上,客户端通常部署在需要穿透的内网服务所在的机器上。
内网服务由于没有公网 IP,不能被非局域网内的其他用户访问。
用户通过访问服务端的 frps,由 frp 负责根据请求的端口或其他信息将请求路由到对应的内网机器,从而实现通信。
代理
在 frp 中一个代理对应一个需要暴露的内网服务。一个客户端支持同时配置多个代理。
代理类型
frp 支持多种代理类型来适配不同的使用场景。
类型 | 描述 |
---|---|
tcp | 单纯的 TCP 端口映射,服务端会根据不同的端口路由到不同的内网服务。 |
udp | 单纯的 UDP 端口映射,服务端会根据不同的端口路由到不同的内网服务。 |
http | 针对 HTTP 应用定制了一些额外的功能,例如修改 Host Header,增加鉴权。 |
https | 针对 HTTPS 应用定制了一些额外的功能。 |
stcp | 安全的 TCP 内网代理,需要在被访问者和访问者的机器上都部署 frpc,不需要在服务端暴露端口。 |
sudp | 安全的 UDP 内网代理,需要在被访问者和访问者的机器上都部署 frpc,不需要在服务端暴露端口。 |
xtcp | 点对点内网穿透代理,功能同 stcp,但是流量不需要经过服务器中转。 |
tcpmux | 支持服务端 TCP 端口的多路复用,通过同一个端口访问不同的内网服务。 |
示例
这里包括多个常见的使用场景和配置示例,你可以用来亲自部署和体验这些示例。
通过 SSH 访问内网机器
这个示例通过简单配置 TCP 类型的代理让用户访问到内网的服务器。
-
在具有公网 IP 的机器上部署 frps,修改 frps.ini 文件,这里使用了最简化的配置,设置了 frp 服务器用户接收客户端连接的端口:
[common] bind_port = 7000
-
在需要被访问的内网机器上(SSH 服务通常监听在 22 端口)部署 frpc,修改 frpc.ini 文件,假设 frps 所在服务器的公网 IP 为 x.x.x.x:
[common] server_addr = x.x.x.x server_port = 7000 [ssh] type = tcp local_ip = 127.0.0.1 local_port = 22 remote_port = 6000
local_ip
和local_port
配置为本地需要暴露到公网的服务地址和端口。remote_port
表示在 frp 服务端监听的端口,访问此端口的流量将会被转发到本地服务对应的端口。 -
分别启动 frps 和 frpc。
-
通过 SSH 访问内网机器,假设用户名为 test:
ssh -oPort=6000 test@x.x.x.x
frp 会将请求
x.x.x.x:6000
的流量转发到内网机器的 22 端口。
通过自定义域名访问内网的 Web 服务
这个示例通过简单配置 HTTP 类型的代理让用户访问到内网的 Web 服务。
HTTP 类型的代理相比于 TCP 类型,不仅在服务端只需要监听一个额外的端口 vhost_http_port
用于接收 HTTP 请求,还额外提供了基于 HTTP 协议的诸多功能。
-
修改 frps.ini 文件,设置监听 HTTP 请求端口为 8080:
[common] bind_port = 7000 vhost_http_port = 8080
-
修改 frpc.ini 文件,假设 frps 所在的服务器的 IP 为 x.x.x.x,
local_port
为本地机器上 Web 服务监听的端口, 绑定自定义域名为custom_domains
。[common] server_addr = x.x.x.x server_port = 7000 [web] type = http local_port = 80 custom_domains = www.yourdomain.com [web2] type = http local_port = 8080 custom_domains = www.yourdomain2.com
-
分别启动 frps 和 frpc。
-
将
www.yourdomain.com
和www.yourdomain2.com
的域名 A 记录解析到 IPx.x.x.x
,如果服务器已经有对应的域名,也可以将 CNAME 记录解析到服务器原先的域名。或者可以通过修改 HTTP 请求的 Host 字段来实现同样的效果。 -
通过浏览器访问
http://www.yourdomain.com:8080
即可访问到处于内网机器上 80 端口的服务,访问http://www.yourdomain2.com:8080
则访问到内网机器上 8080 端口的服务。
转发 DNS 查询请求
这个示例通过简单配置 UDP 类型的代理转发 DNS 查询请求。
DNS 查询请求通常使用 UDP 协议,frp 支持对内网 UDP 服务的穿透,配置方式和 TCP 基本一致。
-
frps.ini 内容如下:
[common] bind_port = 7000
-
frpc.ini 内容如下:
[common] server_addr = x.x.x.x server_port = 7000 [dns] type = udp local_ip = 8.8.8.8 local_port = 53 remote_port = 6000
这里反代了 Google 的 DNS 查询服务器的地址,仅仅用于测试 UDP 代理,并无实际意义。
-
分别启动 frps 和 frpc。
-
通过 dig 测试 UDP 包转发是否成功,预期会返回
www.baidu.com
域名的解析结果。dig @x.x.x.x -p 6000 www.baidu.com
转发 Unix 域套接字
这个示例通过配置 Unix域套接字客户端插件来通过 TCP 端口访问内网的 Unix域套接字服务,例如 Docker Daemon。
-
frps.ini 内容如下:
[common] bind_port = 7000
-
frpc.ini 内容如下:
[common] server_addr = x.x.x.x server_port = 7000 [unix_domain_socket] type = tcp remote_port = 6000 plugin = unix_domain_socket plugin_unix_path = /var/run/docker.sock
-
分别启动 frps 和 frpc。
-
通过 curl 命令查看 docker 版本信息
curl http://x.x.x.x:6000/version
对外提供简单的文件访问服务
这个示例通过配置 static_file
客户端插件来将本地文件暴露在公网上供其他人访问。
通过 static_file
插件可以对外提供一个简单的基于 HTTP 的文件访问服务。
-
frps.ini 内容如下:
[common] bind_port = 7000
-
frpc.ini 内容如下:
[common] server_addr = x.x.x.x server_port = 7000 [test_static_file] type = tcp remote_port = 6000 plugin = static_file # 要对外暴露的文件目录 plugin_local_path = /tmp/file # 用户访问 URL 中会被去除的前缀,保留的内容即为要访问的文件路径 plugin_strip_prefix = static plugin_http_user = abc plugin_http_passwd = abc
-
分别启动 frps 和 frpc。
-
通过浏览器访问
http://x.x.x.x:6000/static/
来查看位于/tmp/file
目录下的文件,会要求输入已设置好的用户名和密码。
为本地 HTTP 服务启用 HTTPS
通过 https2http
插件可以让本地 HTTP 服务转换成 HTTPS 服务对外提供。
-
frps.ini 内容如下:
[common] bind_port = 7000
-
frpc.ini 内容如下:
[common] server_addr = x.x.x.x server_port = 7000 [test_htts2http] type = https custom_domains = test.yourdomain.com plugin = https2http plugin_local_addr = 127.0.0.1:80 # HTTPS 证书相关的配置 plugin_crt_path = ./server.crt plugin_key_path = ./server.key plugin_host_header_rewrite = 127.0.0.1 plugin_header_X-From-Where = frp
-
分别启动 frps 和 frpc。
-
通过浏览器访问
https://test.yourdomain.com
。
安全地暴露内网服务
这个示例将会创建一个只有自己能访问到的 SSH 服务代理。
对于某些服务来说如果直接暴露于公网上将会存在安全隐患。
使用 stcp(secret tcp)
类型的代理可以避免让任何人都能访问到要穿透的服务,但是访问者也需要运行另外一个 frpc 客户端。
-
frps.ini 内容如下:
[common] bind_port = 7000
-
在需要暴露到内网的机器上部署 frpc,且配置如下:
[common] server_addr = x.x.x.x server_port = 7000 [secret_ssh] type = stcp # 只有 sk 一致的用户才能访问到此服务 sk = abcdefg local_ip = 127.0.0.1 local_port = 22
-
在想要访问内网服务的机器上也部署 frpc,且配置如下:
[common] server_addr = x.x.x.x server_port = 7000 [secret_ssh_visitor] type = stcp # stcp 的访问者 role = visitor # 要访问的 stcp 代理的名字 server_name = secret_ssh sk = abcdefg # 绑定本地端口用于访问 SSH 服务 bind_addr = 127.0.0.1 bind_port = 6000
-
通过 SSH 访问内网机器,假设用户名为 test:
ssh -oPort=6000 test@127.0.0.1
点对点内网穿透
这个示例将会演示一种不通过服务器中转流量的方式来访问内网服务。
frp 提供了一种新的代理类型 xtcp
用于应对在希望传输大量数据且流量不经过服务器的场景。
使用方式同 stcp
类似,需要在两边都部署上 frpc 用于建立直接的连接。
目前处于开发的初级阶段,并不能穿透所有类型的 NAT 设备,所以穿透成功率较低。穿透失败时可以尝试 stcp
的方式。
-
frps.ini 内容如下,需要额外配置监听一个 UDP 端口用于支持该类型的客户端:
[common] bind_port = 7000 bind_udp_port = 7000
-
在需要暴露到内网的机器上部署 frpc,且配置如下:
[common] server_addr = x.x.x.x server_port = 7000 [p2p_ssh] type = xtcp # 只有 sk 一致的用户才能访问到此服务 sk = abcdefg local_ip = 127.0.0.1 local_port = 22
-
在想要访问内网服务的机器上也部署 frpc,且配置如下:
[common] server_addr = x.x.x.x server_port = 7000 [p2p_ssh_visitor] type = xtcp # xtcp 的访问者 role = visitor # 要访问的 xtcp 代理的名字 server_name = p2p_ssh sk = abcdefg # 绑定本地端口用于访问 ssh 服务 bind_addr = 127.0.0.1 bind_port = 6000
-
通过 SSH 访问内网机器,假设用户名为 test:
ssh -oPort=6000 test@127.0.0.1
参考
服务端配置
frp 服务端详细配置说明。
基础配置
参数 | 类型 | 说明 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|
bind_addr | string | 服务端监听地址 | 0.0.0.0 | ||
bind_port | int | 服务端监听端口 | 7000 | 接收 frpc 的连接 | |
bind_udp_port | int | 服务端监听 UDP 端口 | 0 | 用于辅助创建 P2P 连接 | |
kcp_bind_port | int | 服务端监听 KCP 协议端口 | 0 | 用于接收采用 KCP 连接的 frpc | |
proxy_bind_addr | string | 代理监听地址 | 同 bind_addr | 可以使代理监听在不同的网卡地址 | |
log_file | string | 日志文件地址 | ./frps.log | 如果设置为 console,会将日志打印在标准输出中 | |
log_level | string | 日志等级 | info | trace, debug, info, warn, error | |
log_max_days | int | 日志文件保留天数 | 3 | ||
disable_log_color | bool | 禁用标准输出中的日志颜色 | false | ||
detailed_errors_to_client | bool | 服务端返回详细错误信息给客户端 | true | ||
heart_beat_timeout | int | 服务端和客户端心跳连接的超时时间 | 90 | 单位:秒 | |
user_conn_timeout | int | 用户建立连接后等待客户端响应的超时时间 | 10 | 单位:秒 | |
udp_packet_size | int | 代理 UDP 服务时支持的最大包长度 | 1500 | 服务端和客户端的值需要一致 | |
tls_cert_file | string | TLS 服务端证书文件路径 | |||
tls_key_file | string | TLS 服务端密钥文件路径 | |||
tls_trusted_ca_file | string | TLS CA 证书路径 |
权限验证
参数 | 类型 | 说明 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|
authentication_method | string | 鉴权方式 | token | token, oidc | |
authenticate_heartbeats | bool | 开启心跳消息鉴权 | false | ||
authenticate_new_work_conns | bool | 开启建立工作连接的鉴权 | false | ||
token | string | 鉴权使用的 token 值 | 客户端需要设置一样的值才能鉴权通过 | ||
oidc_issuer | string | oidc_issuer | |||
oidc_audience | string | oidc_audience | |||
oidc_skip_expiry_check | bool | oidc_skip_expiry_check | |||
oidc_skip_issuer_check | bool | oidc_skip_issuer_check |
管理配置
参数 | 类型 | 说明 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|
allow_ports | string | 允许代理绑定的服务端端口 | 格式为 1000-2000,2001,3000-4000 | ||
max_pool_count | int | 最大连接池大小 | 5 | ||
max_ports_per_client | int | 限制单个客户端最大同时存在的代理数 | 0 | 0 表示没有限制 | |
tls_only | bool | 只接受启用了 TLS 的客户端连接 | false |
Dashboard, 监控
参数 | 类型 | 说明 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|
dashboard_addr | string | 启用 Dashboard 监听的本地地址 | 0.0.0.0 | ||
dashboard_port | int | 启用 Dashboard 监听的本地端口 | 0 | ||
dashboard_user | string | HTTP BasicAuth 用户名 | |||
dashboard_pwd | string | HTTP BasicAuth 密码 | |||
enable_prometheus | bool | 是否提供 Prometheus 监控接口 | false | 需要同时启用了 Dashboard 才会生效 | |
asserts_dir | string | 静态资源目录 | Dashboard 使用的资源默认打包在二进制文件中,通过指定此参数使用自定义的静态资源 |
HTTP & HTTPS
参数 | 类型 | 说明 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|
vhost_http_port | int | 为 HTTP 类型代理监听的端口 | 0 | 启用后才支持 HTTP 类型的代理,默认不启用 | |
vhost_https_port | int | 为 HTTPS 类型代理监听的端口 | 0 | 启用后才支持 HTTPS 类型的代理,默认不启用 | |
vhost_http_timeout | int | HTTP 类型代理在服务端的 ResponseHeader 超时时间 | 60 | ||
subdomain_host | string | 二级域名后缀 | |||
custom_404_page | string | 自定义 404 错误页面地址 |
TCPMUX
参数 | 类型 | 说明 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|
tcpmux_httpconnect_port | int | 为 TCPMUX 类型代理监听的端口 | 0 | 启用后才支持 TCPMUX 类型的代理,默认不启用 |
客户端配置
frp 客户端的详细配置说明。
基础配置
参数 | 类型 | 说明 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|
server_addr | string | 连接服务端的地址 | 0.0.0.0 | ||
server_port | int | 连接服务端的端口 | 7000 | ||
http_proxy | string | 连接服务端使用的代理地址 | 格式为 {protocol}://user:passwd@192.168.1.128:8080 protocol 目前支持 http、socks5、ntlm | ||
log_file | string | 日志文件地址 | ./frpc.log | 如果设置为 console,会将日志打印在标准输出中 | |
log_level | string | 日志等级 | info | trace, debug, info, warn, error | |
log_max_days | int | 日志文件保留天数 | 3 | ||
disable_log_color | bool | 禁用标准输出中的日志颜色 | false | ||
pool_count | int | 连接池大小 | 0 | ||
user | string | 用户名 | 设置此参数后,代理名称会被修改为 {user}.{proxyName},避免代理名称和其他用户冲突 | ||
dns_server | string | 使用 DNS 服务器地址 | 默认使用系统配置的 DNS 服务器,指定此参数可以强制替换为自定义的 DNS 服务器地址 | ||
login_fail_exit | bool | 第一次登陆失败后是否退出 | true | ||
protocol | string | 连接服务端的通信协议 | tcp | tcp, kcp, websocket | |
tls_enable | bool | 启用 TLS 协议加密连接 | false | ||
tls_cert_file | string | TLS 客户端证书文件路径 | |||
tls_key_file | string | TLS 客户端密钥文件路径 | |||
tls_trusted_ca_file | string | TLS CA 证书路径 | |||
tls_server_name | string | TLS Server 名称 | 为空则使用 server_addr | ||
heartbeat_interval | int | 向服务端发送心跳包的间隔时间 | 30 | ||
heartbeat_timeout | int | 和服务端心跳的超时时间 | 90 | ||
udp_packet_size | int | 代理 UDP 服务时支持的最大包长度 | 1500 | 服务端和客户端的值需要一致 | |
start | string | 指定启用部分代理 | 当配置了较多代理,但是只希望启用其中部分时可以通过此参数指定,默认为全部启用 |
权限验证
参数 | 类型 | 说明 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|
authentication_method | string | 鉴权方式 | token | token, oidc | 需要和服务端一致 |
authenticate_heartbeats | bool | 开启心跳消息鉴权 | false | 需要和服务端一致 | |
authenticate_new_work_conns | bool | 开启建立工作连接的鉴权 | false | 需要和服务端一致 | |
token | string | 鉴权使用的 token 值 | 需要和服务端设置一样的值才能鉴权通过 | ||
oidc_client_id | string | oidc_client_id | |||
oidc_client_secret | string | oidc_client_secret | |||
oidc_audience | string | oidc_audience | |||
oidc_token_endpoint_url | string | oidc_token_endpoint_url |
UI
参数 | 类型 | 说明 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|
admin_addr | string | 启用 AdminUI 监听的本地地址 | 0.0.0.0 | ||
admin_port | int | 启用 AdminUI 监听的本地端口 | 0 | ||
admin_user | string | HTTP BasicAuth 用户名 | |||
admin_pwd | string | HTTP BasicAuth 密码 | |||
asserts_dir | string | 静态资源目录 | AdminUI 使用的资源默认打包在二进制文件中,通过指定此参数使用自定义的静态资源 |
代理配置
frp 代理的详细配置说明。
通用配置
通用配置是指不同类型的代理共同使用的一些配置参数。
基础配置
参数 | 类型 | 说明 | 是否必须 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|---|
type | string | 代理类型 | 是 | tcp | tcp, udp, http, https, stcp, sudp, xtcp, tcpmux | |
use_encryption | bool | 是否启用加密功能 | 否 | false | 启用后该代理和服务端之间的通信内容都会被加密传输 | |
use_compression | bool | 是否启用压缩功能 | 否 | false | 启用后该代理和服务端之间的通信内容都会被压缩传输 | |
proxy_protocol_version | string | 启用 proxy protocol 协议的版本 | 否 | v1, v2 | 如果启用,则 frpc 和本地服务建立连接后会发送 proxy protocol 的协议,包含了原请求的 IP 地址和端口等内容 | |
bandwidth_limit | string | 设置单个 proxy 的带宽限流 | 否 | 单位为 MB 或 KB,0 表示不限制,如果启用,会作用于对应的 frpc |
本地服务配置
local_ip
和 plugin
的配置必须配置一个,且只能生效一个,如果配置了 plugin
,则 local_ip
配置无效。
参数 | 类型 | 说明 | 是否必须 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|---|
local_ip | string | 本地服务 IP | 是 | 127.0.0.1 | 需要被代理的本地服务的 IP 地址,可以为所在 frpc 能访问到的任意 IP 地址 | |
local_port | int | 本地服务端口 | 是 | 配合 local_ip | ||
plugin | string | 客户端插件名称 | 否 | 见客户端插件的功能说明 | 用于扩展 frpc 的能力,能够提供一些简单的本地服务,如果配置了 plugin,则 local_ip 和 local_port 无效,两者只能配置一个 | |
plugin_params | map | 客户端插件参数 | 否 | map 结构,key 需要都以 "plugin_" 开头,每一个 plugin 需要的参数也不一样,具体见客户端插件参数中的内容 |
负载均衡和健康检查
参数 | 类型 | 说明 | 是否必须 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|---|
group | string | 负载均衡分组名称 | 否 | 用户请求会以轮询的方式发送给同一个 group 中的代理 | ||
group_key | string | 负载均衡分组密钥 | 否 | 用于对负载均衡分组进行鉴权,group_key 相同的代理才会被加入到同一个分组中 | ||
health_check_type | string | 健康检查类型 | 否 | tcp,http | 配置后启用健康检查功能,tcp 是连接成功则认为服务健康,http 要求接口返回 2xx 的状态码则认为服务健康 | |
health_check_timeout_s | int | 健康检查超时时间(秒) | 否 | 3 | 执行检查任务的超时时间 | |
health_check_max_failed | int | 健康检查连续错误次数 | 否 | 1 | 连续检查错误多少次认为服务不健康 | |
health_check_interval_s | int | 健康检查周期(秒) | 否 | 10 | 每隔多长时间进行一次健康检查 | |
health_check_url | string | 健康检查的 HTTP 接口 | 否 | 如果 health_check_type 类型是 http,则需要配置此参数,指定发送 http 请求的 url,例如 "/health" |
TCP
参数 | 类型 | 说明 | 是否必须 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|---|
remote_port | int | 服务端绑定的端口 | 是 | 用户访问此端口的请求会被转发到 local_ip:local_port |
UDP
参数 | 类型 | 说明 | 是否必须 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|---|
remote_port | int | 服务端绑定的端口 | 是 | 用户访问此端口的请求会被转发到 local_ip:local_port |
HTTP
custom_domains
和 subdomain
必须要配置其中一个,两者可以同时生效。
参数 | 类型 | 说明 | 是否必须 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|---|
custom_domains | []string | 服务器绑定自定义域名 | 是(和 subdomain 两者必须配置一个) | 用户通过 vhost_http_port 访问的 HTTP 请求如果 Host 在 custom_domains 配置的域名中,则会被路由到此代理配置的本地服务 | ||
subdomain | string | 自定义子域名 | 是(和 custom_domains 两者必须配置一个) | 和 custom_domains 作用相同,但是只需要指定子域名前缀,会结合服务端的 subdomain_host 生成最终绑定的域名 | ||
locations | []string | URL 路由配置 | 否 | 采用最大前缀匹配的规则,用户请求匹配响应的 location 配置,则会被路由到此代理 | ||
http_user | string | 用户名 | 否 | 如果配置此参数,暴露出去的 HTTP 服务需要采用 Basic Auth 的鉴权才能访问 | ||
http_pwd | string | 密码 | 否 | 结合 http_user 使用 | ||
host_header_rewrite | string | 替换 Host header | 否 | 替换发送到本地服务 HTTP 请求中的 Host 字段 | ||
headers | map | 替换 header | 否 | map 中的 key 是要替换的 header 的 key,value 是替换后的内容 |
HTTPS
custom_domains
和 subdomain
必须要配置其中一个,两者可以同时生效。
参数 | 类型 | 说明 | 是否必须 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|---|
custom_domains | []string | 服务器绑定自定义域名 | 是(和 subdomain 两者必须配置一个) | 用户通过 vhost_http_port 访问的 HTTP 请求如果 Host 在 custom_domains 配置的域名中,则会被路由到此代理配置的本地服务 | ||
subdomain | string | 自定义子域名 | 是(和 custom_domains 两者必须配置一个) | 和 custom_domains 作用相同,但是只需要指定子域名前缀,会结合服务端的 subdomain_host 生成最终绑定的域名 |
STCP
参数 | 类型 | 说明 | 是否必须 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|---|
role | string | 角色 | 是 | server | server,visitor | server 表示服务端,visitor 表示访问端 |
sk | string | 密钥 | 是 | 服务端和访问端的密钥需要一致,访问端才能访问到服务端 |
SUDP
参数 | 类型 | 说明 | 是否必须 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|---|
role | string | 角色 | 是 | server | server,visitor | server 表示服务端,visitor 表示访问端 |
sk | string | 密钥 | 是 | 服务端和访问端的密钥需要一致,访问端才能访问到服务端 |
XTCP
参数 | 类型 | 说明 | 是否必须 | 默认值 | 可选值 | 备注 |
---|---|---|---|---|---|---|
role | string | 角色 | 是 | server | server,visitor | server 表示服务端,visitor 表示访问端 |
sk | string | 密钥 | 是 | 服务端和访问端的密钥需要一致,访问端才能访问到服务端 |