CentOS7自建Anki同步服务器(python3)

CentOS7自建Anki同步服务器(python3)

什么是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-xxxxpython36-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,点击顶部菜单栏的ToolsAdd-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
Xnip2019-03-15_02-48-41.jpg

如果想更多的了解supervisor,请查看:使用supervisor管理进程

打赏

13
Leave a Reply

avatar
6 Comment threads
7 Thread replies
5 Followers
 
Most reacted comment
Hottest comment thread
6 Comment authors
xiebruceheartingrassilovlowphyiambossMasami Nagasawa Recent comment authors

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  Subscribe  
Notify of
heartingrass
Guest
heartingrass

我在有的网站上看到:
在 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”,不知道是什么作用

heartingrass
Guest
heartingrass

网上搜索了一大批关于自建ANKI服务器文件,只有这一篇是成功,非常感谢。
请问:删除“requirements.txt”文件中的“pyaudio”是什么原因?
这个自建服务器只是媒体文件的上传吧?

ilovlowphy
Guest
ilovlowphy

多谢博主! 这里记录一下我遇到的问题,以供参考。我的版本安装python后,发现运行命令不是python36,而是python3(还有一个python3.6),所以将文中的python36全换成了python3.
我使用了supervisor方法。由于配置中的python36未改成python3,导致错误。更新新的supervisor配置的命令是supervisorctl update,再重新启动所用程序supervisorctl reload。我在编辑/etc/supervisord.d/ankisyncd.ini文件时,复制黏贴后莫名的行首添加了“;”(“;”表示注释),需要按文中重新修改一下。

iamboss
Guest
iamboss

谢谢博主,终于OK了,完美解决

Masami Nagasawa
Guest
Masami Nagasawa

完美解决我的问题

gakki
Guest
gakki

谢谢博主,成功在小鸡上搭建anki服务,而且PC端anki 2.1.11也能同步使用了,ankidroid也ok

扫码在手机查看
iPhone请用自带相机扫
安卓用UC/QQ浏览器扫

CentOS7自建Anki同步服务器(python3)