Python : Aplikasi SCP: Difference between revisions
m (Protected "Python : Aplikasi SCP" ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))) |
No edit summary |
||
| (2 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
[[File:Aplikasi-python-scp.jpg|thumb|Aplikasi-python-scp]] | [[File:Aplikasi-python-scp.jpg|thumb|Aplikasi-python-scp]] | ||
Ini adalah script python untuk membuat aplikasi SCP di windows, tujuannya adalah untuk mempermudah kita melakukan copy file dari Windows ke Linux. | 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<syntaxhighlight lang="python"> | |||
pip install paramiko scp | |||
</syntaxhighlight>Setelah menjalankan perintah di atas, berikut adalah script pythinnya.<syntaxhighlight lang="python" line="1"> | |||
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() | |||
</syntaxhighlight>Simpan dengan nama <code>aplikasi-scp.py</code> | |||
Setelah itu jalankan aplikasinya dengan perintah<syntaxhighlight lang="python"> | |||
python aplikasi-scp.py | |||
</syntaxhighlight>jika tidak ada error, maka akan tampil seperti pada gambar berikut ini | |||
[[File:Aplikasi-python-scp.jpg]] | |||
Latest revision as of 07:10, 25 October 2025

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
