在这里插入图片描述

自己写个 rsync + fswatch 实时增量同步脚本,干掉 Cursor AI、Sublime Text 的 SFTP等 插件!

作为一个码农,我最头疼的事情之一就是编辑器同步代码到服务器这块。用过各种各样的sftp、rsync插件,感觉不好用。。

我琢磨着:难道就没有既快速,又安全,还能只上传修改过文件差异的解决方案?最终,我自己动手写了个基于 rsync + fswatch 的实时增量同步脚本,实现了只同步新增和修改文件,不做全量同步,支持任何编辑器,简单又靠谱。


说说这几个插件的坑

  • Cursor AI 的 SFTP:传输速度慢得哭,尤其项目文件多一点,等得我花儿都谢了。
  • Sublime Text 的 SFTP:要收费,虽说速度能快点,但不支持 rsync,上传的是整个文件,没法只传差异处,浪费流量和时间。

我的解决思路

为什么不自己写个脚本,用 rsync 来同步,只针对新增和修改的文件?而且还不被编辑器限制?

  • 只上传改动的文件,大大节省时间和带宽
  • fswatch 实时监听文件变化,做到自动触发同步
  • 支持配置排除目录,避免上传 .gitnode_modules 等垃圾文件夹
  • 彩色输出日志,清晰明了,方便调试
  • 同步成功还能播放提示音,避免盯屏幕发呆
  • 任何编辑器都能用,不依赖插件,灵活又安全

环境准备

  • macOS/Linux,本文以 macOS 为例
  • 安装 fswatch
  brew install fswatch
  • 安装 jq
  brew install jq
  • 配置好 SSH 免密登录服务器

配置文件示例(rsync_config.json

{"remote_host": "11.22.33.44","remote_user": "root","remote_path": "/www/wwwroot/test.myprojec.com","exclude": [".git", "node_modules", "dist"]
}

核心脚本:rsync_project.sh

#!/bin/bashRED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
RESET='\033[0m'# 获取脚本路径
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TIMESTAMP=$(date +%s)
LOG_FILE="$SCRIPT_DIR/.rsync_sync_${TIMESTAMP}.log"if [[ -z "$1" ]]; thenecho -e "${RED}[错误] 请输入项目根目录路径,比如:sh rsync_project.sh ~/my-project${RESET}"exit 1
fiPROJECT_DIR="$(cd "$1" && pwd)"
CONFIG_FILE="$PROJECT_DIR/rsync_config.json"
DETAILED=falsefor arg in "$@"; doif [[ "$arg" == "--detail" ]]; thenDETAILED=truefi
doneif [[ ! -f "$CONFIG_FILE" ]]; thenecho -e "${RED}[错误] 找不到配置文件:$CONFIG_FILE${RESET}"exit 1
fiif ! command -v jq &> /dev/null; thenecho -e "${RED}[错误] 你需要先装 jq:brew install jq${RESET}"exit 1
fiif ! command -v fswatch &> /dev/null; thenecho -e "${RED}[错误] 你需要先装 fswatch:brew install fswatch${RESET}"exit 1
fiREMOTE_HOST=$(jq -r '.remote_host' "$CONFIG_FILE")
REMOTE_USER=$(jq -r '.remote_user' "$CONFIG_FILE")
REMOTE_PATH=$(jq -r '.remote_path' "$CONFIG_FILE")EXCLUDE_ARR=()
for line in $(jq -r '.exclude[]?' "$CONFIG_FILE"); doEXCLUDE_ARR+=("${line%/}")
doneif [[ -z "$REMOTE_HOST" || -z "$REMOTE_USER" || -z "$REMOTE_PATH" ]]; thenecho -e "${RED}[错误] 配置文件缺少 remote_host、remote_user 或 remote_path${RESET}"exit 1
fiecho -e "${BLUE}[测试] 尝试连接 $REMOTE_USER@$REMOTE_HOST ...${RESET}"
ssh -q -o ConnectTimeout=5 "$REMOTE_USER@$REMOTE_HOST" "echo pong" 2>/dev/null
if [[ $? -ne 0 ]]; thenecho -e "${RED}[失败] 无法连接服务器 $REMOTE_USER@$REMOTE_HOST,请检查 SSH 配置${RESET}"exit 1
fiecho -e "${GREEN}[] 成功连接服务器:$REMOTE_USER@$REMOTE_HOST${RESET}"
echo -e "${CYAN}目标路径:$REMOTE_PATH${RESET}"
$DETAILED && echo -e "${YELLOW}[模式] 详细日志已启用${RESET}"
echo -e "${BLUE}[日志] 同步记录保存到:$LOG_FILE${RESET}"HAS_OSASCRIPT=false
command -v osascript &> /dev/null && HAS_OSASCRIPT=trueecho -e "${BLUE}[监听中] 等待文件变更...${RESET}"fswatch -0 -e "\\.DS_Store$" "$PROJECT_DIR" | while IFS= read -r -d "" changed_path; doskip=falsefor excl in "${EXCLUDE_ARR[@]}"; do[[ "$changed_path" == *"/$excl/"* || "$changed_path" == *"/$excl"* ]] && skip=true && breakdone$skip && continue[[ ! -f "$changed_path" ]] && continueREL_PATH="${changed_path#"$PROJECT_DIR"/}"CURRENT_TIME=$(date '+%Y-%m-%d %H:%M:%S')echo ""echo -e "${BLUE}[变更] 文件新增或修改:$REL_PATH${RESET}"echo -e "${MAGENTA}[时间] $CURRENT_TIME${RESET}"RSYNC_CMD=(rsync -az -e "ssh")RSYNC_CMD+=(--rsync-path="mkdir -p \"$(dirname "$REMOTE_PATH/$REL_PATH")\" && rsync")RSYNC_CMD+=("$changed_path" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH/$REL_PATH")if $DETAILED; thenecho -e "${CYAN}[执行] rsync 命令:${RESET}"printf '%q ' "${RSYNC_CMD[@]}"echo ""elseecho -e "${CYAN}[执行] 正在同步文件...${RESET}"fiecho "[$CURRENT_TIME] 变更文件: $REL_PATH" >> "$LOG_FILE""${RSYNC_CMD[@]}" >> "$LOG_FILE" 2>&1if [[ $? -eq 0 ]]; then# 同步成功后设置 chownssh "$REMOTE_USER@$REMOTE_HOST" "chown www:www \"$REMOTE_PATH/$REL_PATH\"" >> "$LOG_FILE" 2>&1echo -e "${GREEN}[完成] 同步成功 ✅ 并设置权限为 www:www${RESET}"echo "[$CURRENT_TIME] ✅ 同步成功并设为 www" >> "$LOG_FILE"if command -v afplay &> /dev/null; thenafplay /System/Library/Sounds/Tink.aiff &fi$HAS_OSASCRIPT && osascript -e 'display notification "文件同步成功" with title "rsync" sound name "Glass"'elseecho -e "${RED}[失败] 同步失败 ❌${RESET}"echo "[$CURRENT_TIME] ❌ 同步失败" >> "$LOG_FILE"$HAS_OSASCRIPT && osascript -e 'display notification "文件同步失败" with title "rsync" sound name "Basso"'fi
done

使用方法

bash rsync_project.sh myprojec --detail

替换 myprojec 为你的项目目录,--detail 参数可选,开启详细日志。


结语

用这套脚本后,文件改动几乎立刻上传,速度杠杠的,且不乱上传无用文件,安全又高效。再也不用担心编辑器 SFTP 插件各种坑,支持所有编辑器,只要能保存文件,统统适用。

如果你也被那些插件折磨过,不妨试试我这套 rsync + fswatch 脚本,真心好用!

欢迎大家留言交流,遇到问题咱们一起吐槽、优化!

Happy coding! 🚀

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/89137.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/89137.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/89137.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux中at命令的常用用法。

Linux 中 at 命令用于安排一次性定时任务,需要用到在某个时间只需要执行一次的命令的时候,可以使用at 1:安装at # Debian/Ubuntu sudo apt install at# CentOS/RHEL sudo yum install at2:启动at sudo systemctl start atd # 启…

【安卓笔记】RxJava的使用+修改功能+搭配retrofit+RxView防快速点击

0. 环境: 电脑:Windows10 Android Studio: 2024.3.2 编程语言: Java Gradle version:8.11.1 Compile Sdk Version:35 Java 版本:Java11 1. 介绍RxJava GitHub开源地址:https://github.com/Reactive…

Windows 下原生使用 claude code + Kimi K2

搞定了kimi k2 claude code在windows下原生使用 Windows下使用claude code的障碍是shell环境(命令行),非posix风格shell无法正常让claude code读取到url和key, 导致无法使用。解决问题的本质是使用符合posix风格的shell环境,我们…

Leetcode Easy题小解(C++语言描述)1

Leetcode Easy题小解(C语言描述) 相交链表 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 图示两个链表在节点 c1 开始相交**:**题目数据…

EP01:【NLP 第二弹】自然语言处理概述

一、NLP通向智能之路 1.1 图灵测试 1.1.1 提出背景 由计算机科学家阿兰・图灵于 1950 年提出,是早期衡量机器智能水平的重要概念。 1.1.2 提出目的 判断机器是否能表现出与人类相当的智能行为。 1.1.3 测试原理 场景设定:测试中存在一位人类测试者&#…

Ansible 查看PostgreSQL的版本

Ansible的基础知识就不说了直接贴剧本- name: Check PostgreSQL versionhosts: db_serversbecome: yesvars:ansible_python_interpreter: /usr/bin/python3db_name: postgresdb_user: postgresdb_password: your_passwordtasks:- name: Install psycopg2ansible.builtin.packag…

【视觉SLAM笔记】第9章 后端1

一、理论1. 状态估计的概率解释我们来深入探讨一下视觉SLAM中状态估计的概率解释。这可以说是理解现代SLAM算法(尤其是后端优化)的基石1. 问题的核心:不确定性SLAM(同步定位与建图)的本质是在一个未知环境中&#xff0…

(数据结构)复杂度

基本概念说明 数据结构 定义:数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在⼀种或多种特定关系的数据元素的集合。没有⼀种单⼀的数据结构对所有用途都有用(要考虑适配、效率问题,在不同情况下使用合适的…

玩转Docker | 使用Docker部署bender个人导航页工具

玩转Docker | 使用Docker部署bender个人导航页工具 前言 一、bender介绍 Bender 简介 Bender 的主要特点 二、系统要求 环境要求 环境检查 Docker版本检查 检查操作系统版本 三、部署bender服务 下载bender镜像 编辑部署文件 创建容器 检查容器状态 检查服务端口 安全设置 四、…

解决了困扰我的upload靶场无法解析phtml等后缀的问题

本文章为解决困扰我的 upload 靶场无法解析 phtml 问题 ​ 这个问题直接让我过不了Upload-Pass-03这一关,一直卡着。 ​ 痛太痛了 ,为什么无法解析上传之后的 phtml 后缀文件!这块儿折磨了博主一天多,太不容易了,查找…

Leetcode百题斩-二分搜索

二分搜索也是一个很有趣的专题,被做过的题中,刚好一个Easy,一个Medium和一个Hard,刚好可以看看,二分搜索的三个难度等级都是啥样的。 124. Binary Tree Maximum Path Sum[Hard](详见二叉树专题)…

【IDEA】格式化代码工具配置

格式化代码快捷键: CtrlAltL格式代码的时候不会再方法名与参数中间添加空格默认不勾选的情况下:代码样例:勾选之后的样例:选择不勾选,IDEA默认情况下就是不勾选的状态忽略加载文件有些非必要加载到开发工具中的文件我们…

驱动开发(3)|rk356x驱动GPIO基础应用之点亮led灯

点亮LED灯看似是一个基础的操作,但实际上,许多高级应用也依赖于高低电平的切换。例如,脉冲宽度调制(PWM)信号可以用来精确控制电机的转速,通过改变脉冲的频率和占空比,实现对电机的精确调节&…

手动搭建PHP环境:步步为营,解锁Web开发

目录一、引言二、准备工作2.1 明确所需软件2.2 下载软件三、Windows 系统搭建步骤3.1 安装 Apache 服务器3.2 安装 PHP3.3 集成 Apache 与 PHP3.4 安装 MySQL3.5 配置 PHP 连接 MySQL四、Linux 系统搭建步骤(以 Ubuntu 为例)4.1 更新系统4.2 安装 Apache…

DrissionPage:一款让网页自动化更简单的 Python 库

在网页自动化领域,Selenium 和 Playwright 早已是开发者耳熟能详的工具。但今天要给大家介绍一款更轻量、更易用的 Python 库 ——DrissionPage。它以 "融合 selenium 和 requests 优势" 为核心设计理念,既能像 requests 一样高效处理静态网页…

理解Grafana中`X-Scope-OrgID`的作用与配置

X-Scope-OrgID的作用 该HTTP Header用于标识Loki日志数据的所属租户(组织)。在多租户模式下,Loki通过此Header隔离不同团队或用户的数据,确保查询和存储的独立性。数据隔离: 租户A的日志标记为X-Scope-OrgID: team-a&a…

【PycharmPyqt designer桌面程序设计】

在 main.py 中调用 Qt Designer 生成的 windows.py(假设它是 PySide2 版)。 只要把两个文件放在同一目录即可直接运行。 ──────────────────── 1️⃣ windows.py(Qt Designer 生成,已转码) # -*-…

Unity Android Logcat插件 输出日志中文乱码解决

背景之前安卓真机调试看日志,一直用的是Android Studio自带的adb命令进行看日志,不太方便,改用Unity自带的安卓日志插件时,存在中文日志乱码问题。插件安装基于Unity6000.1.11版本:Window -> Package Management -&…

Halcon双相机单标定板标定实现拼图

1.Halcon图像拼接算法在之前的文章里也写过,主要是硬拼接和特征点拼接两种方式,今天增加另一种拼接图像的方式。应用场景是多个相机联合一起拍大尺寸的物体,并且相机视野之间存在重叠区域。通过在同一个标定板上面标定,计算两个相…

动物世界一语乾坤韵芳华 人工智能应用大学毕业论文 -仙界AI——仙盟创梦IDE

提示词在一个奇幻的童话森林里,所有的动物都像人类一样直立行走,穿着各种搞怪的衣服。 一只戴着超大眼镜、穿着背带裤的乌龟,正一本正经地站在一个蘑菇舞台上,拿着一根树枝当作麦克风,准备唱歌。它的眼镜总是往下滑&am…