Comandos de Linux que todo dev necesita saber

1. Visión general

Todo dev alguna vez ha hecho SSH a un servidor, abierto una terminal para debuggear o desplegar una app, y luego se ha visto tratando de encontrar el comando correcto. Este artículo recopila los comandos de Linux más usados en el trabajo diario: gestión de archivos, búsqueda, procesamiento de texto, monitoreo de procesos, verificación de red, visualización de logs. Después de leerlo, tendrás un conjunto de comandos “vitales” para debuggear rápidamente sin necesidad de recurrir a Google cada vez.

Uso bash en Ubuntu/Debian como ejemplo principal, estos comandos son prácticamente los mismos en cualquier distribución.

2. Operaciones básicas con archivos y directorios

mkdir -p ~/projects/order-service/src/main/java
cd ~/projects/order-service
touch application.properties
ls -la
  • mkdir -p crea árboles de directorios anidados y no reporta error si el directorio ya existe.
  • touch crea un archivo vacío (o actualiza la marca de tiempo si ya existe).
  • ls -la lista todos los archivos (incluyendo ocultos como .env, .git) con permisos, propietario y tamaño.
drwxr-xr-x  3 nonla nonla 4096 Oct  5 10:00 .
-rw-r--r--  1 nonla nonla    0 Oct  5 10:00 application.properties

Algunos comandos de movimiento/eliminación requieren cuidado:

cp -r src/ src-backup/     # copia recursivamente el directorio
mv OrderService.java OrderServiceImpl.java   # renombra o mueve
rm -rf target/            # elimina recursivamente, sin preguntar

Nota: rm -rf no tiene papelera de reciclaje, la eliminación es permanente. Siempre verifica la ruta con pwd antes de ejecutar, especialmente al copiar y pegar comandos de otros lugares.

3. Búsqueda con find y grep

3.1. find — buscar archivos por condición

find . -name "*.java" -newer pom.xml

Este comando busca todos los archivos .java modificados después de pom.xml — útil para saber qué archivos han cambiado antes de hacer commit.

find . -type f -size +10M

Busca archivos mayores de 10MB, usualmente para limpiar logs o artefactos de compilación que ocupan espacio.

3.2. grep — buscar contenido en archivos

grep -rn "PaymentService" --include="*.java" src/
  • -r busca recursivamente en subdirectorios.
  • -n imprime junto con el número de línea.
  • --include limita solo a archivos .java, evitando buscar en target/.
src/main/java/com/nonla/OrderController.java:15:    private final PaymentService paymentService;

Combina grep con find mediante pipe cuando necesitas filtros más complejos:

find . -name "*.log" | xargs grep -l "OutOfMemoryError"

xargs pasa la lista de archivos de find a grep -l (imprime solo nombres de archivos que contienen el patrón, no el contenido).

4. Procesamiento de texto con awk, sed, cut

Este es el grupo de comandos “come-logs” — extremadamente potente cuando necesitas extraer datos de outputs largos.

cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -5
  • awk '{print $1}' obtiene la primera columna (usualmente la IP) de cada línea de log.
  • sort | uniq -c agrupa y cuenta el número de apariciones.
  • sort -rn ordena descendentemente por número, head -5 obtiene los top 5.
    152 192.168.1.10
     98 10.0.0.5
     47 172.16.0.3

Esta es la forma más rápida de encontrar la IP que hace más requests sin necesidad de escribir un script.

sed se usa para reemplazar texto directamente en un archivo:

sed -i 's/spring.profiles.active=dev/spring.profiles.active=prod/' application.properties

-i modifica el archivo directamente (in-place). Si quieres ser más seguro, usa sed -i.bak '...' para crear automáticamente un archivo de respaldo .bak.

cut separa columnas por delimitador, más ligero que awk cuando solo necesitas una columna simple:

cat /etc/passwd | cut -d: -f1 | head -3

5. Monitoreo de procesos y recursos del sistema

ps aux | grep java

Lista todos los procesos, filtra líneas que contienen java — forma rápida de saber si tu app Spring Boot está corriendo y cuál es su PID.

nonla    12345  2.1  5.3 2345678 432100 ?      Sl   10:00   0:15 java -jar order-service.jar

La segunda columna es el PID. Usa este PID para matar el proceso o ver detalles:

kill -15 12345     # envía SIGTERM, permite que la app haga graceful shutdown
kill -9 12345       # force kill, solo usa cuando -15 no funciona

Nota: kill -9 no permite que la app ejecute shutdown hooks (por ejemplo cerrar el connection pool, flush de logs). Siempre intenta -15 primero.

Visualiza los recursos en tiempo real:

top -o %MEM

-o %MEM ordena procesos por RAM usado — útil cuando sospechas un memory leak. Si quieres una interfaz más bonita, instala htop.

Verifica el disco:

df -h
du -sh /var/log/*

df -h muestra el espacio de cada partición (en formato legible). du -sh muestra cuánto espacio usa cada subdirectorio en /var/log — imprescindible cuando el servidor reporta “no space left on device”.

6. Verificación de red y puertos

ss -tulnp | grep 8080
  • ss reemplaza al viejo netstat, más rápido.
  • -t TCP, -u UDP, -l escuchando, -n numérico (sin resolver DNS), -p con el proceso.
tcp   LISTEN  0  128  0.0.0.0:8080  0.0.0.0:*  users:(("java",pid=12345,fd=45))

Sabes inmediatamente que el puerto 8080 está siendo usado por el proceso Java PID 12345 — muy útil cuando encuentras el error Address already in use.

Prueba API rápidamente con curl:

curl -s -X POST http://localhost:8080/api/orders \
  -H "Content-Type: application/json" \
  -d '{"customerId":1,"amount":99.5}'

-s silencioso (oculta la barra de progreso), -X POST especifica el método, -d cuerpo JSON. Añade -i si quieres ver también los headers de la respuesta.

El comando lsof se usa cuando necesitas saber exactamente qué archivos/sockets tiene abiertos un proceso:

lsof -i :8080

7. Permisos de acceso a archivos

chmod +x deploy.sh
chown nonla:nonla application.properties
chmod 640 .env
  • chmod +x permite ejecutar el script.
  • chown user:group cambia el propietario — usualmente necesitas sudo si el archivo pertenece a otro usuario.
  • chmod 640 significa el propietario puede leer/escribir (6), el grupo solo leer (4), otros no tienen permisos (0) — estándar para archivos secretos como .env.
-rw-r----- 1 nonla nonla 128 Oct  5 10:00 .env

Nota: nunca hagas chmod 777 en producción. Es la forma más rápida para que cualquier usuario en la máquina pueda leer/modificar tus archivos sensibles.

8. Compresión y descompresión

tar -czvf order-service.tar.gz order-service/
tar -xzvf order-service.tar.gz -C /opt/apps/
  • -c crea un archivo, -x descomprime, -z usa gzip, -v verbose, -f especifica el nombre del archivo.
  • -C al descomprimir especifica el directorio de destino en lugar de descomprimir en el directorio actual.

Al desplegar, combina con scp o rsync para empujar archivos al servidor:

scp order-service.tar.gz user@10.0.0.5:/opt/apps/
rsync -avz --progress target/*.jar user@10.0.0.5:/opt/apps/

rsync solo transmite las partes de datos que cambiaron (delta transfer), mucho más rápido que scp cuando actualizas archivos grandes múltiples veces.

9. Visualización de logs en tiempo real

tail -f /var/log/order-service/app.log

-f (follow) mantiene la terminal abierta e imprime nuevas líneas en tiempo real cuando se escriben en el archivo — comando imprescindible para debuggear en producción.

Filtra logs por patrón cuando usas tail:

tail -f app.log | grep --line-buffered "ERROR"

--line-buffered es necesario porque grep por defecto buferea por bloque, sin esta bandera el output puede retrasarse cuando haces pipe con tail -f.

Si la app se ejecuta bajo systemd, usa journalctl en lugar de buscar archivos de log manualmente:

journalctl -u order-service -f --since "10 minutes ago"

-u especifica la unidad de servicio, -f follow, --since limita el tiempo — evita tener que leer millones de líneas de logs antiguos.

10. Ejecutar comandos de Linux desde Java

A menudo necesitas llamar comandos shell directamente desde código Java, por ejemplo verificar el espacio en disco antes de escribir un archivo grande:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.List;

public class ShellRunner {

    public static String run(List<String> command) throws Exception {
        ProcessBuilder builder = new ProcessBuilder(command);
        builder.redirectErrorStream(true);
        Process process = builder.start();

        try (BufferedReader reader =
                new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String output = reader.lines().reduce("", (a, b) -> a + b + "\n");
            process.waitFor();
            return output;
        }
    }
}
  • ProcessBuilder recibe una lista de argumentos (no una cadena de comando concatenada manualmente, evita shell injection).
  • redirectErrorStream(true) fusiona stderr con stdout para leer un solo flujo.
  • process.waitFor() bloquea el thread actual hasta que el proceso hijo termine.

Prueba con JUnit 5 + AssertJ:

import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;

class ShellRunnerTest {

    @Test
    void shouldReturnCurrentDirectoryListing() throws Exception {
        String output = ShellRunner.run(List.of("ls", "-la"));

        assertThat(output).contains("total");
    }
}

Esta prueba ejecuta ls -la realmente en el sistema y verifica que el output contenga la línea total (la primera línea que ls -la siempre imprime con el número total de bloques) — confirma que ProcessBuilder realmente puede llamar comandos shell.

Nota: llamar comandos shell desde código Java en producción es un arma de doble filo — fácil de volverse dependiente del OS, difícil de testear, y riesgo de inyección si los argumentos provienen de entrada del usuario. Usa solo para herramientas internas o scripts operacionales, evita usarlo para lógica de negocio crítica.

11. Errores comunes

  • Ejecutar rm -rf con una variable de entorno vacía, por ejemplo rm -rf $DIR/* cuando $DIR no está definida — eliminar accidentalmente el directorio raíz. Siempre usa set -u en scripts o verifica la variable antes.
  • Olvidar sudo cuando necesitas permisos de root, causando un error vago Permission denied — verifica con ls -la antes de culpar a la app.
  • Usar kill -9 por costumbre, haciendo que la app Spring Boot no tenga tiempo de cerrar el connection pool, causando leaks en la base de datos.
  • Hacer pipe de grep después de tail -f olvidando --line-buffered, pensando que el log no funciona pero en realidad está siendo buffered.
  • Ejecutar chmod 777 para “pasar rápido el error de permisos” — crea una vulnerabilidad de seguridad, especialmente peligroso con archivos .env o claves SSH.

12. Conclusión

Los comandos en este artículo — find, grep, awk/sed, ps/kill, ss/curl, tar, tail -f, journalctl — son el conjunto mínimo de herramientas para que debuggees por ti mismo sin necesidad de esperar al equipo de DevOps. Dominarlos no significa memorizar todas las banderas, solo necesitas saber qué comando resuelve qué problema y consultar man cuando necesites detalles. La terminal sigue siendo la herramienta de debug más rápida, incluso cuando tienes Grafana, Kibana o herramientas de APM disponibles.

linuxdevopsbashproductividadjava