为什么 mkdir -p 在 checkinstall 调用的脚本中不能正常工作?
我正在尝试编译 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 (If the exec
is there -- doesn't that guarantee that the remainder of the script (after the esac
) will never execute?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 (Tom explained in comment.)"$*"
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.
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用
应该可以解决这个问题。
或者
在
/etc/checkinstallrc
中重试。Using
should fix this.
Or
in
/etc/checkinstallrc
and try again.mkdir -p
无法正常工作,因为它是 mkdir 的 checkinstall 版本,而不是“真正的”mkdir。 checkinstall 中肯定存在一些错误,导致其工作方式有所不同。该补丁解决了该错误:
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: