Я устанавливаю огромную программу, ресурсы которой представлены в виде файла rpm. Он застрял на линии

#!/bin/sh
SCITEGICPERLBIN=`dirname $0`
SCITEGICPERLHOME=`dirname $SCITEGICPERLBIN`
if [ $SCITEGICPERLHOME == "." ]

По-видимому, sh работает для bash в Red Hat Linux с этим синтаксисом, но выдает ошибку unexpected operator в Ubuntu.

Я не могу изменить сценарий на bash, так как он взят из пакета rpm. Я могу распаковать и переупаковать пакет rpm, но таких скриптов может быть много.

Есть ли способ изменить стандартную оболочку для обработки #!/bin/sh как bash или чего-то еще, что может обрабатывать оператор [?

18
Peter Mortensen 8 Май 2018 в 17:01
5
Единственное, что неправильно, это ==, которое должно быть =. Это и то, что расширения переменных должны быть заключены в двойные кавычки.
 – 
Kusalananda
8 Май 2018 в 14:29
4
[ — это не оператор, а встроенная команда, которая называется test. Неожиданный оператор — ==, и его следует заменить на =, поскольку он несовместим с POSIX.
 – 
schily
8 Май 2018 в 14:34
Второе единственное, что неправильно, это то, что $SCITEGICPERLHOME нужно заключать в кавычки.
 – 
l0b0
8 Май 2018 в 22:35
13
Вам следует пожаловаться автору программы. Если они используют #!/bin/sh, они должны убедиться, что используют только функции оболочки POSIX, а не расширения bash. Этот программатор очень неаккуратный. Он должен либо исправить свой код, либо использовать #!/bin/bash.
 – 
Barmar
8 Май 2018 в 22:44
Для тех, кто интересуется другими подобными проблемами, вот список "Bashisms". См. также этот вопрос.
 – 
Captain Man
9 Май 2018 в 02:00

2 ответа

Лучший ответ

Существует несколько программ, реализующих язык /bin/sh. В Ubuntu /bin/sh – это тире, которое предназначено для быстрой работы, использования небольшого объема памяти и не поддерживает намного больше, чем минимум, ожидаемый от /bin/sh. В RHEL /bin/sh — это bash, который медленнее и использует больше памяти, но имеет больше возможностей. Одной из таких функций является оператор == для условного синтаксиса [. Dash поддерживает [, базовую функцию sh, но не имеет оператора ==, являющегося расширением bash (а также ksh и zsh).

Вы можете переключить свою систему на использование bash. В Ubuntu /bin/sh является символической ссылкой на dash. Вместо этого вы можете сделать символическую ссылку на bash. Текущие версии Debian и Ubuntu (и производные) делают этот вариант установки dash. Чтобы изменить его, запустите

sudo dpkg-reconfigure dash

И ответьте «да», чтобы оставить тире как /bin/sh, или «нет», чтобы переключиться на bash.

Вы можете оставить bash как /bin/sh, но это сделает вашу систему немного медленнее. Возможно даже, что некоторые системные скрипты несовместимы с bash, хотя это маловероятно, поскольку bash в основном представляет собой надмножество dash.


Для дистрибутивов, в которых нет интерфейса для выбора между реализациями /bin/sh, вот как переключиться на bash.

sudo ln -s bash /bin/sh.bash
sudo mv /bin/sh.bash /bin/sh

Держите терминал открытым и убедитесь, что вы все еще можете запускать некоторые сценарии sh после этого. Если вы ошибетесь с этой командой, ваша система станет непригодной для использования. (Между прочим, причина, по которой я использовал несколько команд выше, а не прямолинейный sudo ln -sf bash /bin/sh, заключается в том, что ln -sf не является атомарным. В маловероятном случае, если ваш компьютер выйдет из строя во время этой операции, вы необходимо загрузиться с загрузочного носителя, чтобы восстановить его. Напротив, mv является атомарным.)

Чтобы восстановить тире как /bin/sh:

sudo ln -s dash /bin/sh.dash
sudo mv /bin/sh.dash /bin/sh

Обратите внимание, что если в вашем дистрибутиве по умолчанию используется значение /bin/bash, переключение на dash может привести к сбою сценариев, поскольку bash имеет гораздо больше возможностей, чем dash. Сценарии Bash должны начинаться с #!/bin/bash, а сценарии, начинающиеся с #!/bin/sh, не должны использовать специфические функции bash, но дистрибутивы, которые поставляются с bash как /bin/sh, могут использовать специфические функции bash в #!/bin/sh скрипты, специфичные для этого дистрибутива (это нормально, если не ожидается, что пользователи смогут переключиться на тире как /bin/sh, и не ожидается, что эти скрипты будут работать в другом дистрибутиве).

31
Gilles 'SO- stop being evil' 12 Сен 2018 в 17:27
По моему не очень скромному мнению, если какой-то скрипт дает сбой, когда /bin/sh является Bash, это ошибка либо в системе (пакете со скриптом), либо в sh-режиме Bash. Как говорит Стивен, система явно позволяет установить /bin/sh обратно в Bash через dpkg-reconfigure. Это также упоминается как возможность в вики Ubuntu по этому поводу: wiki.ubuntu.com/DashAsBinSh
 – 
ilkkachu
8 Май 2018 в 14:50
5
Да, если скрипт не работает, если /bin/sh - это bash, это ошибка. Однако случаются баги. Я рекомендую придерживаться значения по умолчанию, если вы не можете и не хотите диагностировать такие ошибки, потому что другие люди протестировали его для вас. Я использовал тире как /bin/sh до того, как он был официально поддержан в Debian, но я пошел на этот риск, зная, что смогу справиться, если что-то случится.
 – 
Gilles 'SO- stop being evil'
8 Май 2018 в 14:55
Обратите внимание, что переопределенные вручную символические ссылки будут восстановлены до любой конфигурации, сохраненной в debconf, при следующем обновлении dash; по общему признанию, это будет происходить не часто (если вообще, в данном выпуске) для систем, работающих под управлением стабильной версии Debian.
 – 
Stephen Kitt
11 Сен 2018 в 22:17

Чтобы переключить sh на bash (вместо dash по умолчанию), перенастройте dash (да, это несколько нелогично):

sudo dpkg-reconfigure dash

Это спросит, хотите ли вы, чтобы dash была системной оболочкой по умолчанию; ответьте «Нет» (Tab, затем Enter), и bash станет значением по умолчанию (т.е. /bin/sh будет указывать до /bin/bash).

42
Stephen Kitt 8 Май 2018 в 14:26
1
Ваше решение действительно самое разумное, но я принял другой ответ из-за подробных описаний, проясняющих проблему. Приносим извинения за неудобства.
 – 
Googlebot
8 Май 2018 в 14:52
Не нужно извиняться, выбор принятого ответа является привилегией спрашивающего. И я получил за это золотой значок ;-).
 – 
Stephen Kitt
9 Май 2018 в 17:34