.sh especificando extensión?


12

¿Por qué algunos sistemas ejecutarán un .sharchivo simplemente especificando el nombre del archivo sin extensión y otros requieren nombre más extensión? En mi caso, estoy tratando de escribir una serie de comandos siguiendo estas instrucciones .

Ahora estoy especificando la extensión, pero .shsería preferible ejecutar los comandos sin ellos.


44
.shEn muchas circunstancias, el uso como extensión se considera una mala práctica: es contrario a la forma en que se nombran otros comandos (no se ejecuta ls.elf), a menudo es engañoso (si foo.shcomienza con #!/bin/bash, entonces la ejecución sh foo.shlo ejecutará con un intérprete diferente al que está diseñado para ), y si reescribe foo.shpara ser un programa Python, usar esa extensión significa que debes elegir entre mantener el nombre ahora engañoso y reescribir cada programa que lo llame.
Charles Duffy

2
... donde es una mejor práctica son las bibliotecas de shell, no los comandos con +xset - donde foo.shhay una biblioteca que puede obtenerse en cualquier shell POSIX, foo.bashpuede obtenerse en bash, foo.kshen ksh, etc.
Charles Duffy

Respuestas:


39

Estas confundido. La .shextensión es solo una pista para los humanos, y no tiene absolutamente ningún efecto sobre cómo el sistema maneja el archivo. Unix / Linux no cometió el Secrets.pdf.exeerror de Windows .

Esto es lo que sucede cuando escribe foo:

  1. Redirección para STDIN, STDOUTy STDERRestán configurados.

  2. El shell comprueba su tabla hash interna para ver si ya conoce una $PATHentrada para foo. Si no existe ninguno, el shell busca en los directorios $PATH, buscando un archivo llamado fooque tenga el bit Ejecutar establecido en sus permisos de archivo. Primero foogana.

  3. Si los dos primeros bytes del archivo fooson #!, la siguiente cadena es el nombre de un intérprete para ejecutar. Por lo tanto, #!/bin/bashintroduce un script Bash, #!/usr/bin/perlintroduce un script Perl, etc.

  4. Si el archivo comienza con \177ELF, es un ejecutable binario y lo ld.soinicia.

Lea man execvey man ld.sopara una explicación más detallada.


15
Sí, en Linux puede hacer doble clic en Secrets.pdf sin tener idea del nombre de que en realidad es un ejecutable;)
OrangeDog

1
@OrangeDog Sé que estás bromeando, pero siento que tengo que señalar que el bit ejecutable ( chmod +x) prácticamente resuelve esto, ¿verdad?
wchargin

3
@WChargin Eso depende del buen comportamiento de su sistema de archivos (por ejemplo, un recurso compartido de red montado o una partición NTFS podría establecer el xbit de manera optimista en todo) y de dónde vino el archivo (cualquier proceso con control del directorio podría ser engañado para establecer los permisos) . Entonces, lo mitiga , pero no diría que lo resuelve .
IMSoP

2
@WChargin, todavía, pero creo que su punto de vista es que, por lo general, los administradores de archivos no muestran el bit ejecutable, es decir, no hay "pistas para los humanos" como una extensión.
Paul Draper

1
Nunca hago clic por error Secrets.pdf.exeporque siempre desactivo la hide file extensionfunción estúpida
phuclv

12

El punto clave es este: las extensiones son irrelevantes en cualquier sistema de sistema similar a Unix. Un nombre de archivo es solo nombre y no tiene ningún efecto sobre si se puede ejecutar un script o un ejecutable compilado . Un programador puede agregar una .shextensión para designar que un archivo es un script de shell, o .pypara un script de Python, pero a diferencia de Windows, a unix no le importan los nombres, se preocupa por los permisos.

Lo que importa es el permiso ejecutable otorgado a un archivo. Que puedes consultar con

ls -l /path/to/file

Ejecutando ejecutables

Para ejecutar el script, generalmente hay varias formas.

  • Si su directorio actual es el mismo que el script, y el script tiene permisos ejecutables, puede ejecutarlo así ./my_script_name. El .directorio actual de medios.
  • Si su directorio actual es diferente y el script tiene permisos ejecutables, puede ejecutarlo especificando la ruta completa: /home/user/bin/my_script_name

(Los dos métodos anteriores se basan en tener un conjunto de permisos ejecutables; si el archivo es o no parte de la $PATHvariable es irrelevante. La presencia de #!línea también es importante; sin ella, el script será ejecutado por el shell actual que haya abierto. Si tengo un cshscript sin esa línea, e intenta ejecutarla en bash con ./my_script.csh, fallará)

  • Si su script se encuentra en el directorio que forma parte de su $PATHvariable, puede ejecutarlo simplemente llamando al nombre. Puede llamar al chmodcomando en la línea de comando simplemente escribiendo su nombre porque está en la /bincarpeta. /binsiempre es parte de la $PATHvariable. En este caso, los permisos ejecutables y la ubicación del script son importantes
  • Especificando un intérprete como comando y script como argumento. De esa manera, el script servirá como archivo de entrada para el intérprete.
  • Abastecimiento de un archivo. El . filename.sho source filename.shhará que el script sea tratado como si fuera una entrada de teclado, es decir, como si estuviera escrito directamente en la línea de comando. En este caso, los permisos ejecutables y la ubicación no importan

Ejemplos

Ejemplo # 1, ejecutando con intérprete, para ejecutar permisos

$-> ls -l abc.py                                                               
-rw-rw-r-- 1 xieerqi xieerqi 44 Apr 27 22:39 abc.py
$-> python abc.py                                                              
a
b
c

Ejemplo # 2, ejecutando con ./conjunto de permisos ejecutables, conjunto de líneas shebang.

$-> cat abc.py                                                                 
#!/usr/bin/env python
for letter in 'a' 'b' 'c' :
   print letter
$-> ls -l abc.py
-rwxrwxr-x 1 xieerqi xieerqi 66 Apr 27 23:02 abc.py*
$-> ./abc.py                                                                   
a
b
c

Ejemplo # 3, ejecutando sin conjunto de líneas shebang (falla, porque bash no puede leer los scripts de python; ninguna línea shebang asume el shell actual como intérprete)

$-> cat abc.py                                                                 
for letter in 'a' 'b' 'c' :
   print letter
$-> ./abc.py                                                                   
./abc.py: 2: ./abc.py: Syntax error: word unexpected (expecting "do")

Ejemplo # 4, ejecutando script que tiene permisos ejecutables configura la carpeta de formulario que es parte de la $PATHvariable

#  /home/xieerqi/bin is part of my path variable
$-> echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/microchip/xc16/v1.25/bin:/opt/microchip/xc32/v1.40/bin:/opt/microchip/xc8/v1.35/bin:/home/xieerqi/bin:/home/xieerqi/bin/sh

$-> # current directory is /home/xieerqi
$-> pwd
/home/xieerqi
$-> # move the file to ~/bin
$-> mv ~/abc.py ~/bin/abc.py
$-> # now I can run it just by calling the name
$-> abc.py
/home/xieerqi/bin/abc.py: 2: /home/xieerqi/bin/abc.py: Syntax error: word unexpected (expecting "do")
$-> # Syntax error because again, no interpreter specified.                    
$-> # must add #!/usr/bin/env python
$-> vi /home/xieerqi/bin/abc.py          
$-> # after adding the line with vi text editor, we can run
$-> abc.py                                                                     
a
b
c

Ejemplo # 5, eliminando la extensión, todavía se ejecuta porque las extensiones no importan, pero tiene permisos y es parte de $PATH:

$-> mv ~/bin/abc.py  ~/bin/abc                                                 
$-> abc
a
b
c

Ejecuté el comando y recibí este '-rwxr-x ---'. ¿Qué deseo que lea el valor y cómo puedo cambiarlo?
Philip Kirkbride

¿O estás diciendo que simplemente debería cambiar el nombre de 'filename.sh' a 'filename'?
Philip Kirkbride

1
@PhilipKirkbride Name es irrelevante. ¿Cómo ejecutas tu comando? Dónde está ? ¿El directorio es parte de tu PATH?
Sergiy Kolodyazhnyy

@PhilipKirkbride Permítanme ampliar mi respuesta en un minuto para aclararla.
Sergiy Kolodyazhnyy

1
Eche un vistazo man chmodpara ver cómo establecer permisos
Nick Mertin

6

Buenas explicaciones aquí ya. Solo quería agregar que idealmente no debería usar extensiones de archivo para ejecutables.

Por lo general, necesita lograr algo relativamente fácil y comienza con un pequeño script de shell. Con el tiempo, comienza a agregar más y más funcionalidades a su secuencia de comandos, hasta que llega un momento en que no se puede mantener o necesita alguna funcionalidad que no puede lograr fácilmente con una secuencia de comandos de shell y piensa en volver a escribir esta secuencia de comandos de shell en otro idioma (python , perl, ...?).

Reescribir desde cero generalmente se considera un error, pero para los scripts puede tener sentido porque generalmente no son tan grandes o tienen mucha funcionalidad. Pero supongamos que es posible reescribir desde cero en algún otro idioma, manteniendo la funcionalidad y los parámetros / indicadores del script de shell inicial.

Los usuarios de este script no necesitan estar al tanto de este cambio de idioma, seguirán ejecutando el mismo comando y continuará funcionando.

Si su script fue nombrado do-something.sh, puede seguir siéndolo do-something.sh, pero ahora está escrito en python (por ejemplo), por lo que su sugerencia inicial ahora es totalmente engañosa.


4

Para ejecutar archivos sin una extensión que normalmente no necesita hacer mucho, solo asegúrese de tener (en caso de scripts de bash) la línea shebang adecuada en la primera línea:

#!/bin/bash

entonces también necesita hacer que el archivo sea ejecutable para el sistema

chmod 755 yourfilename

Esto es lo mismo que usar chmod +x yourfilenamelos números que se explican fácilmente.

Es un número triple de octales agregados, el primer número representa al usuario, el segundo para el grupo y el tercero para los demás, más sobre eso puede encontrar aquí .

Y si está en el mismo directorio que su script, no olvide usarlo ./así:

./yourfilename

Intenté esto. Lamentablemente no hay diferencia con los resultados originales.
Philip Kirkbride

@PhilipKirkbride eche un vistazo a mi respuesta revisada, esto probablemente arrojará algo más de luz.
Videonauth

0

El sufijo .sh en realidad puede interferir, porque para ejecutarlo debe escribir myscript.sh en lugar de solo myscript, que no funcionará. Es mejor llamarlo "myscript" sin el sufijo .sh, y un uso rápido del comando "file" le dirá si es un ejecutable binario (formato ELF en Linux) o un script de shell, o cualquier otro tipo de script.

QDOS (Sistema operativo rápido y sucio, más tarde renombrado a "DOS" por IBM después de que mirosoft lo pirateó y se lo vendió ilegalmente) y otras estafas baratas de CP / M, incluidas las ventanas, mezclan todo esto porque en esos sistemas no hay tales como ejecutar permisos en archivos. Esto ha resultado en innumerables f'ups de seguridad en los últimos 30-40 años. En realidad, hace solo unos minutos, recibí varios correos basura con un archivo zip atrapado con un piquete renombrado a MYPICTURE.JPG.zip :)

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.