LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1307|回复: 3

cfgtool - 用 git 管理 etc 和软件包安装列表

[复制链接]
发表于 2008-4-28 00:32:59 | 显示全部楼层 |阅读模式
一个小脚本,用途是插入到 apt.conf 的 hook 里,在调用 dpkg
前后(包括 install, remove, purge, upgrade, dist-upgrade)
提交 etc/ 内容以及 dpkg --list 和 dpkg --get-selections 输出
到 git 库里。

git 库在 /.git,dpkg 输出在 /root 目录下,注意可能需要 git
v1.5.5 才行,我只在这上面测试过,Debian testing 满足这个要求。

使用办法:
  1. su                                                 # 切换到 root 身份
  2. aptitude install git-core  gitk    # 安装 git
  3. ./cfgtool init                                 # 建立 /.git 并保存软件包列表
  4. ./cfgtool hook                             # 安装 hook 到 /etc/apt/apt.conf
  5. cp cfgtool /root/cfgtool && chmod 500 /root/cfgtool
复制代码
以后调用  aptitude 或者 apt-get 的 install, remove 等操作时
都会记录 /etc 和软件包列表修改情况到 /.git 里,用 gitk 能很
方便的看到安装软件包记录。

用 ./cfgtool help 能看到一个简单的说明。
  1. #!/bin/bash
  2. #
  3. # A little script to backup /etc or dot files in home directory
  4. # and record installed software list under version control.
  5. #
  6. # When executed with root permission, it does:
  7. #   * create a .git directory in /
  8. #   * fully manage /etc and partially /root, /var
  9. #   * record installed software list(dpkg --list and dpkg --get-selections)
  10. #     by APT hooks
  11. #
  12. # When executed without root permissioin, it does:
  13. #   * partially manage ~/.*
  14. #
  15. #
  16. # Example:
  17. #   # cfgtool init
  18. #   # cd /; cfgtool add etc; cfgtool commit -m "import /etc to init"
  19. #   # cfgtool hook
  20. #   # cfgtool log
  21. #
  22. #
  23. # Reference:
  24. #   * Tracking /etc etc
  25. #     http://www.selenic.com/mercurial/wiki/index.cgi/TrackingEtcEtc
  26. #   * Maintain /etc with mercurial on Debian
  27. #     http://michael-prokop.at/blog/2007/03/14/maintain-etc-with-
  28. #       mercurial-on-debian/
  29. #   * A case for hg on /etc
  30. #     http://ygingras.net/b/2007/11/a-case-for-hg-on-etc
  31. #
  32. # Author:
  33. #   Liu Yubao <yubao.liu@gmail.com>
  34. #
  35. # Copyright:
  36. #   Copyright (c) 2008 Liu Yubao, all rights reserved.
  37. #
  38. # License:
  39. #   This program is free software; you can redistribute it and/or
  40. #   modify it under the terms of the GNU General Public License
  41. #   as published by the Free Software Foundation; either version 2
  42. #   of the License, or (at your option) any later version.
  43. #
  44. # ChangeLog:
  45. #   2008-1-25 Liu Yubao
  46. #       * initial version 0.1.
  47. #   2008-1-26 Liu Yubao
  48. #       * add APT hook support, version 0.2.
  49. #   2008-4-27 Liu Yubao
  50. #            * remove hg support to make it simple.
  51. #       * remove simple wrapper functions.
  52. #       * rewrite some code to make it more robust.
  53. #       * release 0.3.
  54. #   2008-4-27 Liu Yubao
  55. #       * fix working tree problem, version 0.3.1.
  56. #   
  57. # TODO:
  58. #   * record file permission
  59. #
  60. log () {
  61.     local opt_e
  62.     if [ "-e" = "$1" ]; then
  63.         opt_e="-e"
  64.         shift
  65.     fi
  66.     echo $opt_e "[cfgtool] $1"
  67. }
  68. init_env () {
  69.     LANG=C
  70.     LC_ALL=C
  71.     export LANG LC_ALL
  72.     VCS=git
  73.     IS_ROOT=0
  74.     VCS_ROOT="$HOME"
  75.     VCS_REPOS=
  76.     VCS_REPOS_ARG=
  77.     VCS_CMD=
  78.     if [ 0 -eq `id -u` ]; then
  79.         VCS=/usr/bin/git
  80.         IS_ROOT=1
  81.         VCS_ROOT=
  82.     fi
  83.     VCS_REPOS="$VCS_ROOT/.git"
  84.     VCS_REPOS_ARG="--git-dir=$VCS_REPOS --work-tree=$VCS_ROOT/"
  85.     VCS_CMD="$VCS $VCS_REPOS_ARG"
  86.     if ! $VCS --version >/dev/null 2>&1; then
  87.         log "Can't find $VCS, please install it first, eg:"
  88.         log "  aptitude install git-core"
  89.         exit 1
  90.     fi
  91. }
  92. check_repos () {
  93.     if [ ! -d "$VCS_REPOS" ]; then
  94.         log "Can't find $VCS_ROOT/.git, please use 'cfgtool init' to initialize repository."
  95.         exit 1
  96.     fi
  97. }
  98. safe_commit () {
  99.     local a m
  100.     [ '-a' = "$1" ] && { a="-a"; shift; }
  101.     [ '-m' = "$1" ] && { m="$2"; shift 2; }
  102.     [ '-a' = "$1" ] && { a="-a"; shift; }
  103.     if [ `$VCS_CMD branch | wc -l` -eq 0 ]; then
  104.         $VCS_CMD commit $a -m "$m" "$@"
  105.     elif [ `$VCS_CMD diff --cached -- "$@" | wc -l` -gt 0 ]; then
  106.         $VCS_CMD commit $a -m "$m" "$@"
  107.     elif [ -n "$a" -a `$VCS_CMD diff -- "$@" | wc -l` -gt 0 ]; then
  108.         $VCS_CMD commit $a -m "$m" "$@"
  109.     else
  110.         return 0
  111.     fi
  112. }
  113. cmd_init () {
  114.     local a
  115.     log -e "Prepare repository $VCS_REPOS..."
  116.     cd "$VCS_ROOT/" || exit 1
  117.     if ! ($VCS_CMD init "$@" && chmod 700 "$VCS_REPOS"); then
  118.         exit 1
  119.     fi
  120.     # save output from dpkg --list and dpkg --get-selections
  121.     if [ 1 -eq $IS_ROOT ] && which dpkg >/dev/null 2>&1; then
  122.         a=0
  123.         [ -e root/dpkg--list.txt ] && { $VCS_CMD add root/dpkg--list.txt; a=1; }
  124.         [ -e root/dpkg--get-selections.txt ] && { $VCS_CMD add root/dpkg--get-selections.txt;
  125.             a=1; }
  126.         [ 1 -eq $a ] && ( safe_commit -m  \
  127.             "save output from dpkg --list and dpkg --get-selections before cfgtool init" \
  128.             root/dpkg--list.txt root/dpkg--get-selections.txt || exit 1)
  129.         dpkg --list > /root/dpkg--list.txt || exit 1
  130.         dpkg --get-selections > /root/dpkg--get-selections.txt || exit 1
  131.         $VCS_CMD add root/dpkg--list.txt
  132.         $VCS_CMD add root/dpkg--get-selections.txt
  133.         safe_commit -m  \
  134.             "save new output from dpkg --list and dpkg --get-selections after cfgtool init" \
  135.             root/dpkg--list.txt root/dpkg--get-selections.txt || exit 1
  136.     fi
  137.     log
  138.     log -e "Use 'cfgtool add' or '$VCS add' to add some files into"
  139.     log -e "repository, eg. /etc, ~/.*\n\n"
  140. }
  141. cmd_hook () {
  142.     if [ 0 -eq $IS_ROOT ]; then
  143.         log "Only root can use this function!"
  144.         return 1
  145.     fi
  146.     if ! which apt-get >/dev/null 2>&1; then
  147.         log "Can't find apt-get in PATH, is this Debian system?"
  148.         return 1
  149.     fi
  150.     # install cfgtool to /root/cfgtool
  151.     if [ ! -e /root/cfgtool ]; then
  152.         log
  153.         log "!!!!! Please copy cfgtool to /root/cfgtool and"
  154.         log "!!!!! run 'chmod 500 /root/cfgtool'"
  155.         log
  156.     fi
  157.     # install APT hook
  158.     cd "$VCS_ROOT/"
  159.     [ -e etc/apt/apt.conf ] && $VCS_CMD add etc/apt/apt.conf
  160.     safe_commit -m "save apt.conf before hook APT" etc/apt/apt.conf ||
  161.         exit 1
  162.     if ! grep cfgtool /etc/apt/apt.conf >/dev/null 2>&1; then
  163.         cat >> /etc/apt/apt.conf <<EOF
  164. // added automatically by cfgtool ------------> begin
  165. DPkg {
  166.   Pre-Invoke { "if [ -x /root/cfgtool ]; then /root/cfgtool hook_pre; fi"; };
  167.   Post-Invoke { "if [ -x /root/cfgtool ]; then /root/cfgtool hook_post; fi"; };
  168. }
  169. // added automatically by cfgtool <------------ end
  170. EOF
  171.         $VCS_CMD add etc/apt/apt.conf
  172.         safe_commit -m "save apt.conf after hook APT" etc/apt/apt.conf ||
  173.             exit 1
  174.         log "Cfgtool has been install in /etc/apt/apt.conf"
  175.     fi
  176. }
  177. do_hook () {
  178.     local pid
  179.     if [ 0 -eq $IS_ROOT ]; then
  180.         log "Only root can use this function!"
  181.         return 1
  182.     fi
  183.     dpkg --list > /root/dpkg--list.txt || exit 1
  184.     dpkg --get-selections > /root/dpkg--get-selections.txt || exit 1
  185.     pid=$PPID
  186.     while [ $pid -gt 0 ]; do
  187.         caller=`/bin/ps -p $pid -o cmd= h`
  188.         (echo $caller | /bin/grep 'aptitude\|apt-get') && break
  189.         pid=`/bin/ps -p $pid -o ppid= h`
  190.     done
  191.     [ $pid -eq 0 ] && caller=`/bin/ps -p $PPID -o cmd= h`
  192.     cd / &&
  193.         $VCS_CMD add root/dpkg--list.txt &&
  194.         $VCS_CMD add root/dpkg--get-selections.txt &&
  195.         $VCS_CMD add etc &&
  196.         ($VCS_CMD ls-files -d | xargs -r $VCS_CMD rm -r -q) &&
  197.         safe_commit -a -m "snapshot from $LOGNAME $1: $caller"
  198. }
  199. cmd_hook_pre () {
  200.     do_hook "before" >/dev/null 2>&1
  201. }
  202. cmd_hook_post () {
  203.     do_hook "after" >/dev/null 2>&1
  204. }
  205. cmd_version () {
  206.     cat <<EOF
  207. Cfgtool 0.3.1, Copyright (C) 2008 Liu Yubao
  208. Cfgtool comes with ABSOLUTELY NO WARRANTY, it is free software, and
  209. you are welcome to redistribute it under certain conditions; read
  210. comment in the beginning of this script for details.
  211. EOF
  212. }
  213. cmd_help () {
  214.     cat <<EOF
  215. Usage: cfgtool subcommand arguments...
  216. Cfgtool is a little script to backup /etc or dot files in home directory
  217. and record installed software list under version control.
  218. Most commands are simple wrappers to the corresponding commands in GIT,
  219. you can use GIT directly.
  220.    
  221. Available sub commands and their equivalent commands in GIT:
  222.     init      : git --git-dir=/path/to/.git --work-tree=/path/to init
  223.     hook      : install Pre-Invoke and Post-Invoke hooks to APT
  224.     <cmd>     : git --git-dir=/path/to/.git --work-tree=/path/to <cmd>
  225.     version   : show version of Cfgtool
  226.     help      : show this help information
  227. The .git directory is in $HOME/ for normal user and / for root user.
  228. EOF
  229. }
  230. #------------- main entry -----------------------
  231. init_env
  232. CMD="$1"
  233. if [ -z "$CMD" ]; then
  234.     log "Missing arguments, use 'cfgtool help' to get help."
  235.     exit 1;
  236. fi
  237. shift
  238. case "$CMD" in
  239.     init)
  240.         cmd_init "$@"
  241.         ;;
  242.     hook|hook_pre|hook_post)
  243.         check_repos
  244.         cmd_$CMD "$@"
  245.         ;;
  246.     version|help)
  247.         cmd_$CMD "$@"
  248.         ;;
  249.     *)
  250.         check_repos
  251.         $VCS_CMD $CMD "$@"
  252.         ;;
  253. esac
  254. # vi: et ts=4 sw=4
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
 楼主| 发表于 2008-4-28 00:43:48 | 显示全部楼层
顺带赞一下 Debian testing,装了 wqy 的两个字体包,汉字显示相当的凑合,
默认的 Epiphany 网页浏览器用的 Gecko 1.8 引擎,排版效果也是相当凑合,
用了三天了还没有起念头装 firefox。Xorg 不需要 915resolution 就上到了
1280x800,mp3 默认支持,alsa 配置默认就好,不需要 esound 也能
混音。rhythmbox 和 totem 做的挺好,整个 gnome 界面感觉很细腻,很清爽,
呵呵,全新安装的系统怎么看都觉得很顺眼。

有点遗憾的是休眠默认不行。
回复 支持 反对

使用道具 举报

发表于 2008-4-28 16:18:52 | 显示全部楼层
赞你的脚本~
考虑改成svn来用。没用过git的说,这种情况下svn似乎很够了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-5-3 19:25:31 | 显示全部楼层
Post by FireMeteor;1843499
赞你的脚本~
考虑改成svn来用。没用过git的说,这种情况下svn似乎很够了


原来支持 Mercurial(也就是 Hg)的,但后来发现要统一两种
版本管理工具的命令行接口是件很琐碎的事情,不胜其烦,就
去掉了。

用 SVN 不好的是它会在每个目录下生成 .svn 目录,妨碍用 tar
之类的工具打包备份,而 git,svn 的版本管理信息只有一个目录,
很方便。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表