更换omnifocus webdav同步服务器的悲催经历

背景:最近自己的omnifocus软件同步总有连接问题,查了下说明,发现omnifocus同步服务器可以被替换成其它支持webdav功能的服务器。看了看国内的webdav的服务,发现都要花钱。我这个人穷不拉几的不想再多一个续费项了。无巧不巧的我手头正好有个阿里云的CentOS系统。上面就跑着个GitLab用来给我存点无关紧要的东西。所以我决定试试自己搞一个webdav试试……嗯,这就是一切噩梦源头的开始……

编译webdav功能的nginx

在http服务上,我选择了nginx,没有去选用apache,主要是由于我以前在系统上部署过nginx。nginx想要支持webdav功能,需要在编译时添加扩展dav插件。所以需要自己下载nginx源码和dav组件源码再一起编译一个混血版。

名称 版本 下载链接
nginx 1.20.1 https://nginx.org/en/download.html
nginx-dav-ext-module N/A https://gitee.com/mirrors/nginx-dav-ext-module?_from=gitee_search
https://github.com/arut/nginx-dav-ext-module
  • 提供了两个nginx-dav-ext-module的下载链接,github我死活下载不下来,幸好Gitee找到了镜像版本,没有让我的想法死在greatwall下,赞Gitee
  • nginx也要注意一下版本,我之前是用的1.12.2版本(我过去部署在服务器上的版本,本来想犯个懒不下nginx的源码了,可编译总是失败。浪费了4根烟后,查了下dav插件的说明,才知道最低支持版本要>=1.13.4,我这运气真好……

两部分代码下载下来,nginx我下下来的是.tar.gz结尾的压缩格式,需要先解压

[root@AliS _Soft]# tar zxvf nginx-1.20.1.tar.gz
[root@AliS _Soft]# ls -ld nginx*
-rw-r--r-- 1 root      root  981687 Jan  5  2018 nginx-1.12.2.tar.gz
drwxr-xr-x 9 sftpusers www     4096 Jul 10 10:43 nginx-1.20.1
-rw-r--r-- 1 root      root 1061461 May 25 23:34 nginx-1.20.1.tar.gz
drwxr-xr-x 3 root      root    4096 Jul  9 21:03 nginx-dav-ext-module

请忽略掉那个无知的nginx-1.12.2的文件……

由于我编译的nginx除了支持webdav,还需要支持我系统上原来的gitlab。gitlab在安装的时候自带一个内嵌的nginx,需要用我新编译的私有nginx替换掉,所以先查看一下gitlab内嵌的nginx带的参数

[root@AliS _Soft]# /opt/gitlab/embedded/sbin/nginx -V
nginx version: nginx/1.12.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC)
built with OpenSSL 1.0.2l  25 May 2017
TLS SNI support enabled
configure arguments: --prefix=/opt/gitlab/embedded --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_v2_module --with-http_realip_module --with-ipv6 --with-debug --with-ld-opt=-L/opt/gitlab/embedded/lib --with-cc-opt='-L/opt/gitlab/embedded/lib -I/opt/gitlab/embedded/include'

打开一个自己必须喜欢的文本文档工具,我用的VSCode,眉飞色舞的写下一个编译用的config。其实就是写个头儿和加个dav的参数,中间的参数大部分都是拷贝的gitlab里面的configure arguments的段……

./configure \
--prefix=/usr/local/nginx-1.20.1 \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-http_v2_module \
--with-http_realip_module \
--with-debug \
--with-ld-opt='-L /opt/gitlab/embedded/lib' \
--with-cc-opt='-L /opt/gitlab/embedded/lib -I /opt/gitlab/embedded/include' \
--with-http_dav_module --add-module='/root/_Soft/nginx-dav-ext-module/nginx-dav-ext-module'
参数 说明
–prefix 指定编译后的nginx目录。我指定了一个和gitlab的nginx不同的目录,这样万一玩砸了,至少我还有机会用老的nginx把我的gitlab服务拉起来,不会死的很惨。
–with-* 都是一些nginx的模块,为了同时支持gitlab,我就原封不动的C/P了它的参数。 一定要把 --with-http_dav_module --add-module=’/root/_Soft/nginx-dav-ext-module/nginx-dav-ext-module’加进来,这个路径就是下的那个模块的存放路径 还有别问我为啥有两级nginx-dav-ext-module,git同步的,结果忘记它自己很聪明会自己建目录,搞技术太难了……
–add-module 指定外部插件源代码的目录
\ 这东西是一行写不下用来换行用的

之后就是进入到nginx源码目录去运行编译了。注意是nginx的源码目录,别进城nginx-dav的插件目录了

[root@AliS _Soft]# cd nginx-1.20.1
[root@AliS nginx-1.20.1]# ls
CHANGES  CHANGES.ru  LICENSE  Makefile  README  auto  conf  configure  contrib  html  man  objs  src

先配置一下要编译的内容,从你喜欢的文本工具中复制刚才已经写好的命令

[root@AliS nginx-1.20.1]# ./configure \
> --prefix=/usr/local/nginx-1.20.1 \
> --with-http_ssl_module \
> --with-http_stub_status_module \
> --with-http_gzip_static_module \
> --with-http_v2_module \
> --with-http_realip_module \
> --with-debug \
> --with-ld-opt='-L /opt/gitlab/embedded/lib' \
> --with-cc-opt='-L /opt/gitlab/embedded/lib -I /opt/gitlab/embedded/include' \
> --with-http_dav_module --add-module='/root/_Soft/nginx-dav-ext-module/nginx-dav-ext-module'

回车自己去敲吧,反正最后提示成功就是成功了。提示别的就是写错了……

之后就是编译了

[root@AliS nginx-1.20.1]# make & make install

后面就是等着编译log去刷屏了,刷完了就好了,不用搭理它。我说个小插曲轻松一下。

在我四处百度编译命令的时候,打开的第一个文章(利用Nginx WebDAV搭建自己的网盘),里面的编译命令是这么写的

# make -j8

我心说哥们你make就make吧,怎么还骂人呢!后来一查才知道,-j 是指定用多少个CPU core并行编译,可以增加编译速度的。丢人~

后来我还特意试了试用不同核数去编译,其实一个nginx用一个核也编译不了多会儿的,j8不j8的问题都不大嘿……

看完那段差不多编译也就结束了,一个属于自己的nginx应该已经静静的躺在你编译配置指定的目录里了(我的在/usr/local/nginx-1.20.1)

[root@AliS local]# ln -s nginx-1.20.1 nginx
[root@AliS local]# ls -ld nginx*
lrwxrwxrwx  1 root root   12 Jul 10 10:46 nginx -> nginx-1.20.1
drwxr-xr-x 11 root root 4096 Sep 29  2018 nginx-1.12.2
drwxr-xr-x 12 root root 4096 Jul 11 21:33 nginx-1.20.1
[root@AliS local]# pwd
/usr/local
[root@AliS local]#

为了图方便,我做了个nginx的软连接仍在相同的目录了,这样玩砸了回滚会简单点,只切换个软连接指向就好了,省的把目录内外搞得乌烟瘴气的

用当前的私有nginx替换gitlab的内嵌nginx

其实没有gitlab影响可以跳过这一章的,都去抽根烟吃个果盘儿歇会儿吧~

文件 说明
/etc/gitlab/gitlab.rb gitlab配置文件
/var/opt/gitlab/nginx/conf/ gitlab内嵌nginx配置文件目录
/usr/local/nginx/conf 私有nginx配置文件目录
/usr/local/nginx/conf/vhosts 私有nginx vhosts配置目录
端口 端口定义
8091 私有nginx提供的gitlab对外访问端口
8891 私有nginx提供的gitlab_workhorse内部访问端口

其实这步说难不难,主要是不要马虎大意。用vi或者喜欢的编辑器打开配置文件一顿脑残编辑就好了

另外,想着先拷贝一份当前的配置文件到别的目录做个备份,备份别放在/etc目录下就行。

先搞一下/etc/gitlab/gitlab.rb,这个是gitlab的配置文件,下面中的#是文件注释,我习惯于拷贝出来一行原参数再取消注释进行修改。

# external_url 'http://gitlab.example.com'
external_url 'http://50.50.50.50:8091' #改成自己gitlab的真实访问的地址就行# nginx['enable'] = true
nginx['enable'] = false #关闭gitlab内置的nginx功能# gitlab_workhorse['listen_network'] = "unix"
gitlab_workhorse['listen_network'] = "tcp" #更改workhorse的传输方式从socket到TCP# gitlab_workhorse['listen_addr'] = "/var/opt/gitlab/gitlab-workhorse/socket"
gitlab_workhorse['listen_addr'] = "127.0.0.1:8891" #我设置了8891端口,其实找个别的没用的端口就行# gitlab_rails['trusted_proxies'] = []
gitlab_rails['trusted_proxies'] = ['50.50.50.50'] #把gitlab的对外地址加到rail的信任列表里# web_server['external_users'] = []
web_server['external_users'] = ['root', 'nobody'] #我一劳永逸的都加进去了

编辑完gitlab.rb文件,还需要把gitlab原先内嵌的nginx提供的服务添加到自己私有的nginx里面

[root@AliS ~]# cd /var/opt/gitlab/nginx/conf/
[root@AliS conf]# ls
gitlab-http.conf  nginx-status.conf  nginx.conf

上面是我的gitlab内嵌nginx放配置的地方,nginx.conf是主配置文件,其他两个都在nginx.conf中被引用了,所以本着能懒就懒的原则,我决定回头把nginx.conf的内容合并到我的私有nginx配置里就好,引用的那两个文件就还放在这里不动了。

传说中nginx可以使用vhosts功能分离配置文件,为了简便,我直接把gitlab的内容拷贝成一个vhosts配置文件,依旧防止我手残的把主配置文件修改的乱七八糟

先在私有的nginx conf目录建一个vhosts的文件夹

[root@AliS conf]# pwd
/usr/local/nginx/conf
[root@AliS conf]# mkdir vhosts

然后在conf目录修改nginx.conf文件,添加要引用vhosts目录的文件

user    root gitlab-www;...http {...include vhosts/*.conf;
}

修改ngnix.conf的时候,要看一下开头的user定义,是用的哪个用户来假装运行nginx的,这个用户要包含在gitlab.rb的下列配置中(我是用的root啦)

web_server[‘external_users’] = [‘root’, ‘nobody’]

之后我就是在vhosts目录新建了一个gitlab.conf,再大刀阔斧的把gitlab里面的nginx配置拷贝了过来。拷贝过来后要注意两点

  • 有些配置参数已经在nginx.conf定义过了,需要在gitlab中注释掉,防止重复定义
  • 因为刚刚在gitlab.rb中把gitlab_workhorse给定义成TCP的形式了,所以要给这个workhorse建立一个虚拟server去提供http服务,让workhorse的数据可以流转
server {listen   8091;server_name    localhost;location / {root      html;index      index.html index.htm;proxy_pass http://127.0.0.1:8891;}}

这里定义的8091端口,是对外访问gitlab的地址,之后获得的数据会被转发给http://127.0.0.1:8891。所以这个8891的端口要和gitlab.rb中修改的配置一致,不然gitlab_workhorse就接收不到数据了,页面也会报告很难搞得504 error……(别问我怎么知道的,8091,8891,8091,8891当初定义的太像了,加上我眼睛又近视,这个错误白白浪费了我5根烟!)

gitlab_workhorse[‘listen_addr’] = “127.0.0.1:8891”

下面上整个配置文件

# gitlab config
# The orignal git lab nginx is /opt/gitlab/embedded/sbin/nginx -p /var/opt/gitlab/nginxlog_format gitlab_access '$remote_addr - $remote_user [$time_local] "$request_method $filtered_request_uri $server_protocol" $status $body_bytes_sent "$filtered_http_referer" "$http_user_agent"';
log_format gitlab_mattermost_access '$remote_addr - $remote_user [$time_local] "$request_method $filtered_request_uri $server_protocol" $status $body_bytes_sent "$filtered_http_referer" "$http_user_agent"';server_names_hash_bucket_size 64;# sendfile on;
tcp_nopush on;
tcp_nodelay on;# keepalive_timeout 65;gzip on;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_proxied any;
gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/json;# include /opt/gitlab/embedded/conf/mime.types;proxy_cache_path proxy_cache keys_zone=gitlab:10m max_size=1g levels=1:2;
proxy_cache gitlab;map $http_upgrade $connection_upgrade {default upgrade;''      close;
}# Remove private_token from the request URI
# In:  /foo?private_token=unfiltered&authenticity_token=unfiltered&rss_token=unfiltered&...
# Out: /foo?private_token=[FILTERED]&authenticity_token=unfiltered&rss_token=unfiltered&...
map $request_uri $temp_request_uri_1 {default $request_uri;~(?i)^(?<start>.*)(?<temp>[\?&]private[\-_]token)=[^&]*(?<rest>.*)$ "$start$temp=[FILTERED]$rest";
}# Remove authenticity_token from the request URI
# In:  /foo?private_token=[FILTERED]&authenticity_token=unfiltered&rss_token=unfiltered&...
# Out: /foo?private_token=[FILTERED]&authenticity_token=[FILTERED]&rss_token=unfiltered&...
map $temp_request_uri_1 $temp_request_uri_2 {default $temp_request_uri_1;~(?i)^(?<start>.*)(?<temp>[\?&]authenticity[\-_]token)=[^&]*(?<rest>.*)$ "$start$temp=[FILTERED]$rest";
}# Remove rss_token from the request URI
# In:  /foo?private_token=[FILTERED]&authenticity_token=[FILTERED]&rss_token=unfiltered&...
# Out: /foo?private_token=[FILTERED]&authenticity_token=[FILTERED]&rss_token=[FILTERED]&...
map $temp_request_uri_2 $filtered_request_uri {default $temp_request_uri_2;~(?i)^(?<start>.*)(?<temp>[\?&]rss[\-_]token)=[^&]*(?<rest>.*)$ "$start$temp=[FILTERED]$rest";
}# A version of the referer without the query string
map $http_referer $filtered_http_referer {default $http_referer;~^(?<temp>.*)\? $temp;
}server {listen 8091;server_name    localhost;location / {root      html;index      index.html index.htm;proxy_pass http://127.0.0.1:8891;}}include /var/opt/gitlab/nginx/conf/gitlab-http.conf;
include /var/opt/gitlab/nginx/conf/nginx-status.conf;

一切顺利的话,现在就可以kill掉gitlab内嵌的nginx,并且启动自己私有的nginx了

[root@AliS ~]# /usr/local/nginx/sbin/nginx

如果幸运的话,你可以快乐的用ps -ef|grep nginx看到你的nginx在快乐的奔跑,但是显然,我不太幸运。我运行的时候,系统残酷的提示我

nginx: error while loading shared libraries: xxxx.so

这个时候,可以使用一个叫做ldd的命令去看,导致都有哪些库没找到。如果没找到,会在对应的库文件下写not found。这个时候,去看看gitlab内嵌的nginx的库文件在哪,做个软链接到/lib64下就好了。

下面给大家看看ldd的输出,我的因为写文章之前已经做过软链接了,所以就看不到报错了

[root@AliS ~]# ldd /usr/local/nginx/sbin/nginx linux-vdso.so.1 =>  (0x00007ffc3bbd6000)libdl.so.2 => /lib64/libdl.so.2 (0x00007f6fc1446000)libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f6fc122a000)libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f6fc0ff2000)libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f6fc0d90000)libssl.so.1.0.0 => /lib64/libssl.so.1.0.0 (0x00007f6fc0b1e000)libcrypto.so.1.0.0 => /lib64/libcrypto.so.1.0.0 (0x00007f6fc06d0000)libz.so.1 => /lib64/libz.so.1 (0x00007f6fc04ba000)libxml2.so.2 => /lib64/libxml2.so.2 (0x00007f6fc0150000)libxslt.so.1 => /lib64/libxslt.so.1 (0x00007f6fbff10000)libexslt.so.0 => /lib64/libexslt.so.0 (0x00007f6fbfcfb000)libc.so.6 => /lib64/libc.so.6 (0x00007f6fbf938000)/lib64/ld-linux-x86-64.so.2 (0x000055ad92e0a000)libfreebl3.so => /lib64/libfreebl3.so (0x00007f6fbf734000)liblzma.so.5 => /lib64/liblzma.so.5 (0x00007f6fbf50e000)libm.so.6 => /lib64/libm.so.6 (0x00007f6fbf20c000)libgcrypt.so.11 => /lib64/libgcrypt.so.11 (0x00007f6fbef8a000)libgpg-error.so.0 => /lib64/libgpg-error.so.0 (0x00007f6fbed85000)
[root@AliS ~]# 

之后就是让gitlab配置生效了

[root@AliS ~]# gitlab-ctl reconfigure
[root@AliS ~]# gitlab-ctl restart

gitlab提供了一个简单的命令把相关的log打印在一起,如果里面没有报错就没啥问题了。

[root@AliS ~]# gitlab-ctl tail

最后就是测试一下,打开一个浏览器输入gitlab的地址,看看能不能正常访问了(虽然只是简单的一句话,但是为了实现这句话花费了我一包烟的时间)

配置webdav功能

端口 端口定义
8094 私有nginx提供的webdav对外访问端口

那些没在系统上部署过gitlab的烟民可以回来了

私有nginx运行正常后,配置webdav的过程就比较简单了

给webdav建个带目录不能直接登录的组和用户,然后再在webdav的home目录建立个用来存放数据的目录,我的是/home/webdav/data

下面这堆命令都是新建用户的固定搭配

[root@AliS home]# groupadd webdav
[root@AliS home]# useradd -d /home/webdav -g webdav -s /sbin/nologin webdav
[root@AliS home]# cd webdav
[root@AliS webdav]# mkdir data
[root@AliS webdav]# ls
data
[root@AliS webdav]# pwd
/home/webdav
[root@AliS webdav]# chown webdav:webdav data
[root@AliS webdav]# ls -l
total 4
drwxr-xr-x 2 webdav webdav 4096 Jul 11 21:30 data

之后回到私有nginx的conf目录,给webdav建立一个用户存放用户名密码的shadow文件
echo 用户名:$(openssl passwd -crypt 密码)>/etc/nginx/webdavpasswd

[root@AliS nginx]# mkdir webdav
[root@AliS nginx]# echo omniuser:$(openssl passwd -crypt omnipassword)>/usr/local/nginx/webdav/webdavpasswd

在/usr/local/nginx/conf/vhosts下添加一个vhosts的配置文件,我的是webdav.conf

文件内容如下

server {server_name localhost;listen 8094;location / {set $dest $http_destination;if (-d $request_filename) {rewrite ^(.*[^/])$ $1/;set $dest $dest/;}if ($request_method ~ MKCOL) {rewrite ^(.*[^/])$ $1/ break;}root /home/webdav/data;autoindex on;dav_methods PUT DELETE MKCOL COPY MOVE;dav_ext_methods PROPFIND OPTIONS;create_full_put_path on;client_max_body_size 0M;dav_access user:rw group:rw all:rw;auth_basic "Authorized Users Only";auth_basic_user_file /usr/local/nginx/webdav/webdavpasswd;}
}
  • 文件里定义的8094是自选的webdav服务端口
  • root /home/webdav/data;这句的路径是你自己建立的webdav存放数据的目录
  • auth_basic_user_file /usr/local/nginx/webdav/webdavpasswd;这个路径是刚刚你再nginx里面建立的用于存放webdav登录的用户名密码文件地址

最后让nginx重新加载下配置文件,基本配置就完成了

[root@AliS webdav]# /usr/local/nginx/sbin/nginx -s reload

后面测试一下,我的linux是没有装davfs的,所以要想在本机测试,要先让系统支持davfs的mount

[root@AliS mnt]# yum search davfs
Failed to set locale, defaulting to C
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
===================================================================== N/S matched: davfs =====================================================================
davfs2.x86_64 : A filesystem driver for WebDAVName and summary matches only, use "search all" for everything.
[root@AliS mnt]#
[root@AliS mnt]# yum install -y davfs2.x86_64
Failed to set locale, defaulting to C
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Resolving Dependencies
--> Running transaction check
---> Package davfs2.x86_64 0:1.4.7-6.el7 will be installed
--> Finished Dependency ResolutionDependencies Resolved==============================================================================================================================================================Package                              Arch                                 Version                                   Repository                          Size
==============================================================================================================================================================
Installing:davfs2                               x86_64                               1.4.7-6.el7                               epel                               148 kTransaction Summary
==============================================================================================================================================================
Install  1 PackageTotal download size: 148 k
Installed size: 341 k
Downloading packages:
davfs2-1.4.7-6.el7.x86_64.rpm                                                                                                          | 148 kB  00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transactionInstalling : davfs2-1.4.7-6.el7.x86_64                                                                                                                  1/1 Verifying  : davfs2-1.4.7-6.el7.x86_64                                                                                                                  1/1 Installed:davfs2.x86_64 0:1.4.7-6.el7                                                                                                                                 Complete!

装好啦,改改配置,我也把use_locks改成了0

[root@AliS mnt]# vi /etc/davfs2/davfs2.conf

mount一下试试,能挂载上就是做好了

[root@AliS mnt]# mkdir webdav
[root@AliS mnt]# mount -t davfs http://50.50.50.50:8094 /mnt/webdav
Please enter the username to authenticate with server
http://50.50.50.50:8094 or hit enter for none.Username: omni
Please enter the password to authenticate user webdav with server
http://50.50.50.50:8094 or hit enter for none.Password:
/sbin/mount.davfs: Warning: can't write entry into mtab, but will mount the file system anyway
[root@AliS mnt]# df -h
Filesystem                 Size  Used Avail Use% Mounted on
/dev/vda1                   40G   29G  8.5G  78% /
devtmpfs                   7.8G     0  7.8G   0% /dev
tmpfs                      7.8G  4.0K  7.8G   1% /dev/shm
tmpfs                      7.8G  480K  7.8G   1% /run
tmpfs                      7.8G     0  7.8G   0% /sys/fs/cgroup
tmpfs                      1.6G     0  1.6G   0% /run/user/0
http://50.50.50.50:8094   26G   13G   13G  50% /mnt/webdav
[root@AliS mnt]# ls
webdav
[root@AliS mnt]# cd webdav/
[root@AliS webdav]# ls
lost+found

当然,上面我删除了一部分信息。我自然没有文章中写的这么顺利,现实和理论总是有差距的,我一直都是下列错误

[root@AliS mnt]# mount -t davfs http://http://50.50.50.50:8094 /mnt/webdav
mount: unknown filesystem type 'davfs'
  • 没装davfs的文件系统支持,装就好了
[root@AliS mnt]# mount -t davfs http://http://50.50.50.50:8094 /mnt/webdav
/sbin/mount.davfs: invalid URL
  • 打错了url路径,都是小事儿
[root@AliS mnt]# mount -t davfs http://50.50.50.50:8094 /mnt/webdav
Please enter the username to authenticate with server
http://50.50.50.50:8094 or hit enter for none.Username: webdav
Please enter the password to authenticate user webdav with server
http://50.50.50.50:8094 or hit enter for none.Password:
/sbin/mount.davfs: connection timed out two times;
  • 这个问题晕了我好久,直到我上阳台抽烟冷静了两次,才想起来,阿里云对外访问端口还需要去它的安全控制台独立配置一下入栈出栈规则,不然默认的安全策略端口是不被外部访问的

omnifocus配置

一切准备妥当,软件这边的设置就异常简单了
只要在omnifocus的设置/同步功能里面,把对应的webdav的服务器地址(http://50.50.50.50:8094)连带端口号填好,输入用户名密码就好了。唯一需要注意的是,用于同步的第一个设备的数据,将成为服务器上的原始数据库,之后这个数据会覆盖其他后加入同步的设备。小心不要用错误数据覆盖正确数据就好了。

参考文章

最后多谢写这些文章的大神们

  • 利用Nginx WebDAV搭建自己的网盘
  • 替换gitlab自带的Nginx,并修改仓库存储路径
  • nginx配置虚拟主机vhost的方法详解
  • Markdown基本语法
    • 原谅我不好用的脑袋,写个文章还得时不时的查下Markdown的语法……

更换omnifocus webdav同步服务器的悲催经历相关推荐

  1. 北斗时钟同步服务器(卫星授时)应用智慧路灯系统

    北斗时钟同步服务器(卫星授时)应用智慧路灯系统 北斗时钟同步服务器(卫星授时)应用智慧路灯系统 在路灯的实际应用过程中会出现控制.检测以及安全问题,包括路灯不能根据实际情况(天气突变.重大事件.节日) ...

  2. 群辉NAS开启和彩云WebDAV同步文件夹,如何优雅的薅移动羊毛

    本人原创,个人博客群辉NAS开启和彩云WebDAV同步文件夹,如何优雅的薅移动羊毛 – 友巷技术分享 上期教程我们讲了如何才LINUX服务器上利用Docker开启和彩云的WebDAV,相信很多同学已经 ...

  3. phpstorm连接php文件夹,PHPstorm配置同步服务器文件

    一.配置服务器 1.连接配置 打开菜单栏 Tools -> Deployment -> Configuration 点击 + 选择 SFTP,并填写相关服务器信息: Type:连接类型,这 ...

  4. PHPstorm配置同步服务器文件

    一.配置服务器 1.连接配置 打开菜单栏 Tools -> Deployment -> Configuration 点击 + 选择 SFTP,并填写相关服务器信息: Type:连接类型,这 ...

  5. 二、用FTP同步服务器

    二.用FTP同步服务器 许多系统管理员喜欢用rsync同步二台服务器之间的数据,但我们更喜欢用FTP来实现,其好处是: FTP比rsync更能耗尽带宽,所以它更适合同步数据库(尤其是几百G的数据) 配 ...

  6. vscode使用sftp同步服务器文件

    环境介绍 服务器:腾讯云 + centos + onestack搭建好的lnmp环境 本地:mac 安装openssh sudo yum install openssh-client openssh- ...

  7. Unity 2018.3.1 SyncVar没有同步服务器变量

    在根据https://blog.csdn.net/cocos2der/article/details/5100学习Unet的过程中,发现客户端的SyncVar一直没有改变,无法同步服务器上的值,查了一 ...

  8. php实现服务器文件同步,PHPstorm配置同步服务器文件

    1.配置服务器 一.链接配置服务器 打开菜单栏 Tools -> Deployment -> Configurationapp 点击 + 选择 SFTP,并填写相关服务器信息:测试 Typ ...

  9. 文件同步服务器,iis 集群 ,代码同步(一)

    文件同步服务器 BitTorrent Sync 有点像TeamViewer远程协助 软件,私钥连接. 使用版本就30 天,最近测试了,功能不够理想.有点遗憾,我觉得我可以写一个! 确实很好用. 转载于 ...

最新文章

  1. python 分数序列求和公式_Python分数序列求和,编程练习题实例二十四
  2. 查看linux系统的性能
  3. 编译时遇到如下错误error C2061: syntax error : identifier 'THIS_FILE'
  4. MySQL存储过程和函数示例
  5. 【Java代码】实现字符串转数据库的 inStr【使用 JDK8 stream.collect(Collectors.joining(delimiter, prefix, suffix)) 实现】
  6. 单片机读tf卡c语言程序,单片机读写U盘闪盘超精简C源程序
  7. 主机甲采用停等协议向主机乙_习题
  8. JDBC在Java Web中的应用——分页查询
  9. redis新数据类型-bitmaps
  10. python如何筛选数据_python如何在列表、字典中筛选数据
  11. SI9000学习笔记
  12. ipad iphone开发_如何在iPad或iPhone上使用外部GPS设备
  13. python下载及安装教程
  14. 【Web技术】(实验一)HTML静态网页设计
  15. 计算机表格布局,使用表格布局网页
  16. 配置案例|Modbus转Profinet网关连接英威腾Goodrive200A 的配置案例
  17. html网站右侧广告位,分享一个html+css对联广告位的代码,网站通用
  18. android studio如何连接夜神模拟器
  19. 诛仙3服务器查询系统,《诛仙3》4月1日服务器数据互通公告
  20. 使用Matlab绘制星座图

热门文章

  1. 诱导契合对接(Induced Fit Docking)
  2. July文章《从头到尾彻底理解KMP(2014年8月22日版)》中,关于求解next数组,进一步理解如何递归前缀索引 k=next[k]
  3. 2021年化工自动化控制仪表新版试题及化工自动化控制仪表模拟考试
  4. 树莓派实现远程控制空调
  5. 【Mac】M1芯片WireShark使用
  6. JS计算请假时间(起始时间与终止时间可跨月)
  7. 解决“倾听者”无法使用超过32GB的TF卡的问题
  8. 各大网盘,云乎其云。
  9. 手把手教你使用NIRS_KIT
  10. Windows关机过程分析与快速关机