En Linux, cada proceso tiene tres flujos de datos estandar abiertos por defecto, identificados por descriptores de archivo (file descriptors):
Descriptor
Nombre
Abreviatura
Descripcion
Dispositivo por defecto
0
Entrada estandar
stdin
Datos que entran al proceso
Teclado
1
Salida estandar
stdout
Datos que salen del proceso (resultado)
Pantalla (terminal)
2
Error estandar
stderr
Mensajes de error del proceso
Pantalla (terminal)
Concepto fundamental
Todo en Linux es un archivo. Los descriptores de archivo son numeros enteros que el kernel asigna a cada flujo abierto. Los tres primeros (0, 1, 2) se abren automaticamente para cada proceso. Los procesos pueden abrir descriptores adicionales (3, 4, 5…) para archivos, sockets, etc.
IMPORTANTE para el examen: stdout (1) y stderr (2) van ambos a la pantalla por defecto, pero son flujos separados que se pueden redirigir de forma independiente.
2. Redireccion de salida estandar (stdout)
Redirigir a archivo (sobreescribir): >
El operador > redirige stdout a un archivo. Si el archivo existe, lo sobreescribe.
ls /etc > listado.txt # Guarda la salida de ls en listado.txtecho "Hola mundo" > saludo.txt # Crea/sobreescribe saludo.txtdate > fecha.txt # Guarda la fecha actual en fecha.txt
Equivalencia:
ls > archivo.txt # Forma abreviadals 1> archivo.txt # Forma explicita (descriptor 1)
Redirigir a archivo (anadir): >>
El operador >> redirige stdout a un archivo sin sobreescribirlo (append/anadir al final):
echo "Primera linea" > log.txt # Crea el archivoecho "Segunda linea" >> log.txt # Anade al finalecho "Tercera linea" >> log.txt # Anade otra lineadate >> registro.txt # Anade la fecha al final del registro
Proteccion contra sobreescritura: noclobber
set -o noclobber # Activa proteccion: > no sobreescribe archivos existentesls > archivo.txt # Error si archivo.txt ya existels >| archivo.txt # Fuerza la sobreescritura aunque noclobber este activoset +o noclobber # Desactiva la proteccion
3. Redireccion de entrada estandar (stdin)
Redirigir desde archivo: <
El operador < usa un archivo como entrada estandar en lugar del teclado:
sort < nombres.txt # sort lee del archivo en vez del tecladowc -l < /etc/passwd # Cuenta lineas de /etc/passwdtr 'a-z' 'A-Z' < archivo.txt # tr convierte a mayusculas leyendo del archivomail usuario@dominio.com < mensaje.txt # Envia el archivo como cuerpo del correo
Diferencia entre < y argumento de archivo
# Ambos producen la misma salida, pero funcionan diferente:sort < nombres.txt # El SHELL abre el archivo y se lo pasa a sort como stdinsort nombres.txt # sort MISMO abre el archivo
La diferencia practica: con <, el comando no sabe el nombre del archivo (solo recibe datos por stdin). Con argumento, el comando abre el archivo directamente.
4. Redireccion de error estandar (stderr)
Redirigir errores a archivo: 2>
ls /directorio_inexistente 2> errores.txt # Redirige errores a un archivofind / -name "*.conf" 2> /dev/null # Descarta los errores
Anadir errores a archivo: 2>>
ls /no_existe 2>> log_errores.txt # Anade errores al archivoscript.sh 2>> errores.log # Acumula errores de ejecucion
Ejemplo completo: separar stdout y stderr
find / -name "*.conf" > resultados.txt 2> errores.txt# stdout va a resultados.txt# stderr va a errores.txt
5. Combinar stdout y stderr
Redirigir ambos al mismo archivo: &>
ls /etc /no_existe &> todo.txt # stdout Y stderr a todo.txtcomando &> /dev/null # Descarta TODA la salida (stdout + stderr)
Redirigir stderr a stdout: 2>&1
ls /etc /no_existe > todo.txt 2>&1 # Redirige stderr al mismo destino que stdoutcomando > salida.txt 2>&1 # Equivalente a &>
IMPORTANTE para el examen: El orden importa. 2>&1 redirige stderr a donde stdout apunte en ese momento:
# CORRECTO: primero redirige stdout, luego stderr sigue a stdoutcomando > archivo.txt 2>&1# INCORRECTO: 2>&1 redirige stderr a stdout (pantalla), luego stdout va al archivocomando 2>&1 > archivo.txt # stderr sigue yendo a la pantalla!
Anadir ambos: &>>
comando &>> log_completo.txt # Anade stdout Y stderr al archivo# Equivalente a:comando >> log_completo.txt 2>&1
6. /dev/null: el agujero negro
/dev/null es un archivo especial que descarta todo lo que se escribe en el. Leer de el produce inmediatamente un fin de archivo (EOF).
# Descartar salida estandarls > /dev/null # Descarta la salida normal# Descartar erroresfind / -name "*.txt" 2> /dev/null # Descarta errores de permisos# Descartar TODA la salidacomando &> /dev/null # Descarta stdout y stderrcomando > /dev/null 2>&1 # Equivalente# Vaciar un archivocat /dev/null > archivo.txt # Vacia el contenido del archivo> archivo.txt # Forma mas corta de vaciar un archivo
Para el examen: /dev/null es la forma estandar de descartar salida no deseada. Es un “sumidero” (sink) que acepta cualquier cantidad de datos y los descarta.
7. Pipes (tuberias): |
El pipe | conecta la salida estandar de un comando con la entrada estandar del siguiente comando. Es uno de los conceptos mas poderosos de Unix.
ls -l /etc | head -10 # Muestra solo las 10 primeras lineascat /etc/passwd | sort # Ordena las lineas de passwdps aux | grep apache # Busca procesos de apachedmesg | tail -20 # Ultimos 20 mensajes del kernelhistory | grep "git" # Busca comandos git en el historial
Encadenar multiples pipes
cat /etc/passwd | cut -d ":" -f 1 | sort | head -5# 1. Lee /etc/passwd# 2. Extrae el primer campo (usuarios)# 3. Ordena alfabeticamente# 4. Muestra los 5 primerosdu -sh /var/log/* | sort -h | tail -10# Muestra los 10 archivos mas grandes de /var/logcat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10# Top 10 IPs con mas accesos en un log de Apache
Pipe solo redirige stdout
El pipe solo pasa stdout al siguiente comando. stderr sigue yendo a la pantalla:
ls /etc /no_existe | wc -l# stderr (error de /no_existe) va a la pantalla# stdout (listado de /etc) va a wc -l# Para incluir stderr en el pipe:ls /etc /no_existe 2>&1 | wc -l# Ahora stderr tambien pasa por el pipe# En bash 4+, existe el operador |&ls /etc /no_existe |& wc -l # Pasa stdout Y stderr al pipe
8. tee: dividir la salida
tee lee de stdin y escribe simultaneamente en stdout y en uno o mas archivos. Es como una “T” en una tuberia de agua que divide el flujo.
ls -l | tee listado.txt # Muestra en pantalla Y guarda en archivols -l | tee listado.txt | wc -l # Guarda, muestra el conteo en pantallals -l | tee -a listado.txt # Anade al archivo en vez de sobreescribirls -l | tee archivo1.txt archivo2.txt # Escribe en multiples archivos
Diagrama de flujo con tee
+-------> archivo.txt
|
comando --> tee -----+
|
+-------> stdout (pantalla o siguiente pipe)
Uso practico: guardar salida intermedia en un pipeline
cat /etc/passwd | cut -d ":" -f 1 | tee usuarios.txt | sort | tee usuarios_ordenados.txt | wc -l# Guarda la lista sin ordenar, luego la ordenada, y muestra el conteo
Uso con sudo
# Esto NO funciona (la redireccion la hace el shell del usuario, no root):sudo echo "linea" > /etc/archivo_protegido# Esto SI funciona (tee se ejecuta como root):echo "linea" | sudo tee /etc/archivo_protegidoecho "linea" | sudo tee -a /etc/archivo_protegido # Anadir
9. xargs: construir comandos desde stdin
xargs lee datos de la entrada estandar y los convierte en argumentos para otro comando. Es esencial cuando un comando no acepta datos por stdin pero necesita recibirlos de un pipe.
Uso basico
# Sin xargs: echo solo muestra textofind /tmp -name "*.log" | echo # No funciona como se espera# Con xargs: convierte stdin en argumentosfind /tmp -name "*.log" | xargs rm # Elimina todos los .log encontradosfind /tmp -name "*.log" | xargs ls -l # Lista detalles de los .log
Opciones importantes
# -I {}: Define un placeholder para colocar el argumentofind . -name "*.txt" | xargs -I {} cp {} /backup/# Equivalente a: cp archivo1.txt /backup/ ; cp archivo2.txt /backup/ ; ...# -n N: Pasa N argumentos por invocacionecho "a b c d e f" | xargs -n 2 echo# echo a b# echo c d# echo e f# -d delimitador: Define el delimitador de entradaecho "a:b:c" | xargs -d ":" echo # echo a b c# -0: Usa null como delimitador (para nombres con espacios)find . -name "*.txt" -print0 | xargs -0 rm# -print0 en find y -0 en xargs usan \0 como delimitador# -p: Modo interactivo (pide confirmacion)find . -name "*.tmp" | xargs -p rm # Pregunta antes de ejecutar# -t: Muestra el comando antes de ejecutarlofind . -name "*.log" | xargs -t gzip # Muestra y ejecuta
Diferencia entre pipe y xargs
# Con pipe: wc recibe datos por stdincat archivo.txt | wc -l # wc lee de stdin# Con xargs: wc recibe el nombre del archivo como argumentoecho "archivo.txt" | xargs wc -l # Ejecuta: wc -l archivo.txt
Para el examen: xargs es necesario cuando el comando destino espera argumentos (no stdin). Por ejemplo, rm, cp, mv, chmod necesitan nombres de archivo como argumentos, no datos por stdin.
10. Here documents: << EOF
Un here document permite pasar un bloque de texto como entrada estandar a un comando, sin necesidad de un archivo externo. El texto se define entre un delimitador (tipicamente EOF, pero puede ser cualquier cadena).
cat << EOFEsta es la primera linea.Esta es la segunda linea.La variable HOME es $HOMEEOF
Caracteristicas
Las variables ($HOME, $USER) se expanden por defecto
Para evitar la expansion, usar comillas en el delimitador: << 'EOF'
# CON expansion de variablescat << EOFUsuario: $USERDirectorio: $HOMEEOF# SIN expansion de variables (comillas en el delimitador)cat << 'EOF'Usuario: $USERDirectorio: $HOMEEOF# Salida literal: $USER y $HOME no se expanden
Uso con tabulacion: <<-
El operador <<- permite usar tabulaciones al inicio de las lineas del here document (las elimina). Util para mantener la indentacion en scripts:
if true; then cat <<-EOF Esta linea esta indentada con tab Pero se mostrara sin la indentacion EOFfi
Uso practico
# Crear un archivo con contenidocat << EOF > /tmp/config.conf# Archivo de configuracionservidor=192.168.1.1puerto=8080EOF# Enviar comandos a un programa interactivomysql -u root << EOFCREATE DATABASE prueba;USE prueba;CREATE TABLE users (id INT, name VARCHAR(50));EOF# Script con multiples lineasssh usuario@servidor << EOFcd /var/logls -latail -5 syslogEOF
11. Here strings: <<<
Un here string es una version simplificada del here document que pasa una sola cadena como entrada estandar a un comando.
cat <<< "Hola Mundo" # Pasa "Hola Mundo" como stdin a catwc -w <<< "uno dos tres cuatro" # Cuenta palabras: 4tr 'a-z' 'A-Z' <<< "hola mundo" # Convierte a mayusculas: HOLA MUNDObc <<< "5 + 3" # Calcula: 8grep "error" <<< "este es un mensaje de error" # Busca en la cadena
Diferencia con echo + pipe
# Equivalentes:echo "Hola Mundo" | catcat <<< "Hola Mundo"# Pero here string es mas eficiente (no crea subproceso para echo)
Expansion de variables
read nombre <<< "Sandra"echo $nombre # Sandra# Las variables se expanden en here stringscat <<< "Mi directorio es $HOME"# Mi directorio es /home/sandra
12. Sustitucion de procesos: <() y >()
La sustitucion de procesos (process substitution) es una funcionalidad avanzada de bash que permite usar la salida de un comando como si fuera un archivo, o enviar datos a un comando como si fuera un archivo de salida.
Sustitucion de entrada: <(comando)
<(comando) ejecuta el comando y presenta su salida como un archivo temporal que puede ser leido.
# Comparar la salida de dos comandos como si fueran archivosdiff <(ls /dir1) <(ls /dir2)# Equivalente a crear archivos temporales manualmente:# ls /dir1 > /tmp/lista1.txt# ls /dir2 > /tmp/lista2.txt# diff /tmp/lista1.txt /tmp/lista2.txt# Comparar archivos ordenados sin crear archivos intermediosdiff <(sort archivo1.txt) <(sort archivo2.txt)# Usar con while read para evitar problemas con subshells en pipeswhile read linea; do echo "Procesando: $linea"done < <(find /etc -name "*.conf")
Sustitucion de salida: >(comando)
>(comando) crea un archivo temporal de escritura que se alimenta como entrada al comando.
# Enviar salida simultaneamente a un archivo y a un comandols -la | tee >(grep "\.txt$" > solo_txt.txt) >(wc -l > conteo.txt) > listado_completo.txt# Comprimir al vuelo mientras se copiatar cf >(gzip > backup.tar.gz) /datos/
Diferencia con pipes
Mecanismo
Descripcion
Ejemplo
Pipe |
Conecta stdout de un comando con stdin de otro
ls | wc -l
<(cmd)
Presenta stdout de un comando como un archivo de lectura
diff <(ls /a) <(ls /b)
>(cmd)
Presenta stdin de un comando como un archivo de escritura
tee >(wc -l)
Para el examen: La sustitucion de procesos es especifica de bash (no funciona en sh). Es particularmente util con diff para comparar la salida de dos comandos, y con while read para evitar problemas de subshell creados por pipes.
13. Named pipes (FIFOs): mkfifo
Una named pipe (tuberia con nombre) o FIFO (First In, First Out) es un archivo especial en el sistema de archivos que actua como un canal de comunicacion entre procesos. A diferencia de los pipes normales (|), las named pipes persisten en el sistema de archivos y pueden ser usadas por procesos no relacionados.
Crear una named pipe
mkfifo mi_pipe # Crea una named pipe llamada mi_pipemkfifo -m 644 mi_pipe # Crea con permisos especificosls -l mi_pipe # Muestra "prw-r--r--" (p = pipe)
Usar una named pipe
Las named pipes se usan con dos procesos: uno escribe y otro lee. El proceso escritor se bloquea hasta que alguien lea, y viceversa.
# Terminal 1 (escritor): se bloquea hasta que alguien leaecho "Hola desde otro proceso" > mi_pipe# Terminal 2 (lector): lee lo que el escritor enviocat < mi_pipe # Muestra: Hola desde otro proceso
Ejemplo practico
# Crear la named pipemkfifo /tmp/datos_pipe# Terminal 1: un proceso genera datos continuamentetail -f /var/log/syslog > /tmp/datos_pipe# Terminal 2: otro proceso los consumegrep "error" < /tmp/datos_pipe# Limpiarrm /tmp/datos_pipe
Caracteristicas de las named pipes
Aparecen en el sistema de archivos con tipo p (visible con ls -l)
Son FIFO: los datos se leen en el mismo orden en que se escribieron
Se bloquean: un extremo espera al otro
No almacenan datos en disco (el kernel los mantiene en memoria)
Se eliminan con rm como cualquier archivo
Pueden ser usadas por procesos que no tienen relacion entre si
Diferencia entre pipe normal y named pipe
Caracteristica
Pipe normal (|)
Named pipe (FIFO)
Persistencia
Solo durante la ejecucion
Persiste en el sistema de archivos
Visibilidad
Solo entre comandos del pipeline
Cualquier proceso puede usarla
Creacion
Automatica con |
Manual con mkfifo
Eliminacion
Automatica al terminar
Manual con rm
Relacion entre procesos
Misma linea de comandos
Pueden ser procesos independientes
14. Resumen de redirecciones
Operador
Descripcion
Ejemplo
>
Redirige stdout a archivo (sobreescribe)
ls > lista.txt
>>
Redirige stdout a archivo (anade)
echo "linea" >> log.txt
<
Redirige archivo a stdin
sort < datos.txt
2>
Redirige stderr a archivo (sobreescribe)
cmd 2> errores.txt
2>>
Redirige stderr a archivo (anade)
cmd 2>> errores.txt
&>
Redirige stdout+stderr a archivo
cmd &> todo.txt
&>>
Anade stdout+stderr a archivo
cmd &>> todo.txt
2>&1
Redirige stderr a donde apunte stdout
cmd > f.txt 2>&1
1>&2
Redirige stdout a donde apunte stderr
echo "error" 1>&2
|
Pipe: stdout del cmd1 a stdin del cmd2
ls | grep txt
|&
Pipe: stdout+stderr al siguiente cmd
cmd |& grep error
<< DELIM
Here document
cat << EOF ... EOF
<<< "cadena"
Here string
cat <<< "texto"
> /dev/null
Descarta stdout
cmd > /dev/null
2> /dev/null
Descarta stderr
cmd 2> /dev/null
&> /dev/null
Descarta todo
cmd &> /dev/null
Trampas del examen
Errores comunes y distinciones criticas que LPI suele evaluar en este subtema:
El orden de > y 2>&1 importa — cmd > archivo 2>&1 redirige stdout al archivo y luego stderr a donde apunte stdout (al archivo). Pero cmd 2>&1 > archivo redirige stderr a la terminal (donde apuntaba stdout originalmente) y solo stdout al archivo. El examen puede invertir el orden.
> sobreescribe; >> anade — echo "texto" > archivo destruye el contenido previo; echo "texto" >> archivo lo anade al final. El examen puede preguntar por que se perdio el contenido de un archivo tras usar >.
tee escribe a archivo Y stdout — comando | tee archivo envia la salida al archivo Y a la pantalla. Sin tee, la redireccion > solo va al archivo. tee -a anade en vez de sobreescribir.
xargs convierte stdin en argumentos — find . -name "*.tmp" | xargs rm pasa los nombres como argumentos a rm. Sin xargs, rm no recibiria nada porque lee argumentos, no stdin. El examen puede preguntar por que find | rm no funciona.
2> redirige stderr solamente — comando 2> errores.txt captura solo los errores. comando > salida.txt captura solo stdout. comando &> todo.txt captura ambos. El examen puede pedir redirigir SOLO los errores.
Here document << EOF expande variables; << 'EOF' no — Sin comillas en el delimitador, $HOME se expande. Con comillas simples (<< 'EOF'), el texto es literal. El examen puede preguntar como evitar la expansion de variables en un here document.
| solo pasa stdout, no stderr — El pipe estandar solo conecta stdout del primer comando con stdin del segundo. Para incluir stderr hay que usar |& o 2>&1 |. El examen puede preguntar por que los errores no aparecen tras el pipe.
/dev/null descarta datos silenciosamente — comando > /dev/null 2>&1 descarta toda la salida. El examen puede preguntar como ejecutar un comando sin producir ninguna salida visible.
Named pipes (mkfifo) persisten en el filesystem — A diferencia de |, una named pipe creada con mkfifo existe como archivo especial (tipo p) y puede ser usada por procesos no relacionados. El examen puede preguntar la diferencia entre pipe anonimo y named pipe.