627 lines
26 KiB
Python
627 lines
26 KiB
Python
import os
|
||
import zipfile
|
||
import boto3
|
||
from boto3.s3.transfer import TransferConfig
|
||
from django.utils.text import slugify
|
||
from datetime import datetime
|
||
import requests
|
||
import stat
|
||
|
||
haric_dosya_uzantilari = ['.zip', ]
|
||
excluded_folders = ['venv', 'yedek', '.idea', '.sock']
|
||
hostname = "ams1.vultrobjects.com"
|
||
secret_key = "Ec1pq3OQAObFLOQrfAVqJKhDAk4BkT7OqgYszlef"
|
||
access_key = "KQAOMJ8CQ8HP4CY23YPK"
|
||
x = 1
|
||
|
||
|
||
def upload_file_via_presigned_url(url, file_path):
|
||
if not os.path.exists(file_path):
|
||
print(f"Dosya bulunamadi: {file_path}")
|
||
return False
|
||
|
||
with open(file_path, 'rb') as file_data:
|
||
try:
|
||
response = requests.put(url, data=file_data)
|
||
if response.status_code == 200:
|
||
print("Dosya yuklendi!")
|
||
return True
|
||
else:
|
||
print(f"Yukleme olmadi. Status code: {response.status_code}")
|
||
print(f"Response: {response.content}")
|
||
return False
|
||
except Exception as e:
|
||
print(f"Yukleme hatasi: {e}")
|
||
return False
|
||
|
||
|
||
def get_filtered_folder_names(directory, excluded_folders):
|
||
folder_names = []
|
||
|
||
for item in os.listdir(directory):
|
||
item_path = os.path.join(directory, item)
|
||
if os.path.isdir(item_path) and item not in excluded_folders:
|
||
folder_names.append(item)
|
||
|
||
return folder_names
|
||
|
||
|
||
def zip_klasor(ziplenecek_klasor, hedef_zip_adi, haric_klasorler=[], haric_dosya_uzantilari=[]):
|
||
# Parametrelerin geçerliliğini kontrol et
|
||
if not ziplenecek_klasor or not hedef_zip_adi:
|
||
raise ValueError("Ziplenecek klasör ve hedef zip adı boş olamaz")
|
||
|
||
if not os.path.exists(ziplenecek_klasor):
|
||
raise FileNotFoundError(f"Ziplenecek klasör bulunamadı: {ziplenecek_klasor}")
|
||
|
||
# Hedef zip dosyasının bulunacağı dizini oluştur ve izinleri ayarla
|
||
hedef_dizin = os.path.dirname(hedef_zip_adi)
|
||
|
||
# Eğer hedef dizin boşsa, mevcut dizini kullan
|
||
if not hedef_dizin:
|
||
hedef_dizin = "."
|
||
hedef_zip_adi = os.path.join(hedef_dizin, hedef_zip_adi)
|
||
|
||
if not os.path.exists(hedef_dizin):
|
||
os.makedirs(hedef_dizin, mode=0o755, exist_ok=True)
|
||
|
||
# Zip dosyası oluşturmadan önce izinleri kontrol et
|
||
if os.path.exists(hedef_zip_adi):
|
||
try:
|
||
os.chmod(hedef_zip_adi, 0o666)
|
||
except Exception as e:
|
||
print(f"Mevcut zip dosyasinin izinleri guncellenemedi: {e}")
|
||
|
||
with zipfile.ZipFile(hedef_zip_adi, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
||
for klasor_yolu, _, dosya_listesi in os.walk(ziplenecek_klasor):
|
||
if not any(k in klasor_yolu for k in haric_klasorler):
|
||
for dosya in dosya_listesi:
|
||
dosya_adi, dosya_uzantisi = os.path.splitext(dosya)
|
||
dosya_yolu = os.path.join(klasor_yolu, dosya)
|
||
|
||
# Dosyanın var olup olmadığını kontrol et
|
||
if not os.path.exists(dosya_yolu):
|
||
print(f"Dosya bulunamadi: {dosya_yolu}")
|
||
continue
|
||
|
||
# Socket dosyalarını atla
|
||
try:
|
||
file_stat = os.stat(dosya_yolu)
|
||
if stat.S_ISSOCK(file_stat.st_mode):
|
||
print(f"Socket dosyasi atlandi: {dosya_yolu}")
|
||
continue
|
||
except (OSError, PermissionError) as e:
|
||
print(f"Dosya stat alinamadi: {dosya_yolu} -> Hata: {e}")
|
||
continue
|
||
|
||
if dosya_uzantisi.lower() not in haric_dosya_uzantilari:
|
||
try:
|
||
# Dosya okuma izinlerini kontrol et
|
||
if os.access(dosya_yolu, os.R_OK):
|
||
zipf.write(dosya_yolu, os.path.relpath(dosya_yolu, ziplenecek_klasor))
|
||
print(f"Dosya eklendi: {dosya_yolu}")
|
||
else:
|
||
print(f"Dosya okuma izni yok: {dosya_yolu}")
|
||
except (PermissionError, OSError) as e:
|
||
print(f"Dosya eklenemedi: {dosya_yolu} -> Hata: {e}")
|
||
except Exception as e:
|
||
print(f"Beklenmeyen hata: {dosya_yolu} -> Hata: {e}")
|
||
|
||
# Oluşturulan zip dosyasının izinlerini ayarla
|
||
try:
|
||
os.chmod(hedef_zip_adi, 0o644)
|
||
print(f"Zip dosyasi olusturuldu: {hedef_zip_adi}")
|
||
except Exception as e:
|
||
print(f"Zip dosyasi izinleri ayarlanamadi: {e}")
|
||
|
||
|
||
|
||
def create_ssh_zip(ssh_manager, source_dir, zip_name, excluded_folders=[], excluded_extensions=[]):
|
||
"""SSH üzerinden uzak sunucuda zip dosyası oluşturur"""
|
||
|
||
# Uzak sunucuda geçici zip dosyası yolu
|
||
remote_zip_path = f"/tmp/{zip_name}"
|
||
|
||
# Önce kaynak dizinin varlığını kontrol et
|
||
check_dir_command = f"test -d '{source_dir}' && echo 'exists' || echo 'not_exists'"
|
||
try:
|
||
stdout, stderr, status = ssh_manager.execute_command(check_dir_command)
|
||
if not status or stdout.strip() != "exists":
|
||
raise Exception(f"Kaynak dizin bulunamadı: {source_dir}")
|
||
except Exception as e:
|
||
raise Exception(f"Dizin kontrolü hatası: {str(e)}")
|
||
|
||
# Zip komutunun varlığını kontrol et ve gerekirse kur
|
||
zip_check_command = "which zip || command -v zip"
|
||
try:
|
||
stdout, stderr, status = ssh_manager.execute_command(zip_check_command)
|
||
if not status:
|
||
print("Zip komutu bulunamadı, kurulum deneniyor...")
|
||
if not install_zip_on_remote(ssh_manager):
|
||
raise Exception("Zip komutu uzak sunucuda bulunamadı ve kurulum başarısız oldu.")
|
||
except Exception as e:
|
||
raise Exception(f"Zip komutu kontrolü hatası: {str(e)}")
|
||
|
||
# Hariç tutulacak klasörler için exclude parametresi
|
||
exclude_args = ""
|
||
for folder in excluded_folders:
|
||
exclude_args += f" --exclude='{folder}/*' --exclude='{folder}'"
|
||
|
||
for ext in excluded_extensions:
|
||
exclude_args += f" --exclude='*{ext}'"
|
||
|
||
# Eski zip dosyasını temizle
|
||
cleanup_command = f"rm -f '{remote_zip_path}'"
|
||
ssh_manager.execute_command(cleanup_command)
|
||
|
||
# Zip komutunu oluştur (daha basit ve güvenilir)
|
||
zip_command = f"cd '{source_dir}' && zip -r '{remote_zip_path}' . {exclude_args}"
|
||
|
||
print(f"Çalıştırılan komut: {zip_command}")
|
||
|
||
try:
|
||
stdout, stderr, status = ssh_manager.execute_command(zip_command)
|
||
|
||
print(f"Zip komutu sonucu - Status: {status}, Stdout: {stdout}, Stderr: {stderr}")
|
||
|
||
# Zip komutu bazen uyarılarla birlikte başarılı olabilir
|
||
# Bu yüzden sadece status kontrolü yerine dosya varlığını da kontrol edelim
|
||
|
||
# Zip dosyasının varlığını kontrol et
|
||
check_command = f"test -f '{remote_zip_path}' && echo 'exists' || echo 'not_exists'"
|
||
stdout_check, stderr_check, status_check = ssh_manager.execute_command(check_command)
|
||
|
||
if not status_check or stdout_check.strip() != "exists":
|
||
error_details = f"Status: {status}, Stdout: {stdout}, Stderr: {stderr}"
|
||
raise Exception(f"Zip dosyası oluşturulamadı. Detaylar: {error_details}")
|
||
|
||
# Dosya boyutunu al
|
||
size_command = f"stat -c%s '{remote_zip_path}' 2>/dev/null || stat -f%z '{remote_zip_path}' 2>/dev/null || wc -c < '{remote_zip_path}'"
|
||
stdout_size, stderr_size, status_size = ssh_manager.execute_command(size_command)
|
||
|
||
file_size = 0
|
||
if status_size and stdout_size.strip().isdigit():
|
||
file_size = int(stdout_size.strip())
|
||
else:
|
||
# Boyut alınamazsa alternatif yöntem
|
||
ls_command = f"ls -la '{remote_zip_path}'"
|
||
stdout_ls, stderr_ls, status_ls = ssh_manager.execute_command(ls_command)
|
||
if status_ls:
|
||
print(f"Zip dosyası bilgileri: {stdout_ls}")
|
||
|
||
print(f"Zip dosyası başarıyla oluşturuldu: {remote_zip_path}, Boyut: {file_size}")
|
||
return remote_zip_path, file_size
|
||
|
||
except Exception as e:
|
||
# Hata durumunda oluşmuş olabilecek zip dosyasını temizle
|
||
cleanup_command = f"rm -f '{remote_zip_path}'"
|
||
ssh_manager.execute_command(cleanup_command)
|
||
raise e
|
||
|
||
|
||
def download_ssh_file(ssh_manager, remote_path, local_path):
|
||
"""SSH üzerinden dosya indirir"""
|
||
try:
|
||
print(f"Dosya indiriliyor: {remote_path} -> {local_path}")
|
||
|
||
# Local dizinin varlığını kontrol et ve oluştur
|
||
local_dir = os.path.dirname(local_path)
|
||
if not os.path.exists(local_dir):
|
||
os.makedirs(local_dir, mode=0o755, exist_ok=True)
|
||
|
||
# SFTP kullanarak dosyayı indir
|
||
with ssh_manager.client.open_sftp() as sftp:
|
||
# Uzak dosyanın varlığını kontrol et
|
||
try:
|
||
file_stat = sftp.stat(remote_path)
|
||
print(f"Uzak dosya boyutu: {file_stat.st_size} byte")
|
||
except FileNotFoundError:
|
||
raise Exception(f"Uzak dosya bulunamadı: {remote_path}")
|
||
|
||
sftp.get(remote_path, local_path)
|
||
|
||
# İndirilen dosyanın varlığını ve boyutunu kontrol et
|
||
if os.path.exists(local_path):
|
||
local_size = os.path.getsize(local_path)
|
||
print(f"Dosya başarıyla indirildi. Local boyut: {local_size} byte")
|
||
return True
|
||
else:
|
||
raise Exception("Dosya indirildikten sonra bulunamadı")
|
||
|
||
except Exception as e:
|
||
print(f"Dosya indirme hatası: {e}")
|
||
# Başarısız indirme durumunda local dosyayı temizle
|
||
if os.path.exists(local_path):
|
||
try:
|
||
os.remove(local_path)
|
||
except:
|
||
pass
|
||
return False
|
||
|
||
|
||
def cleanup_ssh_file(ssh_manager, remote_path):
|
||
"""SSH sunucusunda geçici dosyayı temizler"""
|
||
try:
|
||
cleanup_command = f"rm -f '{remote_path}'"
|
||
ssh_manager.execute_command(cleanup_command)
|
||
except Exception as e:
|
||
print(f"Temizleme hatası: {e}")
|
||
|
||
|
||
from ssh_manager.models import SSHLog, Project, SSHCredential
|
||
|
||
def job(folder, calisma_dizini, project_id=None):
|
||
import ssl
|
||
logs = []
|
||
|
||
# Parametrelerin geçerliliğini kontrol et
|
||
if not folder or folder.strip() == "":
|
||
return {'success': False, 'message': 'Klasör adı boş olamaz', 'logs': logs}
|
||
|
||
if not calisma_dizini or calisma_dizini.strip() == "":
|
||
return {'success': False, 'message': 'Çalışma dizini boş olamaz', 'logs': logs}
|
||
|
||
if not project_id:
|
||
return {'success': False, 'message': 'Proje ID gerekli', 'logs': logs}
|
||
|
||
# NOT: calisma_dizini SSH sunucusundaki bir yol olduğu için burada local kontrol yapılmaz
|
||
# Dizin kontrolü views.py'da SSH üzerinden yapılmalı
|
||
|
||
try:
|
||
project = Project.objects.get(id=project_id)
|
||
ssh_manager = project.ssh_credential.get_manager()
|
||
except Exception as e:
|
||
return {'success': False, 'message': f'SSH bağlantısı kurulamadı: {str(e)}', 'logs': logs}
|
||
|
||
# --- Vultr/S3 config ---
|
||
config = {
|
||
'access_key': "KQAOMJ8CQ8HP4CY23YPK",
|
||
'secret_key': "Ec1pq3OQAObFLOQrfAVqJKhDAk4BkT7OqgYszlef",
|
||
'host_base': "ams1.vultrobjects.com",
|
||
'bucket_location': "US",
|
||
'use_https': True,
|
||
'check_ssl_certificate': False, # SSL doğrulamasını kapat
|
||
'multipart_chunk_size_mb': 50, # Chunk boyutunu artır
|
||
}
|
||
endpoint_url = f"https://{config['host_base']}"
|
||
region_name = config['bucket_location']
|
||
# ---
|
||
session = boto3.session.Session()
|
||
client = session.client('s3',
|
||
region_name=region_name,
|
||
endpoint_url=endpoint_url,
|
||
aws_access_key_id=config['access_key'],
|
||
aws_secret_access_key=config['secret_key'],
|
||
use_ssl=config['use_https'],
|
||
verify=False, # SSL doğrulamasını tamamen kapat
|
||
config=boto3.session.Config(
|
||
signature_version='s3v4',
|
||
retries={'max_attempts': 3},
|
||
s3={
|
||
'addressing_style': 'path',
|
||
'payload_signing_enabled': False,
|
||
'chunked_encoding': False
|
||
}
|
||
)
|
||
)
|
||
def log_and_db(msg, status=True):
|
||
logs.append(msg)
|
||
if project_id:
|
||
try:
|
||
project = Project.objects.get(id=project_id)
|
||
SSHLog.objects.create(
|
||
ssh_credential=project.ssh_credential,
|
||
log_type='backup',
|
||
command=f'Backup: {folder}',
|
||
output=msg,
|
||
status=status
|
||
)
|
||
except Exception:
|
||
pass
|
||
log_and_db("<span style='color:#8bc34a'>S3 oturumu başlatıldı.</span>")
|
||
local_dt = datetime.now()
|
||
current_date = slugify(str(local_dt))
|
||
|
||
# Zip dosyası için tam yol oluştur
|
||
zip_dosya_adi = folder + "_" + current_date + ".zip"
|
||
output_zip = os.path.join("/tmp", zip_dosya_adi) # /tmp dizininde oluştur
|
||
|
||
log_and_db(f"<span style='color:#bdbdbd'>SSH üzerinden zip dosyası oluşturuluyor...</span>")
|
||
|
||
try:
|
||
# SSH üzerinden uzak sunucuda zip oluştur
|
||
zip_dosya_adi = folder + "_" + current_date + ".zip"
|
||
|
||
log_and_db(f"<span style='color:#bdbdbd'>Kaynak dizin: {calisma_dizini}</span>")
|
||
log_and_db(f"<span style='color:#bdbdbd'>Zip dosyası adı: {zip_dosya_adi}</span>")
|
||
|
||
try:
|
||
remote_zip_path, file_size = create_ssh_zip(
|
||
ssh_manager,
|
||
calisma_dizini,
|
||
zip_dosya_adi,
|
||
excluded_folders,
|
||
haric_dosya_uzantilari
|
||
)
|
||
|
||
log_and_db(f"<span style='color:#8bc34a'>Uzak sunucuda zip oluşturuldu: {remote_zip_path} ({file_size} byte)</span>")
|
||
|
||
# Zip dosyasını local'e indir
|
||
local_zip_path = os.path.join("/tmp", zip_dosya_adi)
|
||
|
||
log_and_db(f"<span style='color:#bdbdbd'>Zip dosyası indiriliyor: {local_zip_path}</span>")
|
||
|
||
if not download_ssh_file(ssh_manager, remote_zip_path, local_zip_path):
|
||
raise Exception("Zip dosyası indirilemedi")
|
||
|
||
log_and_db(f"<span style='color:#8bc34a'>Zip dosyası başarıyla indirildi</span>")
|
||
|
||
# Uzak sunucudaki geçici zip dosyasını temizle
|
||
cleanup_ssh_file(ssh_manager, remote_zip_path)
|
||
|
||
output_zip = local_zip_path
|
||
|
||
except Exception as zip_error:
|
||
log_and_db(f"<span style='color:#ff9800'>Zip oluşturma başarısız: {str(zip_error)}</span>")
|
||
log_and_db(f"<span style='color:#bdbdbd'>Tar ile yedekleme deneniyor...</span>")
|
||
|
||
# Zip başarısız olursa tar kullan
|
||
tar_dosya_adi = folder + "_" + current_date + ".tar.gz"
|
||
|
||
remote_tar_path, file_size = create_tar_backup(
|
||
ssh_manager,
|
||
calisma_dizini,
|
||
tar_dosya_adi,
|
||
excluded_folders,
|
||
haric_dosya_uzantilari
|
||
)
|
||
|
||
log_and_db(f"<span style='color:#8bc34a'>Uzak sunucuda tar.gz oluşturuldu: {remote_tar_path} ({file_size} byte)</span>")
|
||
|
||
# Tar dosyasını local'e indir
|
||
local_tar_path = os.path.join("/tmp", tar_dosya_adi)
|
||
|
||
log_and_db(f"<span style='color:#bdbdbd'>Tar dosyası indiriliyor: {local_tar_path}</span>")
|
||
|
||
if not download_ssh_file(ssh_manager, remote_tar_path, local_tar_path):
|
||
raise Exception("Tar dosyası indirilemedi")
|
||
|
||
log_and_db(f"<span style='color:#8bc34a'>Tar dosyası başarıyla indirildi</span>")
|
||
|
||
# Uzak sunucudaki geçici tar dosyasını temizle
|
||
cleanup_ssh_file(ssh_manager, remote_tar_path)
|
||
|
||
output_zip = local_tar_path
|
||
|
||
except Exception as e:
|
||
error_msg = f"SSH zip oluşturma hatası: {str(e)}"
|
||
log_and_db(f"<span style='color:#ff5252'>{error_msg}</span>", status=False)
|
||
|
||
# SSH bağlantısını kapat
|
||
try:
|
||
ssh_manager.close()
|
||
except:
|
||
pass
|
||
|
||
return {'success': False, 'message': error_msg, 'logs': logs}
|
||
log_and_db(f"<span style='color:#bdbdbd'>Zip işlemi tamamlandı: <b>{output_zip}</b></span>")
|
||
|
||
# --- Zip dosyası oluştu mu ve boş mu kontrolü ---
|
||
if not os.path.exists(output_zip):
|
||
log_and_db(f"<span style='color:#ff5252'>Zip dosyası oluşmadı: <b>{output_zip}</b></span>", status=False)
|
||
return {'success': False, 'message': 'Zip dosyası oluşmadı', 'logs': logs}
|
||
else:
|
||
size = os.path.getsize(output_zip)
|
||
log_and_db(f"<span style='color:#bdbdbd'>Zip dosyası boyutu: <b>{size} byte</b></span>")
|
||
if size == 0:
|
||
log_and_db(f"<span style='color:#ff5252'>Zip dosyası BOŞ!</span>", status=False)
|
||
return {'success': False, 'message': 'Zip dosyası boş', 'logs': logs}
|
||
|
||
bucket_name = folder
|
||
s3_key = output_zip # Bucket içinde alt klasör olmadan doğrudan zip dosyası
|
||
try:
|
||
# Bucket kontrol/oluşturma
|
||
buckets = client.list_buckets()
|
||
bucket_exists = any(obj['Name'] == bucket_name for obj in buckets['Buckets'])
|
||
if not bucket_exists:
|
||
client.create_bucket(Bucket=bucket_name)
|
||
log_and_db(f"<span style='color:#ffd600'>Bucket oluşturuldu: <b>{bucket_name}</b></span>")
|
||
else:
|
||
log_and_db(f"<span style='color:#ffd600'>Bucket mevcut: <b>{bucket_name}</b></span>")
|
||
# S3'e yükle (Vultr Object Storage için özel yöntem)
|
||
log_and_db(f"<span style='color:#bdbdbd'>Dosya S3'e yükleniyor: <b>{s3_key}</b></span>")
|
||
|
||
# Dosya boyutunu kontrol et
|
||
file_size = os.path.getsize(output_zip)
|
||
log_and_db(f"<span style='color:#bdbdbd'>Yüklenecek dosya boyutu: <b>{file_size} bytes</b></span>")
|
||
|
||
try:
|
||
# Küçük dosyalar için basit put_object kullan
|
||
if file_size < 50 * 1024 * 1024: # 50MB'dan küçükse
|
||
with open(output_zip, 'rb') as file_data:
|
||
client.put_object(
|
||
Bucket=bucket_name,
|
||
Key=s3_key,
|
||
Body=file_data.read(),
|
||
ACL='private',
|
||
ContentType='application/zip',
|
||
Metadata={
|
||
'uploaded_by': 'ssh_manager',
|
||
'upload_date': current_date
|
||
}
|
||
)
|
||
else:
|
||
# Büyük dosyalar için multipart upload
|
||
transfer_config = TransferConfig(
|
||
multipart_threshold=1024 * 1024 * 50, # 50MB
|
||
max_concurrency=1, # Tek thread kullan
|
||
multipart_chunksize=1024 * 1024 * 50, # 50MB chunk
|
||
use_threads=False
|
||
)
|
||
|
||
client.upload_file(
|
||
output_zip,
|
||
bucket_name,
|
||
s3_key,
|
||
ExtraArgs={
|
||
'ACL': 'private',
|
||
'ContentType': 'application/zip',
|
||
'Metadata': {
|
||
'uploaded_by': 'ssh_manager',
|
||
'upload_date': current_date
|
||
}
|
||
},
|
||
Config=transfer_config
|
||
)
|
||
except Exception as upload_error:
|
||
# Son çare: presigned URL ile yükleme
|
||
log_and_db(f"<span style='color:#ff9800'>Standart yükleme başarısız, presigned URL deneniyor: {upload_error}</span>")
|
||
|
||
try:
|
||
presigned_url = client.generate_presigned_url(
|
||
'put_object',
|
||
Params={'Bucket': bucket_name, 'Key': s3_key},
|
||
ExpiresIn=3600
|
||
)
|
||
|
||
import requests
|
||
with open(output_zip, 'rb') as file_data:
|
||
headers = {'Content-Type': 'application/zip'}
|
||
response = requests.put(presigned_url, data=file_data, headers=headers)
|
||
|
||
if response.status_code not in [200, 201]:
|
||
raise Exception(f"Presigned URL yükleme hatası: {response.status_code} - {response.text}")
|
||
|
||
except Exception as presigned_error:
|
||
raise Exception(f"Tüm yükleme yöntemleri başarısız: {presigned_error}")
|
||
log_and_db(f"<span style='color:#8bc34a'>S3'e başarıyla yüklendi: <b>{bucket_name}/{s3_key}</b></span>")
|
||
except Exception as e:
|
||
log_and_db(f"<span style='color:#ff5252'>S3 yükleme hatası: {e}</span>", status=False)
|
||
return {'success': False, 'message': str(e), 'logs': logs}
|
||
finally:
|
||
if os.path.exists(output_zip):
|
||
os.remove(output_zip)
|
||
log_and_db(f"<span style='color:#bdbdbd'>Geçici zip dosyası silindi: <b>{output_zip}</b></span>")
|
||
return {'success': True, 'message': 'Yedekleme tamamlandı', 'logs': logs}
|
||
|
||
def install_zip_on_remote(ssh_manager):
|
||
"""Uzak sunucuya zip kurulumu yapar"""
|
||
|
||
# Önce zip komutunun varlığını kontrol et
|
||
check_zip = "which zip || command -v zip"
|
||
stdout, stderr, status = ssh_manager.execute_command(check_zip)
|
||
|
||
if status and stdout.strip():
|
||
print(f"Zip komutu zaten kurulu: {stdout.strip()}")
|
||
return True
|
||
|
||
print("Zip komutu bulunamadı, kurulum yapılıyor...")
|
||
|
||
# İşletim sistemi kontrolü
|
||
os_check = "cat /etc/os-release 2>/dev/null || uname -a"
|
||
stdout, stderr, status = ssh_manager.execute_command(os_check)
|
||
|
||
install_commands = []
|
||
|
||
if "ubuntu" in stdout.lower() or "debian" in stdout.lower():
|
||
install_commands = [
|
||
"sudo apt-get update -y",
|
||
"sudo apt-get install -y zip unzip"
|
||
]
|
||
elif "centos" in stdout.lower() or "rhel" in stdout.lower() or "red hat" in stdout.lower():
|
||
install_commands = [
|
||
"sudo yum install -y zip unzip"
|
||
]
|
||
elif "alpine" in stdout.lower():
|
||
install_commands = [
|
||
"sudo apk update",
|
||
"sudo apk add zip unzip"
|
||
]
|
||
else:
|
||
# Diğer sistemler için genel deneme
|
||
install_commands = [
|
||
"sudo apt-get update -y && sudo apt-get install -y zip unzip",
|
||
"sudo yum install -y zip unzip",
|
||
"sudo apk add zip unzip"
|
||
]
|
||
|
||
# Kurulum komutlarını dene
|
||
for cmd in install_commands:
|
||
print(f"Denenen komut: {cmd}")
|
||
stdout, stderr, status = ssh_manager.execute_command(cmd)
|
||
|
||
if status:
|
||
# Kurulum sonrası zip kontrolü
|
||
stdout_check, stderr_check, status_check = ssh_manager.execute_command("which zip")
|
||
if status_check and stdout_check.strip():
|
||
print(f"Zip başarıyla kuruldu: {stdout_check.strip()}")
|
||
return True
|
||
else:
|
||
print(f"Kurulum hatası: {stderr}")
|
||
|
||
print("Zip kurulumu başarısız")
|
||
return False
|
||
|
||
|
||
def create_tar_backup(ssh_manager, source_dir, tar_name, excluded_folders=[], excluded_extensions=[]):
|
||
"""SSH üzerinden tar kullanarak yedek oluşturur (zip alternatifi)"""
|
||
|
||
# Uzak sunucuda geçici tar dosyası yolu
|
||
remote_tar_path = f"/tmp/{tar_name}"
|
||
|
||
# Kaynak dizinin varlığını kontrol et
|
||
check_dir_command = f"test -d '{source_dir}' && echo 'exists' || echo 'not_exists'"
|
||
stdout, stderr, status = ssh_manager.execute_command(check_dir_command)
|
||
|
||
if not status or stdout.strip() != "exists":
|
||
raise Exception(f"Kaynak dizin bulunamadı: {source_dir}")
|
||
|
||
# Hariç tutulacak klasörler için exclude parametresi
|
||
exclude_args = ""
|
||
for folder in excluded_folders:
|
||
exclude_args += f" --exclude='{folder}'"
|
||
|
||
for ext in excluded_extensions:
|
||
exclude_args += f" --exclude='*{ext}'"
|
||
|
||
# Eski tar dosyasını temizle
|
||
cleanup_command = f"rm -f '{remote_tar_path}'"
|
||
ssh_manager.execute_command(cleanup_command)
|
||
|
||
# Tar komutunu oluştur (gzip ile sıkıştır)
|
||
tar_command = f"cd '{source_dir}' && tar -czf '{remote_tar_path}' {exclude_args} . 2>/dev/null"
|
||
|
||
print(f"Çalıştırılan tar komutu: {tar_command}")
|
||
|
||
try:
|
||
stdout, stderr, status = ssh_manager.execute_command(tar_command)
|
||
|
||
print(f"Tar komutu sonucu - Status: {status}, Stdout: {stdout}, Stderr: {stderr}")
|
||
|
||
# Tar dosyasının varlığını kontrol et
|
||
check_command = f"test -f '{remote_tar_path}' && echo 'exists' || echo 'not_exists'"
|
||
stdout_check, stderr_check, status_check = ssh_manager.execute_command(check_command)
|
||
|
||
if not status_check or stdout_check.strip() != "exists":
|
||
error_details = f"Status: {status}, Stdout: {stdout}, Stderr: {stderr}"
|
||
raise Exception(f"Tar dosyası oluşturulamadı. Detaylar: {error_details}")
|
||
|
||
# Dosya boyutunu al
|
||
size_command = f"stat -c%s '{remote_tar_path}' 2>/dev/null || stat -f%z '{remote_tar_path}' 2>/dev/null || wc -c < '{remote_tar_path}'"
|
||
stdout_size, stderr_size, status_size = ssh_manager.execute_command(size_command)
|
||
|
||
file_size = 0
|
||
if status_size and stdout_size.strip().isdigit():
|
||
file_size = int(stdout_size.strip())
|
||
|
||
print(f"Tar dosyası başarıyla oluşturuldu: {remote_tar_path}, Boyut: {file_size}")
|
||
return remote_tar_path, file_size
|
||
|
||
except Exception as e:
|
||
# Hata durumunda oluşmuş olabilecek tar dosyasını temizle
|
||
cleanup_command = f"rm -f '{remote_tar_path}'"
|
||
ssh_manager.execute_command(cleanup_command)
|
||
raise e
|
||
|
||
|