Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ef6bf690c5 | |||
| 148ad340d6 | |||
| 5817347d6e | |||
| 6a87248cc0 | |||
| c81abeda54 | |||
| 52f28d517b |
@@ -25,6 +25,12 @@ cd dbutils_mongo && ./db-start.sh up
|
|||||||
cd dbrestore_mongo && ./db-restore.sh
|
cd dbrestore_mongo && ./db-restore.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### File Sync
|
||||||
|
|
||||||
|
| Script | Description |
|
||||||
|
|---|---|
|
||||||
|
| [`dirsync/`](dirsync/) | Watch a local directory and sync changes to a remote host via SCP in real time |
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
Each script lists its own requirements in its README. Common dependencies:
|
Each script lists its own requirements in its README. Common dependencies:
|
||||||
@@ -32,6 +38,7 @@ Each script lists its own requirements in its README. Common dependencies:
|
|||||||
- **Bash**
|
- **Bash**
|
||||||
- **MongoDB Database Tools** (`mongodump` / `mongorestore`) — [download](https://www.mongodb.com/try/download/database-tools)
|
- **MongoDB Database Tools** (`mongodump` / `mongorestore`) — [download](https://www.mongodb.com/try/download/database-tools)
|
||||||
- **Docker & Docker Compose** (for `dbutils_mongo` only)
|
- **Docker & Docker Compose** (for `dbutils_mongo` only)
|
||||||
|
- **fswatch + ssh + scp** (for `dirsync` only)
|
||||||
|
|
||||||
## Author
|
## Author
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Author: Julien Gautier <jgautier.webdev@gmail.com>
|
# Author: Julien Gautier <jgautier.webdev@gmail.com>
|
||||||
# Organization: AdAstra
|
# Organization: AdAstra
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Author: Julien Gautier <jgautier.webdev@gmail.com>
|
# Author: Julien Gautier <jgautier.webdev@gmail.com>
|
||||||
# Organization: AdAstra
|
# Organization: AdAstra
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Author: Julien Gautier <jgautier.webdev@gmail.com>
|
# Author: Julien Gautier <jgautier.webdev@gmail.com>
|
||||||
# Organization: AdAstra
|
# Organization: AdAstra
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# Directory Sync Utility
|
||||||
|
|
||||||
|
This directory contains a tool for syncing a local directory to a remote host in real time.
|
||||||
|
It watches for file changes and transfers them immediately via SCP, making it useful for
|
||||||
|
live development on a remote server.
|
||||||
|
|
||||||
|
## Scripts
|
||||||
|
|
||||||
|
| Script | Description |
|
||||||
|
|---|---|
|
||||||
|
| `dir-sync.sh` | Improved version — recommended |
|
||||||
|
| `scpsync.sh` | Original version |
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./dir-sync.sh -s /path/to/local/dir/ -d /path/to/remote/dir/ -r sshhost
|
||||||
|
```
|
||||||
|
|
||||||
|
The script starts watching the local directory immediately. Press **Ctrl+C** to stop —
|
||||||
|
it will reset the remote repository (`git reset --hard`) and clear the remote cache before exiting.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|---|---|
|
||||||
|
| `-s, --source <path>` | Local directory absolute path |
|
||||||
|
| `-d, --dest <path>` | Remote directory absolute path |
|
||||||
|
| `-r, --remote-host <h>` | Remote SSH host (as configured in `~/.ssh/config`) |
|
||||||
|
| `-h, --help` | Print help |
|
||||||
|
|
||||||
|
If an option is omitted, the script falls back to the default values defined at the top of the script.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
1. **File watching**: `fswatch` monitors the source directory for any change, excluding `.git/`
|
||||||
|
2. **Batch end marker**: `fswatch --batch-marker` emits a `NoOp` signal at the end of each batch
|
||||||
|
3. **File sync**: each changed file is transferred with `scp`, preserving the relative path under the destination directory
|
||||||
|
4. **Cache clear**: on each `NoOp` (end of batch), `composer front-cache-clear` is run on the remote
|
||||||
|
5. **Cleanup on exit**: Ctrl+C triggers `git reset --hard` and a final cache clear on the remote
|
||||||
|
|
||||||
|
## Default Configuration
|
||||||
|
|
||||||
|
Edit the three constants at the top of `dir-sync.sh` to set your own defaults:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DEFAULT_LOCAL_PATH='/path/to/local/dir/'
|
||||||
|
DEFAULT_REMOTE_PATH='/path/to/remote/dir/'
|
||||||
|
DEFAULT_HOST='devac'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- [`fswatch`](https://github.com/emcrisostomo/fswatch) — file system watcher
|
||||||
|
- `scp` and `ssh` — standard OpenSSH tools
|
||||||
|
- A remote host configured in `~/.ssh/config` (password-less key auth recommended)
|
||||||
|
- `composer` available on the remote host (for cache clearing)
|
||||||
|
|
||||||
|
### Installing fswatch
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# macOS
|
||||||
|
brew install fswatch
|
||||||
|
|
||||||
|
# Linux (Ubuntu/Debian)
|
||||||
|
sudo apt install fswatch
|
||||||
|
```
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
**Author:** Julien Gautier ([jgautier.webdev@gmail.com](mailto:jgautier.webdev@gmail.com))
|
||||||
|
|
||||||
|
**Organization:** AdAstra
|
||||||
|
|
||||||
|
**Project:** adastra_scripts
|
||||||
Executable
+164
@@ -0,0 +1,164 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Author: Julien Gautier <jgautier.webdev@gmail.com>
|
||||||
|
# Organization: AdAstra
|
||||||
|
# Project: adastra_scripts
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
# Directory Sync Utility Script
|
||||||
|
#
|
||||||
|
# Watches a local directory for file changes and syncs them to a remote host
|
||||||
|
# via SCP in real time. On exit (Ctrl+C), resets the remote repository and
|
||||||
|
# clears the remote cache.
|
||||||
|
#
|
||||||
|
# Usage: ./dir-sync.sh [OPTIONS]
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# -s, --source <path> Local directory absolute path
|
||||||
|
# -d, --dest <path> Remote directory absolute path
|
||||||
|
# -r, --remote-host <h> Remote SSH host
|
||||||
|
# -h, --help Print this help
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# ./dir-sync.sh -s /var/www/myapp/ -d /var/www/myapp/ -r myserver
|
||||||
|
# ./dir-sync.sh -s ~/projects/app/ -d /srv/app/ -r devhost
|
||||||
|
#
|
||||||
|
# Requirements:
|
||||||
|
# fswatch, scp, ssh
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
# --- Configuration -----------------------------------------------------------
|
||||||
|
DEFAULT_LOCAL_PATH='/path/to/local/dir/'
|
||||||
|
DEFAULT_REMOTE_PATH='/path/to/remote/dir/'
|
||||||
|
DEFAULT_HOST='devhost'
|
||||||
|
|
||||||
|
# --- Colors ------------------------------------------------------------------
|
||||||
|
NONE='\033[0m'
|
||||||
|
BOLD='\033[1m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
MAGENTA='\033[0;35m'
|
||||||
|
BBLUE='\033[1;94m'
|
||||||
|
|
||||||
|
# --- Usage -------------------------------------------------------------------
|
||||||
|
usage() {
|
||||||
|
echo -e "
|
||||||
|
${BOLD}NAME${NONE}
|
||||||
|
dir-sync — Synchronize a local folder to a remote host
|
||||||
|
|
||||||
|
${BOLD}SYNOPSIS${NONE}
|
||||||
|
bash $0 [OPTION]...
|
||||||
|
|
||||||
|
${BOLD}OPTIONS${NONE}
|
||||||
|
-h, --help Print this help
|
||||||
|
-s, --source <path> Local directory absolute path
|
||||||
|
-d, --dest <path> Remote directory absolute path
|
||||||
|
-r, --remote-host <h> Remote SSH host
|
||||||
|
|
||||||
|
${RED}Example:${NONE} $0 -s /path/to/local/ -d /path/to/remote/ -r sshhost
|
||||||
|
"
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Prerequisite checks -----------------------------------------------------
|
||||||
|
check_deps() {
|
||||||
|
local missing=0
|
||||||
|
for cmd in fswatch scp ssh; do
|
||||||
|
if ! command -v "$cmd" &>/dev/null; then
|
||||||
|
echo -e "${RED}✗ Missing required command: ${cmd}${NONE}"
|
||||||
|
missing=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
[ "$missing" -eq 0 ] || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Cleanup (runs on INT/TERM) ----------------------------------------------
|
||||||
|
cleanup() {
|
||||||
|
echo -e "\n${CYAN}♻️ Resetting remote repository...${NONE}"
|
||||||
|
echo -e "\$> ${MAGENTA}ssh ${host} \"cd '${dir_remote}'; git reset --hard\"${NONE}"
|
||||||
|
ssh "$host" "cd '${dir_remote}'; git reset --hard"
|
||||||
|
|
||||||
|
echo -e "\n${CYAN}🗑️ Clearing remote cache...${NONE}"
|
||||||
|
echo -e "\$> ${MAGENTA}ssh ${host} \"cd '${dir_remote}'; composer front-cache-clear\"${NONE}"
|
||||||
|
ssh "$host" "cd '${dir_remote}'; composer front-cache-clear"
|
||||||
|
|
||||||
|
wait
|
||||||
|
echo -e "\n${GREEN}✔ Done.${NONE}"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Sync a single file ------------------------------------------------------
|
||||||
|
sync_file() {
|
||||||
|
local local_path="$1"
|
||||||
|
local remote_path="${local_path/$dir_local/$dir_remote}"
|
||||||
|
echo -e "\n${CYAN}🔄 Syncing ${YELLOW}${local_path/$dir_local/}${NONE}"
|
||||||
|
echo -e "\$> ${MAGENTA}scp '${local_path}' ${host}:'${remote_path}'${NONE}"
|
||||||
|
scp "${local_path}" "${host}:${remote_path}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Main --------------------------------------------------------------------
|
||||||
|
clear
|
||||||
|
|
||||||
|
echo -e "${BBLUE}🔎 Starting $0${NONE}"
|
||||||
|
echo -e "${BLUE}-------------------------------${NONE}"
|
||||||
|
|
||||||
|
check_deps
|
||||||
|
|
||||||
|
dir_local=''
|
||||||
|
dir_remote=''
|
||||||
|
host=''
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-h|--help) usage; exit 0 ;;
|
||||||
|
-s|--source) dir_local="$2"; shift 2 ;;
|
||||||
|
-d|--dest) dir_remote="$2"; shift 2 ;;
|
||||||
|
-r|--remote-host) host="$2"; shift 2 ;;
|
||||||
|
*)
|
||||||
|
echo -e "${RED}✗ Unknown option: $1${NONE}"
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$dir_local" ]]; then
|
||||||
|
dir_local="$DEFAULT_LOCAL_PATH"
|
||||||
|
echo -e "${YELLOW}⚠ Local path: ${dir_local} (default)${NONE}"
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}⚙️ Local path: ${dir_local}${NONE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$dir_remote" ]]; then
|
||||||
|
dir_remote="$DEFAULT_REMOTE_PATH"
|
||||||
|
echo -e "${YELLOW}⚠ Remote path: ${dir_remote} (default)${NONE}"
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}⚙️ Remote path: ${dir_remote}${NONE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$host" ]]; then
|
||||||
|
host="$DEFAULT_HOST"
|
||||||
|
echo -e "${YELLOW}⚠ Remote host: ${host} (default)${NONE}"
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}⚙️ Remote host: ${host}${NONE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
trap cleanup INT TERM
|
||||||
|
|
||||||
|
echo -e "\n${BBLUE}⏳ Watching for changes...${NONE}"
|
||||||
|
echo -e "${BLUE}-----------------------------${NONE}"
|
||||||
|
|
||||||
|
while IFS= read -r file; do
|
||||||
|
if [[ "$file" == "NoOp" ]]; then
|
||||||
|
echo -e "\n${CYAN}🗑️ Clearing remote cache...${NONE}"
|
||||||
|
echo -e "\$> ${MAGENTA}ssh ${host} \"cd '${dir_remote}'; composer front-cache-clear\"${NONE}"
|
||||||
|
ssh "$host" "cd '${dir_remote}'; composer front-cache-clear"
|
||||||
|
echo -e "\n${BBLUE}⏳ Watching for changes...${NONE}"
|
||||||
|
echo -e "${BLUE}-----------------------------${NONE}"
|
||||||
|
else
|
||||||
|
sync_file "$file" &
|
||||||
|
fi
|
||||||
|
done < <(fswatch --batch-marker -0 --exclude '.git/' "$dir_local" | tr '\0' '\n')
|
||||||
Reference in New Issue
Block a user