Un script de shell es un programa informático diseñado para ser ejecutado por un shell de Unix , un intérprete de línea de comandos . [1] Los diversos dialectos de los scripts de shell se consideran lenguajes de comandos . Las operaciones típicas realizadas por los scripts de shell incluyen la manipulación de archivos, la ejecución de programas y la impresión de texto. Un script que configura el entorno, ejecuta el programa y realiza cualquier limpieza o registro necesario se denomina contenedor .
El término también se utiliza de forma más general para significar el modo automatizado de ejecutar un shell de sistema operativo; cada sistema operativo utiliza un nombre particular para estas funciones, incluidos archivos por lotes (MSDos-Win95 stream, OS/2 ), procedimientos de comando (VMS) y scripts de shell ( Windows NT stream y derivados de terceros como 4NT —el artículo está en cmd.exe ), y los sistemas operativos de mainframe están asociados con varios términos.
Los shells que suelen estar presentes en sistemas Unix y similares incluyen Korn shell , Bourne shell y GNU Bash . Si bien un sistema operativo Unix puede tener un shell predeterminado diferente, como Zsh en macOS , estos shells suelen estar presentes por compatibilidad con versiones anteriores.
El shell ignora los comentarios#
. Normalmente comienzan con el símbolo numeral ( ) y continúan hasta el final de la línea. [2]
El shebang , o hash-bang, es un tipo especial de comentario que el sistema utiliza para determinar qué intérprete utilizar para ejecutar el archivo. El shebang debe ser la primera línea del archivo y comenzar con " #!
". [2] En sistemas operativos tipo Unix, los caracteres que siguen al #!
prefijo " " se interpretan como una ruta a un programa ejecutable que interpretará el script. [3]
Un script de shell puede proporcionar una variación conveniente de un comando de sistema donde las configuraciones especiales del entorno, las opciones de comando o el posprocesamiento se aplican automáticamente, pero de una manera que permite que el nuevo script todavía actúe como un comando Unix completamente normal .
Un ejemplo sería crear una versión de ls , el comando para listar archivos, dándole un nombre de comando más corto l
, que normalmente se guardaría en el bin
directorio de un usuario como , y un conjunto predeterminado de opciones de comando suministradas previamente./home/username/bin/l
#!/bin/sh LC_COLLATE = C ls -FCas " $@ "
Aquí, la primera línea utiliza un shebang para indicar qué intérprete debe ejecutar el resto del script, y la segunda línea hace una lista con opciones para indicadores de formato de archivo, columnas, todos los archivos (no se omite ninguno) y un tamaño en bloques. LC_COLLATE=C
Establece el orden de intercalación predeterminado para no combinar mayúsculas y minúsculas, no mezclar archivos de puntos con nombres de archivo normales como un efecto secundario de ignorar la puntuación en los nombres (los archivos de puntos generalmente solo se muestran si -a
se usa una opción como) y "$@"
hace que cualquier parámetro dado a l
pase como parámetros a ls, de modo que todas las opciones normales y otra sintaxis conocida por ls aún se puedan usar.
El usuario podría entonces simplemente utilizar l
la lista corta más utilizada.
Otro ejemplo de un script de shell que podría usarse como acceso directo sería imprimir una lista de todos los archivos y directorios dentro de un directorio determinado.
#!/bin/shclarols -al
En este caso, el script de shell comenzaría con su línea de inicio normal #!/bin/sh . A continuación, el script ejecuta el comando clear que limpia la terminal de todo el texto antes de pasar a la siguiente línea. La siguiente línea proporciona la función principal del script. El comando ls -al enumera los archivos y directorios que se encuentran en el directorio desde el que se ejecuta el script. Los atributos del comando ls se pueden cambiar para reflejar las necesidades del usuario.
Los scripts de shell permiten ejecutar automáticamente varios comandos que se introducirían manualmente en una interfaz de línea de comandos, y sin tener que esperar a que un usuario active cada etapa de la secuencia. Por ejemplo, en un directorio con tres archivos de código fuente en C, en lugar de ejecutar manualmente los cuatro comandos necesarios para crear el programa final a partir de ellos, se podría crear un script para shells compatibles con POSIXbuild
, nombrado aquí y guardado en el directorio con ellos, que los compilaría automáticamente:
#!/bin/sh printf 'compilando...\n'
cc -c foo.c cc -c barra.ccc -c qux.ccc -o myprog foo.o bar.o qux.o printf 'hecho.\n'
El script permitiría al usuario guardar el archivo que se está editando, pausar el editor y luego ejecutarlo ./build
para crear el programa actualizado, probarlo y luego regresar al editor. Sin embargo, desde la década de 1980, los scripts de este tipo han sido reemplazados por utilidades como make , que están especializadas en la creación de programas.
Los trabajos por lotes simples no son inusuales para tareas aisladas, pero el uso de bucles de shell, pruebas y variables proporciona mucha más flexibilidad a los usuarios. Con este archivo se puede crear un script sh de POSIX para convertir imágenes JPEG en imágenes PNG, donde los nombres de las imágenes se proporcionan en la línea de comandos (posiblemente mediante comodines) en lugar de que cada una de ellas se incluya en el script, y normalmente se guarda en un archivo como/home/username/bin/jpg2png
#!/bin/sh for jpg ; do # usa $jpg en lugar de cada nombre de archivo dado, a su vez png = ${ jpg %.jpg } .png # construye la versión PNG del nombre de archivo reemplazando .jpg con .png printf 'converting "%s" ...\n' " $jpg " # envía información de estado al usuario que ejecuta el script if convert " $jpg " jpg.to.png ; then # usa convert (proporcionado por ImageMagick) para crear el PNG en un archivo temporal mv jpg.to.png " $png " # si funcionó, cambia el nombre de la imagen PNG temporal al nombre correcto else # ...de lo contrario, queja y sale del script printf > & 2 'jpg2png: error: salida fallida guardada en "jpg.to.png".\n' exit 1 fi # el final de la construcción de la prueba "if" done # el final del bucle "for" printf 'all conversions successful\n' # dile al usuario las buenas noticias
El jpg2png
comando se puede ejecutar en un directorio completo lleno de imágenes JPEG con solo/home/username/bin/jpg2png *.jpg
Muchos shells modernos también proporcionan varias características que normalmente se encuentran solo en lenguajes de programación de propósito general más sofisticados , como construcciones de flujo de control, variables, comentarios , matrices, subrutinas , etc. Con este tipo de características disponibles, es posible escribir aplicaciones razonablemente sofisticadas como scripts de shell. Sin embargo, aún están limitados por el hecho de que la mayoría de los lenguajes de shell tienen poco o ningún soporte para sistemas de tipificación de datos, clases, subprocesos, matemáticas complejas y otras características comunes de los lenguajes completos, y también son generalmente mucho más lentos que el código compilado o los lenguajes interpretados escritos con la velocidad como objetivo de rendimiento.
Las herramientas estándar de Unix sed y awk proporcionan capacidades adicionales para la programación de shell; Perl también se puede integrar en scripts de shell, al igual que otros lenguajes de programación como Tcl . Perl y Tcl también incluyen herramientas gráficas.
Los lenguajes de script que se encuentran comúnmente en instalaciones de sistemas operativos compatibles con UNIX, Linux y POSIX incluyen:
ksh
) en varias versiones posibles como ksh88, Korn Shell '93 y otras.sh
), una de las conchas más antiguas que todavía se utilizan habitualmentecsh
)bash
)tclsh
, un shell que es un componente principal del lenguaje de programación Tcl/Tk .Los shells C y Tcl tienen una sintaxis bastante similar a la de dichos lenguajes de programación, y los shells Korn y Bash son desarrollos del shell Bourne, que se basa en el lenguaje ALGOL con elementos de varios otros añadidos también. [4] Por otro lado, los diversos shells más herramientas como awk , sed , grep y BASIC , Lisp , C , etc. contribuyeron al lenguaje de programación Perl . [5]
Otros shells que pueden estar disponibles en una máquina o para descargar y/o comprar incluyen:
ash
)nu
)msh
)zsh
, un KornShell mejorado particularmente común)tcsh
).También hay disponibles programas relacionados, como shells basados en Python , Ruby , C , Java , Perl , Pascal , Rexxosh
, etc., en diversas formas. Otro shell bastante común es Old shell ( ), cuya página de manual indica que "es un puerto mejorado y compatible con versiones anteriores del intérprete de comandos estándar de la Sexta Edición de UNIX". [6]
Los llamados shells remotos como
rsh
)ssh
)son en realidad sólo herramientas para ejecutar un shell más complejo en un sistema remoto y no tienen características propias de un 'shell'.
Se han introducido muchos lenguajes de programación potentes para tareas que son demasiado grandes o complejas para ser manejadas cómodamente con scripts de shell comunes, pero para las cuales las ventajas de un script son deseables y la sobrecarga de desarrollo de un lenguaje de programación completo y compilado sería desventajosa. Los detalles de lo que separa a los lenguajes de programación de scripts de los lenguajes de programación de alto nivel son una fuente frecuente de debate, pero, en términos generales, un lenguaje de programación de scripts es uno que requiere un intérprete.
Los scripts de shell suelen servir como una etapa inicial en el desarrollo de software y, con frecuencia, están sujetos a una conversión posterior a una implementación subyacente diferente, que normalmente se convierte a Perl , Python o C. La directiva interpreter permite que los detalles de la implementación se oculten por completo dentro del script, en lugar de exponerlos como una extensión de nombre de archivo, y permite una reimplementación sin problemas en diferentes lenguajes sin afectar a los usuarios finales.
Si bien los archivos con la extensión ".sh" suelen ser algún tipo de script de shell, la mayoría de los scripts de shell no tienen ninguna extensión de nombre de archivo. [7] [8] [9] [10]
Quizás la mayor ventaja de escribir un script de shell es que los comandos y la sintaxis son exactamente los mismos que los que se introducen directamente en la línea de comandos. El programador no tiene que cambiar a una sintaxis totalmente diferente, como lo haría si el script estuviera escrito en un lenguaje diferente o si se utilizara un lenguaje compilado.
A menudo, escribir un script de shell es mucho más rápido que escribir el código equivalente en otros lenguajes de programación. Las numerosas ventajas incluyen una selección sencilla de programas o archivos, un inicio rápido y una depuración interactiva. Un script de shell se puede utilizar para proporcionar un vínculo de secuenciación y toma de decisiones en torno a programas existentes, y para scripts de tamaño moderado, la ausencia de un paso de compilación es una ventaja. La ejecución interpretativa facilita la escritura de código de depuración en un script y su reejecución para detectar y corregir errores. Los usuarios no expertos pueden utilizar scripts para adaptar el comportamiento de los programas, y los scripts de shell proporcionan un alcance limitado para el multiprocesamiento.
Por otra parte, la ejecución de scripts de shell es propensa a errores costosos. Los errores de escritura involuntarios como rm -rf * /
(en lugar del rm -rf */
) son un folclore en la comunidad Unix; un solo espacio adicional convierte el comando de uno que borra todos los subdirectorios contenidos en el directorio actual, a uno que borra todo lo del directorio raíz del sistema de archivos . Problemas similares pueden transformar cp
y mv
en armas peligrosas, y el mal uso de la >
redirección puede borrar el contenido de un archivo. Esto se vuelve más problemático por el hecho de que muchos comandos UNIX difieren en nombre por solo una letra: cp
, cd
, dd
, df
, etc.
Otra desventaja importante es la baja velocidad de ejecución y la necesidad de iniciar un nuevo proceso para casi cada comando de shell ejecutado. Cuando el trabajo de un script se puede realizar configurando una secuencia de comandos en la que comandos de filtrado eficientes realizan la mayor parte del trabajo, la ralentización se mitiga, pero un script complejo suele ser varios órdenes de magnitud más lento que un programa compilado convencional que realiza una tarea equivalente.
También existen problemas de compatibilidad entre diferentes plataformas. Larry Wall , creador de Perl , escribió la famosa frase "Es más fácil portar un shell que un script de shell". [11]
De manera similar, los scripts más complejos pueden encontrarse con las limitaciones del propio lenguaje de scripts de shell; los límites dificultan la escritura de código de calidad, y las extensiones de varios shells para mejorar los problemas con el lenguaje de shell original pueden empeorar los problemas. [12]
Muchas desventajas de usar algunos lenguajes de script son causadas por fallas de diseño dentro de la sintaxis o implementación del lenguaje, y no son necesariamente impuestas por el uso de una línea de comandos basada en texto; hay una cantidad de shells que usan otros lenguajes de programación de shell o incluso lenguajes completos como Scsh (que usa Scheme ).
Diferentes lenguajes de programación pueden compartir muchos elementos comunes, en gran medida debido a que se basan en POSIX, y algunos shells ofrecen modos para emular diferentes shells. Esto permite que un script de shell escrito en un lenguaje de programación se adapte a otro.
Un ejemplo de esto es Bash, que ofrece la misma gramática y sintaxis que Bourne Shell, y que también proporciona un modo compatible con POSIX. [13] Como tal, la mayoría de los scripts de shell escritos para Bourne Shell se pueden ejecutar en BASH, pero lo inverso puede no ser cierto ya que BASH tiene extensiones que no están presentes en Bourne Shell. Como tal, estas características se conocen como bashismos. [14]
El software de interoperabilidad como Cygwin , MKS Toolkit , Interix (que está disponible en Microsoft Windows Services para UNIX), Hamilton C shell , UWIN (AT&T Unix para Windows) y otros permiten que los programas de shell de Unix se ejecuten en máquinas que ejecutan Windows NT y sus sucesores, con cierta pérdida de funcionalidad en la rama MS-DOS - Windows 95 , así como en versiones anteriores de MKS Toolkit para OS/2. Al menos tres implementaciones de DCL para sistemas operativos tipo Windows (además de XLNT , un paquete de lenguaje de script de uso múltiple que se usa con el shell de comandos, Windows Script Host y programación CGI ) también están disponibles para estos sistemas. Mac OS X y posteriores también son similares a Unix. [15]
Además de las herramientas mencionadas anteriormente, algunas funciones de POSIX y OS/2 también se pueden utilizar con los subsistemas ambientales correspondientes de la serie de sistemas operativos Windows NT hasta Windows 2000. Un tercer subsistema de 16 bits , a menudo llamado subsistema MS-DOS, utiliza el Command.com que se proporciona con estos sistemas operativos para ejecutar los archivos por lotes MS-DOS mencionados anteriormente. [16]
Las alternativas de consola 4DOS , 4OS2 , FreeDOS , NDOS de Peter Norton y 4NT/Take Command, que añaden funcionalidad a cmd.exe de estilo Windows NT, a los archivos por lotes MS-DOS/Windows 95 (ejecutados por Command.com), a cmd.exe de OS/2 y a 4NT respectivamente, son similares a los shells que mejoran y están más integrados con Windows Script Host, que viene con tres motores preinstalados, VBScript, JScript y VBA, y al que se pueden añadir numerosos motores de terceros, como Rexx, Perl, Python, Ruby y Tcl, que tienen funciones predefinidas en 4NT y programas relacionados. PC DOS es bastante similar a MS-DOS, mientras que DR DOS es más diferente. Las versiones anteriores de Windows NT pueden ejecutar versiones contemporáneas de 4OS2 mediante el subsistema OS/2.
Los lenguajes de scripts son, por definición, extensibles; por ejemplo, los sistemas tipo MS-DOS/Windows 95/98 y Windows NT permiten que los programas de shell/batch llamen a herramientas como KiXtart , QBasic , varias implementaciones de BASIC , Rexx , Perl y Python , el Windows Script Host y sus motores instalados. En Unix y otros sistemas compatibles con POSIX , awk y sed se utilizan para extender la capacidad de procesamiento numérico y de cadenas de los scripts de shell. Tcl , Perl, Rexx y Python tienen kits de herramientas gráficas y pueden usarse para codificar funciones y procedimientos para scripts de shell que plantean un cuello de botella de velocidad (C, Fortran, lenguaje ensamblador, etc. son mucho más rápidos aún) y para agregar funcionalidad no disponible en el lenguaje de shell, como sockets y otras funciones de conectividad, procesamiento de texto de alta resistencia, trabajo con números si el script que llama no tiene esas capacidades, código autoescrito y automodificable, técnicas como recursión , acceso directo a memoria, varios tipos de clasificación y más, que son difíciles o imposibles en el script principal, etc. Visual Basic para Aplicaciones y VBScript se pueden usar para controlar y comunicarse con cosas como hojas de cálculo, bases de datos, programas de script de todo tipo, software de telecomunicaciones, herramientas de desarrollo, herramientas gráficas y otro software al que se puede acceder a través del Modelo de objetos componentes .
shell es en realidad un lenguaje de programación: tiene variables, bucles, toma de decisiones, etc.
En lugar de usar una extensión de archivo para scripts de shell, se prefiere mantener un nombre de archivo sin extensión y dejar que un intérprete identifique el tipo buscando en shebang(#!).
Los scripts de shell no necesitan una extensión de archivo especial, así que deje la extensión en blanco (o puede agregar la extensión .sh si lo prefiere, pero esto no es obligatorio).