为什么 mkdir -p 在 checkinstall 调用的脚本中不能正常工作?

发布于 2024-10-17 05:03:42 字数 3229 浏览 5 评论 0原文

我正在尝试编译 Quarter 并使用 checkinstall

如果我执行标准 ./configure &&制作&& 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 行为。) 我也不明白为什么它在回显中使用 "$*" 并在下一行使用 "$@" ,但它似乎并不重要的是——它们都是同一件事,因为这个脚本只用一个参数调用。(Tom 在评论中解释了。)

如果我在 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 运行code>,它实际上在 /var/tmp/... 中工作,而不是真正的 /usr/local/...)。我认为发生的情况是,第一个 mkdir 调用(我添加的那个)实际上只是创建了 Quarter 目录并退出,然后当第二个 mkdir 运行时,它能够创建 devices 子目录,因为 Quarter 目录已经存在。但为什么 mkdir 会这样工作???

我的解决方法是以某种方式修补 mkinstalldirs 脚本,但我真的很好奇为什么会出现这种情况!

这是在 Win7 上的 VirtualBox 中运行的 Ubuntu 10.10 客户机,通过 apt-get 检查安装版本 1.6.2。


编辑: 我做了一些测试,看看在这个环境中什么有效,什么失败......

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),但不在其中工作。

我还验证了尽管失败,但它能够创建第一个目录级别。

仍然是个谜。

I'm trying to compile Quarter and package it using checkinstall.

If I do the standard ./configure && make && sudo make install, things go fine.

$ 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

But when I use checkinstall, it fails on a mkdir -p that should work perfectly fine. The way it fails is exactly how it would as if the -p option weren't given. This is the checkinstall command line I'm using:

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

This is the failure:

....
/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
....

This is the relevant part of the script:

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

I don't understand why that exec is there -- doesn't that guarantee that the remainder of the script (after the esac) will never execute? (If the if test passes, then the script assumes mkdir -p works correctly, so once it does the real mkdir -p it can quit; otherwise the remainder of the script implements proper mkdir -p behavior.) I also don't understand why it uses "$*" in the echo and "$@" in the next line, but it doesn't seem to matter -- they're both the same thing since this script is being called with just one argument. (Tom explained in comment.)

If I add two lines between echo and exec that does mkdir -p -- "$@" and then echo "Now doing the exec mkdir..." then it works like this -- better, but still bewildering:

/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!

Now, the fact that doing the mkdir line twice made it work tells me it's not a permissions issue (beside, that would generate a different diagnostic from mkdir, and this is being run as sudo, and it's actually working in /var/tmp/... not the real /usr/local/...). I think what's happening is that the first mkdir invocation (the one I added) is actually creating just the Quarter directory and bailing out, and then when the second mkdir runs, it's able to create the devices subdirectory, because the Quarter directory is already there. But why would mkdir work that way???

My workaround is to patch that mkinstalldirs script somehow, but I'm really curious why this is breaking!

This is a Ubuntu 10.10 guest running in VirtualBox on Win7, checkinstall version 1.6.2 installed thru apt-get.


EDIT:
I did some testing to see what works and what fails in this environment...

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

Weird that -p works for relative pathnames but not for absolute pathnames. Or maybe the correct distinction is that -p works outside of the "chroot" tree (if it's even really using chroot) but not within it.

I also verified that despite the failure, it is able to create the first directory level.

Still a mystery.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

做个ˇ局外人 2024-10-24 05:03:42

使用

checkinstall --fstrans=no

应该可以解决这个问题。
或者

Set "TRANSLATE=0"

/etc/checkinstallrc 中重试。

Using

checkinstall --fstrans=no

should fix this.
Or

Set "TRANSLATE=0"

in /etc/checkinstallrc and try again.

或十年 2024-10-24 05:03:42

mkdir -p 无法正常工作,因为它是 mkdir 的 checkinstall 版本,而不是“真正的”mkdir。 checkinstall 中肯定存在一些错误,导致其工作方式有所不同。

该补丁解决了该错误:

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

mkdir -p isn't working like it should because it's a checkinstall version of mkdir, not the "true" mkdir. Must be some bug in checkinstall that makes it work a bit differently.

This patch works around the bug:

./configure
sed -i 's/if mkdir .*-p --.*; then/if false; then ## &/' cfg/mkinstalldirs
....
止于盛夏 2024-10-24 05:03:42
sed -i -e 's/TRANSLATE=1/TRANSLATE=0/g' /etc/checkinstallrc
sed -i -e 's/TRANSLATE=1/TRANSLATE=0/g' /etc/checkinstallrc
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文