Initial Commit
This commit is contained in:
Executable
+134
@@ -0,0 +1,134 @@
|
||||
'''
|
||||
Copyright 2025-2026 AIIrondev
|
||||
|
||||
Licensed under the Inventarsystem EULA (Endbenutzer-Lizenzvertrag).
|
||||
See Legal/LICENSE for the full license text.
|
||||
Unauthorized commercial use, SaaS hosting, or removal of branding is prohibited.
|
||||
For commercial licensing inquiries: https://github.com/AIIrondev
|
||||
'''
|
||||
"""
|
||||
Backup-DB.py
|
||||
|
||||
Usage:
|
||||
python Backup-DB.py \
|
||||
--uri mongodb://user:pass@host:port/ \
|
||||
--db my_database \
|
||||
--out /path/to/backup_folder
|
||||
"""
|
||||
import os
|
||||
import csv
|
||||
import sys
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
from pymongo import MongoClient
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Backup a MongoDB database to CSV files (one per collection)."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--uri", "-u",
|
||||
required=True,
|
||||
help="MongoDB URI, e.g. mongodb://user:pass@host:port/"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--db", "-d",
|
||||
required=True,
|
||||
help="Name of the database to back up"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--out", "-o",
|
||||
default=f"mongo_backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
|
||||
help="Output directory (will be created if it doesn't exist)"
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def flatten_dict(d, parent_key="", sep="."):
|
||||
"""
|
||||
Flatten nested dicts into a single level, concatenating keys with sep.
|
||||
Lists are left as-is (converted to string later).
|
||||
"""
|
||||
items = {}
|
||||
for k, v in d.items():
|
||||
new_key = f"{parent_key}{sep}{k}" if parent_key else k
|
||||
if isinstance(v, dict):
|
||||
items.update(flatten_dict(v, new_key, sep=sep))
|
||||
else:
|
||||
items[new_key] = v
|
||||
return items
|
||||
|
||||
|
||||
def export_collection(db, coll_name, out_dir):
|
||||
coll = db[coll_name]
|
||||
cursor = coll.find()
|
||||
docs = list(cursor)
|
||||
if not docs:
|
||||
print(f"[{coll_name}] No documents found, skipping.")
|
||||
return
|
||||
|
||||
# Flatten and collect all keys
|
||||
all_keys = set()
|
||||
flat_docs = []
|
||||
for doc in docs:
|
||||
# Convert ObjectId and other non-serializable types
|
||||
doc = {k: str(v) for k, v in doc.items()}
|
||||
flat = flatten_dict(doc)
|
||||
flat_docs.append(flat)
|
||||
all_keys.update(flat.keys())
|
||||
|
||||
out_file = os.path.join(out_dir, f"{coll_name}.csv")
|
||||
with open(out_file, "w", newline="", encoding="utf-8") as csvfile:
|
||||
writer = csv.DictWriter(csvfile, fieldnames=sorted(all_keys))
|
||||
writer.writeheader()
|
||||
for flat in flat_docs:
|
||||
writer.writerow(flat)
|
||||
|
||||
print(f"[{coll_name}] Exported {len(flat_docs)} docs → {out_file}")
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
|
||||
# Create output directory
|
||||
try:
|
||||
os.makedirs(args.out, exist_ok=True)
|
||||
print(f"Backing up database '{args.db}' → '{args.out}'")
|
||||
except PermissionError:
|
||||
print(f"Error: Permission denied when creating directory {args.out}")
|
||||
print("Try running with sudo or to a different output directory")
|
||||
return 1
|
||||
|
||||
# Verify write permissions
|
||||
test_file = os.path.join(args.out, ".write_test")
|
||||
try:
|
||||
with open(test_file, 'w') as f:
|
||||
f.write("test")
|
||||
os.remove(test_file)
|
||||
except (IOError, PermissionError) as e:
|
||||
print(f"Error: Cannot write to output directory {args.out}")
|
||||
print(f"Reason: {str(e)}")
|
||||
print("Try running with sudo or to a different output directory")
|
||||
return 1
|
||||
|
||||
try:
|
||||
# Connect to MongoDB
|
||||
client = MongoClient(args.uri)
|
||||
# Test connection
|
||||
client.server_info()
|
||||
db = client[args.db]
|
||||
|
||||
# Export each collection
|
||||
for coll_name in db.list_collection_names():
|
||||
export_collection(db, coll_name, args.out)
|
||||
|
||||
print("Backup complete.")
|
||||
return 0
|
||||
except Exception as e:
|
||||
print(f"Error: {str(e)}")
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user