Administración de Sistemas Operativos – 2ASIR
Unidad 1. Aplicación de lenguajes de <<scripting>> en
sistemas operativos libres y propietarios
PARTE I.
Contenido
1. El Shell-Bash2
1.2 El nombre Bash4
1.3 Abrir una sesión con Bash5
1.4 Comandos básicos6
2. Expresiones regulares7
3. Variables del shell9
4. Operaciones aritméticas y lógicas en Shell Script15
4.1 Aritméticas15
4.2 Lógicas16
4.3 Expansión aritmética17
5. Redirección de la entrada y la salida19
6. Filtros y 'pipelines'26
7. Referencias28
Agustín Herrero Cola 1 | 29
Administración de Sistemas Operativos – 2ASIR
1. El Shell-Bash
No es un secreto que los sistemas operativos Unix/Linux se han
popularizado en los últimos años. Para los programadores que han utilizado
Unix/Linux durante muchos años, los sistemas Unix/Linux proveen una
plataforma eficiente y elegante para el desarrollo de sistemas.
Una de las principales características de estos sistemas es su gran colección de
más de 200 comandos básicos que se incluyen con el sistema operativo. Y su
principal fortaleza radica no solo en la gran cantidad de comandos, sino también
en la elegancia y facilidad con la que estos comandos pueden ser combinados
para realizar funciones más sofisticadas.
El Shell de Linux es un programa que lee los comandos y los convierte en una
forma más entendible para el sistema. Una de las grandes ventajas es que el
Shell es más que un simple intérprete de comandos, también es un lenguaje de
programación completo, con instrucciones, asignación, ciclos y funciones.
Uno de los aspectos que caracteriza un sistema operativo de tipo Unix es el
hecho de que es multiusuario, es decir, permite el uso del mismo ordenador a
más de un usuario al mismo tiempo (por ejemplo, a través de SSH). Para cada
sesión de usuario, el sistema genera un Shell propio para él que actúa
como intérprete interactivo de las órdenes que el usuario ejecuta, lo que
permite que los usuarios puedan elegir un Shell u otro de acuerdo con sus
necesidades.
El hecho de que el Shell esté separado del resto del sistema operativo
proporciona flexibilidad, porque permite seleccionar la interfaz más adecuada a
las necesidades de cada usuario.
Agustín Herrero Cola 2 | 29
Administración de Sistemas Operativos – 2ASIR
1. Shell, intermediario entre núcleo y aplicaciones
El archivo /etc/shells da información sobre los Shell válidos para iniciar sesión en
un sistema Unix determinado. Que sean válidos no significa que estén
instalados, si se quieren utilizar necesario que previamente nos aseguramos de
que están instalados en el sistema.
Ejemplo del fichero /etc/shells de un Ubuntu 22.04 LTS
2: Fichero shells
El Shell que se ejecuta por defecto cuando un usuario inicia sesión queda
definido en el archivo /etc/passwd, en el último campo de la línea
correspondiente al usuario.
Agustín Herrero Cola 3 | 29
Administración de Sistemas Operativos – 2ASIR
El Shell del usuario agustinherrero es /bin/bash. /bin/false es solo un binario
que sale inmediatamente, devolviendo falso, cuando se llama, por lo que cuando
alguien que tiene false como Shell inicia sesión, se desconecta inmediatamente
cuando sale falso. /sbin/nologin hace lo mismo, pero es menos restrictiva, ya
que no evita el acceso vía ftp al sistema, sin embargo, /bin/false cierra cualquier
tipo de entrada por consola, ssh, telnet y ftp al sistema.
Si hemos iniciado sesión con un usuario con un Shell determinado, en la misma
sesión podemos arrancar con un nuevo Shell.
A este le llamamos subshell o Shell hijo, que puede ser del mismo tipo o de uno
diferente disponible en el sistema. Para iniciar un subshell sencillamente
tenemos que escribir el nombre del programa (sh, bash, csh, ksh, etc.) en la línea
de comandos y pulsar la tecla de retorno. Si hemos cambiado de Shell, en
general, aparecerá un indicador de línea de comandos diferente, ya que cada
Shell tiene una apariencia diferente. Podemos finalizar la ejecución del subshell
y devolver al Shell padre escribiendo la orden exit.
Si tenemos un usuario ya creado, le podemos cambiar la shell o terminal a
utilizar, con el comando:
usermod -s “/bin/sh” usuario
1.2 El nombre Bash
Es un acrónimo de Bourne-Again Shell (“otro Shell Bourne"), haciendo un
juego de palabras (born-again significa "renacimiento") sobre el Shell Bourne
(sh), que fue uno de los primeros intérpretes importantes de Unix.
El Bash es un intérprete de comandos compatible con el Shell Bourne (sh), que
incorpora características útiles del Shell Korn (ksh) y del Shell C (csh), con el
objetivo de cumplir con el estándar POSIX (Es el acrónimo de Portable Operating
Agustín Herrero Cola 4 | 29
Administración de Sistemas Operativos – 2ASIR
System Interface. La X proviene de Unix. Una traducción aproximada del
acrónimo podría ser "interfaz de sistema operativo portátil basado en Unix".).
Bash ofrece mejoras funcionales sobre sh tanto para la programación como para
el uso interactivo y se ha convertido en el estándar de facto para la programación
de guiones de Shell.
NOTA: Como el Shell Bash (Bash) es compatible con el Shell Bourne (sh), las
órdenes y los programas escritos para sh pueden ser ejecutados con Bash sin
modificación, pero al revés no siempre es cierto.
1.3 Abrir una sesión con Bash
Cuando arranca, el sistema presenta a los usuarios una interfaz
determinada que puede ser de texto o gráfica, dependiendo de los sistemas
operativos o de cómo esté configurado el modo de arranque.
La interacción con Bash se hace a través de un emulador de terminal. Si hemos
iniciado sesión al sistema en modo consola (texto), una vez validados
obtendremos el acceso directo a un shell. Si hemos iniciado sesión en modo
gráfico, tendremos que ejecutar alguno de los programas de emulación de
terminal disponibles. La mayoría de los sistemas Unix disponen de una
aplicación de terminal accesible por alguna de las opciones del menú principal,
por ejemplo, la distribución de Linux Debian, por ejemplo, Ubuntu, accedemos a
un terminal desde
Aplicaciones > Accesorios > Terminal (depende de la versión y el escritorio
instalado).
Un shell hace lo siguiente:
1. Muestra por pantalla el indicador de la línea de comandos (el prompt)
señalando que está listo para aceptar órdenes.
2. Cuando el usuario introduce una orden, el shell la interpreta (busca las
órdenes, hace la expansión de nombres de ficheros, sustituye los valores
de variables para variables referenciadas, etc.).
Agustín Herrero Cola 5 | 29
Administración de Sistemas Operativos – 2ASIR
3. Si encuentra algún error muestra al usuario un mensaje de error.
4. Si la orden está bien escrita, entonces localiza el programa a ejecutar y
pide al sistema operativo que la ejecute, pasando a él el control.
5. Cuando finaliza la ejecución del programa, el control retorna al shell, que
vuelve a mostrar el prompt esperando una nueva orden.
Después de iniciar sesión, podemos comprobar cuál es el shell que tenemos
establecido por defecto y con el que estamos trabajando, ejecutando el siguiente
orden:
echo $SHELL
1.4 Comandos básicos
La función principal del shell es interpretar órdenes, ya sea las órdenes
escritas de manera interactiva en la interfaz de la línea de comandos que
proporciona, o las órdenes escritas en un archivo de texto (guión de shell).
Las órdenes que escribimos, ya sea en el indicador de la línea de comandos del
shell o en un programa de shell (por ejemplo, terminator), tienen el siguiente
formato:
• Nombre_comando [ -opciones ] [ argumentos ], donde:
• Nombre_comando: es el nombre del comando que queremos ejecutar.
• Opciones: las órdenes pueden o no llevar opciones. Normalmente las
opciones se escriben con un guion delante o con doble guión seguido de
una palabra.
• Argumentos: dependiendo de la orden, se pueden poner argumentos que
muchas veces representan una cadena de caracteres, el nombre de un
archivo o directorio.
El shell interpreta siempre el espacio en blanco como separador de órdenes,
opciones o argumentos. Si no ponemos los espacios correctamente,
obtendremos un mensaje de error.
Ejemplo de ejecución de comandos
Agustín Herrero Cola 6 | 29
Administración de Sistemas Operativos – 2ASIR
Es posible que una misma orden acepte diferentes modos de ejecución:
sin argumentos, con opciones, con argumentos. Por ejemplo, el comando ls:
Ls
Ls -l
2. Expresiones regulares
En Linux, las expresiones regulares son patrones utilizados para buscar y
manipular texto en archivos y comandos de línea de comandos. Las expresiones
regulares permiten buscar y hacer coincidir patrones específicos en el texto, lo
que es extremadamente útil para tareas como búsqueda, filtrado y manipulación
de datos. Aquí tienes una introducción a las expresiones regulares en Linux:
1. Metacaracteres básicos:
• `.` (punto): Coincide con cualquier carácter excepto el salto de línea.
• `*` (asterisco): Coincide con cero o más repeticiones del carácter o patrón
anterior.
• `+` (signo más): Coincide con una o más repeticiones del carácter o
patrón anterior.
• `?` (signo de interrogación): Coincide con cero o una repetición del
carácter o patrón anterior.
• `|` (barra vertical): Se utiliza para alternar entre diferentes patrones. Por
ejemplo, `patrón1|patrón2` coincidirá con cualquiera de los dos patrones.
• `[]` (corchetes): Se utiliza para definir un conjunto de caracteres que se
pueden coincidir. Por ejemplo, `[aeiou]` coincidirá con cualquier vocal.
• `[^]` (corchetes negativos): Coincide con cualquier carácter que no esté
en el conjunto especificado. Por ejemplo, `[^0-9]` coincidirá con cualquier
carácter que no sea un dígito.
• `()` (paréntesis): Se utiliza para agrupar patrones. Por ejemplo, `(abc)+`
coincidirá con una o más repeticiones de "abc".
Agustín Herrero Cola 7 | 29
Administración de Sistemas Operativos – 2ASIR
2. Metacaracteres de escape:
Puedes escapar metacaracteres especiales utilizando una barra invertida `\`.
Por ejemplo, para coincidir con un punto literal, debes usar `\.`.
3. Anclas:
- `^` (circunflejo): Coincide con el inicio de una línea.
- `$` (signo de dólar): Coincide con el final de una línea.
4. Ejemplos:
- `^abc`: Coincide con líneas que comienzan con "abc".
- `abc$`: Coincide con líneas que terminan con "abc".
- `[0-9]+`: Coincide con una secuencia de uno o más dígitos.
- `(\d{3}-\d{2}-\d{4})`: Coincide con un formato de número de seguridad social
en EE. UU.
- `colou?r`: Coincide con "color" o "colour" debido al uso del cuantificador `?`.
5. Ejemplo de generación de nombres de ficheros con expresiones
regulares:
Sitúate en el directorio /usr/bin y lista los nombres de archivos y directorios que
empiecen por c:
Los que empiecen por la letra y ó z: ls -l y* z* Los que terminen en .sh: ls -l *.sh:
Agustín Herrero Cola 8 | 29
Administración de Sistemas Operativos – 2ASIR
Los que empiecen por alguna letra comprendida entre la a y la d:
3. Variables del shell
En shell, una variable es un nombre que representa un valor. La sintaxis para
definir y asignar un valor a una variable es:
nombre_variable=valor
Ojo: ten en cuenta que no hay ningún espacio antes ni después del signo igual.
Si se pone algún obtendremos un error.
Los siguientes son ejemplos válidos de definición de variables:
NOMBRE=Agustin
APELLIDO="Herrero Cola"
EDAD=32
El valor asignado a la variable APELLIDOS la hemos cerrado entre comillas
dobles para que el shell no interprete el espacio que hay entre los dos apellidos.
Para evitar la posibilidad de cometer errores, podemos optar por poner el valor
siempre entre comillas dobles:
nombre_variable="valor"
Agustín Herrero Cola 9 | 29
Administración de Sistemas Operativos – 2ASIR
El valor de la variable siempre lo podemos cambiar asignándole otro valor (es
decir, es como si eliminamos la variable y la volvemos a crear con un nuevo
valor). Por ejemplo:
NOMBRE=Javier
El valor asociado a una variable puede ser utilizado mediante el nombre de la
variable precedido con el símbolo dólar:
$nombre_variable
Este mecanismo se llama sustitución de variables.
El shell realiza la sustitución de variables a cualquier línea de comandos que
contenga un símbolo $ seguido de un nombre de variable válido.
Podemos visualizar el valor de una variable definida con el orden echo y
utilizando el mecanismo de sustitución de variables:
echo $nombre_variable
Por ejemplo:
echo $APELLIDOS
Después de ejecutar la orden anterior, el valor asociado a la variable llamada
APELLIDOS se muestra por pantalla.
En la sustitución de variables se puede hacer uso de llaves para delimitar el
nombre de la variable: ${nom_variable}. La utilización de llaves nos permite, por
ejemplo, hacer la sustitución de la variable seguida de un texto. Por ejemplo:
Agustín Herrero Cola 10 | 29
Administración de Sistemas Operativos – 2ASIR
PREFIJO=extra
echo ${PREFIJO}ordinario
La orden anterior muestra por pantalla la palabra "extraordinario". Haciendo uso
de la misma variable PREFIJO podemos escribir la siguiente orden:
echo "Palabras que empiezan por $PREFIJO: ${PREFIJO}ordinario,
${PREFIJO}polar”
Por convención, los nombres de las variables se escriben en mayúsculas,
pero se pueden poner en minúsculas. Los nombres de las variables deben
empezar obligatoriamente por carácter alfabético (az, AZ) y pueden contener
caracteres alfabéticos, numéricos y subrayados. No hay restricciones respecto
al número de caracteres que puede tener el nombre de una variable.
Las variables pueden ser de dos tipos, variables locales o variables de entorno:
Variables locales: sólo son visibles por el shell en el que estamos trabajando,
no son visibles por ningún shell hijo.
Variables de entorno: son visibles tanto por shell padre como por los shells
hijos. Al ser creado, el shell hijo "hereda" las variables de entorno del padre
(recibe una copia). El shell hijo puede cambiar las variables heredadas del shell
padre, pero, al ser una copia, los cambios hechos en el hijo no afectan al padre.
Una variable definida en un proceso hijo, ya sea local o de entorno, no es visible
por su proceso padre.
La manera de hacer una variable, variable de entorno, es mediante la orden
export:
nombre_var = valor export nombre_var
La asignación y exportación se puede hacer en un solo paso:
export nombre_var = valor
Ejemplo de manipulación de variables locales y de entorno
Agustín Herrero Cola 11 | 29
Administración de Sistemas Operativos – 2ASIR
Ejecuta de manera secuencial las líneas de comandos siguientes:
Hay varias órdenes relacionadas con las variables:
• Orden set: permite ver todas las variables (locales y de entorno) definidas
en una sesión.
• Orden env: permite ver las variables de entorno definidas en una sesión.
Orden unset nom_variable: elimina la variable y el valor asociado a la
variable.
Variables de entorno predeterminadas: En cualquier sesión de shell Bash
están presentes una serie de variables de entorno predeterminadas por el
sistema que nos pueden resultar de mucha utilidad en la programación de
guiones de shell, ya que guardan información genérica del entorno de los
usuarios.
La siguiente tabla muestra el nombre y la descripción de algunas de estas
variables.
Agustín Herrero Cola 12 | 29
Administración de Sistemas Operativos – 2ASIR
Sustitución de órdenes o comandos
La sustitución de comandos se utiliza para reemplazar la salida de la ejecución
de una orden dentro de la misma línea de comandos.
Se puede hacer con la siguiente sintaxis:
1. $(orden)
2. Poniendo la orden entre acentos graves (tecla del circunflejo): `orden`.
Las dos formas son válidas, pero si estamos escribiendo un shell script es mejor
elegir una y utilizar la misma manera a lo largo de todo el programa.
Del mismo modo que en la sustitución de variables, la sustitución de órdenes se
hace siempre antes de ejecutar la línea de comandos. Cuando el shell encuentra
en la línea de comandos un $ seguido de un paréntesis abierto, ejecuta todo lo
Agustín Herrero Cola 13 | 29
Administración de Sistemas Operativos – 2ASIR
que encuentra hasta llegar al paréntesis cerrado. El resultado lo pone en la línea
de comandos en el lugar donde estaba el orden que sustituía.
Haciendo uso de la sustitución de comandos escribe una línea de comandos que
al ejecutarse la muestre por pantalla el texto: "La fecha del sistema es: fecha". El
valor de fecha se debe obtener del resultado de ejecutar la orden adecuada.
echo "La fecha del sistema es: $(date)"
También se podría haber hecho así:
echo “La fecha del sistema es: `date`”
La sustitución de órdenes es un mecanismo muy utilizado en la programación de
guiones de shell. Muchas veces se utiliza en la asignación de valores a variables.
Por ejemplo:
La orden date admite varios modificadores de formato de salida que se indican
con +%. Por ejemplo, date +%x indica la fecha del sistema con formato
dd/mm/aa.
HORA = $(date +%x)
$echo $HORA
Si la salida de la orden que sustituimos contiene saltos de línea, el shell los
sustituirá por espacios en blanco.
Por ejemplo, ejecuta el siguiente:
seq 10
La orden seq es utilizada para generar secuencias de números (para más
información ver man seq).
La orden anterior muestra por pantalla los números del 1 al 10 separado por
saltos de línea. Ahora introduce la misma orden en una sustitución de comandos,
por ejemplo:
$echo $(seq 10)
Agustín Herrero Cola 14 | 29
Administración de Sistemas Operativos – 2ASIR
El resultado de la orden anterior es la lista de números separados por espacios.
Ejemplo de uso de variables y sustitución de órdenes
Asignar a una variable la lista de números pares que hay entre el 0 y el 20
(incluidos) separados por espacios:
PARES = $(seq 0 2 20)
4. Operaciones aritméticas y lógicas en Shell Script
4.1 Aritméticas
En un Bash podemos realiza directamente sumas, restas, divisiones,
multiplicaciones y resto de números enteros. Para ello tendemos que poner la
operación dentro de $(( ))
Los operadores aritméticos en Bash:
Ejemplo:
Para operaciones con decimales tendríamos que ayudarnos de comandos
externos como bc.
Ejemplo:
Agustín Herrero Cola 15 | 29
Administración de Sistemas Operativos – 2ASIR
4.2 Lógicas
La finalidad de las operaciones lógicas es determinar si algo es verdadero o
falso. Para poder hacer multitud de comprobaciones, tenemos al orden test. Se
puede ejecutar con el comando test seguido de la comprobación que queremos
hacer, o delimitar la comprobación entre corchetes.
Es decir, si quiero comprobar si $A es igual a $B puedo poner test $A = $B, pero
también puedo poner [ $A = $B ]
Operaciones que podemos hacer con test
Comparación de números
Comparación de texto
Agustín Herrero Cola 16 | 29
Administración de Sistemas Operativos – 2ASIR
Comparaciones sobre ficheros y directorios
Otras expresiones
4.3 Expansión aritmética
El mecanismo de expansión aritmética del Bash permite la evaluación de una
expresión aritmética y la sustitución del resultado.
El formato para hacer la expansión aritmética es:
$((expresión_aritmética))
No confundir el mecanismo de sustitución de órdenes, $(orden)con el de
expansión aritmética, $((expresión)).
<Ejemplo>
La evaluación de expresiones aritméticas sólo admite números enteros.
Los operadores admitidos son casi los mismos que en el lenguaje de
programación C.
Agustín Herrero Cola 17 | 29
Administración de Sistemas Operativos – 2ASIR
La siguiente tabla muestra la lista de operadores existentes (no incluimos los que
operan con bits) en orden decreciente de precedencia. Podemos utilizar
paréntesis para alterar el orden de precedencia de los operadores.
En las expresiones se admiten tanto variables del shell como operandos y
podemos utilizarlas haciendo la expansión de la variable $nombre_var, o bien
sólo con su nombre, nombre_var. Por ejemplo, dadas dos variables con los
valores siguientes:
X=2 Y=3
La expresión siguiente:
Z=$((X + Y))
También la podemos escribir así: Z=$(($X + $Y))
El mecanismo de expansión aritmética nos permite realizar operaciones y
sustituir el resultado en otra orden, por ejemplo:
echo "El resultado de sumar $X y $Y es: $((X + Y))"
En el ejemplo anterior usamos la orden echo y en el argumento utilizamos la
expansión aritmética directamente para visualizar el resultado de la operación X
+ Y.
Tratamiento de los caracteres especiales
Agustín Herrero Cola 18 | 29
Administración de Sistemas Operativos – 2ASIR
Los caracteres especiales son aquellos que tienen algún significado concreto
para el shell, por ejemplo:
1. El carácter espacio indica separación de órdenes, opciones o
argumentos.
2. El carácter salto de línea indica final de orden.
3. El carácter $ delante de un nombre indica referenciar el valor de una
variable con ese nombre.
4. El carácter * es utilizado como expresión regular en la generación de
nombres de archivos.
Cuando no queremos que el shell interprete estos caracteres de manera especial
sino como caracteres normales, podemos anular su significado de las siguientes
formas:
• Precediendo el carácter del símbolo \. Esta técnica anula el significado
especial del carácter que va detrás.
• Con comillas dobles, "" . Esta técnica anula el significado de todos los
• Con comillas simples, '' (en el teclado es la tecla ? arriba y ‘ abajo). Esta
• técnica anula el significado de todos los caracteres especiales que estén
dentro de las comillas simples.
5. Redirección de la entrada y la salida
La redirección de entrada y salida en Linux es una característica fundamental
que te permite controlar cómo fluyen los datos dentro y fuera de los programas
y comandos en la línea de comandos.
Sobre entrada y salida
Cualquier comando que se ejecuta puede generar dos tipos de salida,
• un resultado. Es decir, aquello para lo que está pensado la herramienta
en cuestión. En el caso de ls, el resultado es el listado de archivos.
Agustín Herrero Cola 19 | 29
Administración de Sistemas Operativos – 2ASIR
• un estado. El estado se refiere a si la ejecución ha sido correcta. En caso
de que la ejecución no haya sido correcta devolverá un mensaje de error
para informar al usuario de los detalles de la ejecución.
En Linux existen tres tipos de archivos por defecto,
1. stdin ó 0. Está conectado con el teclado.
2. stdout ó 1. Este archivo está conectado con la pantalla.
3. stderr ó 2. Cuando se produce un error, este se envía a este archivo, que
también está conectado con la pantalla.
Redirigir entrada y salida te permite modificar tanto la entrada como la salida. Si
normalmente introduces información desde el teclado, stdin, podemos hacer
porque entre desde otro archivo, por ejemplo. Igualmente puedes proceder con
la salida, tal y como he comentado anteriormente.
Como redirigir entrada y salida
Redirigir salida
¿Como se puede redirigir entrada y salida estándar? Para esto tienes dos
operadores de redirección, > y <. Así, por ejemplo, para guardar el resultado
de ls en un archivo, tan solo tienes que ejecutar el siguiente comando,
ls > salida.txt
De esta manera tan sencilla e intuitiva, estás guardando el resultado de listar
archivos y directorios en un fichero.
Si quieres ver el resultado de la ejecución puedes ejecutar el comando cat
salida.txt.
Esto es equivalente a ejecutar ls 1>salida.txt. Aquí estoy indicando que redirijo
la salida estandar stdout o 1 al archivo salida.txt.
Si este archivo ya existe, lo que va a suceder es que lo vas a reemplazar con el
resultado de la ejecución de esta instrucción.
Añadir contenido a la salida
Agustín Herrero Cola 20 | 29
Administración de Sistemas Operativos – 2ASIR
¿Como hacer para añadir contenido a un archivo? En este caso utilizarás el
operador >>. Así, por ejemplo cada vez que ejecutes ls >> salida.txt, el
resultado se añadirá al archivo existente.
Redirigir los errores
Para redirigir la salida de error de un comando, es necesario especificar el
número del archivo de error. Así anteriormente, te he dicho que puedes ejecutar
opcionalmente ls 1>salida.txt. Para el caso del error, esto no es opcional. En
este caso debes ejecutar ls 2>error.log.
Por ejemplo, puedes probar con ls -l /root 2>error.log, y verás el resultado. Igual
que antes puedes ejecutar cat error.log.
Redirigir la entrada estándar
La mayoría de los comandos reciben su entrada desde la entrada estándar, que
por defecto está conectada al teclado, como has visto anteriormente.
Para utilizar un archivo como entrada, en lugar de la entrada estándar, tienes
que utilizar el operador <. Prueba con cat < salida.txt.
Redirigir entrada y salida estándar
Ahora ya puedes combinar tanto entrada como salida en una misma línea de
comando. Esto, quizá no resulte tan intuitivo como lo que has visto
anteriormente, al menos a mi así me resulta.
Por ejemplo, puedes utilizar el comando rev para darle la vuelta al contenido de
un archivo de texto. Así por ejemplo, en el caso de que tengas el archivo hola.txt,
que contenga hola, y utilices rev hola.txt te devolverá por pantalla aloh.
Ahora vas a redirigir entrada y salida. La entrada será hola.txt y la salida
será hola_al_reves.txt. Así la línea de comando será,
rev < hola.txt > hola_al_reves.txt
Igualmente puedes añadir contenido en lugar de reemplazar,
Agustín Herrero Cola 21 | 29
Administración de Sistemas Operativos – 2ASIR
rev < hola.txt >> hola_al_reves.txt
La siguiente tabla muestra un resumen de los caracteres utilizados para redirigir
la entrada y la salida de las órdenes.
Si queremos redirigir la salida estándar y la salida de errores a un fichero con la
doble redirección, para que si el archivo no existe el cree y que si ya existe añada
las dos salidas, podemos hacerlo así:
ls /tmp /kk >> registro.log 2>> registro.log
Tuberías ó encadenar comandos
Una interesante opción que te ofrece Linux es la posibilidad de encadenar
comandos. De esta forma la salida de un comando resulta ser la entrada del
siguiente. Esto es muy interesante, en tanto en cuanto, obviarás tener que
guardar resultados intermedios en archivos.
Agustín Herrero Cola 22 | 29
Administración de Sistemas Operativos – 2ASIR
Tuberías o 'pipes'
El shell permite enlazar la salida de una orden como entrada de otra orden
mediante lo que llamamos tuberías o pipes.
La sintaxis es la siguiente:
orden1 | orden2
La salida de la orden 1 se utiliza como entrada de la orden 2. El
símbolo | llama pipe ("tubería" en inglés). Se pueden poner espacios entre la
tubería y las órdenes para hacer más legible la línea de comandos, pero no es
obligatorio, los espacios son opcionales.
Por ejemplo, ejecutamos una orden echo para mostrar por pantalla una línea de
texto:
echo “Adriana: Herrero: 02001: ALBACETE”
La orden anterior muestra por pantalla una serie de datos separados por dos
puntos así: "Nombre: Apellidos: CP: Ciudad". Si de esta salida sólo queremos
tomar el tercer campo (el de código postal), la podemos redirigir con una tubería
hacia el orden cut para que seleccione únicamente el campo que nos interesa
de la manera siguiente:
echo “Adriana: Herrero: 02001: ALBACETE” | cut -d: -f3
En la figura siguiente podemos ver este ejemplo de manera gráfica. La salida del
comando echo pasa por la tubería y la recibe como entrada la orden cut, la cual
la procesa y muestra por pantalla la salida procesada.
Agustín Herrero Cola 23 | 29
Administración de Sistemas Operativos – 2ASIR
Vemos otro ejemplo sencillo de utilización de tuberías:
cat /etc/passwd | more
En el ejemplo anterior la salida del comando cat /etc/passwd se utiliza como
entrada del orden more para ver el contenido del fichero /etc/passwd de forma
paginada, es decir, haciendo una pausa cada vez que se llena la pantalla.
Observación: con la orden more avanzamos de página con la tecla de espacio.
Una línea de comandos escrita con una tubería o pipe se conoce como pipeline.
Las tuberías no están limitadas sólo a dos órdenes. Se pueden hacer pipelines
más largas asociando la salida de una orden con la entrada de la siguiente y así
sucesivamente.
orden1 | orden2 | orden3 | orden4 ...
Por ejemplo:
$cat /etc/passwd | sort | more
En el ejemplo anterior hay un encadenamiento de tres órdenes con transmisión
de sus datos de una a la otra: la salida de cat envía de entrada a sort y la salida
Agustín Herrero Cola 24 | 29
Administración de Sistemas Operativos – 2ASIR
de sort se envía de entrada a more. El resultado final consiste en mostrar las
líneas del fichero
/etc/passwd, ordenadas y haciendo una pausa cada vez que se llena la pantalla.
La forma en que enlazamos las diferentes órdenes no es aleatoria, sino que se
debe hacer de manera adecuada para obtener los resultados esperados. En la
construcción de pipelines largas conviene ser metódicos para evitar errores, es
preferible hacer el pipeline paso a paso e ir comprobando los resultados
intermedios para corregir los posibles errores. El proceso para seguir sería el
siguiente:
1. Comprobamos las dos primeras órdenes del pipeline: orden1 | orden2 2.-
Si el resultado es correcto, entonces añadimos la orden siguiente del
2. proceso y comprobamos el resultado intermedio: orden1 | orden2 | orden3
3. Si el resultado es correcto, añadimos la siguiente: orden1 | orden2 |
orden3 | orden 4
4. Y así sucesivamente hasta obtener el pipeline final.
No todas las órdenes se pueden enlazar de cualquier manera con tuberías. Para
hacer un pipeline debemos tener en cuenta las siguientes consideraciones:
1. Una orden puede tener a la derecha una tubería si admite salida estándar.
Por ejemplo, las órdenes ls, who, date, cat, etc.
2. Una orden puede tener a la izquierda una tubería si admite entrada
estándar. Por ejemplo, las órdenes wall, write, etc.
3. Una orden puede tener una tubería a su izquierda ya su derecha si admite
tanto entrada como salida estándares. Por ejemplo, las órdenes sort, cut,
grep, etc.
Observación: Oneliners
Entre los administradores de sistemas es común el término oneliners. Se refiere
a un conjunto de órdenes unidas generalmente por tuberías que enlazadas
adecuadamente producen un resultado útil y práctico. Por ejemplo, si queremos
Agustín Herrero Cola 25 | 29
Administración de Sistemas Operativos – 2ASIR
saber cuáles son los cinco procesos que consumen más CPU podemos ejecutar
el siguiente:
ps -eo pcpu, user, pid, cmd | sort -r | head -6
Esto podía ser una tarea automatizada al ser un comando complejo.
Crea un script, procesos_x.sh, guárdalo en /usr/local/bin y pruébalo.
Hemos utilizado la opción o de la orden ps, que permite personalizar la salida, y
hemos indicado las columnas que queremos que se muestren. La opción e dela
orden indica extended, es decir, los procesos de todos los usuarios. Toda la
salida de ps es enviada a sort, que hace un ordenamiento inverso (opción r)
basándose en la primera columna (pcpu). Por último, la salida ordenada es
enviada a la orden head, que mostrará las seis primeras líneas (la cabecera y
los cinco procesos con más consumo).
6. Filtros y 'pipelines'
En Unix hay unas órdenes que se utilizan mucho en los pipelines y que llamamos
filtros. Los filtros son órdenes que aceptan datos de la entrada estándar, escriben
la salida a la salida estándar y escriben los errores en la salida estándar de
errores, y nunca modifican los datos de entrada. Debido a su funcionamiento, es
frecuente utilizar filtros en los pipelines.
Por ejemplo, un filtro muy utilizado es sort, que sirve para ordenar líneas de texto.
La orden acepta datos desde la entrada estándar (el teclado). Para introducirlas
sólo hay que escribir la orden y pulsar la tecla de retorno:
$sort [Intro]
El cursor se sitúa debajo esperando líneas de entrada. Escribimos las líneas de
texto que queremos que la orden ordene separadas por saltos de línea y, al
terminar, debemos pulsar la combinación de teclas Ctrl + D para indicar la
finalización de la entrada de datos (fin de fichero en Linux). A continuación, nos
aparecerán por pantalla las líneas ordenadas.
Agustín Herrero Cola 26 | 29
Administración de Sistemas Operativos – 2ASIR
Para comprender los pipelines del ejemplo de los procesos, es recomendable
que las ejecutes comprobando los resultados intermedios, siguiendo el proceso
descrito en el apartado "Tuberías o pipes".
Como los filtros aceptan los datos del teclado (entrada estándar) y muestran el
resultado por la pantalla (salida estándar), podemos utilizarlos en pipelines para
procesar mediante una tubería la salida de cualquier orden que dé el resultado
en líneas de texto. Por ejemplo:
$who |sort
La orden who muestra una línea para cada usuario conectado al sistema. Al
enviar esta salida a la entrada de sort, las líneas se muestran ordenadas por
pantalla.
Veamos otro ejemplo:
$cat /etc/group | sort
La orden cat muestra las líneas del fichero /etc /group. Al enviar esta salida a la
orden sort, las líneas del archivo se muestran ordenadas por pantalla, pero el
archivo no se modifica.
Los filtros no sólo aceptan datos desde la entrada estándar, sino que también
aceptan datos desde uno o más ficheros puestos como argumentos en la línea
de comandos. Entonces, la orden anterior también se puede escribir así:
sort /etc/group
En general los filtros son muy útiles para procesar el contenido de los archivos
de texto. Algunos de los más utilizados son wc, sort, grep y cut:
Contar el número de líneas de un archivo:
$wc -l /etc/passwd
Ordenar alfabéticamente las líneas deu archivo:
$sort /etc/passwd
Agustín Herrero Cola 27 | 29
Administración de Sistemas Operativos – 2ASIR
Hacer la búsqueda de líneas que contengan un patrón determinado:
$grep root /etc/passwd
Extraer partes de las líneas del archivo:
$cut -d: -f1 /etc/passwd
Ejemplo de construcción de pipelines con filtros
Cuenta los archivos del directorio actual.
$ls| wc -l
Muestra los nombres (sólo los nombres) de los usuarios dados de alta en el
sistema ordenados alfabéticamente.
$cat /etc/passwd | cut -f1 -d: | sort
Muestra los nombres de los usuarios dados de alta en el sistema y su shell de
inicio, ordenados alfabéticamente y separando los dos campos por un tabulador.
$cat /etc/passwd | cut -f1, 7 -d: | sort | tr ":" " \t "
Muestra el identificador (PID) y el nombre (CMD) de todos los procesos que
pertenecen al usuario root.
$ps -ef | grep "^root" | tr -s "" | cut -f2, 8 -d ""
Observación: tr -s “ “ hace que el carácter expresado entre “ “ solo aparezca
una vez en caso de que se repita.
Muestra una lista con el propietario, grupo y nombre de archivo de todos los
archivos que hay en /etc. La lista debe estar ordenada por el nombre del grupo
del archivo.
$ls -l /etc | tr -s "" | cut -f3, 4 ,9 -d "" | sort -k2 -t ""
7. Referencias
Apuntes de Francisco Jesús en Administración de Sistemas Operativos
https://franciscojesusgu.wordpress.com/
Agustín Herrero Cola 28 | 29
Administración de Sistemas Operativos – 2ASIR
Agustín Herrero Cola 29 | 29