V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
mstmdev
V2EX  ›  Go 编程语言

用 golang 造个轮子-一款开箱即用的跨平台文件同步工具 gofs

  •  
  •   mstmdev ·
    no-src · 2022-05-26 10:11:05 +08:00 · 2405 次点击
    这是一个创建于 914 天前的主题,其中的信息可能已经有所发展或是发生改变。

    gofs

    Chat Build License Go Reference Go Report Card codecov Release Mentioned in Awesome Go

    English | 简体中文

    gofs是基于 golang 开发的一款开箱即用的跨平台文件同步工具,支持在本地磁盘之间同步、从远程服务器同步变更到本地、将本地文件变更推送到远程服务器三种模式。开源地址如下:Github & Gitee

    安装

    首先需要确保已经安装了Go (版本必须是 1.18+),然后你就可以使用下面的命令来安装gofs

    go install github.com/no-src/gofs/...@latest
    

    在 Docker 中运行

    如果你想要在 docker 中运行,请在安装或者编译的时候使用-tags netgo命令行参数或者设置环境变量CGO_ENABLED=0,否则当你运行 docker 容器时可能会报找不到gofs的错误

    go install -tags netgo github.com/no-src/gofs/...@latest
    

    你可以使用build-docker.sh脚本来构建 docker 镜像,首先你需要克隆本仓库并且cd到本仓库的根目录

    $ ./scripts/build-docker.sh
    

    或者使用以下命令直接从DockerHub中拉取 docker 镜像

    $ docker pull nosrc/gofs
    

    更多关于发布与 docker 的脚本参见scripts目录

    后台运行

    在 windows 系统中,你可以使用下面的命令构建一个在后台运行的不带命令行界面的程序

    go install -ldflags="-H windowsgui" github.com/no-src/gofs/...@latest
    

    快速开始

    先决条件

    请确保文件同步的源目录和目标目录都已经存在,如果目录不存在,则用你实际的目录替换下面的路径进行提前创建

    $ mkdir source dest
    

    生成仅用于测试的证书和密钥文件,生产中请替换为正式的证书

    TLS 证书和密钥文件仅用于与[Web 文件服务器]( https://github.com/no-src/gofs/blob/main/README-CN.md#web 文件服务器)和远程磁盘服务端进行安全通讯

    $ go run $GOROOT/src/crypto/tls/generate_cert.go --host 127.0.0.1
    2021/12/30 17:21:54 wrote cert.pem
    2021/12/30 17:21:54 wrote key.pem
    

    查看你的工作目录

    $ ls
    cert.pem  key.pem  source  dest
    

    本地磁盘

    监控本地源目录将变更同步到目标目录

    你可以使用logically_delete命令行参数来启用逻辑删除,从而避免误删数据

    设置checkpoint_count命令行参数来使用文件中的检查点来减少传输未修改的文件块,默认情况下checkpoint_count=10 ,这意味着它最多有10+2个检查点。在头部和尾部还有两个额外的检查点。第一个检查点等于chunk_size ,它是可选的。最后一个检查点等于文件大小,这是必需的。由checkpoint_count设置的检查点偏移量总是大于chunk_size,除非文件大小小于或等于chunk_size,那么checkpoint_count 将变为0,所以它是可选的

    默认情况下,如果源文件的大小和修改时间与目标文件相同,则忽略当前文件的传输。你可以使用force_checksum命令行参数强制启用校验和来比较文件是否相等

    如果你想要降低同步的频率,你可以使用sync_delay命令行参数来启用同步延迟,当事件数量大于等于sync_delay_events或者距离上次同步已经等待超过sync_delay_time时开始同步

    $ gofs -source=./source -dest=./dest
    

    全量同步

    执行一次全量同步,直接将整个源目录同步到目标目录

    $ gofs -source=./source -dest=./dest -sync_once
    

    定时同步

    定时执行全量同步,将整个源目录同步到目标目录

    # 每 30 秒钟将源目录全量同步到目标目录
    $ gofs -source=./source -dest=./dest -sync_cron="*/30 * * * * *"
    

    守护进程模式

    启动守护进程来创建一个工作进程处理实际的任务,并将相关进程的 pid 信息记录到 pid 文件中

    $ gofs -source=./source -dest=./dest -daemon -daemon_pid
    

    Web 文件服务器

    启动一个 Web 文件服务器用于访问远程的源目录和目标目录

    Web 文件服务器默认使用 HTTPS 协议,使用tls_cert_filetls_key_file命令行参数来指定相关的证书和密钥文件

    如果你不需要使用 TLS 进行安全通讯,可以通过将tls命令行参数指定为false来禁用它

    如果将tls设置为true,则服务器默认运行端口为443,反之默认端口为80,你可以使用server_addr命令行参数来自定义服务器运行端口,例如-server_addr=":443"

    如果你在服务器端启用tls命令行参数,可以通过tls_insecure_skip_verify命令行参数来控制客户端是否跳过验证服务器的证书链和主机名,默认为true

    出于安全考虑,你应该设置rand_user_count命令行参数来随机生成指定数量的用户或者通过users命令行参数自定义用户信息来保证数据的访问安全,禁止用户匿名访问数据

    如果rand_user_count命令行参数设置大于 0 ,则随机生成的账户密码将会打印到日志信息中,请注意查看

    如果你需要启用 gzip 压缩响应结果,则添加server_compress命令行参数,但是目前 gzip 压缩不是很快,在局域网中可能会影响传输效率

    # 启动一个 Web 文件服务器并随机创建 3 个用户
    # 在生产环境中请将`tls_cert_file`和`tls_key_file`命令行参数替换为正式的证书和密钥文件
    $ gofs -source=./source -dest=./dest -server -tls_cert_file=cert.pem -tls_key_file=key.pem -rand_user_count=3
    

    远程磁盘服务端

    启动一个远程磁盘服务端作为一个远程文件数据源

    source命令行参数详见远程磁盘服务端数据源协议

    注意远程磁盘服务端的用户至少要拥有读权限,例如:-users="gofs|password|r"

    你可以使用checkpoint_countsync_delay命令行参数就跟本地磁盘一样

    # 启动一个远程磁盘服务端
    # 在生产环境中请将`tls_cert_file`和`tls_key_file`命令行参数替换为正式的证书和密钥文件
    # 为了安全起见,请使用复杂的账户密码来设置`users`命令行参数
    $ gofs -source="rs://127.0.0.1:8105?mode=server&local_sync_disabled=true&path=./source&fs_server=https://127.0.0.1" -dest=./dest -users="gofs|password|r" -tls_cert_file=cert.pem -tls_key_file=key.pem
    

    远程磁盘客户端

    启动一个远程磁盘客户端将远程磁盘服务端的文件变更同步到本地目标目录

    source命令行参数详见远程磁盘服务端数据源协议

    使用sync_once命令行参数,可以直接将远程磁盘服务端的文件整个全量同步到本地目标目录,就跟全量同步一样

    使用sync_cron命令行参数,可以定时将远程磁盘服务端的文件整个全量同步到本地目标目录,就跟定时同步一样

    使用force_checksum命令行参数强制启用校验和来比较文件是否相等,就跟本地磁盘一样

    你可以使用sync_delay命令行参数就跟本地磁盘一样

    # 启动一个远程磁盘客户端
    # 请将`users`命令行参数替换为上面设置的实际账户名密码
    $ gofs -source="rs://127.0.0.1:8105" -dest=./dest -users="gofs|password"
    

    远程推送服务端

    启动一个远程磁盘服务端作为一个远程文件数据源,并使用push_server命令行参数启用远程推送服务端

    注意远程推送服务端的用户至少要拥有读写权限,例如:-users="gofs|password|rw"

    # 启动一个远程磁盘服务端并启用远程推送服务端
    # 在生产环境中请将`tls_cert_file`和`tls_key_file`命令行参数替换为正式的证书和密钥文件
    # 为了安全起见,请使用复杂的账户密码来设置`users`命令行参数
    $ gofs -source="rs://127.0.0.1:8105?mode=server&local_sync_disabled=true&path=./source&fs_server=https://127.0.0.1" -dest=./dest -users="gofs|password|rw" -tls_cert_file=cert.pem -tls_key_file=key.pem -push_server
    

    远程推送客户端

    启动一个远程推送客户端将本地文件变更同步到远程推送服务端

    使用chunk_size命令行参数来设置大文件上传时切分的区块大小,默认值为1048576,即1MB

    你可以使用checkpoint_countsync_delay命令行参数就跟本地磁盘一样

    更多命令行参数用法请参见远程磁盘客户端

    # 启动一个远程推送客户端并且启用本地磁盘同步,将 source 目录下的文件变更同步到本地 dest 目录和远程推送服务器上
    # 请将`users`命令行参数替换为上面设置的实际账户名密码
    $ gofs -source="./source" -dest="rs://127.0.0.1:8105?local_sync_disabled=false&path=./dest" -users="gofs|password"
    

    远程磁盘服务端数据源协议

    远程磁盘服务端数据源协议基于 URI 基本语法,详见RFC 3986

    方案

    方案名称为rs

    主机名

    远程磁盘服务端数据源在远程磁盘服务端模式下使用0.0.0.0或者其他本地网卡 IP 地址作为主机名,在远程磁盘客户端 模式下使用远程磁盘服务端的 IP 地址或者域名作为主机名

    端口号

    远程磁盘服务端数据源端口号,默认为8105

    参数

    仅在远程磁盘服务端模式下设置以下参数

    示例

    远程磁盘服务端模式下的示例

     rs://127.0.0.1:8105?mode=server&local_sync_disabled=true&path=./source&fs_server=https://127.0.0.1
     \_/  \_______/ \__/ \____________________________________________________________________________/
      |       |       |                                      |
     方案   主机名   端口号                                    参数
    

    管理接口

    基于[Web 文件服务器]( https://github.com/no-src/gofs/blob/main/README-CN.md#web 文件服务器)的应用管理接口

    默认情况下,仅允许私有地址和回环地址访问管理接口的相关路由

    你可以通过将manage_private命令行参数设置为false来禁用默认行为,允许公网 IP 访问管理接口的路由

    $ gofs -source=./source -dest=./dest -server -tls_cert_file=cert.pem -tls_key_file=key.pem -rand_user_count=3 -manage
    

    性能分析接口

    pprof 访问地址如下:

    https://127.0.0.1/manage/pprof/
    

    配置接口

    读取应用程序配置,默认返回json格式,当前支持jsonyaml格式

    https://127.0.0.1/manage/config
    

    或者使用format参数来指定返回的配置格式

    https://127.0.0.1/manage/config?format=yaml
    

    报告接口

    使用report命令行参数来启用报告接口的路由并且开始收集报告数据,需要先启用manage命令行参数

    报告接口详情参见Report API

    https://127.0.0.1/manage/report
    

    日志

    默认情况下会启用文件日志与控制台日志,你可以将log_file命令行参数设置为false来禁用文件日志

    使用log_level命令行参数设置日志的等级,默认级别是INFO,可选项为:DEBUG=0 INFO=1 WARN=2 ERROR=3

    使用log_dir命令行参数来设置日志文件目录,默认为./logs/

    使用log_flush命令行参数来设置自动刷新日志到文件中,默认启用

    使用log_flush_interval命令行参数设置自动刷新日志到文件中的频率,默认为3s

    使用log_event命令行参数启用事件日志,所有事件都会记录到文件中,默认为禁用

    使用log_sample_rate命令行参数设置采样日志的采样率,取值范围为 0 到 1 ,默认值为1

    # 在"本地磁盘"模式下设置日志信息
    $ gofs -source=./source -dest=./dest -log_file -log_level=0 -log_dir="./logs/" -log_flush -log_flush_interval=3s -log_event
    

    使用配置文件

    如果需要的话,你可以使用配置文件来代替所有的命令行参数,当前支持jsonyaml格式

    所有的配置字段名称跟命令行参数一样,你可以参考配置示例或者配置接口的响应结果

    $ gofs -conf=./gofs.yaml
    

    校验和

    你可以使用checksum命令行参数来计算并打印文件的校验和

    chunk_sizecheckpoint_count命令行参数在这里同在本地磁盘中一样有效

    $ gofs -source=./gofs -checksum
    

    更多信息

    帮助信息

    $ gofs -h
    

    版本信息

    $ gofs -v
    

    关于信息

    $ gofs -about
    
    8 条回复    2022-05-26 14:21:12 +08:00
    fuis
        1
    fuis  
       2022-05-26 10:22:49 +08:00
    iamzuoxinyu
        2
    iamzuoxinyu  
       2022-05-26 10:27:31 +08:00
    吐槽下名字,叫 fs 可能有点标题党的感觉。gosync 之类的可能更准确点……
    xiaoyanbot
        3
    xiaoyanbot  
       2022-05-26 10:31:25 +08:00
    这个项目非常赞
    HarrisonZ
        4
    HarrisonZ  
       2022-05-26 10:35:02 +08:00
    rclone
    mstmdev
        5
    mstmdev  
    OP
       2022-05-26 10:52:37 +08:00
    @HarrisonZ Inotify lsync rsync rclone syncthing croc robocopy... 哈哈,适应的场景和需求不同
    mstmdev
        6
    mstmdev  
    OP
       2022-05-26 11:01:33 +08:00
    @iamzuoxinyu 巧合巧合
    weak
        7
    weak  
       2022-05-26 12:31:25 +08:00 via iPhone
    有没有中继模式
    mstmdev
        8
    mstmdev  
    OP
       2022-05-26 14:21:12 +08:00
    @weak 目前没有内置的中继支持,不过可以使用 ngrok 等第三方的代理做中继器也可以实现等效功能,如自动同步公司电脑与家里的电脑的文件,只需要把程序中的两个端口映射出去就好了,默认为 8105 与 443 。后面会考虑实现内置的中继器,简化这一操作
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   6123 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 06:15 · PVG 14:15 · LAX 22:15 · JFK 01:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.