经确认,如果 IP 来源为 CN,且客户端类型汇报为 libtorrent 这个库而非其他正常客户端的 peer,既有可能是迅雷等下载软件的离线客户端。对于一部分同样表现的海外 IP 暂时未能确认,不确定是否有一些极小众的客户端表现确实如此,对于此问题,在 qBittorrent 增强版未作修改之前,建议采取 ipfilter 的方式屏蔽这些客户端。
IP Filter 来源如下:https://emulefans.com/offline-server-ip-170205/
也可以直接下载
经确认,如果 IP 来源为 CN,且客户端类型汇报为 libtorrent 这个库而非其他正常客户端的 peer,既有可能是迅雷等下载软件的离线客户端。对于一部分同样表现的海外 IP 暂时未能确认,不确定是否有一些极小众的客户端表现确实如此,对于此问题,在 qBittorrent 增强版未作修改之前,建议采取 ipfilter 的方式屏蔽这些客户端。
IP Filter 来源如下:https://emulefans.com/offline-server-ip-170205/
也可以直接下载
重要的事情说三遍。
实际上这次也没做什么理论上很麻烦的事情,就是 clone 一个 qBittorrent 4.0.4.3 的源码,配合 libtorrent 1.0.11 编译一下,理论上不应该有什么问题的对吧。然而就是出问题了……
编译的过程很顺利,安装 Deluge PPA 的 libtorrent-rasterbar-dev 和一些 boost 库之后开始编译,然后到了 linking 的过程就报错了:src/base/bittorrent/private/filterparserthread.cpp:99: reference to `boost::asio::ip::address_v4::address_v4(std::array<unsigned char, 4u> const&)'
按照 GitHub Issue #6721,这个问题可能是因为 std::array
和 boost::array
这两个名称的选择在 libtorrent 和 qbittorrent 里面不同,在没有使用 stdc++11 编译的时候,使用的是 boost::array
,反之使用 std::array
,考虑到 qbittorrent 默认需要 C++ 11,所以 libtorrent 应该使用同样的 CXXFLAGS 编译才能在 linking 的时候不报错。因此既然出现了现在这个问题,就证明 Deluge PPA 的 libtorrent 是没有使用 C++11 编译的。
之前在编译 qb 3.3.16 的时候并没有出现这个错误,可能是 qb3 不要求 C++11 的原因。
那么如果要解决这个问题,就必须从源码开始编译 libtorrent。考虑到 lt1.1.x 至今无法解决 U2 的双栈 IP 汇报问题,因此只能采用 lt1.0。
git clone https://github.com/arvidn/libtorrent.git cd libtorrent git checkout $(git tag | grep libtorrent-1_0_ | sort -t _ -n -k 3 | tail -n 1) ./autotool.sh ./configure --disable-debug --enable-encryption --with-libgeoip=system CXXFLAGS=-std=c++11
在编译完成之后,checkinstall 安装,然后再去编译 qb 就应该可以了。
Boost 版本的选择也有一些讲究,Ubuntu Package 默认的是 1.58 版本的 boost,qb 经过测试,最高只能使用 1.65.1 版本的 boost,如果想要使用新一些的版本,只能自己编译。
我在编译 1.65.1 的时候,遇到了一个以前从来没有的问题,找不要 pyconfig.h,这个文件本应该存在于 /usr/include/python
或者 python2.7 或者 python3.5 的目录下(取决于默认 Python 版本),但是我那个 Python 2 就是没有这个文件,因此将 Python 默认改为 3.5(sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.5 10
)才让 boost 的编译器找到对应的 Python 头文件。如果出现这样的问题需要注意。
使用 echo -e '#include <boost/version.hpp>\nBOOST_VERSION' | gcc -x c++ -E -
这个命令可以查看当前 include 的 boost 版本。
如果安装了 Deluge,然后再切换到 Python3,可能会让 Python 找不到 Deluge 的包,然后无法运行,解决方法是修改 /usr/bin/deluged 和 /usr/bin/deluge-web 的第一行,用 python2.7 运行。或者也可以编译完 boost 以后再把默认 python 改回来。
首先感谢 youlun 大佬介绍了 Syncthing 这个好用的文件同步工具,一次性解决了 Nextcloud 同步残废的问题。
有人可能会问,Nextcloud 不就已经可以搭建私有云平台了吗,为什么还要借助 Syncthing 这样一个同步工具呢?如果文件量不大的话,可能这并不是什么大问题,但是由于 Nextcloud 即使是使用它的客户端,也只能通过网页方式上传,在遇到较大的文件的时候,就会遇到各种各样的限制,比如上传超时或者是文件过大不能上传等等。但是 Syncthing 就不存在这样的问题,可以顺畅地进行文件同步。那么,有没有办法让二者配合工作,即 Syncthing 负责文件同步,Nextcloud 负责网页端的界面和移动端访问的功能呢?答案是有的,而且非常可行,考虑到没有现成的教程,因此在这里记录一下。
WebServer 环境依然使用了 LinuxEye 的 LNMP 一键包,需要注意的问题是 PHP 选择 7.1 版本(Nextcloud 13.0.1 的依赖),以及需要通过 addon.sh 安装 fileinfo 这个 PHP 模块。
在部署完成环境之后,添加一个 nginx vhost,现在最新版的一键包中已经加入了 Nextcloud 的 Rewrite Rule,这个给我们的安装带来了极大的方便,再也不用去折腾那些重写规则了。
然后需要调整一下 Zend OPcache 的设置,不然在下载源码之后无法进入配置。具体步骤为在 /usr/local/php/etc/php.d/ 文件夹中找到 opcache 的 .ini 配置文件,将里面的数值按照如下的错误信息调整:
之后在官网下载 tar.bz2 的安装包,解压之后拷贝进 wwwroot,注意这里需要将所有的文件权限改为 www:www,默认一般是登录的用户,会造成无法访问,之后在 MariaDB 中创建一个数据库,在初始化的时候填进 Nextcloud 中,这一步还是比较方便的。
然后更改一下 Nextcloud 的配置,消除缓存的警告。在 <site root>/config/config.php 中添加如下字段即可:
'memcache.local' => '\OC\Memcache\Redis', 'memcache.locking' => '\OC\Memcache\Redis', 'redis' => array( 'host' => 'localhost', 'port' => 6379, ),
至此 Nextcloud 应该就可以正常使用了。
首先需要安装 Syncthing,官方文档中给出了 Ubuntu .deb 的链接,按照它配置即可。
这时候就会遇到一个问题,Syncthing 需要以 www 用户启动才能在和 Nextcloud 一同工作时避免一些权限的问题,但是 www 用户默认是 nologin 配置的,如何登陆进这个用户完成一些初始的设置是一个比较麻烦的问题。由于 www 用户无法登录,所以不能使用一般的 su <user> 来进行用户切换,以该用户的权限启动一个 bash 又不能完成完整的用户环境切换操作。在搜索之后,以一种比较 Tricky 的方法登录了进去:
su -s /bin/bash www
这条命令的意思是 override www 默认的 shell,再登录,然后就会发现你已经切换到 www 用户下了。运行 syncthing,该做什么做什么。
Syncthing 默认监听 localhost:8384 端口,那么在远端 VPS 上,如何进行配置呢?有两个方案,一个是修改监听端口,让程序监听 0.0.0.0:8384,另外一个是通过 nginx 配置一个反代。显然,第二个方案无论是在安全性,还是便利性(不用在域名后面输入端口号)上都优于第一个,所以我们就采用第二个方案。
Nginx 配置文件的关键部分如下:
server { listen 80; listen 443 ssl http2; if ($ssl_protocol = "") { return 301 https://$host$request_uri; } location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host localhost; proxy_set_header X-NginX-Proxy true; proxy_pass http://localhost:8384; } }
需要注意的一点就是 proxy header 中的 Host 字段必须改为 localhost,否则 Syncthing 发现你的访问地址不是它的监听地址,就会拒绝访问,返回“Host check error“。
之后就是正常的 Syncthing 使用,这个不难,看官方文档就可以了。
一开始我以为,把 Syncthing 的同步文件夹设置为我的 Nextcloud 的数据目录就可以完成同步,实际上 Nextcloud 的文件列表并不是实时的,需要运行 OCC 重新进行扫描,但是这样的扫描并不能保证数据完全无损,而且在使用时也不可能频繁 SSH 上去进行重扫,因此必须采取其他的方法。
关于这个问题,官方给出的答案是 External Storage,在 Nextcloud 中启用 External Storage 这个组件以后,在设置中挂载外部的文件夹,这个可以是本地,也可以是 SFTP/FTP/Amazon S3/WebDAV 等等,在这个情况下,我们选择本地,然后添加对应的文件夹就可以在 Nextcloud 文件列表中看到我们的文件了,无论是网页版还是手机都可以。
在 Ubuntu 上,我们通过 systemd 服务来完成:
[Unit] Description=syncthing After=network-online.target [Service] ExecStart=/usr/bin/syncthing -no-browser -home="/home/www/.config/syncthing" ExecStop=/bin/kill -9 $(/bin/cat /run/syncthing.pid) Restart=always PIDFile=/run/syncthing.pid TimeoutStopSec=300 User=www [Install] WantedBy=multi-user.target
在 Windows 上,我们可以通过这样一个 .bat 完成启动:
start "Syncthing" syncthing.exe -no-console -no-browser
https://docs.syncthing.net/
https://docs.nextcloud.com/server/13/admin_manual/
https://serverfault.com/questions/333321/executing-a-command-as-a-nologin-user
https://www.jianshu.com/p/4235cc85c32d
其实 HWE Kernel 和 Frequency Scaling 是两个东西,只不过频率调节的工具是 Kernel 里面的一个组件,我因为没找到对应的 meta-package 而没有安装上正确的版本,然后发现是 HWE Kernel 和 GA Kernel 的不同版本造成的,所以想着干脆一起写篇东西解释一下这些东西的不同。
首先要说一说的是 HWE Kernel,按照官网的说法,是为了让 LTS 的 Linux 系统能够迅速支持最新的硬件,所以才命名为 HWE (HardWare Enable)。实际在使用过程中,可能也是我经验不足的原因,没碰上什么硬件太新 Kernel 不支持造成的 bug,所以这个名字怎么定义的其实意义不大。
在使用 Ubuntu 的过程中,应该都会遇到这样一种情况,Ubuntu 会帮我们自动更新内核,在 LTS 版本的 Roadmap 中,我们也可以看到不同的 point release 对应了不同的内核版本,比如 16.04.4 LTS 对应的就是 4.13 的内核。但有的时候,我们会发现,明明自己的系统已经是 16.04.4,为什么内核还是 4.4 版本呢?这是因为 HWE kernel 和 4.4 这样长期支持的 GA Kernel 其实是两个 meta-package,GA Kernel 对应的包是 linux-generic,下有 linux-image-generic 和 linux-headers-generic 这两个包,再往下才是具体的内核包。如果想要跟随 point release 更新系统的内核,那么就应该安装对应的 HWE 内核,HWE 内核是和 LTS 版本绑定的,比如 16.04 就需要加上 -hwe-16.04 后缀,那么对应的内核包就是 linux-generic-hwe-16.04,下面的包是 linux-headers-generic-hwe-16.04 和 linux-image-generic-hwe-16.04。使用这个包,就能安装最新的 4.13 内核(LTS 16.04.04)。
除了普通的 HWE 内核之外,还有一个更加激进的更新版本是 Rolling HWE Stacks,将上面的 -hwe-16.04 换成 -hwe-16.04-edge 就可以使用到这个 Stack。在这个 Stack 中可以提前使用 下一个 point release 中使用的 HWE 内核版本,就有点类似于 beta 测试的分支,这个可能会存在一定的稳定性问题,所以是否使用请自行斟酌。
接下来要说一说的是 CPU 频率调节的问题,在 Windows 上很多人应该都使用过的一个功能是电源方案,里面对 CPU 的最大频率、最小频率,散热方式等等可以做出一些自定义设置,Linux 上同样也提供了这样的功能。
在 Arch Wiki 中,对于这个问题有比较详细的介绍,在这里就简单地说一说:Linux 内核有自己的 CPU 调频实现,称为 cpufreq,这个在 3.4 的内核之后,必要的模块都会自行加载,用户也可以通过一些工具实现自己的调节。
CPU 频率的驱动程序随着 CPU 型号的不同会有很多的版本,具体可以查看 Arch Wiki 上面的说明,对于现在使用的 SandyBridge 以后架构的 CPU,通常使用 intel_pstate 来对频率进行调节。可以通过如下命令来查看 pstate 是否已经启用:
$ cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_driver
如果显示的都是 intel_pstate,那么你的 CPU 调节使用的就是 p-state 驱动。
CPU 频率的手动调节通常使用 cpupower 这个工具,可以通过如下的命令安装(需要和内核版本一直,这里使用 HWE Kernel 对应的版本):
$ sudo apt-get install linux-tools-common linux-tools-generic-hwe-16.04
之后运行 $ cpupower frequency-info
就可以看到 CPU 的信息,大概是这样的输出:
$ cpupower frequency-info analyzing CPU 0: driver: intel_pstate CPUs which run at the same hardware frequency: 0 CPUs which need to have their frequency coordinated by software: 0 maximum transition latency: Cannot determine or is not supported. hardware limits: 1.60 GHz - 3.90 GHz available cpufreq governors: performance powersave current policy: frequency should be within 1.60 GHz and 3.90 GHz. The governor "performance" may decide which speed to use within this range. current CPU frequency: Unable to call hardware current CPU frequency: 3.70 GHz (asserted by call to kernel) boost state support: Supported: yes Active: yes 3700 MHz max turbo 4 active cores 3800 MHz max turbo 3 active cores 3900 MHz max turbo 2 active cores 3900 MHz max turbo 1 active cores
可以发现,信息比我们从 Windows 上面获取的要多得多,不仅可以看到当前的频率,还能看到最大睿频的信息。
Scaling Governor 相当于预设的 CPU 电源方案,在文档中有 6 种不同的调速器,但是在实际使用中,通常只有 performance 和 powersave 两种。performance 相当与强制 CPU 运行在最高频率,而 powersave 可以让 CPU 按需自动调节频率。当前在使用的调速器可以通过如下命令查看:
$ cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
通常来说默认配置是 powersave 模式,如果想调整为 performance,可以执行如下的命令:
$ sudo cpupower frequency-set -g performance
之后再进行查看,应该就是 performance 模式了,CPU 也会被固定在最大睿频上。
直接使用 cpupower 修改之后会存在一个问题,重启之后会被修改回 powersave,可以安装 cpufrequtils 将其固定:
$ sudo apt-get install cpufrequtils $ sudo systemctl disable ondemand
一定要将 ondemand 这个服务关闭,这个服务会将 governor 设置为 ondemand 模式,但是通常 CPU 都不支持这个模式,然后就会 fallback 到 powersave。
之后在/etc/default/cpufrequtils
中添加GOVERNOR="performance"
,重启即可。
https://wiki.archlinux.org/index.php/CPU_frequency_scaling_(简体中文)
https://wiki.ubuntu.com/Kernel/LTSEnablementStack
https://wiki.ubuntu.com/Kernel/RollingLTSEnablementStack
http://www.webupd8.org/2014/04/prevent-your-laptop-from-overheating.html
Cisco 的设备配置时一般分为四种模式,分别为:
各模式间切换如下:
User EXEC -> (enable) -> Privileged EXEC -> (configure terminal) -> Global Configuration -> (Specify Interface) -> Interface Configuration
Interface Configuration -> (exit) -> Global Configuration -> (exit / end / Ctrl-Z) -> Privileged EXEC -> (disable) -> User EXEC
Interface Configuration -> (end / Ctrl-Z) -> Privileged EXEC
# configure terminal (config)# vlan <vlan-id> (config)# name <vlan-name> [Optional] (config)# mtu <mtu-size> [Optional] (config)# end # show vlan { name <vlan-name> | id <vlan-id> } # copy running-config startup-config
# configure terminal (config)# interface <interface-id> (config-if)# switchport mode access (config-if)# switchport access vlan <vlan-id> (config-if)# end # show running-config interface <interface-id> # copy running-config startup-config
如果手抖输错了命令,交换机开始进行 DNS 查询,并且一直卡在那里,可以用 Shift + Ctrl + 6 停下来。使用 no ip domain-lookup 可以彻底禁用该功能。
Router#configure terminal Router(config)#interface fastethernet0/0.1 Router(config-if)#encapsulation dot1q 1 Router(config-if)#ip address 10.1.1.128 255.255.0.0 Router(config-if)#no shutdown
该命令创建了 Fa0/0 下的一个 SubInterface Fa0/0.1,配置为属于 VLAN 1,IP 地址为 10.1.1.128/16,将端口状态设置为 up。
Reference:
%token INTEGER
#ifndef YYSTYPE #define YYSTYPE int #endif #define INTEGER 258 extern YYSTYPE yylval;
[0-9]+ { yylval = atoi(yytext); return INTEGER; }
%union { int iValue; /* integer value */ char sIndex; /* symbol table index */ nodeType *nPtr; /* node pointer */ };
则生成的头文件中的内容是:
typedef union { int iValue; /* integer value */ char sIndex; /* symbol table index */ nodeType *nPtr; /* node pointer */ } YYSTYPE; extern YYSTYPE yylval;
可以把标志(token)绑定到 YYSTYPE 的某个域。如:
%token INTEGER %% program: program expr '\n' { printf("%d\n", $2); } ; expr: INTEGER { $$ = $1; } | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } ; %% int yyerror(char *s) { fprintf(stderr, "%s\n", s); return 0; }
其中,$1 表示右边的第一个标记的值,$2 表示右边的第二个标记的值,依次类推。$$ 表示规约后的值。
main 函数是调用 yacc 解析入口函数 yyparse()。如:
int main(void) { yyparse(); return 0; }
递归的处理
//L文件: %{ #include "FIRST_TA.H" #include <stdio.h> #include <stdlib.h> %} %% a {return A_STATE;} b {return B_STATE;} c {return C_STATE;} not {return NOT;} %% //Y文件: %{ #include <stdio.h> #include <stdlib.h> %} %token A_STATE B_STATE C_STATE NOT %% program : A_STATE B_STATE { int c, d; c = 20; d = 25; } c_state_not { int e,f; e = 30; f = 35; } | A_STATE B_STATE { int a, b; a = 10; b = 15; } c_state_not : C_STATE NOT{} %% 输入文件的字符:a, b, c, f, c, not
碰上垃圾 VPS 提供商怎么办,商家说是亚洲优化,到本地还是绕 GTT 怎么办?不用担心,KCPTun 来帮你。
说来,网上那堆教程实在是写得不怎么好,要么太复杂,我就想加速一下网络连接,写那么多原理干什么……要么就是太简单,我真的不喜欢一键包。所以还是自己来吧。
KCP 简单来说,就是一个 UDP 暴力发包软件,如果原先建立的连接是这样
Client -> (TCP) -> Server
那么加入 KCP 以后就变成了这样
Client -> (TCP) -> KCP Client -> (UDP) -> KCP Server -> (TCP) -> Server
KCP 无论是客户端,还是服务端,都涉及到两个端口,在客户端有一个 listening port 和 remote,服务端有 一个 listening port 和一个 target。从连接的角度来说,是这样的一个流程:
Client -> KClient_Listening_Port -> KClient -> KRemote
KRemote = KServer_Listening_Port -> KServer -> KTarget = Server
原先 C->S 怎么连接,只要把地址改成对应的 KCP 端地址就可以无缝工作。
举个例子来说,比如我本地有个程序需要连接 Server:8388,原先直接连接就可以了,但是特别慢,打算用 KCP 来加速一下,且 KServer 监听 3389 端口。那么本地需要做的事情是:
"client_windows_amd64.exe" -l :1081 -r Server:3389 -key "test" -crypt none -mode fast2
这个的意思是说,KClient 监听 1081 端口并转发至 Server 的 3389 端口,密码是 test,没有加密,使用的模式是 fast2。
服务端要做的事情是:
server_linux_amd64 -l :3389 -t 127.0.0.1:8388 --key test --crypt none --mode fast2 --quiet
监听 3389 端口的传入连接,转发至本地的 8388 端口,也就是原来的服务端,其他和 Client 的配置相同。
这么简单就配置好了。
项目的 Github 在这里:https://github.com/xtaci/kcptun
这是一个图形化的 Windows 客户端:https://github.com/dfdragon/kcptun_gclient
Git 是一个很好用的工具,相信不用我说大家也承认。以下记录一些会用到的命令行:
首先是这个反复弹出 Tracker Authentication 窗口的问题,这个是因为 Tracker 对未授权的种子返回了 HTTP/401 错误,导致 qb 弹出窗口要求验证。这是一个正常行为,如果不需要它:
qBittorrent/src/base/bittorrent/torrenthandle.cpp
文件的 void TorrentHandle::handleTrackerErrorAlert(libtorrent::tracker_error_alert *p)
函数中注释掉关于 401 错误的两行即可。然后就是在 qb 中有大量种子的情况下,同时开始会导致 Tracker 始终处于 “Not Working” 状态,如果一个一个启动,那么就是好的,这个应该是qb本身并发设计不良导致的问题。
AWS p2 实例虽然方便,不用本地买显卡,但是碰到比较大的网络,p2 开一天就得 50 块钱,还是有点肉疼的。那么,既然付了钱,就把实例的性能发挥到极致吧。
Tesla K80 显卡通常工作在 AutoBoost 模式,这个模式会动态调整显卡的频率,在很多情况下都比最大频率要低,并且显卡驱动默认的功率限制并没有被开到最大,因此这两点都会影响我们最终获得的性能。
设置显卡工作频率比较简单:
sudo nvidia-persistenced sudo nvidia-smi --auto-boost-default=0 sudo nvidia-smi -ac 2505,875 #(2505,875) for p2; (877,1530) for p3; (2505,1177) for g3
关于功率的调整,首先我们要查看显卡的最大功率限制 nvidia-smi -q | grep 'Power Limit'
,如果是 p2 实例,发现这个值是 175W,而驱动默认的限制是 149W,我们需要提高这个限制,使用 nvidia-smi -pl 175
即可,如果权限不足,用 sudo 运行。
参考资料:
https://www.ibm.com/support/knowledgecenter/en/SSFHY8_5.5.0/com.ibm.cluster.essl.v5r5.essl100.doc/am5gr_nvidcap.htm
https://devblogs.nvidia.com/increase-performance-gpu-boost-k80-autoboost/
https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/optimize_gpu.html