Skip to content

Instantly share code, notes, and snippets.

@fortinux
Last active July 17, 2021 14:17
Show Gist options
  • Save fortinux/e727e61d477745ab53e08169e1b4702b to your computer and use it in GitHub Desktop.
Save fortinux/e727e61d477745ab53e08169e1b4702b to your computer and use it in GitHub Desktop.
Shell scripts Presentación
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "7b25d544",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# shell scripts\n",
"## Aprendiendo a programar shell scripts en GNU/Linux"
]
},
{
"cell_type": "markdown",
"id": "13c88d5b",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Shell scripts. Aprendiendo a programar shell scripts en GNU/Linux por Marcelo Horacio Fortino. Versión 1.3. Julio 2021.\n",
"\n",
"Esta obra está sujeta a la licencia Reconocimiento-CompartirIgual 4.0 Internacional de Creative Commons. Para ver una copia de esta licencia, visite http://creativecommons.org/licenses/by-sa/4.0/. \n",
"Puede hallar permisos más allá de los concedidos con esta licencia en https://fortinux.com. Sugerencias y comentarios a info@fortinux.com \n",
"\n",
"Todas las marcas son propiedad de sus respectivos dueños. Linux® es una marca registrada de Linus Torvalds. Ubuntu® es una marca registrada de Canonical Limited. Google® es una marca registrada de Google Inc."
]
},
{
"cell_type": "markdown",
"id": "744adccb",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"| Versión | Autor/es | Fecha | Observaciones |\n",
"|------- | ---------------- | -------- | -----------|\n",
"| 1.0 | Marcelo Horacio Fortino | 2021/Marzo | Curso shell scripts |\n",
"| 1.1 | Marcelo Horacio Fortino | 2021/Mayo | Convertido a markdown - ipynb |\n",
"| 1.2 | Marcelo Horacio Fortino | 2021/Junio | Nuevo curso shell scripts |\n",
"| 1.3 | Marcelo Horacio Fortino | 2021/Julio | Agregado comando find |"
]
},
{
"cell_type": "markdown",
"id": "d75c6e3a",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Esta obra se distribuye con la esperanza de que sea útil, pero SIN NINGUNA GARANTÍA, incluso sin la garantía MERCANTIL implícita o sin garantizar la CONVENIENCIA PARA UN PROPÓSITO PARTICULAR. El autor no asume ninguna responsabilidad si el lector hace un mal uso de la mismo.\n",
"\n",
"Sugerencias y comentarios a info@fortinux.com."
]
},
{
"cell_type": "markdown",
"id": "61eb08b2",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Estos apuntes didácticos se basan en:\n",
"\n",
"- El manual de referencia de Bash, \n",
"https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html,\n",
"- La bibliografía presentada en este documento, y\n",
"- Documentación propia recogida a lo largo de los años de diversas fuentes."
]
},
{
"cell_type": "markdown",
"id": "627e4adf",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Bibliografía"
]
},
{
"cell_type": "markdown",
"id": "a60f17cd",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- FSF. Bash Reference Manual 5.1. (2020). \n",
"Recuperado de https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html \n",
"- IEEE. POSIX.1-2017 (2017). \n",
"Recuperado de https://pubs.opengroup.org/onlinepubs/9699919799/ \n",
"- Cooper, M. Advanced Bash-Scripting Guide. (2014). \n",
"Recuperado de https://tldp.org/LDP/abs/html/ \n",
"- Shotts Jr., W. E. The Linux Command Line (Openbook). (2011). \n",
"Recuperado de https://linuxcommand.org/tlcl.php \n",
"- Elsner, T., Lingnau, A. Advanced Linux: The Linux Shell and Toolkit. (2015). \n",
"Recuperado de https://www.tuxcademy.org/product/grd2/ \n",
"- Fernández Jiménez, F. J., Muñoz Calle, G. J. Programación Shell-script en Linux. (2018). \n",
"DIT, Universidad de Sevilla. Recuperado de http://trajano.us.es/~fjfj/shell/shellscript.htm "
]
},
{
"cell_type": "markdown",
"id": "0b423feb",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# TEMA 1: Personalizar y usar el entorno de shell"
]
},
{
"cell_type": "markdown",
"id": "8135d315",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Introducción a la programación\n",
"- El intérprete de comandos\n",
"- Ficheros de configuración\n",
"- Tipos de shell\n",
"- Parámetros especiales de Bash\n",
"- Parámetros de posición\n",
"- Uso de comillas y llaves\n",
"- Expansión aritmética y de ruta\n",
"- Sourcing files\n",
"- Uso de alias\n",
"- La variable SKEL\n",
"- Creación de shell scripts\n",
"- Ejemplo básico shell script"
]
},
{
"cell_type": "markdown",
"id": "9b244586",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Introducción a la programación"
]
},
{
"cell_type": "markdown",
"id": "97dc1a30",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Un programa es una secuencia de instrucciones que especifican cómo se debe realizar una tarea en un dispositivo (ordenador, mainframe, smartphone, etc.) o en una infraestructura distribuida tipo Cloud computing. \n",
"- Esta tarea puede ser por ejemplo buscar y reemplazar texto, realizar una operación matemática, o procesar una imagen, entre muchas otras. \n"
]
},
{
"cell_type": "markdown",
"id": "c735df20",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Las instrucciones básicas son similares a todos los lenguajes de programación: \n",
" \n",
"* entradas (obtener datos de un teclado, fichero, etc.),\n",
"* salidas (mostrar datos en pantalla, imprimirlos, guardarlos, etc.),\n",
"* operaciones matemáticas (cálculos),\n",
"* ejecución condicional, y\n",
"* repetición.\n"
]
},
{
"cell_type": "markdown",
"id": "ee2e9c94",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Los lenguajes de programación son lenguajes formales que tienen sus propias reglas de sintaxis a seguir, una estructura (su análisis sintáctico se denomina *parsing* en inglés), y utilizan palabras, números y símbolos (*tokens*) como elementos básicos. \n",
" "
]
},
{
"cell_type": "markdown",
"id": "d6a000a9",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Un aspecto importante a tener en cuenta es que un lenguaje de programación es literal y evita la ambigüedad y la redundancia. \n",
"- Cuando surgen errores, el proceso de eliminarlos se llama depuración (*debugging*). \n",
" "
]
},
{
"cell_type": "markdown",
"id": "d682f3f4",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Por otro lado se suele clasificar como lenguajes de bajo nivel a los que interactúan directamente con\n",
"la máquina como por ejemplo assembler; y de alto nivel como C, Java o Python que proporcionan\n",
"un nivel de abstracción más cercano al humano. \n",
" \n",
"Los lenguajes de alto nivel por sus características a su vez se pueden clasificar como: \n",
" \n"
]
},
{
"cell_type": "markdown",
"id": "f26597e6",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"- Imperativos: procedimentales (Fortran, ALGOL, COBOL, PL/I, BASIC, Pascal, C), orientados a objetos - POO ( Smalltalk, C++, PHP, Java); \n",
"- Declarativos: funcionales (Haskell), lógicos (Prolog), matemáticos, y reactivos. \n",
" \n",
"Fuente: (https://en.wikipedia.org/wiki/Programming_paradigm) "
]
},
{
"cell_type": "markdown",
"id": "2c4bcf76",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Igualmente hay lenguajes de programación que soportan múltiples paradigmas, como pueden ser Pascal, C++, Java, JavaScript, Scala, Visual Basic, Common Lisp, Perl, PHP, Python y Ruby, entre otros. \n",
"- Es el programador quien decide cuáles y como utilizar los elementos del paradigma. "
]
},
{
"cell_type": "markdown",
"id": "93cf0c72",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Para que la máquina pueda leer las instrucciones de los programas utiliza unos traductores llamados\n",
"compiladores (generan un ejecutable a partir del código fuente), o intérpretes (analizan y traducen\n",
"las instrucciones una a una). Esto implica que los lenguajes de programación sean compilados o\n",
"interpretados. \n",
" \n",
"* Lenguajes compilados: C, Pascal, C++...\n",
"* Lenguajes interpretados: Bash, Python, Perl, PHP, Ruby... \n",
" "
]
},
{
"cell_type": "markdown",
"id": "af41c115",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Los métodos de desarrollo del software en cascada (waterfall) suelen dividir la tarea de programación en etapas: Especificación, Diseño, Implementación, Validación, y Mantenimiento. \n",
"- Los métodos ágiles por su parte desarrollan en ciclos cortos iterando y de forma incremental."
]
},
{
"cell_type": "markdown",
"id": "be5123a8",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## El intérprete de comandos"
]
},
{
"cell_type": "markdown",
"id": "d7329bdb",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- La shell o intérprete de comandos es una interfaz entre el usuario y el kernel del sistema operativo. \n",
"- En los sistemas operativos GNU/Linux la shell de facto es BASH (*Bourne Again Shell*) aunque hay otras que se pueden utilizar, como por ejemplo sh (*Bourne shell*) y ksh (*Korn shell*).\n",
"- El estándar utilizado es el definido por el IEEE: es el 1003.2-1992 - *IEEE Standard for Information Technology--Portable Operating System Interfaces (POSIX(R)) Part 2: Shell and Utilities.*\n",
"(https://ieeexplore.ieee.org/document/6880751) "
]
},
{
"cell_type": "markdown",
"id": "5f45a484",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Cuando se inicia, la shell ejecuta los scripts de personalización de la sesión del usuario. \n",
"- Éstos scripts que contienen variables, funciones y aliases, pueden ser globales o específicos para este usuario concreto. "
]
},
{
"cell_type": "markdown",
"id": "c5c8116c",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Abrir un emulador GNU/Linux en el navegador: https://replit.com/join/helxztrjlz-fortinux"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "36130a3e",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"env # Muestra las variables de entorno"
]
},
{
"cell_type": "markdown",
"id": "dad1ffc5",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"`bash # Ambiente shell`"
]
},
{
"cell_type": "markdown",
"id": "53efe599",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"`sh # Ambiente sh`"
]
},
{
"cell_type": "markdown",
"id": "6655f17b",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"`exit # Salir del ambiente` "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ba0849d5",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"echo $0 # Verifica el tipo de shell usado"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8797371f",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"$SHELL --version # Conocer la versión de la shell"
]
},
{
"cell_type": "markdown",
"id": "ba20d765",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Los prompts de usuario se distinguen por usar el símbolo numeral para root y el símbolo de dólar para el usuario sin permisos de administrador: \n",
" \n",
"`# root` \n",
"`$ usuario`"
]
},
{
"cell_type": "markdown",
"id": "984681aa",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Ficheros de configuración"
]
},
{
"cell_type": "markdown",
"id": "ac1904d6",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Los ficheros personales de los usuarios de bash son:\n"
]
},
{
"cell_type": "markdown",
"id": "f8f427bd",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"`~/.bashrc` \n",
"`~/.bash_profile` "
]
},
{
"cell_type": "markdown",
"id": "6eee5a95",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Dash (*Debian Almquist shell*) utiliza a su vez: \n",
" "
]
},
{
"cell_type": "markdown",
"id": "ccc1026d",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"`~/.profile`"
]
},
{
"cell_type": "markdown",
"id": "da9a912f",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Los ficheros globales de inicio son: \n",
" "
]
},
{
"cell_type": "markdown",
"id": "1be36f80",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"`/etc/profile` \n",
"`/etc/profile.d/*` \n",
"`/etc/bashrc # CentOS 8 ` \n",
"`/etc/bash.bashrc # Ubuntu 20.04` "
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "a43f021d",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"lrwxrwxrwx 1 root root 4 Apr 29 18:29 /bin/sh -> dash\n"
]
}
],
"source": [
"ls -l /bin/sh # Muestra el enlace simbólico en SO basados en Debian a Dash"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "0c907086",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"-rwxr-xr-x 1 root root 1183448 Jun 18 2020 /bin/bash\n"
]
}
],
"source": [
"ls -l /bin/bash"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "6de407ae",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"-rwxr-xr-x 1 root root 129816 Jul 18 2019 /bin/dash\n"
]
}
],
"source": [
"ls -l /bin/dash"
]
},
{
"cell_type": "markdown",
"id": "a98117ef",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Los ficheros locales tienen precedencia sobre los ficheros globales. \n",
"- Ficheros del perfil de la sesión de usuario localizados en la carpeta del usuario, por ej. */home/usuario*:"
]
},
{
"cell_type": "markdown",
"id": "6f72a682",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"`bash_history` \n",
"`.bash_logout` \n",
"`.bashrc` \n",
"`.profile` \n",
"`...` "
]
},
{
"cell_type": "markdown",
"id": "96ff328f",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Ficheros del perfil de la sesión en el servidor Ubuntu 18.04: \n",
" "
]
},
{
"cell_type": "markdown",
"id": "e7703f50",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"`/etc/profile/profile.d` \n",
"`bash_completion` \n",
"`...` "
]
},
{
"cell_type": "markdown",
"id": "ea36704f",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Funciones de todo el sistema: \n",
" "
]
},
{
"cell_type": "markdown",
"id": "7ead1f95",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"`/etc/bash.bashrc`"
]
},
{
"cell_type": "markdown",
"id": "27948ef2",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Controlar el comportamiento de cierre de sesión:\n",
" "
]
},
{
"cell_type": "markdown",
"id": "e9a7d938",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"`.bash_logout` "
]
},
{
"cell_type": "markdown",
"id": "0963a80e",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Para verificar como se ejecutan los ficheros de inicio en bash: \n",
" "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5b2e3a46",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"echo 'echo Hola desde /etc/bash.bashrc' >> /etc/bash.bashrc "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "063a6ba0",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"echo 'echo Hola desde ~/.bashrc' >> ~/.bashrc"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6ccddd6a",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"bash"
]
},
{
"cell_type": "markdown",
"id": "15e7e6d6",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Tipos de shell"
]
},
{
"cell_type": "markdown",
"id": "16886871",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Hay cuatro tipos de shell: interactivas, no interactivas, de login, sin login.\n",
"\n",
"- Interactivas de login: grupos de usuarios con una variable de ambiente personalizada.\n",
"- Interactivas sin login: las que se usan para realizar tareas administrativas o de mantenimiento del SO.\n",
"- No interactivas sin login: sin intervención humana (entradas). scripts automatizados.\n",
"- No interactivas login: imprácticas, raramente se usan."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c260c51f",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"su - root o su - # Abre una sesión interactiva de login como usuario root"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8c497592",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"su root o su # Abre una sesión interactiva sin login como usuario root"
]
},
{
"cell_type": "markdown",
"id": "a98feddb",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- El comando sudo sirve para tener permisos de root temporales. \n",
"- El usuario debe estar dentro del grupo sudoers. \n",
"- Para agregar un usuario al grupo sudoers, como root se ejecuta:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "25966f16",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"usermod -aG sudo nombre_usuario"
]
},
{
"cell_type": "markdown",
"id": "9db3ad37",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- La consola de sistema comúnmente se denomina tty (*teletypewriter*) shell. \n",
"- Cuando es un emulador de terminal en un ambiente gráfico (como *gnome-terminal, konsole* o *xterm* entre otros) se la nombra como pts (*pseudo terminal slave*).\n",
"- En SO GNU/Linux las teclas CTRL + ALT + F1 hasta F6 abren una shell interactiva.\n",
"- Con CTRL + ALT + F7 se vuelve al entorno gráfico. "
]
},
{
"cell_type": "markdown",
"id": "8fc93f90",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- *PS1* es una variable del indicador principal (*prompt*) que contiene los caracteres especiales de bash.\n",
"- Es la estructura predeterminada del indicador de bash para las sesiones del usuario en la consola.\n",
"- Estos valores predeterminados se establecen en el fichero */etc/bashrc*. \n",
"- Fuente: https://www.cyberciti.biz/tips/howto-linux-unix-bash-shell-setup-prompt.html"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5987cc10",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"echo $PS1 # Mostrar la configuración de la shell actual"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "450a3333",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"ps aux | grep bash # Mostrar las shells abiertas"
]
},
{
"cell_type": "markdown",
"id": "bbdb9bff",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Parámetros especiales de Bash"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "343fce2d",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [],
"source": [
"# Fuente: Bash-Beginners-Guide 3.2.5 https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_02.html \n",
"\n",
"$* # Todos los argumentos pasados al script\n",
"$@ # Todos los argumentos pasados al script\n",
"$# # El número de argumentos\n",
"$0 # El nombre del script\n",
"$! # PID del último programa ejecutado\n",
"$$ # PID de la actual shell\n",
"$? # Código de estado del último comando: 0 significa suceso"
]
},
{
"cell_type": "markdown",
"id": "8db5c04c",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- En el siguiente ejemplo se encuentran algunos de los parámetros que se pueden utilizar en los scripts:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ae75bd7b",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [],
"source": [
"#!/bin/bash\n",
"# Adaptado de https://www.howtogeek.com/442332/how-to-work-with-variables-in-bash/ \n",
"# Ejecutar el script con tres parámetros a elección\n",
"echo \"Existen $# parámetros en la línea de comandos\"\n",
"echo \"Ellos son: $@\"\n",
"echo \"El parámetro 1 es: $1\"\n",
"echo \"Este script se llama: $0\"\n",
"# Test para ver el estatus de salida\n",
"echo \"El directorio actual es: \"\n",
"pwd\n",
"echo \"El comando pwd devuelve $?\"\n",
"echo \"El ID de este script es $$\"\n",
"echo \"El script fue iniciado por $USER\"\n",
"echo \"Se está ejecutando en el servidor $HOSTNAME\"\n",
"sleep 3\n",
"echo \"Se ha ejecutado sleep durante $SECONDS segundos\"\n",
"echo \"Un número random: $RANDOM\"\n",
"echo \"Esta es la línea número $LINENO del script\""
]
},
{
"cell_type": "markdown",
"id": "5248dc62",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Parámetros de posición "
]
},
{
"cell_type": "markdown",
"id": "1138dca4",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Un parámetro de posición es un parámetro indicado por uno o más dígitos distintos del 0. \n",
"- Por ejemplo, la variable `$1` corresponde al primer argumento dado al script. \n",
"- Al segundo argumento corresponde la `$2`, y así hasta el décimo. \n",
"- A partir del decimo se debe hacer referencia a él con llaves, como en `${11}`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "993c3f03",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"echo $1\n",
"echo ${10}"
]
},
{
"cell_type": "markdown",
"id": "ad88c166",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Uso de comillas y llaves en variables"
]
},
{
"cell_type": "markdown",
"id": "79420118",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Las comillas simples conservan el valor literal de todos los caracteres,\n",
"las dobles conservan todos los caracteres excepto $, `, \\ y, en algunos casos, !. El carácter de escape \\ indica que el siguiente carácter debe mantener su valor literal."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "810dd454",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"echo '$HOME/directorio' # Valor literal"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ec22f903",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"echo “$HOME” # Muestra el valor de la variable HOME"
]
},
{
"cell_type": "markdown",
"id": "d440827c",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Uso de llaves para delimitar una variable (obligatoria cuando se quiere separar la variable de otros caracteres, o si es un parámetro con más de un dígito)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fe296a28",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"echo \"${HOME}/directorio\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d85a4e5c",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"echo ${VARIABLE} TEXTO"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9ced4e1b",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"echo $SHELL # Muestra la shell del usuario"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2faf1f5a",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"export VARIABLE # Para convertirla en una variable de ambiente"
]
},
{
"cell_type": "markdown",
"id": "2d7841da",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Para mostrar las variables de ambiente también podemos usar los comandos *env* o *printenv.*"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "110a0dfb",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"env -i bash # Inicia una shell con la mínima cantidad de variables"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "30b5a805",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"echo $USER "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0e25acdd",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"env # Para ver las variables en la nueva shell"
]
},
{
"cell_type": "markdown",
"id": "dbabd88f",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Expansión aritmética y de ruta"
]
},
{
"cell_type": "markdown",
"id": "c0fa282b",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- La expansión aritmética evalúa una expresión aritmética y la sustitución del resultado. \n",
"- El formato para la expansión aritmética es: `$((expresión_aritmética))`."
]
},
{
"cell_type": "markdown",
"id": "9865f1e1",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Ejemplo de expansión aritmética:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a09457aa",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"#!/bin/sh\n",
"VAR=1\n",
"VAR=$VAR+1\n",
"echo $VAR \"variable 1+1\"\n",
"RES1=$(($VAR))+1\n",
"echo $RES1 \"suma variable\""
]
},
{
"cell_type": "markdown",
"id": "ae2426ec",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Los operadores se evalúan por orden de precedencia. \n",
"- Las subexpresiones entre paréntesis se evalúan primero y pueden anular las reglas de precedencia anteriores. "
]
},
{
"cell_type": "markdown",
"id": "51f93ca4",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"- Para la expansión de ruta se pueden usar los campos * , ? y {} (asterisco, interrogación y apertura de corchetes).\n",
"- Enlace al manual: https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5969b191",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"ls -l /etc/resolv.conf /etc/hosts /etc/hostname"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "852abbdc",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"ls -l /etc/{resolv.conf,hosts,hostname}"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "028807e1",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"touch fichero{1..5}.txt"
]
},
{
"cell_type": "markdown",
"id": "3f2f4597",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Sourcing files"
]
},
{
"cell_type": "markdown",
"id": "fc66da3f",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Cuando un script es ejecutado utilizando el comando source utilizará las shell actual. \n",
"- Ejecutar el mismo script usando ./script creará una sub-shell específica para ese proceso. -\n",
"- Por lo tanto, si se necesita hacer algún cambio a la shell actual se deberá hacer el sourcing de ese script."
]
},
{
"cell_type": "markdown",
"id": "a2ffe197",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"- Creamos el script sourcing.sh:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ee65937c",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"#!/bin/bash\n",
"cd /etc"
]
},
{
"cell_type": "markdown",
"id": "6abcfb54",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"- Lo ejecutamos y luego confirmamos que no hemos cambiado al directorio */etc*"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bdf62dc8",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"chmod 755 sourcing.sh\n",
"./sourcing.sh\n",
"pwd"
]
},
{
"cell_type": "markdown",
"id": "bc122bd0",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Ahora utilizamos source:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2b956354",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"source sourcing.sh\n",
"pwd"
]
},
{
"cell_type": "markdown",
"id": "51d051a3",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- En sistemas operativos GNU/Linux existen scripts que contienen las órdenes para inicializar variables o llamar a funciones, por ejemplo los del directorio */etc/default/*. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9a1c725b",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"less /etc/default/rsync"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "562a4e7c",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"less /etc/init.d/rsync"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "66fb6cff",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"echo \"alias hola='echo Un saludo.'\" >> ~/.bashrc # Agrega un alias a ~/.bashrc"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c1c2605f",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"tail -n 1 !$ # Para verificar que está correcto"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "41f3d04b",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"source ~/.bashrc # Se llama al script. También se puede usar un punto como comando "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6248d7c7",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"hola # Se prueba"
]
},
{
"cell_type": "markdown",
"id": "29f9eeab",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Si se quiere hacer permanente este alias se debería colocar en *~/.profile*."
]
},
{
"cell_type": "markdown",
"id": "5fff4c45",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"- Fuentes: \n",
"- https://tldp.org/HOWTO/Bash-Prompt-HOWTO/x237.html \n",
"- http://hayne.net/MacDev/Notes/unixFAQ.html#shellStartup \n",
"- https://apple.stackexchange.com/questions/12993/why-doesnt-bashrc-run-automatically#comment13715_13019 \n"
]
},
{
"cell_type": "markdown",
"id": "08e292f2",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Alias"
]
},
{
"cell_type": "markdown",
"id": "7f9fdcc8",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Un alias es un nombre puesto como substituto de uno o más comandos:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ed601c4a",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"alias git_info='which git;git --version' # Crea el alias git_info"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d76d252e",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"unalias git_info # Borra el alias"
]
},
{
"cell_type": "markdown",
"id": "0b6fdd39",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Para que los alias queden grabados en el sistema operativo, se deben registrar dentro de los scripts de inicio, por ejemplo en *~/.bashrc*."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fa4fb808",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"grep alias .bashrc"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1a39c9b7",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"alias # Muestra los alias"
]
},
{
"cell_type": "markdown",
"id": "d69e7830",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## La variable SKEL"
]
},
{
"cell_type": "markdown",
"id": "c474f4b3",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- SKEL es una variable cuyo valor es la ruta absoluta al directorio skel. \n",
"- En este directorio está la plantilla de la estructura y los ficheros de configuración de los directorios HOME de los usuarios. \n",
"- SKEL y las demás variables se encuentran en *etc/adduser.conf* o */etc/default/useradd*."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c2267594",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"grep SKEL /etc/adduser.conf # SO Debian/Ubuntu"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f60efc8d",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"grep SKEL /etc/default/useradd # Red Hat/CentOS"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "24347dc5",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"less /etc/default/useradd # Fichero de configuración parámetros de un nuevo usuario"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9715fe68",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"ls -a /etc/skel/ # Scripts de inicio"
]
},
{
"cell_type": "markdown",
"id": "c00cf5bc",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Systemd está cambiando actualmente la gestión del directorio de inicio e implementará *systemd-homed* próximamente. \n",
"- Fuente: https://www.howtogeek.com/673018/systemd-will-change-how-your-linux-home-directory-works/ "
]
},
{
"cell_type": "markdown",
"id": "14928afc",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Creación de shell scripts"
]
},
{
"cell_type": "markdown",
"id": "20316935",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Los shell scripts se pueden crear y ejecutar directamente en la línea de comando o se puede grabar un fichero con extensión .sh, asignarle permisos de ejecución (*chmod 755* o *chmod +x*), y ejecutarlo de tres maneras posibles:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a515f3f9",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"/bin/dash/ ejemplo.sh # Explícita, se escribe el shell que se desea invocar"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cb667aba",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
". ejemplo.sh # Implícita, se ignora el !#"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2836ec09",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"./ejemplo.sh # Implícita como si fuera un ejecutable"
]
},
{
"cell_type": "markdown",
"id": "779251d2",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Ejemplo básico de shell script"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0576aa82",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [],
"source": [
"#! /bin/bash\n",
"\n",
"# Mensaje de bienvenida\n",
"echo “Hola mundo”\n",
"\n",
"# Crear una variable\n",
"NOMBRE=Marcelo\n",
"echo “Hola $NOMBRE, bienvenido al mundo de shell script”"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "295a8220",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"# Se puede dar permisos de ejecución al fichero de dos formas:\n",
"chmod 755 editor.sh \n",
"chmod +x editor.sh\n",
"\n",
"# Orden para ejecutarlo\n",
"./editor.sh"
]
}
],
"metadata": {
"celltoolbar": "Slideshow",
"kernelspec": {
"display_name": "Bash",
"language": "bash",
"name": "bash"
},
"language_info": {
"codemirror_mode": "shell",
"file_extension": ".sh",
"mimetype": "text/x-sh",
"name": "bash"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@fortinux
Copy link
Author

Version 1.2 Junio 2021.

@fortinux
Copy link
Author

Version 1.3 Julio 2021.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment