Почему mkdir -p не работает правильно в сценарии, вызываемом checkinstall?

Я пытаюсь скомпилировать Quarter и упаковать его, используя checkinstall.

Если я выполню стандартный ./configure && make && sudo make install, все пойдет нормально.

$ wget http://ftp.coin3d.org/coin/src/all/Quarter-1.0.0.tar.gz
$ tar xzf Quarter-1.0.0.tar.gz
$ cd Quarter-1.0.0
$ ./configure
$ make
$ sudo make install

Но когда я использую checkinstall, он терпит неудачу на mkdir -p, который должен работать отлично. То, как это терпит неудачу, точно так же, как если бы опция -p не была указана. Это командная строка checkinstall, которую я использую:

$ checkinstall -D -y --install=no --pkgname=libquarter --pkgversion=1.0.0 \
  --arch=i386 --pkglicense=GPL [email protected] --reset-uids=yes

Это провал:

....
/bin/bash ../../../cfg/mkinstalldirs /usr/local/include/Quarter/devices
mkdir -p -- /usr/local/include/Quarter/devices
mkdir: cannot create directory `/usr/local/include/Quarter': No such file or directory
make[4]: *** [install-libdevicesincHEADERS] Error 1
....

Это соответствующая часть скрипта:

$ cat cfg/mkinstalldirs
....
case $dirmode in
  '')
    if mkdir -p -- . 2>/dev/null; then
      echo "mkdir -p -- $*"
      exec mkdir -p -- "$@"
    fi
    ;;
....

Я не понимаю, почему здесь присутствует exec -- разве это не гарантирует, что оставшаяся часть скрипта (после esac) никогда не будет выполняться? (Если тест if пройден, сценарий предполагает, что mkdir -p работает правильно, так что как только он выполнит настоящий mkdir -p, он может завершить работу; в противном случае оставшаяся часть скрипта реализует правильное поведение mkdir -p.) Я также не понимаю, почему он использует "$*" в эхе и "$@" в следующей строке, но это, кажется, не имеет значения - это одно и то же, поскольку этот скрипт вызывается только с одним аргументом. (Том объяснил в комментарии.)

Если я добавлю две строки между echo и exec, которые делают mkdir -p -- "$@", а затем echo "Now doing the exec mkdir...", то это будет работать так — лучше, но все равно сбивает с толку:

/bin/bash ../../../cfg/mkinstalldirs /usr/local/include/Quarter/devices
mkdir -p -- /usr/local/include/Quarter/devices
mkdir: cannot create directory `/usr/local/include/Quarter': No such file or directory
Now doing the exec mkdir...
 /usr/bin/install -c -m 644 InputDevice.h /usr/local/include/Quarter/devices/InputDevice.h
.... finishes successfully!

Теперь тот факт, что выполнение строки mkdir дважды заставило ее работать, говорит мне, что это не проблема с разрешениями (кроме того, это приведет к другой диагностике из mkdir, и это запускается как sudo, и на самом деле работает в /var/tmp/..., а не в реальном /usr/local/... ). Я думаю, что происходит то, что первый вызов mkdir (тот, который я добавил) на самом деле создает только каталог Quarter и отключается, а затем, когда запускается второй mkdir, он может создать подкаталог devices, потому что каталог Quarter уже существует. . Но почему mkdir так работает???

Мой обходной путь - как-то исправить этот скрипт mkinstalldirs, но мне действительно любопытно, почему он ломается!

Это гость Ubuntu 10.10, работающий в VirtualBox на Win7, версия checkinstall 1.6.2, установленная через apt-get.


EDIT: я провел несколько тестов, чтобы увидеть, что работает, а что нет в этой среде...

mkdir -p /foo works correctly
mkdir -p /foo && mkdir -p /foo/bar works correctly
mkdir -p foo/bar works correctly
mkdir /foo/bar failed as expected (correct)
mkdir foo/bar failed as expected (correct)
mkdir -p /foo/bar fails

Странно, что -p работает с относительными путями, но не с абсолютными путями. Или, возможно, правильное различие заключается в том, что -p работает за пределами дерева "chroot" (если он даже действительно использует chroot), но не внутри него.

Я также проверил, что, несмотря на сбой, он может создать первый уровень каталога.

Еще загадка.


person Dan    schedule 11.02.2011    source источник
comment
Что вы подразумеваете под тем, что он на самом деле работает в /tmp/... а не в реальном /usr/local/...? Чрут?   -  person Tom Anderson    schedule 12.02.2011
comment
FWIW, я полагаю, что использование $* в эхе заключается в том, что эхо получает один параметр, содержащий всю командную строку, а не N параметров, по одному для каждого аргумента, которые он получил бы, если бы использовался $@. Это очень незначительная вещь, связанная с аккуратностью и эффективностью. Тем не менее, это выглядит странно рядом с использованием $@.   -  person Tom Anderson    schedule 12.02.2011
comment
@ Том, это мое предположение. Мне нужно sudo, чтобы он вообще работал, но он не выполняет настоящую установку (это то, что я хотел, так как я просто хочу создать пакет). Не знаю, зачем мне вообще sudo, но я могу с этим жить. И спасибо за объяснение $* против $@!   -  person Dan    schedule 12.02.2011
comment
@tom есть разница между "$*" и "$@"   -  person Foo Bah    schedule 12.02.2011
comment
@Tom, я читаю исходный код checkinstall, похоже, он перехватывает такие вызовы, как mkdir () и т. Д., И заменяет их своими собственными версиями. Где-то там должен быть баг. Так что, вероятно, он не использует chroot.   -  person Dan    schedule 12.02.2011
comment
Это ошибка.   -  person Aryeh Leib Taurog    schedule 29.05.2013
comment
Просто наткнулся на это mkdir -p абсолютное ограничение пути. Довольно раздражает. Но в своем последнем комментарии вы говорите, что несмотря на сбой, он может создать первый уровень каталога, но у меня этого не происходит. Если бы это было так, вы могли бы просто запустить одну и ту же команду несколько раз, пока она не разделит каждый шаг каталога, но этого не происходит.   -  person Dss    schedule 10.12.2014


Ответы (2)


С использованием

checkinstall --fstrans=no

должен исправить это. Или же

Set "TRANSLATE=0"

в /etc/checkinstallrc и повторите попытку.

person Name    schedule 26.10.2011
comment
Это было исправлено, это checkinstall git давным-давно, но его все еще нет в релизной версии. В любом случае, это отличный совет. - person 10robinho; 18.04.2014
comment
Очевидно, что это не работает, если вам нужна трансляция файловой системы, то есть если у вас нет root-доступа. Не столько исправление, сколько очень ограничивающий обходной путь. - person Niklas Holm; 25.02.2020

mkdir -p не работает должным образом, потому что это версия mkdir для проверки установки, а не «настоящий» mkdir. Должна быть какая-то ошибка в checkinstall, из-за которой он работает немного по-другому.

Этот патч работает вокруг ошибки:

./configure
sed -i 's/if mkdir .*-p --.*; then/if false; then ## &/' cfg/mkinstalldirs
....
person Dan    schedule 12.02.2011