Bug 32110

Summary: bash --rpm-requires fails on the syntax of shopt -s extglob
Product: Sisyphus Reporter: Ivan Zakharyaschev <imz>
Component: bashAssignee: placeholder <placeholder>
Status: NEW --- QA Contact: qa-sisyphus
Severity: normal    
Priority: P3 CC: aen, alex, alexey.tourbin, at, cas, ekorneechev, glebfm, kde, ldv, mike, placeholder, rider
Version: unstable   
Hardware: all   
OS: Linux   
URL: https://lists.altlinux.org/pipermail/devel/2016-May/201432.html
Bug Depends on: 31399    
Bug Blocks: 32136    
Attachments:
Description Flags
gear patch for bash4+ none

Description Ivan Zakharyaschev 2016-05-18 21:47:55 MSK
bash-3.2.57-alt1

As described in https://lists.altlinux.org/pipermail/devel/2016-May/201432.html , the following failure:

Executing: /bin/sh -e /usr/src/tmp/rpm-tmp.yxuvVs
find-requires: running scripts (cpp,debuginfo,files,lib,pam,perl,pkgconfig,pkgconfiglib,python,rpmlib,shebang,shell,static,symlinks)
/usr/src/tmp/mosquito-hive-buildroot/usr/share/mosquito-hive/rebuild-helper-one.sh: line 22: syntax error near unexpected token `('
/usr/src/tmp/mosquito-hive-buildroot/usr/share/mosquito-hive/rebuild-helper-one.sh: line 22: `	-*([0-9])) num="${1#-}"; shift;;'
shell.req: ERROR: /usr/src/tmp/mosquito-hive-buildroot/usr/share/mosquito-hive/rebuild-helper-one.sh: /bin/bash --rpm-requires failed
find-requires: ERROR: /usr/lib/rpm/shell.req failed
error: /bin/sh failed
error: Failed to find Requires


RPM build errors:
    /bin/sh failed
    Failed to find Requires

can be reproduced by running gear-hsh in mosquito-hive from http://git.altlinux.org/people/imz/public/mosquito-hive.git and is caused by code like http://git.altlinux.org/people/imz/public/mosquito-hive.git?p=mosquito-hive.git;a=blob;f=rebuild-helper-one.sh;h=e229ef04e9a03db69704de2be95773320ef2ea6f;hb=HEAD#l22 :

    shopt -s extglob

    case "$1" in
	-*([0-9])) num="${1#-}"; shift;;
    esac

(*(fooBAR) is the special form from the extended globs. I use it substantially in other places of mosquito-hive; but, anyway, a correct bash script shouldn't break this mode. )
Comment 1 Ivan Zakharyaschev 2016-05-19 16:08:48 MSK
A simple test case:

----extglob.sh-----
#!/bin/bash

shopt -s extglob

case foo in
    !(bar)) echo yes
    ;;
esac
--------------------

~/tests/test-sh $ bash --rpm-requires extglob.sh 
executable(/etc/bashrc)
extglob.sh: line 6: syntax error near unexpected token `('
extglob.sh: line 6: `    !(bar)) echo yes'
~/tests/test-sh $ bash extglob.sh 
yes
~/tests/test-sh $
Comment 2 Ivan Zakharyaschev 2016-05-19 17:08:57 MSK
An idea:

----extglob.sh-----
#!/bin/bash

shopt -s extglob

case foo in
    !(bar)) /bin/echo yes
    ;;
esac
--------------------

~/tests/test-sh $ bash --rpm-requires -O extglob extglob.sh
executable(/etc/bashrc)
executable(/bin/echo)

BTW, other cases with errors:

~/tests/test-sh $ bash -O extglob --rpm-requires extglob.sh
/bin/bash: --: invalid option
Usage:	/bin/bash [GNU long option] [option] ...
	/bin/bash [GNU long option] [option] script-file ...
GNU long options:
	--debug
	--debugger
	--dump-po-strings
	--dump-strings
	--help
	--init-file
	--login
	--noediting
	--noprofile
	--norc
	--posix
	--protected
	--rcfile
	--rpm-requires
	--restricted
	--verbose
	--version
	--wordexp
Shell options:
	-irsD or -c command or -O shopt_option		(invocation only)
	-abefhkmnptuvxBCHP or -o option
~/tests/test-sh $ 

----extglob.sh-----
#!/bin/bash -O extglob

shopt -s extglob

case foo in
    !(bar)) /bin/echo yes
    ;;
esac
--------------------

~/tests/test-sh $ ./extglob.sh 
/bin/bash: - : invalid option
Usage:	/bin/bash [GNU long option] [option] ...
	/bin/bash [GNU long option] [option] script-file ...
GNU long options:
	--debug
	--debugger
	--dump-po-strings
	--dump-strings
	--help
	--init-file
	--login
	--noediting
	--noprofile
	--norc
	--posix
	--protected
	--rcfile
	--rpm-requires
	--restricted
	--verbose
	--version
	--wordexp
Shell options:
	-irsD or -c command or -O shopt_option		(invocation only)
	-abefhkmnptuvxBCHP or -o option
~/tests/test-sh $
Comment 3 Ivan Zakharyaschev 2016-05-21 22:06:56 MSK
The same problem has been discussed in https://lists.altlinux.org/pipermail/sisyphus/2012-August/358222.html -- at@ :

...

Выходит что, к сожалению, выполнение текущей команды может влиять
на синтаксический разбор последующей команды - получается такой недо-перл
(в перле команды, модифицирующие синтаксис, выполняются безусловно, даже в
режиме syntax check).

...

Простого способа передать "-O extglob" в shell.req пока нету.
Можно избирательно отключить поиск зависимостей в проблемном скрипте:
%add_findreq_skiplist */usr/bin/zpool_layout
либо менее избирательно:
AutoReq: yes, noshell
Тогда часть зависимостей, если в скриптах есть самостоятельные
нетривиальные зависимости, нужно будет написать вручную.
Comment 4 Ivan Zakharyaschev 2016-05-22 00:41:44 MSK
(In reply to comment #3)

> Простого способа передать "-O extglob" в shell.req пока нету.

В bash4 можно будет сделать export BASHOPTS=extglob (или export BASHOPTS="$BASHOPTS:extglob") -- https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html .

Вообще-то, (когда это будет действовать в bash4) это похоже на ситуацию с LD_PRELOAD, который сначала люди экспортили из spec-а, но это было слишком грязно. Сделали механизм привязки желаемого значения переменной окружения к конкретным файлам, которые будут обрабатываться verify-elf. (Для lib.req почему-то такого желания остро не чувствовалось.) Тут аналогично для shell.req.

Т.е. если этот механизм обобщать до полезного в большем числе ситуаций, надо не зашивать в него конкретные имена переменных (как сейчас LD_PRELOAD, которое важно для тех, кто работает с ELF, а BASHOPTS будут для для shell.req), а привязывать к путям набор переменных с их значениями и заставить все RPM-скрипты их уважать и выставлять перед вызовом инструмента для обработки такого файла.

> Можно избирательно отключить поиск зависимостей в проблемном скрипте:
> %add_findreq_skiplist */usr/bin/zpool_layout
> либо менее избирательно:
> AutoReq: yes, noshell
> Тогда часть зависимостей, если в скриптах есть самостоятельные
> нетривиальные зависимости, нужно будет написать вручную.
Comment 5 Ivan Zakharyaschev 2016-05-25 20:39:14 MSK
(In reply to comment #4)
> (In reply to comment #3)
> 
> > Простого способа передать "-O extglob" в shell.req пока нету.
> 
> В bash4 можно будет сделать export BASHOPTS=extglob (или export
> BASHOPTS="$BASHOPTS:extglob") --
> https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html .

Сейчас в Sisyphus есть пакет bash4.

Если у Вас скрипты на bash4 (а ведь за этим будущее, и большинство скриптов должно становиться правильными bash4-скриптами), то в нынешней ситуации (т.е. когда bash -- это не bash4) с rpm-4.0.4-alt100.94 можно делать так:

* в shebang написать bash4
* в .spec-е экспортировать BASHOPTS:

# For shell.req:
%global __spec_autodep_custom_pre export BASHOPTS=extglob

Я так собрал пакет -- http://git.altlinux.org/people/imz/packages/mosquito-hive.git?p=mosquito-hive.git;a=commitdiff;h=c00c2380ca0b3529833d75b1ba3d6777dcccbd01 .
Comment 6 alexey.tourbin 2016-05-26 21:32:57 MSK
Created attachment 6735 [details]
gear patch for bash4+

This patch might be redundant: only one hunk might be needed.
Comment 7 alexey.tourbin 2016-05-26 21:33:24 MSK
Имхо, нет смысла дальше поддерживать bash != bash4. Bash < 4 прекратился обновляться уже почти 10 лет назад (версия 3.2 вышла в октябре 2006 года; дальше только errata и security fixes).

Я у себя на одной машине с альлинуксом уже второй год обновляю bash самостоятельно; сейчас это bash43-042. Кроме того, я сделал всего один подпакет - bash, и симлинк "ln -s bash %buildroot/bin/sh". Я считаю, что всякие игры в другие шеллы неинтересны и никому не нужны. Люди рассчитывают на bash4+. (For the record, я также скептически отношусь к dash.)

Я столкнулся с тем, что в bash < 4 не работают следующие вещи:
- доступ к массиву с конца; вот строчка кода, которую я написал:
w=1280 h=720 orig=("${orig[-1]}" "${orig[@]}")
- самое главное, "wait -n", ожидание завершения первого процесса;
без этого примитива нельзя реализовать сложный пайплайн с параллельной обработкой каждой стадии; я где-то писал наброс на эту тему, кажется в группе ВКонтакте "Типичный Линукс", но сейчас не смог его найти.

К сожалению, если обновить системный bash до bash4+, то часть скриптов в альт линуксе перестает работать. К счастью, этих скриптов не так много. Разозлил меня один раз только gear(1), где используется eval. Методом исправления по-живому "sudo vim" я его немного подправил, и вроде он заработал.
Comment 8 Ivan Zakharyaschev 2016-05-27 14:52:23 MSK
(In reply to comment #7)

> К сожалению, если обновить системный bash до bash4+, то часть скриптов в альт
> линуксе перестает работать. К счастью, этих скриптов не так много. Разозлил
> меня один раз только gear(1), где используется eval. Методом исправления
> по-живому "sudo vim" я его немного подправил, и вроде он заработал.

Записал в https://bugzilla.altlinux.org/show_bug.cgi?id=32147 (про gear)
Comment 9 alexey.tourbin 2016-05-27 16:50:52 MSK
> Записал в https://bugzilla.altlinux.org/show_bug.cgi?id=32147 (про gear)

Запишите еще, что всё остальное с bash4 более-менее работает; если у меня попросят еще один unrelated patch насчет bash4, то я очень затруднюсь. Хост-система загружается, по крайней мере.

Проблема обновления bash4 - мне кажется, это проблема политической воли и пассионарности генерального конструктора. Генеральный конструктор пробовал года два назад собирать bash4, но потом бросил git.altlinux.org/gears/b/bash4.git

Новые дистрибутивы имеют все шансы выйти с интерпретатором /bin/bash десятилетней давности. Мне кажется, эта перспектива не имеет никакого рационального обоснования.
Comment 10 Evgeniy Korneechev 2017-10-20 11:48:12 MSK
(В ответ на комментарий №7)
> Я столкнулся с тем, что в bash < 4 не работают следующие вещи:
> - доступ к массиву с конца; вот строчка кода, которую я написал:
> w=1280 h=720 orig=("${orig[-1]}" "${orig[@]}")
> - самое главное, "wait -n", ожидание завершения первого процесса;

еще например, объявление словаря (ассоциативного массива) ...
$ declare -A array
bash: declare: -A: неправильная опция
declare: usage: declare [-afFirtx] [-p] [name[=value] ...]
Comment 11 Dmitry V. Levin 2018-12-21 01:19:51 MSK
(In reply to comment #4)
> (In reply to comment #3)
> 
> > Простого способа передать "-O extglob" в shell.req пока нету.
> 
> В bash4 можно будет сделать export BASHOPTS=extglob (или export
> BASHOPTS="$BASHOPTS:extglob") --
> https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html .

Нет, bash4 это явно запрещает.

$ bash --version
GNU bash, version 4.4.23(1)-release (x86_64-alt-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

$ bash -c 'BASHOPTS=extglob; echo OK'; echo $?
bash: BASHOPTS: readonly variable
1