Сценарий не работает, когда он выполняется с помощью '#!/bin/sh'

У меня есть сценарий, которые используют хижину: #!/bin/sh, но когда я выполняю его в своем терминале Ubuntu 14.04, это не работает, и это говорит, что некоторые строки имеют неожиданный оператор.

Мой друг в MacOSX мог запустить тот скрипт с помощью #!/bin/sh хижина.

Я пытался изменить хижину в #!/usr/bin/env bash, и внезапно, работы сценария! Что происходит здесь на самом деле?

Я действительно надеюсь, что мог также работать !#/bin/sh хижина, так, чтобы я не должен был изменять каждый сценарий, который я имею.

6
задан 6 June 2016 в 13:33

2 ответа

Ваш друг на другом компьютере, вероятно, использует ОС, которая имеет /bin/sh связанный с /bin/bash. В Ubuntu (на самом деле, Debian и большинство производных Debian), /bin/sh не связан с /bin/bash, но к /bin/dash, который не поддерживает многих bash- определенные функции, но значительно быстрее.

На дуге Linux:

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

На Ubuntu:

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

Правильный поступок

Если Вы используете хижину, имеете в виду это. Так как Ваш сценарий содержит bash- измы, использовать /bin/bash в хижине. Или напишите портативный, совместимый POSIX код.

Можно ускорить этот процесс при помощи checkbashisms программа упоминается в этой статье LWN. Это - часть devscripts пакет, так установите его сначала:

sudo apt-get install devscripts

Таким образом:

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

Можно преобразовать это в сценарий (сказать convert.sh):

#! /bin/sh

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

Определенный код возврата 1 средства это checkbashisms найденный возможным bashизм и другие возвращаемые значения указывают на другие проблемы (файл не читаемая, недостающая хижина, и т.д.), таким образом, мы можем проверить на то конкретное возвращаемое значение.

И затем назовите его с:

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

Неправильный поступок

Замена /bin/sh с символьной ссылкой на /bin/bash.

Рекомендуемое чтение:

  • Bashism - выдерживает сравнение bash и dash синтаксис и выставочные изменения необходимы.
  • Тире как /bin/sh - подобный.
24
ответ дан 23 November 2019 в 07:16

В моем случае проблемой был экспорт IFS определение переменной в ~/.bashrc (~/.profile)

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

При изменении на также
export IFS=$' \t\n' #default according to man dash
или
IFS=$'\n'
#!/bin/sh сценарии начал работать снова. В последнем случае определение больше не распространяет к разветвленным процессам/bin/sh. Значение IFS объяснено здесь, и установка его к '\n' вызывает проблемы в сценариях, интерпретируемых оболочкой тире, которая может быть оболочкой по умолчанию /bin/sh -> dash связанный с в Вашем распределении (например, debian).

0
ответ дан 23 November 2019 в 07:16

Другие вопросы по тегам:

Похожие вопросы: