O script não funciona quando é executado usando '#! / bin / sh'

5

Eu tenho um script que usa shebang: #!/bin/sh , mas quando eu o executo no meu terminal Ubuntu 14.04, ele não funciona e diz que algumas linhas têm um operador inesperado.

Meu amigo no MacOSX pode executar esse script usando o #!/bin/sh shebang.

Eu tentei mudar o shebang para #!/usr/bin/env bash e, de repente, o script funciona! O que acontece aqui, na verdade?

Espero sinceramente que eu também possa executar o !#/bin/sh shebang, para que eu não precise alterar cada script que tenho.

    
por everlasting-learner 16.10.2014 / 08:56

2 respostas

24

Seu amigo em outro computador provavelmente usa um sistema operacional que tenha /bin/sh vinculado a /bin/bash . No Ubuntu (na verdade, Debian e a maioria dos derivados Debian), /bin/sh não está ligado a /bin/bash , mas a /bin/dash , que não suporta muitos recursos bash -específicos, mas é consideravelmente mais rápido.

No Arch Linux:

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Sep 28 15:26 /bin/sh -> bash

No Ubuntu:

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Feb 19  2014 /bin/sh -> dash

A coisa certa a se fazer

Se você usar um shebang, significa isso. Como o script contém bash -isms, use /bin/bash no shebang. Ou escreva código compatível com POSIX e portátil.

Você pode acelerar esse processo usando o programa checkbashisms mencionado em este artigo do LWN . Faz parte do pacote devscripts , então instale primeiro:

sudo apt-get install devscripts

Assim:

checkbashisms /path/to/script.sh || sed -i '1 s;/bin/sh;/bin/bash;' /path/to/script.sh

Você pode converter isso em um script (digamos convert.sh ):

#! /bin/sh

for i
do
    checkbashisms "$i"
    if [ $? = "1" ]
    then
        sed -i '1 s;/bin/sh;/bin/bash;' "$i"
    fi
done

O código de retorno específico de 1 significa que checkbashisms encontrou um possível bash ism, e outros valores de retorno indicam outros problemas (arquivo não legível, ausente shebang, etc.), para que possamos verificar esse particular valor de retorno.

E, em seguida, chame-o com:

./convert.sh /path/to/first/script.sh /path/to/second/script.sh
# or 
./convert.sh *.sh
# or
find . -iname '*.sh' -exec ./convert.sh {} +

A coisa errada a fazer

Substitua /bin/sh por um link simbólico para /bin/bash .

Leitura recomendada:

por muru 16.10.2014 / 09:12
0

No meu caso, o problema foi a exportação da definição da variável IFS em ~ / .bashrc (~ / .profile)

#Loop over filenames with spaces
export IFS=$'\n'

Quando alterado para o% export IFS=$' \t\n' #default according to man dash
ou IFS=$'\n'
Os scripts #! / bin / sh começaram a funcionar novamente. Neste último caso, a definição não se propaga mais para processos bifurcados / bin / sh. O significado do IFS é explicado aqui e defini-lo como '\ n' causa problemas em scripts interpretados pelo shell traço , que pode ser o shell padrão /bin/sh -> dash vinculado à sua distribuição (por exemplo, debian).

    
por macieksk 08.03.2017 / 18:05