【问题标题】:Why isn't mkdir -p working right in a script called by checkinstall?为什么 mkdir -p 在 checkinstall 调用的脚本中不能正常工作?
【发布时间】:2011-06-25 21:32:36
【问题描述】:

我正在尝试编译 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 --maintainer=me@example.com --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 之后)永远不会执行吗?(如果 @ 987654332@ 测试通过,然后脚本假定mkdir -p 工作正常,所以一旦它执行真正的mkdir -p 它可以退出;否则脚本的其余部分实现正确的mkdir -p 行为。)我也没有了解为什么它在 echo 中使用 "$*" 并在下一行中使用 "$@" ,但这似乎并不重要——它们都是同一件事,因为只使用一个参数调用此脚本。(汤姆在评论中解释。)

如果我在 echoexec 之间添加两行,然后是 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 脚本,但我真的很好奇为什么会出现这种情况!

这是在 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)但不在其中。

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

还是个谜。

【问题讨论】:

  • 您所说的“它实际上是在 /tmp/...而不是真正的 /usr/local/...”是什么意思? Chroot?
  • FWIW,我想在 echo 中使用 $* 是为了给 echo 一个包含整个命令行的参数,而不是 N 个参数,每个参数一个,如果 $使用了@。这是一个非常小的整洁和效率的事情。不过,坐在使用 $@ 的旁边确实看起来很奇怪。
  • @Tom,这是我的猜测。我需要 sudo 才能让它工作,但它并没有进行真正的安装(这是我想要的,因为我只想创建包)。不知道为什么我必须 sudo,但我可以忍受它。并感谢 $* 与 $@ 的解释!
  • @tom "$*""$@" 之间有区别
  • 这是a bug

标签: linux mkdir checkinstall


【解决方案1】:
sed -i -e 's/TRANSLATE=1/TRANSLATE=0/g' /etc/checkinstallrc

【讨论】:

    【解决方案2】:

    使用

    checkinstall --fstrans=no
    

    应该解决这个问题。 或者

    Set "TRANSLATE=0"
    

    /etc/checkinstallrc 再试一次。

    【讨论】:

    • 很久以前就修复了 checkinstall git 但它仍然不是发布版本。无论如何,这是一个很好的提示。
    • 显然,如果您需要文件系统翻译,即如果您没有 root 访问权限,这将不起作用。与其说是修复,不如说是一种非常有限的解决方法。
    【解决方案3】:

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

    这个补丁可以解决这个错误:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-06
      • 1970-01-01
      • 2023-02-20
      • 1970-01-01
      • 2019-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多