101 lines
3.2 KiB
Python
101 lines
3.2 KiB
Python
import paramiko
|
|
from scp import SCPClient
|
|
import os
|
|
|
|
# === CONFIGURATION ===
|
|
ssh_host = '192.168.130.9'
|
|
ssh_port = 22
|
|
ssh_user = 'root'
|
|
ssh_password = '' # Or use SSH key (see notes below)
|
|
remote_folder = '/temp/bc/'
|
|
local_folder = r'C:\Backup\Telefonsentral' # Use raw string for Windows paths
|
|
|
|
# === SETUP LOCAL FOLDER ===
|
|
os.makedirs(local_folder, exist_ok=True)
|
|
|
|
def create_ssh_client(host, port, user, password):
|
|
client = paramiko.SSHClient()
|
|
client.load_system_host_keys()
|
|
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
client.connect(host, port, username=user, password=password)
|
|
return client
|
|
|
|
def copy_folder(ssh_client, remote_path, local_path):
|
|
print(f"Downloading files from {remote_path} to {local_path}...")
|
|
|
|
sftp = ssh_client.open_sftp()
|
|
|
|
# Get all remote files
|
|
stdin, stdout, _ = ssh_client.exec_command(f"find {remote_path} -type f")
|
|
remote_files = [line.strip() for line in stdout.readlines()]
|
|
|
|
for remote_file in remote_files:
|
|
relative_path = os.path.relpath(remote_file, remote_path).replace('/', os.sep)
|
|
local_file_path = os.path.join(local_path, relative_path)
|
|
|
|
local_dir = os.path.dirname(local_file_path)
|
|
os.makedirs(local_dir, exist_ok=True)
|
|
|
|
try:
|
|
print(f"Downloading {remote_file} → {local_file_path}")
|
|
sftp.get(remote_file, local_file_path)
|
|
except Exception as e:
|
|
print(f"Failed to download {remote_file}: {e}")
|
|
|
|
sftp.close()
|
|
|
|
def list_remote_files(ssh, path):
|
|
# Returns list of full file paths (e.g. /home/user/data/file.txt)
|
|
stdin, stdout, stderr = ssh.exec_command(f"find {path} -type f")
|
|
files = [line.strip() for line in stdout.readlines()]
|
|
return files
|
|
|
|
def list_local_files(path):
|
|
# Returns full local file paths
|
|
local_files = []
|
|
for dirpath, _, filenames in os.walk(path):
|
|
for f in filenames:
|
|
full_path = os.path.normpath(os.path.join(dirpath, f))
|
|
local_files.append(full_path)
|
|
return local_files
|
|
|
|
def sync_delete_unmatched(remote_files, local_base_path, remote_base_path):
|
|
print("Checking for stale local files to delete...")
|
|
|
|
# Compute relative paths from remote files
|
|
remote_relative = [
|
|
os.path.normpath(f.replace(remote_base_path, '').lstrip('/').replace('/', os.sep))
|
|
for f in remote_files
|
|
]
|
|
expected_local = {os.path.normpath(os.path.join(local_base_path, rel)) for rel in remote_relative}
|
|
|
|
local_files = set(list_local_files(local_base_path))
|
|
|
|
to_delete = local_files - expected_local
|
|
for f in to_delete:
|
|
try:
|
|
print(f"Deleting stale file: {f}")
|
|
os.remove(f)
|
|
except Exception as e:
|
|
print(f"Failed to delete {f}: {e}")
|
|
|
|
def main():
|
|
try:
|
|
ssh = create_ssh_client(ssh_host, ssh_port, ssh_user, ssh_password)
|
|
|
|
# 1. List remote files
|
|
remote_files = list_remote_files(ssh, remote_folder)
|
|
|
|
# 2. Download all files from remote
|
|
copy_folder(ssh, remote_folder, local_folder)
|
|
|
|
# 3. Delete local files not on remote
|
|
sync_delete_unmatched(remote_files, local_folder, remote_folder)
|
|
|
|
ssh.close()
|
|
except Exception as e:
|
|
print(f"Error: {e}")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|