Tom*_*che 5 backup debian package-management restore
请注意version-specific
问题标题!这个问题不是,如何
这个问题更确切地说是如何
最近,我对我的一个 Debian 机器进行了一次“大更新”(即涉及大量软件包或内核等主要软件包,或两者兼而有之),但它没有“干净地”更新(即没有重大问题)。将来,当我对 Debian 机器应用错误更新时,我希望能够将(a)同一机器上设置的软件包(b)回滚到以前的版本。(之前没有进行图像备份,这很慢。)不幸的是我不知道该怎么做。我知道如何
感谢许多讨论如何做到这一点的网页,包括几个 SE。大多数(包括这个、这个和这个)都会或多或少地进行复杂的变化
dpkg --get-selections > ${PACKAGE_LIST_FILEPATH}
dpkg --set-selections < ${PACKAGE_LIST_FILEPATH}
可能是关于这个主题的最全面的(也是最脚本化的,我更喜欢的)SE 是这个:它是少数几个推荐备份存储库列表(使用cp -R /etc/apt/sources.list*
)和存储库密钥(使用apt-key exportall
)的 SE 之一,但它也使用dpkg
上面的方法。此 SE建议使用aptitude
(FWIW,我更喜欢,并且怀疑它比dpkg
) 进行备份和安装,并且此 SE建议deborphan
进行备份。
但以上都没有保存包版本,因此没有一个适合我的用例。(IIUC——我错过了什么吗?)
显然,人们必须从自己的设备备份(并能够根据需要恢复)任意文件。同样,人们应该能够备份/恢复软件包,并将其集成到定期运行的备份工具中。幸运的是,包列表的备份/恢复是很好理解的。可以使用bash
以下代码进行备份
## setup
PACKAGE_LIST_FILENAME='package.list' # see use below
REPO_KEYS_FILENAME='repo.keys' # ditto
DATE_FORMAT="%Y%m%d_%H%M%S"
BACKUP_TIMESTAMP="$(date +${DATE_FORMAT})" # get current timestamp, to the second
# Parent directory of that to which you will backup.
BACKUP_ROOT="/media/$(whoami)/my_backup_drive"
BACKUP_DIR="${BACKUP_ROOT}/backup_${BACKUP_TIMESTAMP}"
echo -e "Backing up to ${BACKUP_DIR}" # debugging
# TODO: check BACKUP_DIR is writable, has sufficient freespace, etc
# ASSERT: all following are subdirs of BACKUP_DIR
ETC_BACKUP_DIR="${BACKUP_DIR}/etc" # backup /etc , typically not large
PKG_BACKUP_DIR="${BACKUP_DIR}/packages"
REPO_BACKUP_DIR="${BACKUP_DIR}/repos" # duplicates some of /etc, but disk is cheap ...
for DIR in \
"${ETC_BACKUP_DIR}" \
"${PKG_BACKUP_DIR}" \
"${REPO_BACKUP_DIR}" \
; do
# make the backup dirs
mkdir -p "${DIR}" # TODO: test retval/errorcode, exit on failure
done
PACKAGE_LIST_FILEPATH="${PKG_BACKUP_DIR}/${PACKAGE_LIST_FILENAME}"
touch "${PACKAGE_LIST_FILEPATH}" # TODO: check that it's writable, exit if not
REPO_KEYS_FILEPATH="${REPO_BACKUP_DIR}/${REPO_KEYS_FILENAME}"
touch "${REPO_KEYS_FILEPATH}" # TODO: check that it's writable, exit if not
## backup
## TODO: for all following: test retval/errorcode, exit on failure
## TODO: give user some progress indication (e.g., echo commands)
deborphan -a --no-show-section > "${PACKAGE_LIST_FILEPATH}" # or other op you prefer
sudo cp -R /etc/apt/sources.list* "${REPO_BACKUP_DIR}/"
sudo apt-key exportall > "${REPO_KEYS_FILEPATH}"
rsync --progress /etc "${ETC_BACKUP_DIR}"
Run Code Online (Sandbox Code Playgroud)
并且可以使用例如bash
类似的代码进行恢复
## setup
## (remember to transfer constants used above)
RESTORE_DIR="set this equal to the BACKUP_DIR from which you are restoring!"
ETC_RESTORE_DIR="${RESTORE_DIR}/etc"
PKG_RESTORE_DIR="${RESTORE_DIR}/packages"
REPO_RESTORE_DIR="${PKG_RESTORE_DIR}/repos"
PACKAGE_LIST_FILEPATH="${PKG_RESTORE_DIR}/${PACKAGE_LIST_FILENAME}"
REPO_KEYS_FILEPATH="${REPO_RESTORE_DIR}/${REPO_KEYS_FILENAME}"
## restore
## TODO: test that all following are readable, exit if not
## TODO: for all following: test retval/errorcode, exit on failure
## TODO: give user some progress indication (e.g., echo commands)
rsync --progress "${ETC_BACKUP_DIR}" /etc
# following will overwrite some of /etc restored above
sudo apt-key add "${REPO_KEYS_FILEPATH}"
sudo cp -R "${REPO_RESTORE_DIR}/sources.list*" /etc/apt/
# TODO: CHECK THIS SYNTAX!
# see my question @ https://serverfault.com/questions/56848/install-the-same-debian-packages-on-another-system/61472#comment920243_61472
sudo xargs aptitude --schedule-only install < "${PACKAGE_LIST_FILEPATH}" ; aptitude install
Run Code Online (Sandbox Code Playgroud)
所以IIUC,我们必须扩展上面的内容来处理包版本。使用如下策略似乎是可行的:
awk '{print $1}' < "${PACKAGE_LIST_FILEPATH}"
awk '{print $2}' < "${PACKAGE_LIST_FILEPATH}"
.deb
包的当前版本(如cas 所示dpkg-repack
) 。术语表:
*current
指用户尝试恢复之前主机的状态。*current PMF
指为当前主机生成的包映射文件,包含当前安装的包元组(key=包名称,value=包版本)。*backup PMF
指之前某个时间为主机生成的包映射文件,包含要恢复的包元组。
sudo aptitude remove [package_name]
)。sudo aptitude install [package_name]=[package_version]
)。感谢Rui F Ribeiro和bigbenaugust的关注aptitude
和apt-get
支持install package=version
。
去做!我将首先对一个我还没有像上面这样的备份的盒子进行手动恢复(因为,当然,我还没有任何盒子像上面这样的备份:-)但是对于我有控制台喷出。
一些有用的注释可以帮助您实现目标:
您可以通过运行以下命令来获取已安装软件包及其版本的列表:
dpkg-query -W
Run Code Online (Sandbox Code Playgroud)
dpkg-repack
您可以通过安装并运行如下命令来创建所有当前安装的软件包的 .deb 软件包的存档:
dpkg-query -W | awk '{print $1}' | xargs dpkg-repack
Run Code Online (Sandbox Code Playgroud)
这将是dpkg-repack
所有当前安装的软件包。此存档是恢复过程中缺少的关键部分 - 没有它,您可能无法恢复完全相同的包集(特别是如果您使用testing
或unstable
)。
警告:重新打包所有conffilesdpkg-repack
的当前内容(可能已修改)。如果您想要原始的原始软件包,则必须从Debian 镜像获取 .deb 文件。/var/cache/apt/archives
可以按照https://wiki.debian.org/HowToSetupADebianRepository上的说明将 .deb 存档转换为 apt-gettable 存储库,或者您可以将它们全部安装dpkg -iBE *.deb
(或者dpkg -iRBE /path/to/deb/files/
如果太多而无法在一个命令行中安装) )。
您仍然需要使用-get-selections
和--set-selections
来保留已卸载的软件包等详细信息。
归档时间: |
|
查看次数: |
2355 次 |
最近记录: |