首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在debian上使用dpkg-repack备份可升级的包

在debian上使用dpkg-repack备份可升级的包
EN

Server Fault用户
提问于 2018-08-10 12:46:27
回答 1查看 333关注 0票数 0

我想列出可升级的软件包,并自动将它们重新打包到.debs。我的尝试:

代码语言:javascript
复制
fakeroot -u dpkg-repack `apt list --upgradable | cut -f1 -d"/" | awk '{if(NR>2)print}'`

因此它获得包名,然后将名称重定向到dpkg-repack。它部分工作,因为dpkg-repack会在存在amd64和i386包时抛出错误,并且两者都有相同的名称--在本例中,它希望将体系结构添加到包名中。

你知道如何管理它吗?如果存在多个拱形,自动生成两个借方?看起来dpkg-repack不够聪明,无法自动生成多个体系结构,它只抛出错误消息,表示安装了多个同名包。

EN

回答 1

Server Fault用户

回答已采纳

发布于 2019-06-20 10:51:00

我使用以下脚本来dpkg-repack所有可能受到apt-get操作影响的包:

代码语言:javascript
复制
#!/bin/zsh
#
# creates subdir and dpkg-repacks all relevant packages in it
#
DIR=$(date +%Y%m%d)
OPER=${@:-dist-upgrade}
mkdir -p $DIR
cd $DIR || exit 1
zmodload zsh/system

renice -n 20 -p $ >/dev/null 2>/dev/null

nproc=$(nproc)
native_arch=$(dpkg --print-architecture)
typeset -U possible_arch=($native_arch all)
[[ $native_arch = amd64 ]] && possible_arch=($possible_arch i386)

function repacked() {
    local p=$1
    local a=$2
    local existing
    existing=(${p}_*${a}.deb(N) ${p}_*all.deb(N))   # no need to try repacking in a binary arch if _all already exists, because arch-specific and arch=all packages of the same name can't exist simultaneously
    if (($#existing)); then
        [[ "$a" = none ]] && unset a    # avoid confusing message with arch specified as "none"
        echo "Skipping $p${a:+:$a}, already repacked." >&2
        return 0
    fi
    return 1
}

function worker() {
    local pkg=$1
    local arch=$2
    local lockfd lockfd2
    local success=0
    local try_arch
    [[ -z "$pkg" ]] && return 0
    : >>"$pkg.$arch.lock"
    if zsystem flock -f lockfd -t 0 "$pkg.$arch.lock" 2>/dev/null; then
        if [[ $arch = none ]]; then
            for try_arch in $possible_arch; do
                repacked $pkg $try_arch && success=1
            done
            if ! ((success)) && ! dpkg-repack $pkg; then
                for try_arch in $possible_arch; do
                    echo "*** DEBUG: *** entering architecture guessing branch in worker()." >&2    # it's unclear whether this branch will ever even be run
                    repacked $pkg $try_arch && break    # avoid even locking if another thread got here first; allows main thread to start an additional worker sooner
                    : >>"$pkg.$try_arch.lock"
                    if zsystem flock -f lockfd2 -t 0 "$pkg.$try_arch.lock" 2>/dev/null; then
                        if repacked $pkg $try_arch; then    # make sure another thread didn't get to this package after our previous check but before acquiring the lock
                            success=1
                        else
                            dpkg-repack --arch=$try_arch $pkg:$try_arch && success=1
                        fi
                        rm $pkg.$try_arch.lock
                        zsystem flock -u $lockfd2
                        ((success)) && break
                    fi
                done
            fi
        else
            repacked $pkg $arch || dpkg-repack --arch=$arch $pkg:$arch  # TODO: run with loadwatch
        fi
        rm $pkg.$arch.lock
        zsystem flock -u $lockfd
    fi
}

# clean up any leftover locks from a previous invocation
for i in *.lock(N); do
    zsystem flock -f lockfd $i  # if they're still locked, a dpkg-repack may still be running; wait for it to finish
    rm $i
    zsystem flock -u $lockfd
done

for i in $(echo n \
    | LC_MESSAGES=C apt-get -d -u ${=OPER} 2>&1 \
    | sed -r '/^The following packages were automatically installed/,/^Use .apt(-get)? autoremove. to remove them/d
          /^The following NEW packages will be installed:/,/^The/s/^[[:space:]].*//
          /^The following packages have been kept back:/,/^The following packages will be upgraded:/d
          /^The following packages have unmet dependencies:/,$d' \
    | grep '^[[:space:]]' \
    | tr -d '*'); do
        if ((${i[(I):]})); then # package name includes architecture (separated by colon) -- index of colon within $i is not zero
            echo ${${i:t}/:/ }  # print name and architecture
        else
            p=${i:t}
            # guess architecture:
            [[ -e /var/lib/dpkg/info/${p}.list ]] && echo $p none   # we don't know the architecture, but perhaps dpkg-repack doesn't need it; have the worker try
            for try_arch in $possible_arch; do
                [[ -e /var/lib/dpkg/info/${p}:${try_arch}.list ]] && echo $p $try_arch
            done
        fi
done | sort -u | while read p a; do
    if ! repacked $p $a; then
        workers=(*.lock(N))
        while [[ $#workers -ge $nproc ]]; do    # wait for a worker slot to become available
            sleep 0.5
            workers=(*.lock(N))
        done
        [[ -n "$p" ]] && worker $p $a &
    fi
done
wait
rm -f *.lock(N)

只需使用传递给apt-get的相同参数调用它即可。它将创建一个以今天的日期命名的目录,并将所有生成的.debs放在其中。它会像你有CPU内核一样并行地重新打包很多包。它是幂等的,因为如果包的.deb已经存在,它就不会再重新打包,从而安全地中止和重新启动。

它有硬连接的i386和amd64体系结构,所以如果您有其他东西,就需要对其进行更改。

票数 1
EN
页面原文内容由Server Fault提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://serverfault.com/questions/925824

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档