Subir archivos a "/"
This commit is contained in:
commit
78c9f8831e
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,44 @@
|
|||
#!/bin/bash
|
||||
# backup_script.sh
|
||||
# Script de Bash para simular una copia de seguridad en Linux.
|
||||
|
||||
# Directorio de destino para el backup y logs
|
||||
BACKUP_DIR="/tmp/BackupData"
|
||||
mkdir -p $BACKUP_DIR
|
||||
|
||||
# Obtener la fecha y hora actual
|
||||
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||
LOG_FILE="$BACKUP_DIR/backup_log_$TIMESTAMP.txt"
|
||||
|
||||
echo "--- Script de Copia de Seguridad Iniciado ($TIMESTAMP) ---" > $LOG_FILE
|
||||
echo "Creando directorio de destino: $BACKUP_DIR" >> $LOG_FILE
|
||||
|
||||
# Simular el proceso de copia de seguridad (ejemplo: comprimir /var/log)
|
||||
# Nota: Esto puede requerir permisos de sudo si /var/log no es accesible para tu usuario.
|
||||
# Usaremos /tmp para un ejemplo más seguro.
|
||||
echo "Simulando compresión de archivos de ejemplo..." >> $LOG_FILE
|
||||
# Creamos un archivo de ejemplo para copiar si no existe
|
||||
if [ ! -f "/tmp/archivos_a_copiar.txt" ]; then
|
||||
echo "Contenido de prueba" > /tmp/archivos_a_copiar.txt
|
||||
fi
|
||||
|
||||
# Simulación de la copia real (usando tar para crear un archivo)
|
||||
tar -czf "$BACKUP_DIR/backup_$TIMESTAMP.tar.gz" /tmp/archivos_a_copiar.txt >> $LOG_FILE 2>&1
|
||||
|
||||
# Simular la tarea con una pausa
|
||||
sleep 3
|
||||
|
||||
# Verificar si el archivo de backup se creó
|
||||
if [ -f "$BACKUP_DIR/backup_$TIMESTAMP.tar.gz" ]; then
|
||||
echo "Copia de seguridad completada con éxito." >> $LOG_FILE
|
||||
EXIT_CODE=0
|
||||
else
|
||||
echo "ERROR: Falló la creación del archivo de copia de seguridad." >> $LOG_FILE
|
||||
EXIT_CODE=1
|
||||
fi
|
||||
|
||||
echo "Log guardado en: $LOG_FILE" >> $LOG_FILE
|
||||
echo "--- Script de Copia de Seguridad Finalizado ---" >> $LOG_FILE
|
||||
|
||||
# Devolver el código de salida
|
||||
exit $EXIT_CODE
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
import sys
|
||||
import os
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
import datetime
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 1. LECTURA DE ARGUMENTOS
|
||||
# ---------------------------------------------------------------------------
|
||||
if len(sys.argv) < 7:
|
||||
print("Uso: python chat_client.py <mi_nombre> <otro_nombre> <f_salida> <f_entrada> <x> <y>")
|
||||
sys.exit(1)
|
||||
|
||||
MY_NAME = sys.argv[1] # Nombre de este cliente (ej: "Cliente A")
|
||||
OTHER_NAME = sys.argv[2] # Nombre del otro cliente (ej: "Cliente B")
|
||||
FILE_OUT = sys.argv[3] # Fichero donde YO escribo mis mensajes
|
||||
FILE_IN = sys.argv[4] # Fichero donde YO leo los mensajes del otro
|
||||
X_POS = int(sys.argv[5]) # Posición horizontal de la ventana
|
||||
Y_POS = int(sys.argv[6]) # Posición vertical de la ventana
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 2. COMUNICACIÓN IPC POR FICHERO
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Contador de líneas ya leídas. Así en cada polling solo procesamos
|
||||
# las líneas NUEVAS, no releemos todo el fichero desde el principio.
|
||||
lines_read = 0
|
||||
|
||||
def write_message(text):
|
||||
"""
|
||||
Escribe un mensaje en el fichero de salida (el que lee el otro cliente).
|
||||
Formato de cada línea: HH:MM|texto\n
|
||||
Usamos modo "a" (append) para no borrar mensajes anteriores.
|
||||
"""
|
||||
with open(FILE_OUT, "a", encoding="utf-8") as f:
|
||||
timestamp = datetime.datetime.now().strftime("%H:%M")
|
||||
f.write(f"{timestamp}|{text}\n")
|
||||
|
||||
def read_new_messages():
|
||||
"""
|
||||
Lee el fichero de entrada y devuelve SOLO las líneas nuevas
|
||||
desde la última vez que se llamó a esta función.
|
||||
Devuelve una lista de tuplas (timestamp, texto).
|
||||
"""
|
||||
global lines_read
|
||||
new = []
|
||||
try:
|
||||
with open(FILE_IN, "r", encoding="utf-8") as f:
|
||||
all_lines = f.readlines()
|
||||
# Solo procesamos desde la línea lines_read en adelante
|
||||
for line in all_lines[lines_read:]:
|
||||
line = line.strip()
|
||||
if line and "|" in line:
|
||||
ts, msg = line.split("|", 1) # Separamos timestamp del texto
|
||||
new.append((ts, msg))
|
||||
# Actualizamos el contador para la próxima llamada
|
||||
lines_read = len(all_lines)
|
||||
except Exception:
|
||||
pass # Si el fichero no existe aún, simplemente no hay mensajes
|
||||
return new
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 3. INTERFAZ GRÁFICA (Tkinter)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
COLOR_BG = "#F0F4F8" # Fondo general (gris claro)
|
||||
COLOR_HEADER = "#2C3E50" # Cabecera (azul oscuro)
|
||||
COLOR_MY_BG = "#DCF8C6" # Burbujas propias (verde tipo WhatsApp)
|
||||
COLOR_OTHER_BG = "#FFFFFF" # Burbujas del otro (blanco)
|
||||
COLOR_SEND_BTN = "#25D366" # Botón enviar (verde)
|
||||
FONT_MSG = ("Segoe UI", 10)
|
||||
FONT_HEADER = ("Segoe UI", 12, "bold")
|
||||
|
||||
root = tk.Tk()
|
||||
root.title(f"Chat — {MY_NAME}")
|
||||
root.geometry(f"500x700+{X_POS}+{Y_POS}") # Tamaño y posición inicial
|
||||
root.minsize(360, 400) # Tamaño mínimo para que no se deforme
|
||||
root.resizable(True, True)
|
||||
root.configure(bg=COLOR_BG)
|
||||
|
||||
# --- Layout con grid: 3 filas ---
|
||||
# fila 0 = cabecera (altura fija, weight=0)
|
||||
# fila 1 = mensajes (crece/encoge, weight=1)
|
||||
# fila 2 = input (altura fija, weight=0)
|
||||
# Usar weight=0 en las filas del input y cabecera garantiza que
|
||||
# siempre tienen su espacio reservado sin importar el tamaño de la ventana.
|
||||
root.grid_rowconfigure(0, weight=0)
|
||||
root.grid_rowconfigure(1, weight=1)
|
||||
root.grid_rowconfigure(2, weight=0)
|
||||
root.grid_columnconfigure(0, weight=1)
|
||||
|
||||
# --- FILA 0: Cabecera ---
|
||||
header = tk.Frame(root, bg=COLOR_HEADER, pady=10)
|
||||
header.grid(row=0, column=0, sticky="ew")
|
||||
|
||||
tk.Label(
|
||||
header,
|
||||
text=f"💬 {MY_NAME} → {OTHER_NAME}",
|
||||
bg=COLOR_HEADER, fg="white",
|
||||
font=FONT_HEADER, anchor="w", padx=15
|
||||
).pack(side="left")
|
||||
|
||||
tk.Label(
|
||||
header, text="● Conectado",
|
||||
bg=COLOR_HEADER, fg="#2ECC71",
|
||||
font=("Segoe UI", 9)
|
||||
).pack(side="right", padx=15)
|
||||
|
||||
# --- FILA 1: Área de mensajes (Canvas con scroll) ---
|
||||
# Usamos un Canvas porque tk.Frame no tiene scrollbar nativa.
|
||||
# El truco es poner un Frame dentro del Canvas y ajustar su ancho
|
||||
# al del Canvas cada vez que este cambia de tamaño (on_canvas_configure).
|
||||
messages_outer = tk.Frame(root, bg=COLOR_BG)
|
||||
messages_outer.grid(row=1, column=0, sticky="nsew", padx=8, pady=(8, 4))
|
||||
messages_outer.grid_rowconfigure(0, weight=1)
|
||||
messages_outer.grid_columnconfigure(0, weight=1)
|
||||
|
||||
canvas_msgs = tk.Canvas(messages_outer, bg=COLOR_BG, highlightthickness=0)
|
||||
canvas_msgs.grid(row=0, column=0, sticky="nsew")
|
||||
|
||||
scrollbar = ttk.Scrollbar(messages_outer, command=canvas_msgs.yview)
|
||||
scrollbar.grid(row=0, column=1, sticky="ns")
|
||||
canvas_msgs.configure(yscrollcommand=scrollbar.set)
|
||||
|
||||
# Frame real donde se añaden las burbujas de mensaje
|
||||
messages_frame = tk.Frame(canvas_msgs, bg=COLOR_BG)
|
||||
canvas_window = canvas_msgs.create_window((0, 0), window=messages_frame, anchor="nw")
|
||||
|
||||
def on_frame_configure(event):
|
||||
"""Actualiza la zona de scroll cuando el frame de mensajes cambia de tamaño."""
|
||||
canvas_msgs.configure(scrollregion=canvas_msgs.bbox("all"))
|
||||
|
||||
def on_canvas_configure(event):
|
||||
"""Ajusta el ancho del frame interior al ancho del canvas (responsivo)."""
|
||||
canvas_msgs.itemconfig(canvas_window, width=event.width)
|
||||
|
||||
messages_frame.bind("<Configure>", on_frame_configure)
|
||||
canvas_msgs.bind("<Configure>", on_canvas_configure)
|
||||
|
||||
# Mensaje de sistema al inicio del chat
|
||||
tk.Label(
|
||||
messages_frame,
|
||||
text=f"── Inicio del chat con {OTHER_NAME} ──",
|
||||
bg=COLOR_BG, fg="#AAAAAA",
|
||||
font=("Segoe UI", 9, "italic")
|
||||
).pack(pady=(10, 5))
|
||||
|
||||
def add_bubble(text, is_mine, timestamp=None):
|
||||
"""
|
||||
Añade una burbuja de mensaje al área de chat.
|
||||
- is_mine=True → burbuja verde a la derecha (mensaje propio)
|
||||
- is_mine=False → burbuja blanca a la izquierda (mensaje recibido)
|
||||
"""
|
||||
if timestamp is None:
|
||||
timestamp = datetime.datetime.now().strftime("%H:%M")
|
||||
|
||||
bg_color = COLOR_MY_BG if is_mine else COLOR_OTHER_BG
|
||||
side = "right" if is_mine else "left"
|
||||
anchor = "e" if is_mine else "w"
|
||||
label = "Tú" if is_mine else OTHER_NAME
|
||||
|
||||
# Fila contenedora (ocupa todo el ancho para poder alinear la burbuja)
|
||||
row = tk.Frame(messages_frame, bg=COLOR_BG)
|
||||
row.pack(fill="x", pady=3, padx=8)
|
||||
|
||||
# Burbuja real (solo tan ancha como su contenido)
|
||||
bubble = tk.Frame(row, bg=bg_color, padx=10, pady=6)
|
||||
bubble.pack(side=side, anchor=anchor)
|
||||
|
||||
tk.Label(bubble, text=label, bg=bg_color, fg="#888888",
|
||||
font=("Segoe UI", 8, "bold")).pack(anchor="w")
|
||||
tk.Label(bubble, text=text, bg=bg_color, fg="#222222",
|
||||
font=FONT_MSG, wraplength=280, justify="left").pack(anchor="w")
|
||||
tk.Label(bubble, text=timestamp, bg=bg_color, fg="#AAAAAA",
|
||||
font=("Segoe UI", 7)).pack(anchor="e")
|
||||
|
||||
# Scroll automático al fondo al recibir/enviar un mensaje
|
||||
root.after(50, lambda: canvas_msgs.yview_moveto(1.0))
|
||||
|
||||
# --- FILA 2: Área de entrada de texto ---
|
||||
input_frame = tk.Frame(root, bg="#E8ECF0", pady=8, padx=8)
|
||||
input_frame.grid(row=2, column=0, sticky="ew")
|
||||
input_frame.grid_columnconfigure(0, weight=1)
|
||||
|
||||
text_entry = tk.Text(
|
||||
input_frame,
|
||||
height=3, # 3 líneas de alto
|
||||
font=FONT_MSG,
|
||||
bg="#FFFFFF", fg="#222222",
|
||||
relief="flat", wrap="word",
|
||||
padx=8, pady=6,
|
||||
bd=1,
|
||||
highlightbackground="#CCCCCC",
|
||||
highlightthickness=1
|
||||
)
|
||||
text_entry.grid(row=0, column=0, sticky="ew", padx=(0, 8))
|
||||
|
||||
def send_message(event=None):
|
||||
"""
|
||||
Recoge el texto del entry, lo escribe en el fichero de salida
|
||||
y añade la burbuja propia en pantalla.
|
||||
Devuelve "break" para que el Enter no inserte un salto de línea.
|
||||
"""
|
||||
msg = text_entry.get("1.0", "end-1c").strip()
|
||||
if not msg:
|
||||
return "break"
|
||||
write_message(msg) # Escribe en el fichero de cola
|
||||
add_bubble(msg, is_mine=True) # Muestra la burbuja en nuestra ventana
|
||||
text_entry.delete("1.0", "end") # Limpia el campo de texto
|
||||
return "break"
|
||||
|
||||
# Enter envía el mensaje; Shift+Enter inserta salto de línea
|
||||
text_entry.bind("<Return>", send_message)
|
||||
text_entry.bind("<Shift-Return>", lambda e: None)
|
||||
|
||||
tk.Button(
|
||||
input_frame,
|
||||
text="Enviar ➤",
|
||||
bg=COLOR_SEND_BTN, fg="white",
|
||||
font=("Segoe UI", 10, "bold"),
|
||||
relief="flat", padx=12, pady=8,
|
||||
cursor="hand2",
|
||||
command=send_message
|
||||
).grid(row=0, column=1)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 4. POLLING DE MENSAJES ENTRANTES
|
||||
# ---------------------------------------------------------------------------
|
||||
def poll_incoming():
|
||||
new_msgs = read_new_messages()
|
||||
for ts, msg in new_msgs:
|
||||
add_bubble(msg, is_mine=False, timestamp=ts) # Burbuja del otro
|
||||
root.after(300, poll_incoming) # Volvemos a llamarnos en 300ms
|
||||
|
||||
root.after(300, poll_incoming) # Primera llamada al arrancar
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 5. BUCLE PRINCIPAL
|
||||
# ---------------------------------------------------------------------------
|
||||
root.mainloop()
|
||||
Loading…
Reference in New Issue