¿Cómo ejecutar un script de shell en una consola Unix o terminal Mac?

507

Lo sé, olvídalo y vuelve a aprenderlo. Es hora de escribirlo.

Pensilvania
fuente
15
escribiendo el tren de votos a favor de la estación de reputación
DivideByZer0
¡no voy a votar solo para admirar ese increíble error que obtuviste allí!
BRHSM

Respuestas:

942

Para ejecutar un shscript no ejecutable , use:

sh myscript

Para ejecutar un bashscript no ejecutable , use:

bash myscript

Para iniciar un ejecutable (que es cualquier archivo con permiso ejecutable); simplemente lo especifica por su ruta:

/foo/bar
/bin/bar
./bar

Para hacer un script ejecutable, dele el permiso necesario:

chmod +x bar
./bar

Cuando un archivo es ejecutable, el núcleo es responsable de descubrir cómo ejecutarlo. Para los no binarios, esto se hace mirando la primera línea del archivo. Debe contener un hashbang:

#! /usr/bin/env bash

El hashbang le dice al núcleo qué programa ejecutar (en este caso, el comando /usr/bin/envse ejecuta con el argumento bash). Luego, el script se pasa al programa (como segundo argumento) junto con todos los argumentos que le dio al script como argumentos posteriores.

Eso significa que cada script ejecutable debe tener un hashbang . Si no lo hace, no le está diciendo al núcleo qué es , y por lo tanto, el núcleo no sabe qué programa usar para interpretarlo. Podría ser bash, perl, python, sh, o alguna otra cosa. (En realidad, el kernel a menudo usará el shell predeterminado del usuario para interpretar el archivo, lo cual es muy peligroso porque podría no ser el intérprete correcto o podría analizarlo, pero con diferencias de comportamiento sutiles como es el caso). el caso entre shy bash).

Una nota sobre /usr/bin/env

Lo más común es que veas hash bangs así:

#!/bin/bash

El resultado es que el núcleo ejecutará el programa /bin/bashpara interpretar el script. Desafortunadamente, bashno siempre se envía de manera predeterminada y no siempre está disponible en /bin. Mientras que en las máquinas Linux suele ser así, hay una gama de otras máquinas POSIX donde se bashenvía en varias ubicaciones, como /usr/xpg/bin/basho /usr/local/bin/bash.

Para escribir un script bash portátil, por lo tanto, no podemos confiar en codificar la ubicación del bashprograma. POSIX ya cuenta con un mecanismo para tratar lo siguiente: PATH. La idea es que instale sus programas en uno de los directorios que se encuentran PATHy el sistema debería poder encontrar su programa cuando quiera ejecutarlo por su nombre.

Lamentablemente, no puedes simplemente hacer esto:

#!bash

El núcleo no (algunos podrían) PATHbuscarlo por usted. Sin PATHembargo, hay un programa que puede buscarlo, se llama env. Afortunadamente, casi todos los sistemas tienen envinstalado un programa /usr/bin. Entonces, comenzamos a envusar una ruta codificada, que luego realiza una PATHbúsqueda bashy la ejecuta para que pueda interpretar su script:

#!/usr/bin/env bash

Este enfoque tiene una desventaja: según POSIX, el hashbang puede tener un argumento . En este caso, lo usamos bashcomo argumento para el envprograma. Eso significa que no nos queda espacio para pasar argumentos bash. Por lo tanto, no hay forma de convertir algo parecido #!/bin/bash -exua este esquema. Tendrás que poner set -exudespués del hashbang en su lugar.

Este enfoque también tiene otra ventaja: algunos sistemas pueden enviarse con un /bin/bash, pero al usuario puede no gustarle, encontrarlo defectuoso u obsoleto, y puede haber instalado el suyo bashen otro lugar. Este suele ser el caso en OS X (Mac) donde Apple envía una /bin/bashversión obsoleta y los usuarios instalan una versión actualizada /usr/local/bin/bashutilizando algo como Homebrew. Cuando utiliza el envenfoque que realiza una PATHbúsqueda, tiene en cuenta las preferencias del usuario y utiliza su bash preferido sobre el que envió su sistema.

lhunath
fuente
66
Gracias por tomarse el tiempo para escribir una buena respuesta a una pregunta simple.
PA
55
Si lo uso zshcomo mi shell, ¿usaría el hashbang #! /usr/bin/env zsh?
stefmikhail
66
@stefmikhail: No importa qué intérprete de shell use para invocar el script, debe usarlo #! /usr/bin/env zshsi (y solo si) el código dentro del script debe ser ejecutado por el shell Z.
Johnsyweb
1
+1 para explicación. tiendo a olvidar, pero conocer el significado del comando me ayudará a recordar.
Angelin Nadar
2
@Carpetsmoker Esto es correcto, y no se limita al hashbang. los scripts de bash siempre deben usar terminaciones de línea UNIX; de lo contrario, el último argumento de cada comando tendrá un \ r añadido, al igual que el nombre del comando hashbang.
lhunath
80

Para iniciar el script de shell 'file.sh':

sh file.sh

bash file.sh

Otra opción es establecer permisos de ejecución utilizando el comando chmod:

chmod +x file.sh

Ahora ejecute el archivo .sh de la siguiente manera:

./file.sh
Pensilvania
fuente
16

Para la cáscara de bourne:

sh myscript.sh

Para bash:

bash myscript.sh

fuente
Gracias por responder esta pregunta bastante obvia. Para un tipo de Mac como yo, es fácil olvidar los viejos comandos de Unix entre las vueltas.
PA
10

Si desea que el script se ejecute en el shell actual (p. Ej., Desea que pueda afectar su directorio o entorno), debe decir:

. /path/to/script.sh

o

source /path/to/script.sh

Tenga en cuenta que /path/to/script.shpuede ser relativo, por ejemplo, . bin/script.shejecuta script.shel bindirectorio en el directorio actual.

Chas Owens
fuente
77
Tenga mucho cuidado al buscar o puntear con nombres de ruta relacionados. Usted debe siempre comenzar con ./ Si no lo hace, y la ruta relativa no contiene ningún barras, se le Sourcing algo en PATH, antes de que algo en el directorio actual! Muy peligroso por abuso.
lhunath
0

Primero, autorice la ejecución: -
chmod +x script_name

  1. Si el script no es ejecutable: -
    Para ejecutar el archivo de script sh: -
    sh script_name
    Para ejecutar el archivo de script bash: -
    bash script_name
  2. Si el script es ejecutable: -
    ./script_name

NOTA : puede verificar si el archivo es ejecutable o no usando 'ls -a'

Vineet Jain
fuente
0

La extensión de archivo .command se asigna a Terminal.app. Hacer doble clic en cualquier archivo .command lo ejecutará.

benwiggy
fuente
0

Pequeña adición, para ejecutar un intérprete desde la misma carpeta, todavía usando #! Hashbang en los scripts.

Como ejemplo, un ejecutable php7.2 copiado de / usr / bin está en una carpeta junto con un script de saludo .

#!./php7.2
<?php

echo "Hello!"; 

Para ejecutarlo:

./hello

Que se comportan igual de igual que:

./php7.2 hello
NVRM
fuente