
Ini adalah script python untuk membuat aplikasi SCP di windows, tujuannya adalah untuk mempermudah kita melakukan copy file dari Windows ke Linux.
Pertama lakukan instalasi pip/dependensi untuk menjalankan script python, berikut adalah scriptnya
pip install paramiko scp
Setelah menjalankan perintah di atas, berikut adalah script pythinnya.
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import paramiko
from scp import SCPClient
import os
import threading
import sys
class SCPTransferApp:
def __init__(self, root):
self.root = root
self.root.title("SCP Transfer - Windows to Linux")
self.root.geometry("700x600")
self.setup_ui()
def setup_ui(self):
# Main frame
main_frame = ttk.Frame(self.root, padding="10")
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# Server Configuration
server_frame = ttk.LabelFrame(main_frame, text="Server Configuration", padding="10")
server_frame.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5)
ttk.Label(server_frame, text="Host:").grid(row=0, column=0, sticky=tk.W, pady=5)
self.host_entry = ttk.Entry(server_frame, width=30)
self.host_entry.grid(row=0, column=1, pady=5, padx=5)
self.host_entry.insert(0, "192.168.1.100")
ttk.Label(server_frame, text="Port:").grid(row=0, column=2, sticky=tk.W, pady=5, padx=(20,0))
self.port_entry = ttk.Entry(server_frame, width=10)
self.port_entry.insert(0, "22")
self.port_entry.grid(row=0, column=3, pady=5, padx=5)
ttk.Label(server_frame, text="Username:").grid(row=1, column=0, sticky=tk.W, pady=5)
self.username_entry = ttk.Entry(server_frame, width=30)
self.username_entry.grid(row=1, column=1, pady=5, padx=5)
self.username_entry.insert(0, "username")
ttk.Label(server_frame, text="Password:").grid(row=1, column=2, sticky=tk.W, pady=5, padx=(20,0))
self.password_entry = ttk.Entry(server_frame, width=15, show="*")
self.password_entry.grid(row=1, column=3, pady=5, padx=5)
# File Selection
file_frame = ttk.LabelFrame(main_frame, text="File Transfer", padding="10")
file_frame.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5)
ttk.Label(file_frame, text="Local File:").grid(row=0, column=0, sticky=tk.W, pady=5)
self.local_file_entry = ttk.Entry(file_frame, width=50)
self.local_file_entry.grid(row=0, column=1, pady=5, padx=5)
ttk.Button(file_frame, text="Browse", command=self.browse_file).grid(row=0, column=2, pady=5, padx=5)
ttk.Label(file_frame, text="Remote Path:").grid(row=1, column=0, sticky=tk.W, pady=5)
self.remote_path_entry = ttk.Entry(file_frame, width=50)
self.remote_path_entry.insert(0, "/home/username/")
self.remote_path_entry.grid(row=1, column=1, pady=5, padx=5)
# Progress and Log
progress_frame = ttk.LabelFrame(main_frame, text="Progress & Log", padding="10")
progress_frame.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S), pady=5)
self.progress = ttk.Progressbar(progress_frame, mode='indeterminate')
self.progress.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5)
self.log_text = tk.Text(progress_frame, height=12, width=80)
self.log_text.grid(row=1, column=0, columnspan=2, pady=5)
scrollbar = ttk.Scrollbar(progress_frame, orient="vertical", command=self.log_text.yview)
scrollbar.grid(row=1, column=2, sticky=(tk.N, tk.S))
self.log_text.configure(yscrollcommand=scrollbar.set)
# Buttons
button_frame = ttk.Frame(main_frame)
button_frame.grid(row=3, column=0, columnspan=2, pady=10)
self.transfer_btn = ttk.Button(button_frame, text="Transfer File", command=self.start_transfer)
self.transfer_btn.grid(row=0, column=0, padx=5)
ttk.Button(button_frame, text="Test Connection", command=self.test_connection).grid(row=0, column=1, padx=5)
ttk.Button(button_frame, text="Clear Log", command=self.clear_log).grid(row=0, column=2, padx=5)
ttk.Button(button_frame, text="Exit", command=self.root.quit).grid(row=0, column=3, padx=5)
def browse_file(self):
filename = filedialog.askopenfilename(
title="Select file to transfer",
filetypes=[("All files", "*.*")]
)
if filename:
self.local_file_entry.delete(0, tk.END)
self.local_file_entry.insert(0, filename)
def log_message(self, message):
self.log_text.insert(tk.END, f"{message}\n")
self.log_text.see(tk.END)
self.root.update_idletasks()
def clear_log(self):
self.log_text.delete(1.0, tk.END)
def test_connection(self):
"""Test SSH connection without file transfer"""
if not self.validate_basic_inputs():
return
thread = threading.Thread(target=self._test_connection)
thread.daemon = True
thread.start()
def _test_connection(self):
try:
host = self.host_entry.get()
port = int(self.port_entry.get())
username = self.username_entry.get()
password = self.password_entry.get()
self.log_message(f"Testing connection to {host}:{port}...")
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, port=port, username=username, password=password, timeout=10)
self.log_message("✓ Connection successful!")
ssh.close()
except Exception as e:
self.log_message(f"✗ Connection failed: {str(e)}")
def start_transfer(self):
if not self.validate_inputs():
return
self.transfer_btn.config(state='disabled')
self.progress.start()
# Run transfer in separate thread
thread = threading.Thread(target=self.transfer_file)
thread.daemon = True
thread.start()
def validate_basic_inputs(self):
if not self.host_entry.get():
messagebox.showerror("Error", "Please enter host address")
return False
if not self.username_entry.get():
messagebox.showerror("Error", "Please enter username")
return False
if not self.password_entry.get():
messagebox.showerror("Error", "Please enter password")
return False
return True
def validate_inputs(self):
if not self.validate_basic_inputs():
return False
if not self.local_file_entry.get():
messagebox.showerror("Error", "Please select local file")
return False
if not os.path.exists(self.local_file_entry.get()):
messagebox.showerror("Error", "Local file does not exist")
return False
return True
def transfer_file(self):
try:
host = self.host_entry.get()
port = int(self.port_entry.get())
username = self.username_entry.get()
password = self.password_entry.get()
local_file = self.local_file_entry.get()
remote_path = self.remote_path_entry.get()
self.log_message(f"Connecting to {host}:{port}...")
# Create SSH client
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Connect to server
ssh.connect(host, port=port, username=username, password=password)
self.log_message("✓ Connected successfully!")
# Get file info
file_size = os.path.getsize(local_file)
file_name = os.path.basename(local_file)
remote_file = os.path.join(remote_path, file_name).replace('\\', '/')
self.log_message(f"Transferring: {file_name}")
self.log_message(f"File size: {file_size} bytes")
self.log_message(f"Remote path: {remote_file}")
# Create SCP client and transfer file
with SCPClient(ssh.get_transport()) as scp:
scp.put(local_file, remote_file)
self.log_message("✓ File transferred successfully!")
# Verify file transfer
stdin, stdout, stderr = ssh.exec_command(f'ls -la "{remote_file}"')
result = stdout.read().decode()
if file_name in result:
self.log_message("✓ File verification: SUCCESS")
# Get file size on remote
stdin, stdout, stderr = ssh.exec_command(f'stat -c%s "{remote_file}"')
remote_size = stdout.read().decode().strip()
self.log_message(f"Remote file size: {remote_size} bytes")
else:
self.log_message("⚠ File verification: WARNING")
ssh.close()
self.log_message("Connection closed")
except paramiko.AuthenticationException:
self.log_message("✗ Authentication failed. Please check username/password.")
except paramiko.SSHException as e:
self.log_message(f"✗ SSH error: {str(e)}")
except Exception as e:
self.log_message(f"✗ ERROR: {str(e)}")
finally:
self.root.after(0, self.transfer_complete)
def transfer_complete(self):
self.progress.stop()
self.transfer_btn.config(state='normal')
def main():
root = tk.Tk()
app = SCPTransferApp(root)
root.mainloop()
if __name__ == "__main__":
main()
Simpan dengan nama aplikasi-scp.py
Setelah itu jalankan aplikasinya dengan perintah
python aplikasi-scp.py
jika tidak ada error, maka akan tampil seperti pada gambar berikut ini
