Last active
December 11, 2023 19:40
-
-
Save divinity76/ec2a492723f408de84f941305b1e2f7f to your computer and use it in GitHub Desktop.
rsync dir indefinitely whenever it changes.. syncer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env php | |
<?php | |
declare (strict_types = 1); | |
global $argc, $argv; | |
if ($argc < 3) { | |
echo ("Usage: {$argv[0]} 'FOLDER' rsync FOLDER foo@bar:server_folder arg1 arg2 arg3 etc\n"); | |
exit(1); | |
} | |
/** | |
* returns a plain string array of path to all files in a directory, including subdirectories, | |
* but does not return directories themselves. (meaning if a directory is empty, it will not be included at all) | |
* | |
* @param string $dir | |
* @param bool $realpath | |
* @throws UnexpectedValueException if $dir is not readable/does not exists | |
* @return string[] files | |
*/ | |
function get_file_list_recursively(string $dir, bool $realpath = false): array | |
{ | |
if (!is_readable($dir)) { | |
throw new UnexpectedValueException("Directory is not readable: {$dir}"); | |
} | |
if(!is_dir($dir)){ | |
return $realpath ? array(realpath($dir)) : array($dir); | |
} | |
$files = array(); | |
$files = []; | |
foreach ((new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS))) as $file) { | |
/** @var SplFileInfo $file */ | |
if ($realpath) { | |
$files[] = $file->getRealPath(); | |
} else { | |
$files[] = $file->getPathname(); | |
} | |
} | |
return $files; | |
} | |
function hasDirChanged(string $dir): bool | |
{ | |
static $old_scans = array(); | |
$files = get_file_list_recursively($dir, true); | |
$files = array_filter($files, function ($file) { | |
return true; | |
$ext = pathinfo($file, PATHINFO_EXTENSION); | |
$basename = pathinfo($file, PATHINFO_BASENAME); | |
if ($basename === "html.html") { | |
return false; | |
} | |
return in_array(strtolower($ext), array( | |
"php", | |
"js", | |
"css", | |
"html", | |
"htm", | |
//"txt", | |
), true); // | |
}); | |
$files = array_values($files); | |
$scan = array(); | |
foreach ($files as $file) { | |
// fnv164 is a very fast non-crypto hash | |
$hash = hash_file("fnv164", $file, true); | |
$scan[$file] = $hash; | |
} | |
if (isset($old_scans[$dir]) && $old_scans[$dir] === $scan) { | |
return false; | |
} | |
$old_scans[$dir] = $scan; | |
return true; | |
} | |
$single_instance = fopen(__FILE__, "rb"); | |
if (!flock($single_instance, LOCK_EX | LOCK_NB)) { | |
fwrite(STDERR, "Another instance is already running.\n"); | |
exit(1); | |
} | |
$scan_dir = $argv[1]; | |
$rsync_command = ''; | |
for ($i = 2; $i < $argc; ++$i) { | |
$rsync_command .= escapeshellarg($argv[$i]) . ' '; | |
} | |
echo "scan_dir: {$scan_dir} rsync_command: {$rsync_command}\n"; | |
$sleep_time = 5; | |
echo "sleep time: {$sleep_time}\n"; | |
for (;;) { | |
sleep($sleep_time); | |
if (!hasDirChanged($scan_dir)) { | |
continue; | |
} | |
echo "syncing!"; | |
if (0) { | |
$cmd = implode(" ", array( | |
"rsync", | |
escapeshellarg(__DIR__), | |
escapeshellarg("solomeme") . "@" . escapeshellarg("solomeme.ratma.net") . ":" . escapeshellarg("/home/solomeme/websites/solomeme.ratma.net/www"), | |
"-aPz", // fsck it | |
"--exclude '*.sqlite3'", | |
"--exclude '*.txt'", | |
"--exclude '*.json'", | |
"--exclude 'html.html'", | |
)); | |
} else { | |
$cmd = $rsync_command; | |
} | |
passthru($cmd, $ret); | |
if ($ret !== 0) { | |
echo "rsync failed with code {$ret}\n"; | |
continue; | |
} | |
echo "SYNCED!\n"; | |
} | |
// |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment