Ejecutar un script de shell cuando "/ bin / sh" apunta a "/ bin / bash"

11

He leído lo siguiente en esta pregunta :

bash admite un conmutador --posix, lo que lo hace más compatible con POSIX. También intenta imitar POSIX si se invoca como sh .

La cita anterior supone que /bin/shes un enlace al que apunta /bin/bash.

Pero no entiendo muy bien qué se entiende por "invocado como sh" .


Digamos que tengo el siguiente script que se llama "script.sh":

#!/bin/bash
echo "Hello World"

Por favor, dígame en cada uno de los siguientes casos si el script se ejecutará en bashmodo normal o en modo POSIX (suponga que he ejecutado los siguientes comandos en un terminal que se está ejecutando bash):

  1. sh script.sh
  2. bash script.sh
  3. ./script.sh

Ahora diga que tengo el siguiente script que se llama "script.sh" (que es como el script anterior pero sin shebang):

echo "Hello World"

Por favor, dígame en cada uno de los siguientes casos si el script se ejecutará en bashmodo normal o en modo POSIX (suponga que he ejecutado los siguientes comandos en un terminal que se está ejecutando bash):

  1. sh script2.sh
  2. bash script2.sh
  3. ./script2.sh
usuario269904
fuente

Respuestas:

19

Solo los casos 1 y 4 se ejecutarán en modo POSIX (suponiendo que shsea ​​bash y no alguna otra implementación de sh). Cualquier caso que llame explícitamente bashsin lo --posixhará, ya sea desde el shebang o no. Cualquier caso que llame explícitamente lo shhará. El shebang solo se usa cuando ya no se inició explícitamente el shell para el script.

El caso 6, si su terminal se está ejecutando bash, no se ejecutará en modo POSIX y Bash lo invocará usándose a sí mismo. Si el terminal se ejecuta zsh lugar, el caso 6 podría también funcionar en modo POSIX. POSIX es ambiguo sobre exactamente lo que debería suceder en ese caso , y Bash y zsh tomaron diferentes decisiones allí. Bash invoca el script usándose, mientras que zsh usa sh(lo que sea que sea). Otras conchas también varían en ese punto.


Una manera simple de saber en qué modo estás es hacer que tu cuerpo de script:

kill -SIGHUP

que fallará con un error en el modo POSIX , pero dará instrucciones de uso killfuera de él. Esta es una distinción fácil y funciona a través de una amplia gama de versiones de Bash que se remontan a lo más probable.

Michael Homer
fuente
3
Hay otras cosas que obligarán basha ejecutarse en modo POSIX, como la POSIXLY_CORRECTvariable de entorno o SHELLOPTS=posix.
Stéphane Chazelas
1
[ -o posix ]es una forma más obvia de verificar que se está ejecutando en modo posix en bash (no en otros shells (excepto yash), por lo que no querrá hacerlo en un shscript). POSIXLY_CORRECT=1 bash -c '[ -o posix ] && echo yes'salidas yes`
Stéphane Chazelas
2
En el caso 6, bash invoca el script consigo mismo en modo POSIX cuando está en modo POSIX como lo requiere POSIX. POSIX no especifica el mecanismo she-bang, y 6 es la única forma POSIX de tener scripts ejecutables y está claramente especificado (en entornos POSIX, el script está destinado a ser interpretado por una utilidad sh compatible).
Stéphane Chazelas
8

El "se invoca como" se refiere a lo que sea que el proceso a partir del golpe pone en su argumento de línea de comandos "cero", argv[0].

Cuando se inicia un programa con las exec*()llamadas al sistema , en realidad no conocen el nombre del archivo binario que contiene el programa, sino que el proceso de llamada es libre de poner lo que quiera allí. Por lo general, por supuesto, el nombre se toma del sistema de archivos, por lo que si ejecuta /bin/sh, eso es lo que se pone allí. Y si /bin/shes Bash, no tiene que ser un enlace simbólico, podría ser un enlace duro o simplemente otra copia del programa de shell.

Como ejemplo de configuración del "nombre del programa", el execcomando de Bash puede establecer el argumento cero con la -aopción. (Podríamos hacer lo mismo con Perl, o directamente con C, etc.)

Aquí mynamehay un simple programa en C que simplemente imprime su argumento cero, el nombre que se ve a sí mismo:

$ ./myname 
I am ./myname
$ (exec -a something ./myname )
I am something
$ mv ./myname somename
$ ln -s somename othername
$ ./somename 
I am ./somename
$ ./othername
I am ./othername

Fuente:

#include <stdio.h>
int main(int argc, char *argv[]) {
    printf("I am %s\n", argv[0]);
    return 0;
}

Pero, para responder las preguntas numeradas ...

(1 y 4) la ejecución sh somescriptejecutará lo shque sea ​​que esté en su PATH, probablemente, /bin/shpero posiblemente algo así/usr/xpg4/bin/sh .

  • Si es Bash, se ejecuta en modo POSIX, ya que ve el nombre sh.
  • Si es el shell Z o el shell Korn, también ve el nombre sh, pero se ejecuta en modo "compatible con SH", que tiene como objetivo ser compatible con el shell Bourne y es sutilmente diferente al modo conforme a POSIX completo en ambos. .
  • Podría ser el caparazón Almquist, un caparazón Bourne real, o algo más, por supuesto.

(2 y 5) La ejecución bash somescriptse ejecutará en el modo Bash normal (de nuevo, por supuesto, depende de lo que haya bashen su PATH).

(3) Aquí, el nombre del script se da directamente a la llamada del sistema en lugar del archivo del programa. El núcleo lee la línea hashbang y la usa para ejecutar el script.

(6) Este es el complejo. Es similar a (3), pero la llamada al sistema para iniciar el programa falla ( ENOEXEC (Exec format error)), ya que no hay una línea hashbang. Lo que sucede después depende de si la cáscara de la que se está ejecutando es en sí en modo POSIX. POSIX requiere que un shell compatible con POSIX se comporte de manera específica en respuesta a ENOEXEC. Sin embargo, hay cierto margen de maniobra en "un comando equivalente a tener un shell invocado", lo que significa que diferentes shells hacen cosas diferentes.

  • El shell Bourne Again se vuelve a ejecutar en el mismo modo con el nombre del script como primer argumento de línea de comandos. En su modo compatible con POSIX, por supuesto se está ejecutando en su modo compatible con POSIX, obedeciendo así el requisito de POSIX para invocar un shell compatible con POSIX.
  • El shell Z, el shell Almquist y el shell Korn se ejecutan /bin/shcon el nombre del script insertado antes de los otros argumentos como su primer argumento de línea de comandos. El shell Z, el shell Almquist y el shell Korn están (intentando) invocar un shell compatible con POSIX a fuerza de suponer que el /bin/shprograma es uno.
ilkkachu
fuente
¿Podría por favor compartir el código fuente de este programa C?
GypsyCosmonaut
int main(int argc, char *argv[]){printf("I am %s\n",argv[0]);}
Stig Hemmer
Eso es practicamente todo.
ilkkachu
4

La cáscara es ejecutado ya sea por una llamada en la línea de comandos o el que está en el tinglado (si la línea de comandos no lo especifica).

Por lo tanto, las versiones 1 y 4 se ejecutarán con sh, 2 y 5 con bash y 6 pueden no ejecutarse si está utilizando sh (y algunos otros) de forma interactiva. Bash inicia el guión. Ksh también. Zsh comienza como sh.

Solo aquellos iniciados como shusarán la opción posix si bash está vinculado /bin/sh.

Agregue esta línea a su script para detectar si alguna versión de bash ksh o zsh la está ejecutando:

echo "Hello World $BASH_VERSION $KSH_VERSION $ZSH_VERSION"
NotAnUnixNazi
fuente