CentOS7自建Anki同步服务器(python3)
Table of Contents
什么是Anki
Anki是一个帮助记忆的Flash Card(教学卡片)软件,比如正面是英语单词,背面显示意思,然后让你选择,你觉得这个单词是容易、困难、或者完全不会,根据你选择的难易程度,这个单词会在接下来的不同时间出现,比如你点的困难,它可能1分钟后又出现了,如果你选的简单,它可能几天后才显示,而具体要几天后才出现这个是可以自己设置的。
Anki是开源的软件,使用python编写,在Windows、Mac、Linux三大平台通用,iOS和Android也有对应的软件,另外还有Web版,除了iOS版之外的所有版本都是免费的。
iOS版收费,是因为电脑版和iOS版都是同一个作者,他是全职做这个的,所以必须要有收入,好像是162还是163块RMB来着,安卓版免费是因为安卓版是另一个业余团队做的,所以安卓版可以自定义同步服务器而iOS版不可以。
Anki官网:https://apps.ankiweb.net
可以看看这些介绍的文章:https://zhuanlan.zhihu.com/-anki
自建AnkiServer原因
默认的Anki服务器同步很慢,而且据说这是个人项目,数据在别人手里也不可靠,说不定哪天丢了也有可能,所以我们自己搭建自己的服务器。但有个缺点就是iOS版的Anki不支持自定义服务器,因为iOS版是官方出品,
AnkiServer github
Anki和anki-sync-server都是python写的,这是python3版本的:anki-sync-server,由于python2版本的AnkiServer已经没有人维护,所以我们最好使用python3版本的。
安装epel
如果你不确定是否安装过epel,运行以下命令安装(如果已经安装它会自动识别,不会重复安装的):
yum -y install epel-release
安装python3
执行以下命令,搜索python3版本:
yum search python3
搜索结果可能有python34-xxxx
,python36-xxxx
等等,这个34,36表示3.4,3.6版本,安装其中最新的版本(当前2019.03.13,最新是python36),所以我们安装python36:
yum -y install python36
如果以后有37甚至38,安装的时候把36改成37或38即可。
安装后执行以下命令以确认是否安装成功(如果正常,则会出现Python 3.6.x
的版本版本,同理,如果你以后有新版本python37,那么出来的就应该是Python 3.7.x
):
python36 -V
安装pip3
从python官网下载get-pip.py
(这个只是暂时使用的,可以下载到任何地方,使用完就可以删除):
wget https://bootstrap.pypa.io/get-pip.py
使用python36运行get-pip.py
,以安装python36对应的pip3(注意此时要在get-pip.py
所在的目录下执行以下命令):
python36 get-pip.py
安装完成后,python36的pip应该会被安装到以下路径:
/usr/local/bin/pip
为了与python2.7的pip区分,我们把它修改一下名字:
mv /usr/local/bin/pip /usr/local/bin/pip3
运行pip3 -V
试试,如果是指向python3.6的路径,说明一切正常。
然后就可以删除get-pip.py
文件了:
rm get-pip.py
使用pip3
安装webob
依赖:
pip3 install webob
安装AnkiServer
由于AnkiServer是用python语言写的,python是脚本语言,所以,所谓的安装,就是把代码clone到本地,你想放在哪里都无所谓,我是放在/usr/local/anki-sync-server
下,你也可以放在~/anki-sync-server
下:
git clone https://github.com/tsudoko/anki-sync-server.git /usr/local/anki-sync-server
安装Anki
注意,AnkiServer是AnkiServer,Anki是Anki,这不是同一个东西,AnkiServer依赖于Anki,所以下载AnkiServer后,还必须下载Anki,Anki下载后要放在anki-sync-server
目录下的一个叫anki-bundled
的目录里。
那Anki从哪里下呢?
方法一:因为Anki本身也是python写的,它也是开源的,它的github地址是:https://github.com/dae/anki, 所以你可以从这个地址里clone到anki-bundled
里。
方法二:直接下载anki-sync-server
项目下的anki-bundled @ cca3fcb
,它其实本身就是Anki
的github源码链接,只不过这个链接不是Anki
的主分支,而是anki-sync-server
作者测试过的可用的稳定分支,所以我们就使用这种方法下载,不要用方法一。
疑问
问:有人可能会觉得奇怪,为什么我clone完anki-sync-server
后,anki-bundled
是空的?为什么它里面的内容不会下载下来?
答:因为它是一个链接,属于另一个版本库,你可以点它试试,它已经跳转到anki项目里了
进入anki-sync-server
目录,注意你自己下载的目录也许跟我的不同:
cd /usr/local/anki-sync-server
运行以下命令,用于下载git子模块代码(即Anki的代码,这一步执行完,就安装了Anki
了):
git submodule update --init
进入以下目录,你会发现已经不是空的了:
cd anki-bundled
删除“requirements.txt”文件中的“pyaudio”:
先用以下命令打开文件,然后用方向选把光标指向pyaudio
那一行,然后按dd
即可删除,最后输入:x
然后回车(注意,都要英文输入法下操作):
vim requirements.txt
执行以下语句,用于安装Anki的依赖:
pip3 install -r requirements.txt
vim编辑ankisyncctl.py
文件,它的第一行默认是:
#!/usr/bin/env python
把它改成:
#!/usr/bin/env python36
表示用python36
运行ankisyncctl.py
脚本。
这样就算安装调试完了,运行以下命令查看使用方法:
./ankisyncctl.py usage
如果正常,出来的结果应该是这样的:
usage: /usr/local/bin/ankisyncctl <command> [<args>]
Commands:
adduser <username> - add a new user
deluser <username> - delete a user
lsuser - list users
passwd <username> - change password of a user
到这里,AnkiServer就安装完毕了。
使用ankisyncctl.py(主要是管理账号)
添加一个用户名为“zhangsan”的用户(它会让你输入密码):
./ankisyncctl.py adduser zhangsan
查看已添加的用户列表:
./ankisyncctl.py lsuser
修改用户名为“zhangsan”的用户的密码:
./ankisyncctl.py passwd zhangsan
删除用户名为“zhangsan”的用户:
./ankisyncctl.py deluser zhangsan
因为没有修改用户名功能,如果你要修改用户名,那么你要先删除,再重新添加。
启动anki-sync-server
执行以下命令启动anki-sync-server
,它的服务名称叫ankisyncd
,注意,以下命令必须在anki-sync-server
文件夹下执行,因为它要找该文件夹下的ankisyncd
文件夹的:
python36 -m ankisyncd &
如果启动正常,它应该会有类似以下的提示:
[2019-03-14 06:28:17,456]:INFO:ankisyncd:Loaded config from /usr/local/anki-sync-server/ankisyncd.conf
[2019-03-14 06:28:17,461]:INFO:ankisyncd:Serving HTTP on 0.0.0.0 port 27701...
查看是否正常启动:
ps -ef | grep ankisyncd
如果你看到有类似以下的结果,说明运行正常:
root 5838 3130 0 06:28 pts/0 00:00:00 python36 -m ankisyncd
注意:一般情况下,在启动命令后加&
表示在后台启动,但是,在这里不行,目前我也不知道原因,如果你想后台启动,有两种方法,一种是使用nohup
(注意该命令还是必须在anki-sync-server
文件夹下执行):
nohup python36 -m ankisyncd >> /var/log/ankisyncd.log 2>&1 &
注意,即便是用nohup
,也不能直接关闭窗口,而是用exit
命令来退出窗口,你需要执行两次exit命令才能退出窗口。
然后把它加入开启启动:
echo "nohup python36 -m ankisyncd >> /var/log/ankisyncd.log 2>&1" >> /etc/rc.d/rc.local
第二种后台运行的方法就是使用supervisor,注意,如果你用了“nohup”这种方法,下边的“使用supervisor管理进程”就不用看了,两种方法选一种。
关闭防火墙
为了避免端口不开放导致的问题,使用以下命令关闭防火墙:
systemctl stop firewalld
systemctl disabled firewalld
当然如果你懂防火墙怎么用,你也可以开放27701
端口。
检测自建AnkiServer是否能正常访问
假设你的服务器ip是12.34.56.78
,那么你在浏览器访问http://12.34.56.78:27701
,会显示Anki Sync Server
,那就说明是正常的,如果打不开,那就有问题。
电脑端设置
以下配置在mac和win测试通过(版本为2.1.11),由于我没有Linux桌面版Linux系统,所以未在Linux上测试,不过原理都是一样的。
注意:由于我本地都是安装的英文版的,所以下面我说的点击哪个菜单我都是用英文的,如果你安装的中文版,请自行对应,相信这几个英文难不倒你。
打开Anki,点击顶部菜单栏的Tools
→Add-ons
会打开插件窗口,然后再点击插件窗口的View files
按钮,会打开插件安装目录。在该目录下新建一个文件夹ankisyncd
,然后在里面新建一个文件,命名为__init__.py
,打开__init__.py
,把以下命令粘贴进去,然后把其中的12.34.56.78
修改成你服务器的ip,如果你修改过ankisyncd.conf
里的“port”(即端口),这里的端口也要与ankisyncd.conf
中的“port”对应,然后保存:
import anki.sync, anki.hooks, aqt
addr = "http://12.34.56.78:27701/" # put your server address here
anki.sync.SYNC_BASE = "%s" + addr
def resetHostNum():
aqt.mw.pm.profile['hostNum'] = None
anki.hooks.addHook("profileLoaded", resetHostNum)
最后重启anki,即把anki软件关掉,再重新打开。
点击Sync
(即“同步”)测试,如果正常,它会提示你输入账号密码,这个账号密码就是你前边用./ankisyncctl.py adduser
添加的账号和密码了。
安卓端
点击左上角三道杠→点击设置
→点击高级设置
→点击自定义同步服务器
→勾选使用自定义同步服务器
,然后下边有同步地址
和媒体文件同步地址
:
同步地址:填http://12.34.45.78:27701
(把ip改成你的服务器ip)
媒体文件同步地址:填http://12.34.45.78:27701/msync
(改成你的服务器ip),即媒体文件同步地址是在同步地址后面添加/msync
(其实这个名字是在服务器的配置文件ankisyncd.conf
中的base_media_url
选项指定的)。
设置好之后,点击同步按钮,正常的话会让你输入账号密码,输入与电脑端相同的账号密码,即可进行同步。
iOS端
App不支持,无解,换手机吧😄
使用supervisor管理进程
supervisor是一个进程管理软件,启动后可以通过网页来查看进程状态并管理进程,如果你已经使用前面的nohup
方式启动ankisyncd
,那么这一步就不用做了,否则就要做这一步, 管是nohup还是supervisor,都是为了使ankisyncd
能在后台运行。
安装supervisor:
yum -y install supervisor
编写配置文件:
vim /etc/supervisord.d/ankisyncd.ini
按i
切换到输入状态,把以下内容粘贴进去,输入:x
保存:
[program:ankisyncd]
command=/bin/python36 -m ankisyncd ; the program (relative uses PATH, can take args)
;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
;numprocs=1 ; number of processes copies to start (def 1)
directory=/usr/local/anki-sync-server/ ; directory to cwd to before exec (def no cwd)
;umask=022 ; umask for process (default None)
;priority=999 ; the relative start priority (default 999)
autostart=true ; start at supervisord start (default: true)
autorestart=true ; retstart at unexpected quit (default: true)
startsecs=3 ; number of secs prog must stay running (def. 1)
;startretries=3 ; max # of serial start failures (default 3)
;exitcodes=0,2 ; 'expected' exit codes for process (default 0,2)
;stopsignal=QUIT ; signal used to kill process (default TERM)
;stopwaitsecs=10 ; max num secs to wait b4 SIGKILL (default 10)
;user=chrism ; setuid to this UNIX account to run the program
;redirect_stderr=true ; redirect proc stderr to stdout (default false)
stdout_logfile=/var/log/ankisyncd.log ; stdout log path, NONE for none; default AUTO
;stdout_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
;stdout_logfile_backups=10 ; # of stdout logfile backups (default 10)
;stdout_capture_maxbytes=1MB ; number of bytes in 'capturemode' (default 0)
;stdout_events_enabled=false ; emit events on stdout writes (default false)
stderr_logfile=/var/log/ankisyncd.error.log ; stderr log path, NONE for none; default AUTO
;stderr_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
;stderr_logfile_backups=10 ; # of stderr logfile backups (default 10)
;stderr_capture_maxbytes=1MB ; number of bytes in 'capturemode' (default 0)
;stderr_events_enabled=false ; emit events on stderr writes (default false)
;environment=A=1,B=2 ; process environment additions (def no adds)
;serverurl=AUTO ; override serverurl computation (childutils)
用以下命令打开supervisord的配置文件:
vim /etc/supervisord.conf
找到[inet_http_server]
,把它下面的三个参数修改成以下的样子,其中username和password修改成你自己想要的用户名和密码(注意:这个用户名密码与ankiserver的用户名密码无关,这个是supervisord这个软件的网页版的登录密码):
[inet_http_server]
port=*:9001
username=zhangsan
password=192837465
启动supervisord:
/usr/bin/supervisord -c /etc/supervisord.conf
把supervisord加入开机自启动:
vim /etc/rc.local
然后把下面这句添加进去:
/usr/bin/supervisord -c /etc/supervisord.conf
浏览器里输入:http://12.34.56.78:9001(ip要修改成你服务器的ip), 输入上边设置的账号和密码即可从页面中访问查看你的anki同步服务进程ankisyncd
:
如果想更多的了解supervisor,请查看:使用supervisor管理进程。
在安卓客户端上显示:网络错误
java.net.UnknownServiceException:
CLEARTEXT communication to
39.103.168.202 not permitted by
network security policy
怎么办,说是https的问题
安卓新版本(安卓10)不能用http传输
那就得配置https了,不过我目前没用这个了,所以没去研究,我博客里有关于https的文章,你可以自己研究一下,或者等我什么时候有空再研究下
[…] 本文转载自Ming的《搭建Anki同步服务器遇到的问题》,并结合Bruce’s Blog的《CentOS7自建Anki同步服务器(python3)》对不完善或有误的地方做出补充或修改。特此感谢原作者。 […]
最后一步,重新打开Anki没提示我输入之前adduser的账户,还是用的Anki的官方账户同步数据怎么回事
可能现在已经更新版本,我当时这么做是完全没问题的,有时间我再走一遍,把不通的地方搞通吧,毕竟我不是一直在用这个,主要因为不是用安卓机,没法自定义服务器,所以当时搭建后就没怎么用它了。
您好,我完全按照您的说明,可到最好Anki还是无法连接
Traceback (most recent call last):
File “aqt\sync.py”, line 376, in _sync
File “aqt\sync.py”, line 356, in _abortingSync
File “anki\sync.py”, line 44, in sync
File “anki\sync.py”, line 592, in meta
File “anki\sync.py”, line 556, in req
File “anki\sync.py”, line 441, in post
File “lib\site-packages\requests\sessions.py”, line 572, in post
File “lib\site-packages\requests\sessions.py”, line 524, in request
File “lib\site-packages\requests\sessions.py”, line 631, in send
File “lib\site-packages\requests\sessions.py”, line 722, in get_adapter
requests.exceptions.InvalidSchema: No connection adapters were found for ‘2http://
遇到同样的问题,但是重新打开Anki尝试同步了几次,就好了,同步成功
自己排查一下吧,我也只是当时搭建了一下,我自己不是安卓机,所以一直没用它
我在有的网站上看到:
在 Windows电脑端的插件里面,需要增加一句:
anki.sync.SYNC_MEDIA_BASE = ‘http://www.tianyunperfect.tk:27701/msync/’
貌似是用于媒体库的管理。
您这个是否也需要增加这一句
不过,您的写法与上面不同,
addr = “http://12.34.56.78:27701/” # put your server address here
anki.sync.SYNC_BASE = “%s” + addr
这里有一个 ”%s”,不知道是什么作用
%s应该是import anki.sync, anki.hooks, aqt 这些某一个里面的变量,我也不知道,我也是网上找的,不是自己写的。你都试试,哪个行用哪个。
网上搜索了一大批关于自建ANKI服务器文件,只有这一篇是成功,非常感谢。
请问:删除“requirements.txt”文件中的“pyaudio”是什么原因?
这个自建服务器只是媒体文件的上传吧?
requirements.txt里写的是anki-server需要的python库依赖,删除pyaudio貌似是用不到这个依赖,我现在已经不太记得当初为什么要删除了
因为云端服务器默认没有安装audio依赖,所以安装会报错,可以通过yum install portaudio-devel来解决这个报错,就不需要把pyaudio给删掉了
哦哦,好的
多谢博主! 这里记录一下我遇到的问题,以供参考。我的版本安装python后,发现运行命令不是python36,而是python3(还有一个python3.6),所以将文中的python36全换成了python3.
我使用了supervisor方法。由于配置中的python36未改成python3,导致错误。更新新的supervisor配置的命令是supervisorctl update,再重新启动所用程序supervisorctl reload。我在编辑/etc/supervisord.d/ankisyncd.ini文件时,复制黏贴后莫名的行首添加了“;”(“;”表示注释),需要按文中重新修改一下。
1、我文章中的命令一直都是
python36
呀。2、你粘贴会自动有分号,那是因为前面行有分号,它会自动添加,如果你不想它添加,vim先用
:set paste
进入粘贴模式,就不会有了,粘贴完,保存后,再用:set nopaste
设置回去。python命令的问题可能是由于centos版本或python版本不同的问题。
vim我不太会,受教了。
谢谢博主,终于OK了,完美解决
不客气,可惜iOS版不支持自定义服务器,安卓还好。
完美解决我的问题
很高兴能帮到你!
谢谢博主,成功在小鸡上搭建anki服务,而且PC端anki 2.1.11也能同步使用了,ankidroid也ok
很高兴能帮到你!