为什么我的Debian后安装脚本没有运行?

8

我使用fpm制作了我的应用程序的.deb包:

fpm -s dir -t deb -n myapp -v 9 -a all -x "*.git" -x "*.bak" -x "*.orig" \
--after-remove debian/postrm  --after-install debian/postinst \
--description "Automated build." -d mysql-client -d python-virtualenv home

除其他事项外,postinst 脚本应该为应用程序创建一个用户:
#!/bin/sh

    set -e

    APP_NAME=myapp

    case "$1" in
        configure)
            virtualenv /home/$APP_NAME/local
            #supervisorctl start $APP_NAME
        ;;

    # http://www.debian.org/doc/manuals/securing-debian-howto/ch9.en.html#s-bpp-lower-privs
       install|upgrade)

       # If the package has default file it could be sourced, so that
       # the local admin can overwrite the defaults

       [ -f "/etc/default/$APP_NAME" ] && . /etc/default/$APP_NAME

       # Sane defaults:

       [ -z "$SERVER_HOME" ] && SERVER_HOME=/home/$APP_NAME
       [ -z "$SERVER_USER" ] && SERVER_USER=$APP_NAME
       [ -z "$SERVER_NAME" ] && SERVER_NAME=""
       [ -z "$SERVER_GROUP" ] && SERVER_GROUP=$APP_NAME

       # Groups that the user will be added to, if undefined, then none.
       ADDGROUP=""

       # create user to avoid running server as root
       # 1. create group if not existing
       if ! getent group | grep -q "^$SERVER_GROUP:" ; then
          echo -n "Adding group $SERVER_GROUP.."
          addgroup --quiet --system $SERVER_GROUP 2>/dev/null ||true
          echo "..done"
       fi
       # 2. create homedir if not existing
       test -d $SERVER_HOME || mkdir $SERVER_HOME
       # 3. create user if not existing
       if ! getent passwd | grep -q "^$SERVER_USER:"; then
         echo -n "Adding system user $SERVER_USER.."
         adduser --quiet \
                 --system \
                 --ingroup $SERVER_GROUP \
                 --no-create-home \
                 --disabled-password \
                 $SERVER_USER 2>/dev/null || true
         echo "..done"
       fi

       # … and a bunch of other stuff.

看起来像是postinst脚本被调用时使用的是configure,而不是install,我正在尝试理解为什么。在/var/log/dpkg.log中,我看到了我预期的行:

2012-06-30 13:28:36 configure myapp 9 9
2012-06-30 13:28:36 status unpacked myapp 9
2012-06-30 13:28:36 status half-configured myapp 9
2012-06-30 13:28:43 status installed myapp 9

我检查了一下,发现/etc/default/myapp文件不存在。但是/var/lib/dpkg/info/myapp.postinst文件存在,如果我手动使用install作为第一个参数运行它,它会按预期工作。
为什么postinst脚本没有使用install运行?我应该如何进一步调试呢?
3个回答

18

我认为你复制的示例脚本是错误的。 postinst 不应该以任何 installupgrade 参数调用。 dpkg 格式的权威定义是 Debian Policy 手册。当前版本在第6章中描述了postinst,仅列出configureabort-upgradeabort-removeabort-removeabort-deconfigure作为可能的第一个参数。

我对我的答案没有完全的信心,因为你的错误示例仍然在 debian.org 上,并且很难相信这样的漏洞会发生。


啊,根据 Debian 政策手册第 6.5 节,看起来是在 configureinstall 中运行 _preinst_。《保护 Debian 手册》实际上提到了 "preinstpostinst",所以它们的示例必须是针对 preinst 的。我会尝试重新排列一下。 - Vebjorn Ljosa
1
啊哈!现在有意义了。如果在preinst中已经有其他依赖于用户创建的操作,请在其中执行此操作。否则,将其放在postinst的$1 = configure分支中。根据我对/var/lib/dpkg/info/*.postinst的快速扫描,大多数软件包似乎都是这样做的。 - Alan Curry
1
也许自2012年以来有些变化,但我认为postinst在安装后运行,可能只是在特定情况下。我正在Debian服务器上安装phpMyAdmin,尽管安装成功,但由于其postinst脚本的结果而失败。这导致apt-get认为它没有正确安装。一旦我调整了/var/lib/dpkg/info/phpmyadmin.postinst,它就可以工作了。此外,我的系统有277个postinst和仅75个preinst,在安装后运行脚本似乎更受欢迎,而不是在删除之后。也许这只是一个维护不良的软件包。 - Blieque

4

我相信Alan Curry提供的答案是错误的,至少在2015年及以后是这样。
你的软件包构建方式可能存在一些问题,或者postinst文件中存在错误,这可能是你遇到问题的原因。
你可以通过将-D(调试)选项添加到命令行来调试安装,即:

sudo dpkg -D2 -i yourpackage_name_1.0.0_all.deb

-D2应该能解决这种问题。

记录一下,调试级别如下:

          Number   Description
               1   Generally helpful progress information
               2   Invocation and status of maintainer scripts
              10   Output for each file processed
             100   Lots of output for each file processed
              20   Output for each configuration file
             200   Lots of output for each configuration file
              40   Dependencies and conflicts
             400   Lots of dependencies/conflicts output
           10000   Trigger activation and processing
           20000   Lots of output regarding triggers
           40000   Silly amounts of output regarding triggers
            1000   Lots of drivel about e.g. the dpkg/info dir
            2000   Insane amounts of drivel
install 命令调用 configure 选项,根据我的经验,postinst 脚本总是会运行。一个可能会让您犯难的事情是,如果升级包,则“旧”版本的 postrm 脚本将在当前软件包的 preinst 脚本之后运行,如果您不了解正在发生的情况,这可能会造成混乱。
来自 dpkg 手册页: 安装包括以下步骤:
          1. Extract the control files of the new package.

          2.  If  another version of the same package was installed before
          the new installation, execute prerm script of the old package.

          3. Run preinst script, if provided by the package.

          4. Unpack the new files, and at the same time back  up  the  old
          files, so that if something goes wrong, they can be restored.

          5.  If  another version of the same package was installed before
          the new installation, execute the postrm script of the old pack‐
          age.  Note that this script is executed after the preinst script
          of the new package, because new files are written  at  the  same
          time old files are removed.

          6.  Configure the package. 

          Configuring consists of the following steps:

          1.  Unpack  the  conffiles, and at the same time back up the old
          conffiles, so that they can be restored if something goes wrong.

          2. Run postinst script, if provided by the package.

我不太清楚你在这里关于“install命令”的说法,但如果它能为任何人澄清问题的话,dpkg永远不会以$1=installupgrade的方式调用postinst脚本。如果您愿意,您可以支持在postinst中添加额外的操作,但dpkg不会使用它们。原始问题中发布的脚本无法正常工作,因为它期望被调用其中之一。也许这是fpm的问题?我不知道。 - the paul
1
@thepaul 我认为我表达得很清楚。install 命令会调用 configure 选项。具体来说,它将使用软件包的版本号和 configure 调用 postinst 脚本,例如 configure 6.4.0(根据我的经验,这是打包自己软件的过程)。 - Rolf of Saxony

2
这是一个老问题,已经得到解决,但我认为已接受的解决方案并不完全正确,因此我认为有必要为像我一样遇到同样问题的人提供信息。 第6.5章详细介绍了调用preinst和postinst文件的所有参数
https://wiki.debian.org/MaintainerScripts中详细描述了安装和卸载流程。
请看下面的情况:
apt-get install package - 它运行preinst install,然后运行postinst configure apt-get remove package - 执行postrm remove,该软件包将被设置为“Config Files
要使软件包实际处于“未安装”状态,必须使用:
apt-get purge package 这是唯一的方法,我们才能在下次安装软件包时运行preinst installpostinst configure

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接