![dpkg:新的预安装脚本返回错误退出状态 1](https://linux22.com/image/25633/dpkg%EF%BC%9A%E6%96%B0%E7%9A%84%E9%A2%84%E5%AE%89%E8%A3%85%E8%84%9A%E6%9C%AC%E8%BF%94%E5%9B%9E%E9%94%99%E8%AF%AF%E9%80%80%E5%87%BA%E7%8A%B6%E6%80%81%201.png)
我最终处理了一个打算使用 dpkg 部署的软件。 .deb 包在测试环境中工作正常,但在暂存时失败。两者都运行相同版本的 Ubuntu,但我不能 100% 确定其余配置。如何进一步调试这个 dpkg 问题?
安装失败是这样的:
sudo dpkg -i --debug=7337 package.deb
D000010: ensure_pathname_nonexisting `/var/lib/dpkg/tmp.ci'
(Reading database ... 201812 files and directories currently installed.)
Unpacking myProprietarySoftware (from package.deb) ...
D000001: process_archive oldversionstatus=not installed
D000002: fork/exec /var/lib/dpkg/tmp.ci/preinst ( install )
dpkg: error processing package.deb (--install):
subprocess new pre-installation script returned error exit status 1
D000002: maintainer_script_new nonexistent postrm `/var/lib/dpkg/tmp.ci/postrm'
D000010: ensure_pathname_nonexisting `/var/lib/dpkg/tmp.ci'
D000010: ensure_pathname_nonexisting running rm -rf
D000010: ensure_pathname_nonexisting `/var/lib/dpkg/reassemble.deb'
Errors were encountered while processing:
package.deb
答案1
该包的 .preinst 脚本由于某种原因失败。
要找出原因,请检查以下脚本/var/lib/dpkg/info/PACKAGENAME.preinst
如果您想准确查看脚本在哪一行失败,请编辑 .preinst 脚本并set -x
立即添加到该#!
行之后。这将打开脚本中的执行跟踪。
笔记:这假设 .preinst 脚本是 shell 脚本(posix sh 或 bash)。 几乎全部.preinst(以及.postinst、.prerm 和.postrm)脚本是shell 脚本,但它们不一定是,它们可以是任何可执行文件。例如,在我安装了 9104 个软件包的主台式机上,14 个是 perl 脚本,1 个是已编译的可执行文件(bash 的 preinst - 它不能假设已经安装了一个正常运行的 shell),其余所有都是 shell 脚本... 9041 个是 POSIX shell 脚本,63 个是 bash 脚本。如果 .preinst 是 perl 或 python 或其他东西,您必须弄清楚如何在该语言中启用调试或执行跟踪模式或类似模式。
然后跑dpkg --configure --pending
。
这将导致 dpkg 尝试配置半安装的软件包。不要使用 重新安装它dpkg -i
,这会用 .deb 包中的版本覆盖您编辑的 .preinst 脚本。
这可能会为您提供足够的信息来解决问题。这可能是一些简单的事情,比如程序中意外或未捕获的退出代码(大多数 .preinst 等脚本都有set -e
,使它们在第一个错误时终止),或者假设目录已经存在(这可能是由于未声明的依赖关系)在包的 debian/control 文件中 - 即它应该依赖于 foo 但无论如何都不会安装 foo )
修复后,dpkg --configure --pending
再次运行,该包应该已正确安装。
如果 .preinst 脚本有错误,则 .postinst (和/或 .prerm 和 .postrm)脚本也很可能有错误。您可能还需要修复它们。
不要忘记向软件包的制作者提交错误报告,以便他们可以修复它。
答案2
您的打包软件包含一个失败的“预安装脚本”(preinst)。这是嵌入在 .deb 文件中的 shell 脚本。您可以使用以下方法提取它:
dpkg-deb -e some-deb.deb out-dir
然后你可以查看out-dir/preinst
并看看是否能找出失败的原因。
如果您想修改该脚本并重建.deb
(也许添加一些调试代码),请尝试
dpkg-deb -x some-deb.deb another-out-dir
dpkg-deb -e some-deb.deb another-out-dir/DEBIAN
(modify another-out-dir/DEBIAN/preinst)
dpkg-deb -b another-out-dir some-deb2.deb
答案3
您需要解压该文件并查看preinst
脚本为何退出并显示 code 1
。
不确定 UNIX.SE 上是否有与如何执行此操作相关的讨论,但您可以看一下这个问题从 AskUbuntu 了解如何提取。
此后,您必须手动运行preinst
脚本以查看软件包安装失败的原因。
答案4
如果您想直接编辑包,请尝试以下操作:
#!/bin/bash
if [[ -z "$1" ]]; then
echo "Syntax: $0 debfile"
exit 1
fi
DEBFILE="$1"
TMPDIR=`mktemp -d /tmp/deb.XXXXXXXXXX` || exit 1
OUTPUT=`basename "$DEBFILE" .deb`.modfied.deb
if [[ -e "$OUTPUT" ]]; then
echo "$OUTPUT exists."
rm -r "$TMPDIR"
exit 1
fi
dpkg-deb -x "$DEBFILE" "$TMPDIR"
dpkg-deb --control "$DEBFILE" "$TMPDIR"/DEBIAN
if [[ ! -e "$TMPDIR"/DEBIAN/control ]]; then
echo DEBIAN/control not found.
rm -r "$TMPDIR"
exit 1
fi
CONTROL="$TMPDIR"/DEBIAN/control
MOD=`stat -c "%y" "$CONTROL"`
vi "$CONTROL"
if [[ "$MOD" == `stat -c "%y" "$CONTROL"` ]]; then
echo Not modfied.
else
echo Building new deb...
dpkg -b "$TMPDIR" "$OUTPUT"
fi
rm -r "$TMPDIR"