Feb 19

一、简介

GTK+ 是一套跨平台的图形用户界面(Graphical User Interface)开发工具包,按 LGPL 许可协议发布的。虽然最初是为 GIMP(GNU Image Manipulation Program) 写的,但早已发展为一个功能强大、设计灵活的通用图形库。特别是在 GTK+ 被 Linux 桌面项目 GNOME 选中使得它广为流传,成为 Linux 下开发图形用户界面应用程序的主流开发工具之一。当然 GTK+ 应用程序开发与运行并不要求必须在 Linux 上,事实上,GTK+ 早已经被成功地移植到了 Mac OS X 以及 MS Windows 上。在开发早期的 GIMP 版本时,Peter Mattis 和 Spencer Kimball 创建了 GTK(GIMP Toolkit) 工具包,作为 Motif 工具包的替代,后者在那个时候不是免费的。当 GTK 开发工具包获得了面向对象特性和可扩展性之后,才在名称后面追加上了符号 "+",也即 GTK+。

二、GCC 工具链

GCC(GNU Compiler Collections) 是 Linux 系统中默认的开发工具、Autotools 是 Linux 中开发大型项目管理工具。Red Hat 系中这些开发工具的安装可执行

$ sudo dnf install "Development Tools"

Debian 系可执行

$ sudo apt-get install build-essential

Gentoo 由于本身的理念就是编译所有的包,因此系统已经自带了 GCC 工具链,无须额外安装其他 GCC 开发工具。

三、C/C++ 的手册页

在编程的过程中有时会记不得某个函数的用法,此时查找手册页是比较快的。为了能够用命令行 man 查看 C/C++ 的函数,需要安装相关的手册页及其工具。在 Red Hat 系中执行

$ sudo dnf install man-pages libstdc++-docs

Debian 系可执行

$ sudo apt-get install manpages-dev manpages-posix manpages-posix-dev glibc-doc libstdc++6-4.3-doc

Gentoo 中安装稍微麻烦一点,可执行

$ sudo sh -c 'echo "sys-devel/gcc doc cxx " >> /etc/portage/package.use'
$ sudo emerge -av1 gcc
$ sudo emerge -av man-pages man-pages-posix

手册页的索引由 mandb 命令管理,有时在安装了新的手册页后,可能需要更新一下索引才能用 man kman f 查询到函数,也即

$ mandb c

然后就可以查看这些文档了。比如,查看 fopen 的手册页:

$ man fopen

四、GTK+ 库的概述

GTK+ 是基于以下库开发的:

  • glib:GTK+ 与 GNOME 的底层核心库,主要提供了 C 数据结构、可移植封装、运行时功能接口,譬如事件循环、多线程、动态装载和对象机制等。换而言之,Glib 是 GTK+ 能够“面向对象”的基础。GTK+ 中与界面无关的底层部分基本都被并入 glib。GLib 库还进一步分离成 GIO、GObject 等库。GIO 专门处理输入输出流。而 GObject 则维护着 GTK+ 所使用的一套对象系统。正是 GObject 提供的面向对象的机制,使得 GTK+ 可绑定很多种开发语言,例如 C++、Python、Perl、Java、C#、PHP 等其他高级语言。
  • pango:国际化文本陈列及渲染库,它是 GTK+ 的文本与字体处理核心;
  • atk:可访问接口库,它可以让 GTK+ 程序很方便地使用屏幕阅读器、放大镜以及一些输入设备等;
  • cairo:过去 cario 被称为 Xr 或 Xr/Xc,它是一个跨平台的开放源代码的矢量图形函数库,可以提供高质量的显示和打印输出。通过 Glitz 函数库, Cairo 能使用 OpenGL 或 X Render 扩展的硬件加速功能来绘制图像,这基于 Cairo 的应用能在现代化的 3D 显示硬件上获得益处。
  • gdk-pixbuf:GDK(GDK 是 GTK+ 从窗口系统细节中提取出来的一组接口,可以直接访问窗口细节。实际上,GDK 是 GTK+ 用户界面图形库提供的一些底层“图形实现”和“窗口实现”的方法,在 Linux 中,GDK 是对 Xlib 库提供接口的封装。)的一个部分,提供了一组位图函数,包括位图变换、位图文件读写等等,用于加载图像和维护图像“缓存”的(pixel buffer)。

要装 GTK+,先安装这写库,当然它们又依赖其它一些库,在 Linux 系统中可完全交由 Linux 的包管理器处理。还有一些库是 GTK+ 运行依赖的,下面是几个重要的:

  • gettext:它是国际化库,主要用于制作多语言程序。运行时 gettext 自动识别操作系统语言,然后从已有语言包中选择一个最合适用户的语言。当操作系统上没有 gettext() 函数的时候需要安装它。
  • libiconv:它是字符集转换库,通常操作系统上没有提供 iconv() 函数的时候才会安装它。GTK+ 内部使用 UTF-8 字符集,有时需要字符集转换。
  • freetype:它是一个操作字体的函数库,不但可以处理点阵字体,也可以处理多种矢量字体,包括 truetype 字体,为上层应用程序提供了一个统一的调用接口。
  • fontconfig:它提供系统范围内字体设置、定制和允许应用程序访问的函数库。实际上,GTK+ 的字体绘制是通过 pango、freetype 与 fontconfig 三者协作来完成的。其中,fontconfig 负责字体的管理和配置,freetype 负责单个字符的绘制,pango 则完成对文字的排版布局。
  • libjpeg:它提供了 JPEG 算法压缩文件图形文件供 GTK+ 程序读写 JPEG 格式的图形文件;
  • libtiff:它是用操作 TIFF 格式(标记图象文件格式)的图形文件并为 GTK+ 程序读写 TIFF 格式的图形文件的库;
  • libpng:它是用来创建与操作 PNG 格式的图形文件并为 GTK+ 程序提供读写 PNG 文件的库。PNG 格式的图形文件是被设计来替代 GIF 格式的,它对于更小范围的 TIFF 格式是来说,有了很多的进步和拓展并且减少了关于专利权的麻烦。

五、GTK+ 的 C 开发包

目前,GTK+ 开发包有三个版本:GTK+ 1、GTK+ 2 与 GTK+ 3,在 Linux 系统上是可以共存的,但由它们开发的程序需要对应的 GTK+ 开发包才能正常编译与运行。现在 GTK+ 2 是主流,但都在向 GTK+ 3 过度。根据自己的需要选择 GTK+ 版本,这里就以 GTK+ 2 为例。安装 GTK+ 开发环境,在 Red Hat 系中执行

$ sudo dnf install gtk2-devel gtk2-devel-docs

Debian 系可执行

$ sudo apt-get install libgtk2.0-dev libgtk2.0-doc

Gentoo 中执行

$ sudo sh -c 'echo "x11-libs/gdk-pixbuf doc \
                    dev-libs/glib doc \
                    x11-libs/pango doc \
                    x11-libs/cairo doc \
                    dev-libs/atk doc \
                    x11-libs/gtk+ doc" >> /etc/portage/package.use'
$ sudo emerge -av gtk+

若在开发过程中需整合 GNOME 环境,在 Red Hat 系中执行

$ sudo dnf install libgnome-devel gnome-devel-docs

Debian 系可执行

$ sudo apt-get install gnome-devel gnome-devel-docs

Gentoo 中执行

$ sudo emerge -av gnome-devel-docs

六、GTK+ 应用程序接口文档查看器

在 GNOME 桌面中,查看 GTK+ 应用程序接口文档的查看器是 DevHelp。安装它的方法很简单,在 Red Hat 系中执行

$ sudo dnf install devhelp

Debian 系可执行

$ sudo apt-get install devhelp

Gentoo 中执行

$ sudo emerge -av devhelp

通常,这些 API 文档会随着开发工具包的安装会被放入 /usr/share/gtk-doc/ 目录下。有了 DevHelp,查看它们非常容易,只需要在应用程序列表中点击 Devhelp 图标,或者在终端模拟器中执行

$ devhelp

八、pkg-config 的安装与使用

pkg-config 是编译器的辅助工具,可以帮助 GCC 找到所需要的头文件与库文件路径。它的安装非常简单。在 Red Hat 系中执行

$ sudo dnf install pkg-config

Debian 系可执行

$ sudo apt-get install pkg-config

Gentoo 中执行

$ sudo emerge -av dev-util/pkgconfig

现在试试 pkg-config,先查看 Linux 系统中是否安装 glib 库:

$ pkg-config --list-all | grep -i glib

若已安装,例如 glib-2.0,接着查看一下所安装的 glib 的具体版本:

$ pkg-config --modversion glib-2.0

再来列出 GCC 所需要的 glib-2.0 头文件所在目录

$ pkg-config --cflags glib-2.0

接着列出 GCC 所需要的 glib-2.0 库文件所在目录

$ pkg-config --libs glib-2.0

当然 pkg-config 无法智能到无所不知的地步,它是通过存放在标准目录 /usr/lib/pkgconfig 下的 .pc 文件来查找 GCC 所需头文件与库文件路径的。当然,也可以通过设置环境变量 PKG_CONFIG_PATH 让 pkg-config 找到非标准目录下的 .pc 文件,在这些文件里同样记录了 GCC 所需要的头文件和库文件所在的路径。例如

$ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

另外,值得提到一下 GTK+ 1 自带的工具 gtk-config,它与 pkg-config 的运作机制相像,但显然已被 pkg-config 取代。

九、GTK+ 的基本概念与约定

首先来解释 GTK+ 中几个基本的概念,以方便将来的分析。

  • 物件(GtkWidget):GTK+ 中每一个窗口里的组成要素都被视为一个物件,如按钮、文本等等,窗口本身也是一个物件。总之 GTK+ 的界面就是由物件构成的。注意,物件都使用指针来管理,物件外在表现就是一个特定类型的指针。
  • 容器(GtkContainer):物件里的一大类,容器的特点是其内部能够容纳其他物件。容器最基本的功能之一是将各种物件良好地组织起来。 GTK+ 的容器能在大小改变时自动调整内含物件的大小,这使得 GTK+ 能够很智能地相应窗口或其他物件的大小改变。这为我们提供了很大的方便,往往我们不需要指定某个物件的大小,只需说明他所在的容器位置, GTK+ 会把物件的实际位置和大小自动计算出来。
  • 继承、组合:虽然是 C 语言写的,但 GTK+ 灵活地运用了面向对象思想。 GTK+ 的物件体系中就有继承、组合这样的关系,如窗口(GtkWindow)是由容器(GtkContainer)派生出来的。
  • 类型转换宏:C 语言本身没有“继承”这个概念,那么,如果把派生的物件直接当做基物件使用,会出现一个编译警告,即“隐式指针类型转换”,但不会出错。为了消除这个警告,需要做指针类型转换。一般情况下类型转换使用类型转换宏。类型转换宏内部会检查物件的继承关系,确定能否进行转换,然后再做显式类型转换。
  • 事件(event):用户的操作,比如按下某个按钮或快捷键,被视为一个事件。
  • 信号(signal):GTK+ 是基于信号回调(signal-slot)机制的。信号捆绑了一个事件和一个函数,在用户触发这个事件时,这个函数会被调用一次。从这个角度来说, GTK+ 是基于物件的,即程序围绕物件属性、事件、方法进行。
  • 主循环(main loop):GTK+ 程序在一个主循环中运行。当一个事件被触发时,它将被插入队列中;在主循环中被触发的事件会被逐个处理(和这个事件绑定的函数被逐个调用);没有事件被触发时,程序就处于等待状态,等待下一个事件被用户触发。直到退出主循环的函数被调用,GTK+ 程序才结束。

GTK+ 拥有开源软件的很多特点,比如结构高度严谨、可读性甚好。现在介绍一下 GTK+ 的关键字命名方式也即 GTK+ 命名规范,以便阅读一段 GTK+ 程序。

  • 普通变量类型名:全小写写法。其中以 "g" 开头属于 GLib 库,如 "gint";
  • 物件类型名:驼峰写法(首字母大写),以 "Gtk" 开头,形如 "GtkWindow"。在 GTK+ 内部,类型是像下面这样定义的(以 GtkWindow 为例)。
    typedef _GtkWindow GtkWindow
  • 函数名:小写夹下划线写法,以 "gtk_"、"g_" 为前缀,形如 "gtk_main()"、"g_print()"。如果是针对某类物件的函数,则前缀中还有物件类型名,形如 "gtk_window_new()"。
  • 常量名:大写夹下划线写法,以 "GTK_" 为前缀,形如 "GTK_WINDOW_TOPLEVEL"。
  • 类型转换宏:大写夹下划线写法,以 "GTK_" 为前缀。一般来说,宏名字和类型名相仿,比如要把 GtkWindow* 类型的物件转换为 GtkContainer* 类型,就使用宏 "GTK_CONTAINER()"。

GTK+ 本身只负责界面组织,它提供的函数大致可分为三类,物件(Widget)、对象(Object)和其它工具函数。物件就不多说了,GTK+ 中的对象是一些功能更加复杂的不可见元素,它们和界面息息相关,比如 GtkBuilder。工具函数提供一些与界面关系密切的实用功能,比如剪贴板读写。

十、GTK+ 开发环境的简单测试

GTK+ 安装完成后,做个测试程序,代码如下

$ cat hellogtk.c

#include <gtk/gtk.h>

void hello(GtkWidget *widget,gpointer data)
{
    g_print("Hello GTK+!\n");
}

gint delete_event(GtkWidget *widget,GdkEvent *event,gpointer data)
{
    g_print ("delete event occurred\n");
    return(TRUE);
}

void destroy(GtkWidget *widget,gpointer data)
{
    gtk_main_quit();
}

int main( int argc, char *argv[] )
{
    GtkWidget *window;
    GtkWidget *button;
    gtk_init (&argc, &argv);
    window=gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_signal_connect (GTK_OBJECT(window),"delete_event",GTK_SIGNAL_FUNC(delete_event),NULL);
    gtk_signal_connect (GTK_OBJECT (window), "destroy",GTK_SIGNAL_FUNC (destroy), NULL);
    gtk_container_set_border_width (GTK_CONTAINER (window), 10);
    button = gtk_button_new_with_label ("Hello Ubuntu!");
    gtk_signal_connect (GTK_OBJECT (button), "clicked",GTK_SIGNAL_FUNC (hello), NULL);
    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                                 GTK_SIGNAL_FUNC(gtk_widget_destroy),GTK_OBJECT (window));
    gtk_container_add (GTK_CONTAINER (window), button);
    gtk_widget_show (button);
    gtk_widget_show (window);   /*显示一个窗口*/
    gtk_main();   /*进入主循环*/
    return(0);
}

用下面命令编译运行

$ gcc hellogtk.c -o hellogtk `pkgconfig --cflags --libs gtk+2.0`
$ ./hellogtk

会显示带有一个按钮的窗口,点击按钮以后窗口关闭,命令行显示 Hello GTK+!

十一、安装 GTK+ 界面快速设计工具

Glade 是 GTK+ 的界面辅助设计工具,可以通过拖放控件的方式快速设计出用户界面,这样的优势在于在设计的同时能直观地看到界面上的控件,并且可以随时调整界面上的设计。用 Glade 设计的图形用户界面是以 XML 格式的文件保存,它描述了控件的结构、每个控件的属性。用户可以动态加载这个界面文件。而且,界面和程序逻辑是完全分离,用户修改了界面,也不需要重新编译程序。Glade 有三个版本:基于 GTK+ 1 版本的 Glade、基于 GTK+ 2 及之后版本的 Glade2、Glade3。一般推荐使用 Glade3 设计 GTK+ 程序界面。

Glade 的布局文件有 2 种格式: Libglade、GtkBuilder。由于布局文件格式的不一样,最终使用的库函数不一样。选择 GtkBuilder 直接生成 XML 格式文件,但是后缀名仍是 .glade。如果选择 Libglade,可通过下述命令行

$ gtk-builder-convert

将它装换为 XML 格式文件。总的来说,推荐使用 GtkBuilder 格式的布局文件。

Glade 的安装很容易,不要要记住,若要使用 Libglade 格式的布局文件,需要安装 libglade 库。在 Red Hat 系中执行

$ sudo dnf install glade3 libglade2-devel

Debian 系可执行

$ sudo apt-get install glade libglade2-dev

Gentoo 中执行

$ sudo sh -c 'echo "dev-util/glade doc" >> /etc/portage/package.use'
$ sudo emerge -av dev-util/glade libglade

安装完成后,在应用程序列表中点击 Devhelp 图标,或者在终端模拟器中执行

$ glade

即可启动 Glade 工具。

1)Glade 画 UI,注意保存为 Libglade 格式,然后在下述 C 代码中使用该布局文件

$ cat libgladedemo.c

#include <glade/glade.h>
#include <gtk/gtk.h>

/**
 * 假设布局文件定义了一个名为 button1 的按钮,并且其 clicked 信号处理函数如下
 * 若是在 MS Windows 中,回调函数要加上修饰词 G_MODULE_EXPORT,也即
 */
/* G_MODULE_EXPORT */
void on_button1_clicked(GtkWidget* widget,gpointer data)
{
    g_print("hello, world!\n\r");
}

int main(int argc,char **argv)
{
    /* Libglade 类型,用于布局 */
    GladeXML *gxml;
    GtkWidget *window;
    gtk_init(&argc,&argv);

    /* 下面开始通过文件获取布局信息了 */
    gxml=glade_xml_new("glade.glade",NULL,NULL);
    /* 信号连接 */
    glade_xml_signal_autoconnect(gxml);

    /* 获取构件 */
    window=glade_xml_get_widget(gxml,"window1");  /* window1 是 glade3 中窗口的名字*/
    button = glade_xml_get_widget(gxml,"button1");  /* button1 是 glade3 中按钮的名字*/

    gtk_widget_show(window);
    gtk_main();
    return 0;
}

在编译代码时,加上 libglade-2.0,如:

$ gcc libgladedemo.c -o libgladedemo `pkg-config --cflags --libs gtk+-2.0 libglade-2.0`
$ ./libgladedemo

2)Glade 画 UI,注意保存为 GtkBuilder 格式,同样在 C 代码中使用该布局文件

$ cat gtkbuilderdemo.c

#include <gtk/gtk.h>

/**
 * 假设布局文件定义了一个名为 button1 的按钮,并且其 clicked 信号处理函数如下
 * 若是在 MS Windows 中,回调函数要加上修饰词 G_MODULE_EXPORT,也即
 */
/* G_MODULE_EXPORT */
void on_button1_clicked(GtkWidget* widget,gpointer data)
{
    g_print("Hello World !\r\n");
}

int main (int argc, char **argv)
{
    /* GtkBuilder 类型,用于布局 */
    GtkBuilder *gtkBuilder;
    GtkWidget *mainwin;
    /* Initialize the widget set */
    gtk_init (&argc, &argv);
    /* Create the main window */
    /* 通过 main.glade 建立布局 */
    gtkBuilder= gtk_builder_new();
    gtk_builder_add_from_file(gtkBuilder,"main.glade",NULL);

    /* 连接信号,信号名在布局文件中定义 */
    gtk_builder_connect_signals (gtkBuilder, NULL);

    /* 通过布局文件获得构件,此处为一个对话框型的窗体 */
    mainwin= GTK_WIDGET(gtk_builder_get_object(gtkBuilder,"dialog1"));
    button = GTK_WIDGET(gtk_builder_get_object (builder, "button1"));
    g_object_unref ( G_OBJECT(gtkBuilder) );
    /* Show the application window */
    gtk_widget_show_all ( mainwin );
    /* Enter the main event loop, and wait for user interaction */
    gtk_main ();
    /* The user lost interest */

    return 0;
}

在编译代码时,无须增加额外库,也即:

$ gcc gtkbuilderdemo.c -o gtkbuilderdemo `pkg-config --cflags --libs gtk+-2.0`
$ ./gtkbuilderdemo

十二、GTK+ 的其他语言开发包

将 GTK+ 与 C 语言的近亲 C++ 绑定,便是 GTKmm。Glade 还是 GTKmm 的界面快速构建工具,推荐使用 Glade3。若使用 libglade 格式的界面布局文件,需额外安装相应的库。在 Red Hat 系中执行

$ sudo dnf install gtkmm24-devel gtkmm24-docs libglademm24-devel

Debian 系可执行

$ sudo apt-get install libgtkmm-2.4-dev libgtkmm-2.4-doc libglademm-2.4-dev libglademm-2.4-doc

Gentoo 中执行

$ sudo sh -c 'echo "dev-cpp/libsigc++ \
                    dev-cpp/glibmm doc \
                    dev-cpp/pangomm doc \
                    dev-cpp/cairomm doc \
                    dev-cpp/atkmm doc \
                    dev-cpp/gtkmm doc \
                    dev-cpp/libglademm doc" >> /etc/portage/package.use'
$ sudo emerge -av gtkmm libglademm

测试一下 GTKmm 开发环境,下面是一个简单 Hello GTKmm 的例子

$ cat hellogtkmm.cpp

#include <gtkmm.h>
#include <libglademm/xml.h>         /* 访问Glade文件所需的头文件 */
#include <iostream>                  /* 输出错误信息到控制台 */
#include <assert.h>                  /* assert()断言 */
 
using namespace Gnome::Glade;
 
class HelloApp: public Gtk::Main {    /* 继承“Gtk::Main”类 */
public:
    HelloApp(int argc, char *argv[]):
        Gtk::Main(argc,argv),             /* 必须在初始化列表中调用父类的构造函数 */
        main_window(0)                     /* 为主窗口的指针赋初值 */
    {
        try
        {
            /* 从同目录下的GLADE文件创建“Gnome::Glade::Xml”对象 */
            ref_xml = Xml::create("helloapp.glade");
        }
        catch(const XmlError& ex)
        {
            /*   出错时错误信息输出到控制台,并返回 */
            std::cerr << ex.what() << std::endl;
            return;
        }
   
        /*
          取得主窗口的指针,存入main_window变量中,并确保成功。
          main_window为0值表示失败,多是因为指定的控件名称不正确或不存在。
          第一个参数就是Glade文件中定义的控件名称,是字符串型。
        */
        ref_xml->get_widget("main_window", main_window);
        assert(main_window);
    }
 
    ~HelloApp()
    {
        /* 由于采用了智能指针,我们不需要管理资源的释放 */
    }
 
    show_window()
    {
        /*
          如果取得主窗口的指针成功,就调用父类的run()函数显示它,
          并进入监听事件的循环状态,当主窗口关闭时返回。
        */
        if (main_window) {
            run( *main_window );
        }
    }
   
protected:
    /* 通过它访问Glade文件的内容,是一种智能指针,能自动释放占用的资源 */
    Glib::RefPtr<Gnome::Glade::Xml> ref_xml;
   
    Gtk::Window* main_window;         /* 存储主窗口的指针 */
};
 
int main (int argc, char *argv[])
{
    /*
      可以看到,这跟“最简单的Gtkmm程序”非常相似。HelloApp继承自
      “Gtk::Main”类,也需要通过 argc 和 argv 两个参数进行实例化。
    */
    HelloApp app(argc, argv);
   
    /*
      在这个函数中调用Gtk::Main::run函数来实现与上面相同的功能。   
      这里不需要窗口对象作参数,因为它已封装在HelloApp类中了。
    */
    app.show_window();
   
    return 0;
}

$ g++ hellogtkmm.cpp -o hellogtkmm `pkg-config --cxxflags --libs gtkmm-2.0`

$ ./hellogtkmm

将 GTK+ 与 Python 语言绑定,便是 PyGTK。Glade 仍是 PyGTK 的界面快速构建工具,若使用 libglade 格式的界面布局文件,需额外安装相应的库。在 Red Hat 系中执行

$ sudo dnf install pygtk2-devel pygtk2-docs pygtk2-libglade

Debian 系可执行

$ sudo apt-get install python-gtk2-dev python-gtk2-doc python-glade2

Gentoo 中执行

$ sudo sh -c 'echo "dev-python/pygtk doc \
                    dev-python/pygobject doc \
                    dev-python/pycairo doc" >> /etc/portage/package.use'
$ sudo emerge -av pygtk pygtk2-libglade

还需测试一下 PyGTK 开发环境,下面是一个简单 Hello PyGTK 的例子

$ cat hellopygtk.py

from gtk import * 
 
window = GtkWindow(WINDOW_TOPLEVEL) # 创建一个顶层窗口 
window.set_title("Hello, world!") 
window.connect("destroy", mainquit) # 将注销事件与mainquit处理连接 
 
window.show() # 显示主窗口 
mainloop() # 进入事件循环 

$ python hellopygtk.py

附录

作为跨平台的图形用户界面开发工具,GTK+ 程序在非 Unix/Linux 平台上并非原生样式。若有这种需要,wxWidgets 便是一个更好的选择,它是由 C++ 开发的跨平台的图形用户界面开发包。另外,基于 wxWidgets 工具包,还开发了 C/C++ 集成开发环境 Code::Blocks,它是跨平台的集成开发环境。该集成开发环境还为 wxWidgets 图形界面开发提供了快速开发插件 wxSmith。在 Linux 平台上,为了让图形用户界面显示 GTK+ 样式,wxWidgets 封装了 GTK+ 包,因此 wxWidgets 在 Linux 平台上也被命名为 wxGTK。好了,要在 Linux 平台上开发 wxWidgets 程序,安装所有的工具包了。在 Red Hat 系中执行

$ sudo dnf install wxGTK-devel wxGTK-docs codeblocks codeblocks-contrib

Debian 系可执行

$ sudo apt-get install libwxgtk3.0-dev wx3.0-doc wx3.0-headers wx3.0-i18n wx3.0-examples codeblocks codeblocks-contrib

Gentoo 中执行

$ sudo sh -c 'echo "dev-util/codeblocks doc contrib " >> /etc/portage/package.use'
$ sudo emerge -av wxGTK codeblocks

在 Gentoo 上使用 wxWidgets,还需要用 eselect 的选择合适的版本

$ sudo eselect list wxWidgets
$ sudo eselect wxWidgets set 1

在 Linux 使用 wxWidgets 的方法非常简单,它提供了 wx-config 工具帮助 GCC 查找头文件与库文件。例如

$ wx-config --cppflags
$ wx-config --libs

再来看一个编译 wxWidgets 程序的实例

$ g++ hellowx.cpp -o hellowx `wx-config --cppflags --libs`
$ ./hellowx

与 GTK+ 类似,wxWidgets 也有其他语言的绑定,这里介绍一下 wxWidgets 与 Python 的绑定,也即 wxPython 开发包,对应的界面快速设计工具是 wxGlade。它们的安装非常简单,Red Hat 系中执行

$ sudo dnf install wxpython wxpython-devel wxpython-docs wxGlade

Debian 系可执行

$ sudo apt-get install python-wxgtk3.0 python-wxtools python-wxversion python-wxglade

Gentoo 中执行

$ sudo emerge -av wxPython wxglade

测试一下 wxPython 开发环境,下面是一个简单 Hello wxPython 的例子

$ cat hellowxpy.py

import sys, os
from wxPython.wx import *
 
class main_window(wxFrame):
      def __init__(self, parent, id, title):
      	  wxFrame.__init__(self, parent, -1, title, size = (200, 100),style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE)
      	  self.control = wxTextCtrl(self, -1, style=wxTE_MULTILINE)
      	  self.Show(true)
 
class App(wxApp):
      def OnInit(self):
      	  frame = main_window(None, -1, "wxPython: (A Demonstration)")
      	  self.SetTopWindow(frame)
      	  return true
 
app = App()
app.MainLoop()

$ python hellowxpy.py
Jul 13

WebDAV(Web-based Distributed Authoring and Versioning)是基于 HTTP 1.1 的一个通信协议。它为 HTTP 1.1 添加了一些扩展(就是在 GET、POST、HEAD 等几个 HTTP 标准方法以外添加了一些新的方法),使得应用程序可以直接将文件写到 Web 服务器上,并且在写文件时候可以对文件加锁,写完后对文件解锁,还可以支持对文件所做的版本控制。现在主流的 Web 服务器一般都支持 WebDAV,如需了解更多有关 webDAV 的一些开源或商业项目,可访问 http://webdav.org/。

下面就来介绍一下在 Fedora 的 Apache 服务器中如何配置 WebDAV。首先,当然是安装 Apache 服务器

$ sudo yum install httpd

查看一下 Apache 服务器是否包含了 WebDAV 模块

$ cat /etc/httpd/conf.modules.d/00-dav.conf
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule dav_lock_module modules/mod_dav_lock.so

确认完了 WebDAV 模块之后,该建立 WebDAV 目录了,这很简单:

$ sudo mkdir -p /var/www/webdav

安全起见,还需为 WebDAV 创建一些用户(当然不创建用户也行,不过记得修改后面的配置文件),可执行以下命令产生密码验证文件

$ sudo htpasswd -cm /var/www/webdav/.htpassword james

提示输入密码时输入该用户的密码;若还需要增加用户 tom,可执行以下命令

$ sudo htpasswd -m /var/www/webdav/.htpassword tom

删除某个用户,如 tom,可以使用下列指令:

$ sudo htpasswd -D /var/www/webdav/.htpassword tom

最后,还需在 Apache 的配置目录 /etc/httpd/conf.d/ 中新建一个名为 webdev.conf 的 WebDAV 配置文件,并输入以下内容

$ sudo nano -w /etc/httpd/conf.d/webdev.conf
<IfModule mod_dav_fs.c>
    DAVLockDB /var/lib/dav/lockdb
</ifmodule>

Alias /webdav "/var/www/webdav/"

<Directory "/var/www/webdav/">
   Options Indexes MultiViews
   IndexOptions FancyIndexing
   AddDefaultCharset UTF-8
   AllowOverride None
   <IfModule mod_authz_core.c>
       # Apache 2.4
       Require all granted
   </IfModule>
   <IfModule !mod_authz_core.c>
       # Apache 2.2
       Order allow,deny
       allow from all
   </IfModule>

   Dav On # 开启 WebDAV
   AuthType Basic
   AuthName "WebDAV Server"
   AuthUserFile /var/www/webdav/.htpassword #密码验证文件
   Require valid-user
   <Limitexcept Get Options>
      Require user james
   </Limitexcept>
</Directory>

一切就绪了之后,重启 Apache 服务器

$ sudo service httpd restart

该测试一下 WebDAV 服务了,这只需在浏览器的地址栏中输入 http://localhost/webdav 来访问共享资源了;也可通过 MS Windows 的网上邻居访问。当然,GNU/Linux 也可使用命令行 cadaver 进入访问

$ sudo yum install cadaver
$ cadaver http://127.0.0.1/webdav/
Sep 21
A、简单说明
CentOS 是一款基于 Red Hat Enterprise Linux 提供的可自由使用源代码的企业级 Linux 发行版本。作为服务器的工作环境,相对于其他 Linux 发行版,它的稳定性是值得信赖的。CentOS 的安装方式也非常的多样,例如用 CentOS 光盘镜像开启图形或文本界面安装程序;再如以 kickstart 进行网络安装。这里主要介绍以 chroot 方式实现 CentOS 的自举,主要利用的工具是 Red Hat 的包管理工具 rpm 以及 yum。它们分别提供了与 chroot 配合的 --root 与 --installroot 选项。这种安装方式不仅适用于双 Linux 系统的安装,也适用于利用 Linux Live CD 环境安装 Fedora/CentOS。
 
B、准备 Linux 宿主环境
想要通过自举的方式安装 CentOS,就需要提供一个 Linux 宿主环境。一般而言,这个宿主环境可以是 Red Hat 系的操作系统,也可以是非 Red Hat 系的操作系统。宿主环境可以是硬盘中安装的 Linux,也可以是 Live CD 中的 Linux。尽管如此,Linux 宿主环境还是必须提供 Red Hat 的包管理工具。如果宿主环境是 Red Hat 系,那么显然已经满足了这一要求,不过最好保证 yum 是最新的
$ sudo yum update yum
下面将给出 Gentoo、Debian 发行版中是如何安装 Red Hat 包管理器?为方便计,切换到 root 用户:
$ su -
1. 在 Gentoo 中安装 YUM 包管理器
Gentoo Portage 中提供了 rpm、yum 等 Red Hat 工具,请安装最新版本,这里以 amd64 架构为例:
# echo 'sys-apps/yum ~amd64' >> /etc/portage/package.keywords
# echo 'dev-python/sqlitecachec ~amd64' >> /etc/portage/package.keywords
# echo 'app-arch/rpm sqlite' >> /etc/portage/package.use
# emerge -avuDN sys-apps/yum app-arch/rpm dev-python/m2crypto
 
2、在 Debian 中安装 YUM 包管理器
Debian 源中也提供了 Red Hat 的包管理工具,不过要安装最新的 yum 包
# apt-get install -t experimental yum rpm python-m2crypto
 
C、准备 CentOS 的安装空间
有了宿主环境,还需要安装 CentOS 的空间。通常根据宿主环境的不同,可以是同一块硬盘中的空闲空间,也可以从其他机器上暂时拆一下一块硬盘提供的空闲空间,还可以是移动硬盘或者 U 盘,当然也不排除虚拟机空间。为了方便起见,不妨假设我们在虚拟机中操作。下面开始分区相关操作。
 
空间分区
# fdisk /dev/sda
假设分了三个区,分别是交换分区 /dev/sda1、根分区 /dev/sda2、启动分区 /dev/sda3。格式化分区
# mkswap /dev/sda1
# mke2fs -j /dev/sda2
# mke2fs -j /dev/sda3
接着挂载分区
# mkdir /mnt/centos
# mount /dev/sda2 /mnt/centos
# mkdir /mnt/centos/boot
# mount /dev/sda3 /mnt/centos/boot
# swapon /dev/sda1
 
D、将 Red Hat 包管理工具安装到 CentOS 的分区中
先建立 RPM 数据库
# mkdir -p /mnt/centos/var/lib/rpm
# rpm --root /mnt/centos --initdb
接着到 CentOS 的官方镜像网站 http://vault.centos.org 下载需要版本的 centos-release 并安装,也可到 http://rpm.pbone.nethttp://www.rpmfind.net 网找查找 centos-release 包:
# rpm -ivh --nodeps --root /mnt/centos http://vault.centos.org/6.4/os/x86_64/Packages/centos-release-6-3.el6.centos.x86_64.rpm
上述命令会将 centos-release 包提供的 CentOS 的官方源的配置文件安装到 /mnt/centos/etc/yum.repos.d 目录。
 
由于 Red Hat 系并没有提供 locale-gen 之类的命令配置系统 locale 的数量,这里采用 RPM 宏的方式来选择它们
# echo %_install_langs en:zh:zh_CN:zh_CN.UTF-8 >> /mnt/centos/etc/rpm/macros.lang
 
可以将 Red Hat 的包管理工具 YUM 安装到 /mnt/centos 了:
# yum --installroot /mnt/centos install yum --nogpgcheck
注意上述命令中的 --nogpgcheck 选项,以防出现 GPG 公匙验证错误。若直接使用官方的 CentOS 镜像进行安装比较慢,也可以替换 CentOS 的源配置,例如
# mv /mnt/centos/etc/yum.repos.d/CentOS-Base.repo /mnt/centos/etc/yum.repos.d/CentOS-Base.repo.backup 
# wget -O /mnt/centos/etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo 
# yum makecache
再试试上述的 yum 操作。
 
若不想进入下一步繁琐的 chroot 操作,实际上,最小安装也可以通过下面的方法直接实现
# wget http://vault.centos.org/6.4/os/x86_64/images/install.img
# yum install squashfs-tools
# unsquashfs -d /mnt/centos install.img
该镜像安装完成之后,chroot 的相关操作会相对简单一些。
 
E、进入预装的 CentOS 系统
复制域名解析配置文件
# cp -L /etc/resolv.conf /mnt/centos/etc/resolv.conf
挂载必要的
# mount --bind /dev /mnt/centos/dev
# mount -t proc none /mnt/centos/proc
# mount -t sysfs none /mnt/centos/sys
好了,进入 chroot 环境
# chroot /mnt/centos /bin/bash
 
1、重建 RPM 数据库
可能由于宿主环境中的 RPM 数据库的版本问题,在 chroot 环境中执行 yum 可能会报 DB 数据库错误,用下述方法重建 RPM 数据库
# rpmdb --rebuilddb -vv
 
2、重置 root 用户的密码
为了确保我们能够以 root 用户进入 CentOS 系统,需要重置密码。由于 Red Hat 系的发行版中都默认开启了 SELinux,因此,chroot 环境中是不能通过 passwd 修改 root 密码的。我们可以通过手动修改 /etc/passwd 文件并通过 shadow-utils 工具来加密密码。为了简单起见,我们重置 root 密码为空
# sed -i 's@^root:x:@root::@' /etc/passwd
接着创建 /etc/shadow 文件
# yum install shadow-utils
# pwconv
 
3、设置系统的默认时区
# cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
 
4、配置 /etc/fstab
在开始内核安装之前,务必配置好系统根分区的信息,例如
# cat > /etc/fstab  << EOF
/dev/sda1     swap          swap       defaults           0 0
/dev/sda2     /             ext3       defaults           1 1
/dev/sda3     /boot         ext3       defaults           1 2
/dev/cdrom    /mnt/cdrom    iso9660    noauto,ro          1 1
tmpfs         /dev/shm      tmpfs      defaults           0 0
devpts        /dev/pts      devpts     gid=5,mode=620     0 0
sysfs         /sys          sysfs      defaults           0 0
proc          /proc         proc       defaults           0 0
EOF
注意到里面的 /mnt/cdrom,故需新建该目录
# mkdir -p /mnt/cdrom
另外,若喜欢使用 UUID 作为分区标记,可先用
# blkid /dev/sda2
# blkid /dev/sda3
参看各个分区的 UUID,随后修改 /etc/fstab 文件。
 
5、安装 Linux 内核
该轮到内核安装了,由于 CentOS 是自举安装的,因此推荐直接安装二进制内核以解决相关的依赖性问题:
# yum install kernel
 
6、配置 CentOS 的网络
设定主机名并启用网络
# cat > /etc/sysconfig/network << EOF
NETWORKING=yes
HOSTNAME=bootstrap
EOF
本地解析主机名设定
# echo '127.0.0.1 bootstrap' >> /etc/hosts
 
根据网络情况设定 IP 地址。如果机器获得静态 IP 地址,则
# cat > /etc/sysconfig/network-scripts/ifcfg-eth0 << EOF
DEVICE=eth0
HWADDR=00:00:00:00:01
ONBOOT=yes
BOOTPROTO=static
TYPE=Ethernet
IPADDR=10.10.19.234
NETMASK=255.255.254.0
GETEWAY=10.10.18.254
EOF
假如机器以动态方式获得 IP 地址,则需先安装 DHCP 客户端
# yum install dhclient
随后配置网络
# cat > /etc/sysconfig/network-scripts/ifcfg-eth0 << EOF
DEVICE=eth0        
ONBOOT=yes
BOOTPROTO=dhcp
EOF
其他方式的网络获得方法,请自行查阅资料。
 
最后,根据实际情况配置域名解析服务器
# cat /etc/resolv.conf
nameserver 208.67.222.222
nameserver 208.67.220.220
 
7、配置 Linux 键盘布局以及终端字体(可选)
这一部分对于大多数用户来说是不需要配置的,因为通常的键盘布局都是美式的;用户的工作方式也大多集中于图形操作界面。不过,如需相关配置的话,请先查阅 /usr/share/doc/initscripts 中的说明文件。
 
配置键盘布局,通常使用的键盘都是美式的,可作如下操作
# yum install kbd
# echo KEYTABLE="/lib/kbd/keymaps/i386/qwerty/us.map.gz" >> /etc/sysconfig/keyboard
有关键盘布局的信息,可到 /lib/kdb/keymanps 目录查看。
 
终端字体的安装
# yum install terminus-fonts-console
使用term系列字体,很漂亮,偶现在用的是ter-g16f.psf.gz字体。即使生效的办法是
# setfont /lib/kbd/consolefonts/ter-g16f.psf.gz
若想永久生效,可配置
# echo SYSFONT="/lib/kbd/consolefonts/ter-g16f.psf.gz" >> /etc/sysconfig/i18n
如需更多终端字体,请到 /lib/kbd/consolefonts 目录中查看。
 
8、安装必要的系统工具
为了方便调试系统以及维护系统,常用的系统日志与日程管理工具是必需的:
# yum install rsyslog crontabs cronie cronie-anacron
 
9、安装引导程序
目前 Linux 的引导程序基本上都是 grub,不过由于 CentOS 相对陈旧,它还没有提供 grub2。
# yum install grub
接着根据分区情况配置 grub
# cat > /boot/grub/grub.conf << EOF
timeout 5
default 0

# (0) CentOS
title CentOS 6.4
root (hd0,1)
kernel /vmlinuz-2.6.32-358.18.1.el6.x86_64 root=/dev/sda2 ro
initrd /initrd-2.6.32-358.18.1.el6.x86_64.img
EOF
用下述命令将 grub 安装到
# grub-install /dev/sda
若安装失败,可尝试
# grub
> root (hd0,1)
> setup (hd0)
> quit
 
10、退出 chroot 环境并重启系统
# exit
# cd /
# umount /mnt/centos/dev
# umount /mnt/centos/proc
# umount /mnt/centos/sys
# umount /mnt/centos/boot
# umount /mnt/centos
# reboot
 
D、进入全新的 CentOS 系统
 
如果一切正常的话,电脑将进入全新的 CentOS 系统,以 root 用户无密码登录即可
login: root
 
进入系统的第一件事情就是重置 root 用户密码,先将常用的 passwd 工具装上
# yum install passwd
试着执行一下 passwd 命令,由于 SELinux 的原因,通常会出现下面的错误
# passwd
passwd: unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 is not authorized to change the password of root
为了让 passwd 正常工作,请禁用 SELinux:
# setenforce 0
如果想永久的禁用 SELinux,请执行
# cat > /etc/selinux/config << EOF
SELINUX=disabled
SELINUXTYPE=targeted
EOF
# ln -s /etc/selinux/config /etc/sysconfig/selinux
好了,试试重置 root 用户的密码吧:
# passwd
 
为方便控制用户权限,可安装 sudo 包:
# yum install sudo
接着开启 wheel 组的 root 权限
# sed -i 's|^# %wheel  ALL=(ALL:ALL) NOPASSWD: ALL|%wheel  ALL=(ALL:ALL) NOPASSWD: ALL|' /etc/sudoers
增加普通用户到 CentOS 系统并将它加入 wheel 组:
# adduser easior -a wheel
接着重置 easior 的密码
# passwd easior
好了再次重启系统
# reboot
测试普通用户的权限设置是否正常?
 
以普通用户登录
login: easior
password: 
尝试用 sudo 安装基本工具
$ sudo yum install nano man-pages openssh
一切正常的话,可以进行其他配置了。
 
E、CentOS/RHEL 软件源简介
 
CentOS 官方发行版提供了四个配置文件:CentOS-Base.repo、CentOS-Vault.repo、CentOS-debuginfo.repo、CentOS-Media.repo。后三个配置文件分别是发行版所有过往的源配置文件、官方源中相应包的 debuginfo 源配置文件、光盘镜像的源配置文件,它们默认是不开启的。因此,CentOS 官方发行版中的源是由 CentOS-Base.repo 决定的。虽然该配置文件里包含了 base、updates、extras、CentOSPlus、contrib 源,但官方源中去除了很多有版权争议的软件,导致可安装的软件数量非常有限;而且相对于 Fedora 等版本,软件版本也不是最新的。这就需要我们使用第三方软件源作为补充,简化 CentOS 用户的使用。下面稍微对 CentOS/RHEL 中的常用源做一些说明。有关 CentOS/RHEL 源的更多介绍,请看 http://wiki.centos.org/AdditionalResources/Repositories。当然,里面的内容可能有些过时。
 
CentOS/RHEL 官方源
正如前面提到的,CentOS/RHEL 官方提供了一些源,不过默认状态下只开启了少量的几个源。例如 CentOS 只开启了 CentOS-base.repo 中的 base、update、extras 这三个源,而其他源均不开启。base 与 updates 是 CentOS/RHEL 发行版中提供的基础组件软件包及其更新。extras 提供了一些额外的不破坏 CentOS/RHEL 系统兼容性且不改变基础组件的软件包。这些软件包已经由 CentOS 开发小组经过测试确保它们在 CentOS 中正常工作。这些软件可能不是由 RHEL 上游提供的。值得指出的是,extras 源中含有持续发行软件源 centos-release-cr,它含有下一个 CentOS 发行版的软件包。CentOSPlus 源是为那些更改 CentOS 基本组件的软件包而设立的。使用该源会导致 CentOS 与上游提供者的内容有异。CentOS 的开发小组已经针对该源内的每个程序作出测试,确定它们能在 CentOS 下创建及运作。contrib 源中则含有 CentOS 用户供献的组件,它们并不会与核心发行版本的组件重叠。这些组件并没有经过 CentOS 的开发者测试,也未必会紧跟 RHEL 的发行。
 
CentOS-Testing 源
该源是由 CentOS 开发者维护并为 CentOSPlus 与 extras 两个源提供软件包的。这些软件包既不一定进入 CentOS 的正式源,也不一定保证正常工作。这些软件包是专门给测试者使用并由他们反馈相关的功能与稳定性。源中这些处于开发阶段的软件随时可能移除,因此在生产环境中务必关闭该源。 CentOS-Testing 源默认不自带在 CentOS 系统中,不过仍可通过下面的方法添加
$ sudo wget http://dev.centos.org/centos/6/testing/CentOS-Testing.repo  -O /etc/yum.repos.d/CentOS-Testing.repo
$ sudo sed -i 's/^enable=0/enable=1'  /etc/yum.repos.d/CentOS-Testing.repo
 
EPEL 源
EPEL(Extra Packages for Enterprise Linux) 源是由 Fedora 社区创建维护的,为 RHEL 及衍生发行版如 CentOS、Scientific Linux 等提供高质量软件包的项目。EPEL 中含有大量的软件,对官方标准源是一个很好的补充。Fedora 的官方说明在 http://fedoraproject.org/wiki/EPEL。EPEL 源的添加方法很简单
$ sudo rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
 
RPMForge 源(REPOForge 源)
RPMForge 源是由 Dag 及其它包装者合作维护的,它为 CentOS/RHEL 提供了超过 10000 多个包,其中包含了dropbox、wine、vlc、mplayer、xmms-mp3 以及其他一些非常流行的媒体工具。它本身不是 CentOS/RHEL 的一部分,但是它与这些发行版是相容的。目前,REPOForge 是 RPMForge 继任者,不过源本身并没有改名。RPMForge 源被 CentOS 社区认为是最安全也是最稳定的一个第三方软件源。RPMForge 的官方网站在 http://repoforge.org/。它的添加方法如下:
i386 架构的系统,请执行
$ sudo rpm -ivh http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.i386.rpm
而 x86_64 架构的系统则执行
$ sudo rpm -ivh http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.x86_64.rpm
接着注入 DAG 的 PGP 公匙
$ sudo rpm --import http://apt.sw.be/RPM-GPG-KEY.dag.txt
 
RPM Fusion 源
RPM Fusion 提供了很多 Fedora Project 或 Red Hat 没有提供的软件包。所有这些软件均以预编译的 RPM 包的形式提供给 Fedora 与 CentOS/RHEL。 RPM Fusion 混合了原先的 Dribble、Freshrpms 与 Livna。RPM Fusion 源中除了提供大量的多媒体工具之外,还提供了 VirtualBox 相关的工具。RPM Fusion 官网位于 http://rpmfusion.org。配置 RPM Fusion 源非常简单,请执行
$ sudo rpm -ivh http://download1.rpmfusion.org/free/el/updates/6/i386/rpmfusion-free-release-6-1.noarch.rpm 
$ sudo rpm -ivh http://download1.rpmfusion.org/nonfree/el/updates/6/i386/rpmfusion-nonfree-release-6-1.noarch.rpm
 
Adobe 源
该源提供了多种语言的 Adobe Reader 与 flash-plugin,它的详细介绍请参看 http://blogs.adobe.com/acroread/2008/02/adobe_reader_now_available_via.html。对于 i386 架构的系统,请执行
$ sudo rpm -ivh http://linuxdownload.adobe.com/linux/x86_64/adobe-release-x86_64-1.0-1.noarch.rpm
来配置 Adobe 源;而对 x86_64 架构的系统,则可执行
$ sudo rpm -ivh http://linuxdownload.adobe.com/linux/i386/adobe-release-i386-1.0-1.noarch.rpm
 
Google 源
Google 源提供了诸如 Google Chrome、Google Earth、Google Talk Plugin 等应用,具体信息参见 http://www.google.com/linuxrepositories/。尽管 Google 并没有提供源的安装方法,不过,关于 Google 源的示例却不难找到,下面便是源安装示例:
$ sudo cat > /etc/yum.repos.d/google.repo << EOF
[google-chrome]
name=Google Chrome - $basearch
baseurl=http://dl.google.com/linux/chrome/rpm/stable/$basearch/
enabled=1
gpgcheck=1
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub

[google-earth]
name=Google Earth - $basearch
baseurl=http://dl.google.com/linux/earth/rpm/stable/$basearch/
enabled=1
gpgcheck=1
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub

[google-musicmanager]
name=Google Music Manager - $basearch
baseurl=http://dl.google.com/linux/musicmanager/rpm/stable/i386
enabled=1
gpgcheck=1
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub

[google-talkplugin]
name=Google Talk Plugin - $basearch baseurl=http://dl.google.com/linux/talkplugin/rpm/stable/$basearch
enabled=1
gpgcheck=1
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub 

[google-mod-pagespeed]
name=Google Mod PageSpeed - $basearch baseurl=http://dl.google.com/linux/mod-pagespeed/rpm/stable/$basearch
enabled=1
gpgcheck=1
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub
EOF
 
以上各源对 CentOS/RHEL 等系统完全兼容,但各软件源之间并不能保证完全兼容没有冲突。如果需要使用以上源,最好安装 yum-plugin-priorities 插件调整各个源之间的优先级
$ sudo yum install yum-plugin-priorities
安装 yum-plugin-priorities 插件后,可以通过修改 /etc/yum.repos.d/ 中各个源的配置文件,在其中插入指令
priority=N
从而设置各个源的优先级 priority,其中 N 为1到99的正整数,数值越小优先级越高。一般官方源优先级设置为 1,最高;第三方源的优先级这只推荐为 >10。例如下面示例中将 base、updates、extras 源优先级设为了 1,而 CentOSplus、contrib 的优先级则为 2:
$ cat /etc/yum.repos.d/CentOS-Base.repo
# CentOS-Base.repo
#
# The mirror system uses the connecting IP address of the client and the
# update status of each mirror to pick mirrors that are updated to and
# geographically close to the client.  You should use this for CentOS updates
# unless you are manually picking other mirrors.
#
# If the mirrorlist= does not work for you, as a fall back you can try the 
# remarked out baseurl= line instead.
#
#

[base]
name=CentOS-$releasever - Base
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
#baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
priority=1

#released updates 
[update]
name=CentOS-$releasever - Updates
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates
#baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
priority=1

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras
#baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
priority=1

#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus
#baseurl=http://mirror.centos.org/centos/$releasever/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
priority=2

#contrib - packages by Centos Users
[contrib]
name=CentOS-$releasever - Contrib
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=contrib
#baseurl=http://mirror.centos.org/centos/$releasever/contrib/$basearch/
gpgcheck=1
enabled=0
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
priority=2
 
F、一些简单的配置
作为服务器而言,CentOS 的配置通常集中在网络服务上面,例如 LAMP、FTP、RSYNC 等。相对而言,它的桌面应用的相关配置反而显得并不重要。不过不管怎样,CentOS 的终端界面总是需要配置的,特别是中文显示、输入等等。
 
为了让中文能够正常显示,需要设定系统的 locale 以及安装一些中文字体
$ su -c 'echo Lang="zh_CN.UTF-8" >> /etc/sysconfig/i18n'
$ sudo yum install wqy-micro-fonts wqy-bitmap-fonts
即使如此,中文字符在 Linux 的终端仍显示为乱码,这涉及到 Linux 内核的问题。解决的办法是要么给 Linux 内核打 UTF-8 补丁,要么安装 Framebuffer 终端模拟器。这里采用后者,为此添加 EPEL 源
$ sudo rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
$ sudo yum clean all
$ sudo yum install fbterm
接着安装中文手册页,并运行 fbterm 测试中文显示是否正常:
$ sudo yum install man-pages-zh-CN
$ fbterm
随便打开一个中文 man page 看看吧!
 
为了在终端输入中文字符,可以安装 fcitx-fbterm 或者 ibus-fbterm 来配合 fbterm 使用。这里使用 ibus-fbterm 来输入中文,不过可惜所有源中均无此包,只能自己动手了。先安装基本的工具链
$ sudo yum install @Development\ Tools
某些包的编译过程可能还需好内核功能:
$ sudo yum install kernel-devel kernel-headers
接着安装 RPM 开发工具并在用户家目录建立 RPM 开发目录
$ sudo yum install rpmdevtools
$ rpmdev-setuptree
接着到 Fedora 官方中下载 ibus-fbterm 的 RPM 源码包进行编译安装
$ wget http://dl.fedoraproject.org/pub/fedora/linux/releases/19/Everything/source/SRPMS/i/ibus-fbterm-0.9.1-16.fc19.src.rpm
$ rpm -ivh /ibus-fbterm-0.9.1-16.fc19.src.rpm
进入 ~/rpmbuild/SPECS 目录适当修改 ibus-fbterm.spec,接着便可生成 ibus-fbterm 的 rpm 包了
$ cd  ~/rpmbuild/SPECS
$ nano -w ibus-fbterm.spec
$ sudo yum install yum-utils
$ sudo yum-builddep ibus-fbterm.spec
$ rpmbuild -ba ibus-fbterm.spec
$ cd ../RPMS/x86_64
$ sudo rpm -ivh ibus-fbterm.*.rpm
为了方便用户使用,可直接查看页面上给出的 FedoraPeople 上的 DoReMi 源。 
 
再来安装 Linux 终端下的图片浏览器 fbi 与 PDF 文档阅读工具 fbgs
$ sudo yum install fbida fbida-fbgs
另外,还有截屏工具 fbgrab
$ sudo yum install fbgrab
 
文本浏览器
$ sudo yum install w3m w3m-img links2
网络聊天工具
$ sudo yum install finch irssi
 
想要获得终端的鼠标支持功能,需安装 gpm 并启动 gpm 服务
$ sudo yum install gpm
$ sudo service gpm start
$ sudo chkconfig gpm on
试试用鼠标左键选择、鼠标中键复制吧。
 
在 CentOS 中安装 VirtualBox 非常简单,只需开启 RPM Fusion 源。不过,VirtualBox 官方也提供了相应的源,这里不妨用 VirtualBox 官方的源:
$ sudo wget http://download.virtualbox.org/virtualbox/rpm/rhel/virtualbox.repo -O /etc/yum.repos.d/virtualbox.repo
接着根据需要安装相应版本的 VirtualBox
$ sudo yum install VirtualBox-4.2
接着配置 VirtualBox,下面的命令行会创建 vboxusers 用户以及用户组,同时将自动编译相关的内核模块
$ sudo service vboxdrv setup
试试以 headless 方式启动 VirtualBox 吧!
Sep 13

众所周知,除去 rawhide 之外,Fedora 的版本是不能滚动的。但是我们仍可以通过启用不同版本的源,直接由 YUM 实现跨版本升级。跨版本升级的好处是显而易见的,如同滚动升级一样,系统上常用的包,除了需要更新之外,不必像装新系统那样一次次地从头安装。这里以 Fedora 18 升级到 Fedora 20(Branched Release) 为例,说明一下大概的步骤。至于上面提到的 Branched Release 的相关信息以及它的生存周期,请参考 https://fedoraproject.org/wiki/Releases/Branched

在开始升级系统之前,先清理一下系统中的孤包、残留包以及没有合并的配置文件。为此,先安装
$ sudo yum install yum-utils
随后执行
$ sudo package-cleanup --orphans
查看孤包列表,根据需要删除孤包列表中的某些软件。注意,要小心列表中的包,因为里面的包并不一定都是没用的包。再来执行
$ sudo package-cleanup --leaves
查看残余包列表,根据需要删除其中的某些包。作为准备工作的最后一步,记得合并一下所有变更过的配置文件:
$ sudo yum install rpmconf
$ sudo rpmconf -a
根据提示查看更改细节,然后决定合并的方式。
 
现在可以开始跨版本升级 Fedora 了,为了防止系统更新过程中 X Window 不能正常工作,请切换到控制台完成以下操作(即 Alt-F1~F6)。先升级 YUM 工具:
$ sudo yum update yum --releasever=20 --disablerepo=* --enablerepo=fedora --enablerepo=updates-testing --disableplugin=presto
注意上述命令中禁用了 yum-presto 插件,以防版本差距较大的 delta 包破坏系统的更新过程。另外,此过程中还可能会出现 GPG 公匙验证错误,可用下面的方式暂时忽略它
$ sudo yum update yum --releasever=20 --disablerepo=* --enablerepo=fedora --enablerepo=updates-testing --nogpgcheck --disableplugin=presto
当然,也可以参看 https://fedoraproject.org/keys 页面中的信息,然后根据提示注入 GPG 公匙,例如 Fedora 20(Branched Release) 的公匙注入方法:
$ sudo rpm --import https://fedoraproject.org/static/246110C1.txt
包管理器 YUM 升级成功之后,可以升级系统了(这是一件相对冒险的事情,记得备份好系统):
$ sudo yum distro-sync --releasever=20 --disablerepo=* --enablerepo=fedora --enablerepo=updates-testing --nogpgcheck --disableplugin=presto
这一步将会经过漫长的时间处理包之间的依赖关系,如果一切顺利的话,便可直接更新系统版本了。倘若这一步仍有依赖性无法解决,那么有三个方法可以解决:一、根据提示暂时删除那些破坏依赖关系的包,不过对我们工作有用的那些包,最好不要用这招,以免日后忘了重新安装它;二、与升级 YUM 的方法一样,单独升级某几个破坏依赖的包,例如
$ sudo yum update python-pexec --releasever=20 --disablerepo=* --enablerepo=fedora --enablerepo=updates-testing --nogpgcheck --disableplugin=presto
三、利用 --skip-broken 暂时跳过无法解决依赖的那些包:例如
$ sudo yum distro-sync --releasever=20 --disablerepo=* --enablerepo=fedora --enablerepo=updates-testing --nogpgcheck --disableplugin=presto --skip-broken
如果开始执行上面这一行命令的话,会有大面积的包需要下载与更新,这就需要我们耐心等待。
 
长时间等待之后,Fedora 18 系统顺利更新到了 Fedora 20(Branched Release)。不过版本更新过程还没有结束,下面开始做必要的检查工作。首先,确认 Fedora 18 中的第三方源中哪些源还能正常工作:
$ sudo yum repolist
根据提示信息,手动禁用那些无法工作的源,例如
$ sudo yum-config-manager --disable livna
接着再来确认 Fedora 20(Branched Release) 的最小系统是否已经更新完成:
$ sudo yum update "Minimal Install"
重新安装 Fedora 系统的引导程序,目前 grub2 是 Fedora 20 中的引导程序,因此
$ sudo grub2-install /dev/sda
$ su -c 'grub2-mkconfig -o /boot/grub2/grub.cfg'
修复一下初始话脚本的启动次序
$ su
# cd /etc/rc.d/init.d; for f in *; do [ -x $f ] && /sbin/chkconfig $f resetpriorities; done
最后,大范围的版本升级可能造成系统配置的更改,请再次运行下述命令合并配置文件
$ sudo rpmconf -a
好了,基本上重启之前的准备工作已经完成了。重启系统吧:
$ sudo reboot

 

尽管 Fedora 20 的系统能够启动起来,不过,由于目前刚进入 Branched Release 不久,系统里面的包还不是很完整。例如,通过下述方式可查看系统中残留的 Fedora 18 的软件包:

$ sudo package-cleanup --leaves

这个列表中有一部分包来自于原先 Fedora 18 系统的第三方源。对于这些包,我们不必急着删除它们,可以等到第三方源更新到 Fedora 20 的时候再升级它们。

Sep 6

cgit 是一款为 Git 服务器提供 Web 浏览界面的工具,与 gitweb 的功能类似。不过,cgit 的界面更加友好一些,速度更快一些。这里就来谈谈如何在 Fedora 19 中安装与配置 cgit,以及用它替代 gitweb 实现与 Gitolite 的整合。

cgit 的安装非常便当,仅需执行:

$ sudo yum install cgit
接着适当地调整 cgit 目录的访问权限,这里以 Apache 服务器为例:
$ sudo nano -w /etc/httpd/conf.d/cgit.conf
#
# cgit configuration for apache
#

ScriptAlias /cgit /var/www/cgi-bin/cgit
Alias /cgit-data /usr/share/cgit/

<Directory "/usr/share/cgit/">
   AllowOverride None
   Options None
  <IfModule mod_authz_core.c>
       # Apache 2.4
       Require all granted
   </IfModule>
   <IfModule !mod_authz_core.c>
       # Apache 2.2
       Order allow,deny
       Allow from all
   </IfModule>
</Directory>

<Directory "/var/www/cgi-bin"> 
  AllowOverride None 
  Options ExecCGI FollowSymlinks
  <IfModule mod_authz_core.c>
       # Apache 2.4
       Require all granted
   </IfModule>
   <IfModule !mod_authz_core.c>
       # Apache 2.2
       Order allow,deny
       Allow from all
   </IfModule>
</Directory>
注意,确保上述设置与 cgit 的一下配置一致,也即编辑 /etc/cgitrc 文件:
$ sudo nano -w /etc/cgitrc
查看下面几行
# cgit config

css=/cgit/cgit.css
logo=/cgit/cgit.png
如果不想被搜索引擎索引的话,还可往里添加一行:
# if you don't want that webcrawler (like google) index your site
robots=noindex, nofollow
修改完成之后,重启 Apache 服务器
$ sudo service httpd restart
如果Apache 服务器已经配置好了的话,可以测试一下 cgit 的功能是否正常工作。这只需在可以访问当该服务器器的电脑上打开网页浏览器,并在地址栏输入 http://serverIP/cgit。如果网页能够打开,那么表明 cgit 已经能够工作了。
 
需要注意,上面只是测试了 cgit 提供的 Web 界面是否工作,但是还没有涉及到 Git 服务器的部分。下面开始来谈论 cgit 如何关联到 Git 服务器。实际上,它是通过 /etc/cgitrc 配置文件来关联 Git 服务器的:
$ sudo nano -w /etc/cgitrc
根据具体情况编辑该配置文件,例如修改下面这些行:
#
# List of repositories.
# This list could be kept in a different file (e.g. '/etc/cgitrepos')
# and included like this:
#   include=/etc/cgitrepos

#repo.url=foo
#repo.path=/var/lib/git/foo.git
#repo.desc=the master foo repository
#repo.owner=fooman@example.com
#repo.readme=info/web/about.html

repo.url=MyRepo
repo.path=/var/lib/git/MyRepo.git
repo.desc=This is my git repository
实际上,真正与 Git 服务有关的只有最后三行,这三行给出了 Git 仓库的位置、名称以及扼要的描述。更多的 Git 仓库,均可按该格式添加至 cgit 的配置文件。现在在网页浏览器的地址栏再次输入 http://serverIP/cgit 测试一下,看看能不能访问到 Git 仓库信息。
 
为了更好地控制 Git 服务器的访问权限,一般 Git 服务部分都是通过 Gitolite 这样的工具实现的。Gitolite 的配置过程在前面已经描述过了。自然而然的,需要考虑如何以 cgit 替代 gitweb,将它与 Gitolite 整合在一起。解决这个问题的方法与实现 gitweb 的整合过程差不多。首先,修改 Gitolite 新建仓库的默认权限,这可通过修改 /var/lib/gitolite/.gitolite.rc 的 UMASK 实现:
$ sudo nano -w /var/lib/gitolite/.gitolite.rc
更改 UMASK 为 0022,也即
#$REPO_UMASK = 0077; # gets you 'rwx------'
#$REPO_UMASK = 0027; # gets you 'rwxr-x---'
$REPO_UMASK = 0022; # gets you 'rwxr-xr-x'
接着通过下述命令修改 Gitolite 中所有现有仓库的权限:
$ sudo find /path/to/the/repository/ -type d -exec chmod og+rx {} \;
$ sudo find /path/to/the/repository/ -type f -exec chmod og+r {} \;
最后,为了让 cgit 能够自动访问到 Gitolite 中仓库信息,仍需修改配置文件 /etc/cgitrc:
$ sudo nano -w /etc/cgitrc
提供类似于 gitweb 中所需要的 projects.list 等信息,例如:
#
# information related to gitolite 
#

enable-git-config=1
enable-gitweb-owner=1
remove-suffix=1
project-list=/var/lib/gitolite/projects.list
scan-path=/var/lib/gitolite/repositories
请注意最后这 5 行,它们包含了与 Gitolite 整合所需要的所有内容。至于 Gitolite 中的修改,完全与 gitweb 所需的修改一致,这里就不再重复了。
 
如果还想为 cgit 锦上添花的话,可安装 highlight 实现 cgit 访问的 Git 仓库中源代码的高亮:
$ sudo yum install highlight

不过这还需要 cgit 的配置,也即

$ sudo nano -w /etc/cgitrc

增加或去掉下面这一行的注释

source-filter=/usr/lib/cgit/filters/syntax-highlighting.sh
Jul 30

Gitolite 是一款由 Perl 语言开发的 Git 服务管理工具,通过 SSH 公钥对用户进行认证,并能够通过配置文件对版本库的写操作进行基于分支、标签以及文件路径等的权限控制。 gitweb 为 Gitolite 提供了版本库的 Web 界面,方便用户浏览版本库的变更与版本打包;另一方面,由于 Gitolite 并没有提供匿名用户的读权限,因此,需要借助 git-daemon 来弥补这一缺陷。

1、Gitolite 的安装与配置

Gitolite 的安装非常简单,执行下述命令即可:
$ sudo yum install gitolite
查看 Gitolite 的用户信息
$ cat /etc/passwd | grep -i gitolite
gitolite:x:976:971:git repository hosting:/var/lib/gitolite:/bin/sh
这表明 Fedora 中 Gitolite 的家目录位于 /var/lib/gitolite。
 
下面开始初始化 Gitolite。由于 Gitolite 采用的是 SSH 协议,因此在初始化开始之前必须注入 Gitolite 管理者的 SSH 公匙。这里不去谈论 SSH 密匙的生成过程了,直接假定拥有 SSH 密匙的用户 James 将成为 Gotolite 的管理者:
$ cp ~/.ssh/id_rsa.pub /tmp/james.pub
请注意公匙的命名方法,这是 Gitolite 区别各个用户的默认办法。另外,可能出于安全的考虑,我们可能修改过 ~/.ssh 目录下文件的权限。由于下面的操作需要用户 James 的公匙具有写权限,所以需要执行下面的命令行
$ chmod a+r /tmp/james.pub
还有一件事情需要指出,既然 Gitolite 使用的是 SSH 协议,因此它工作的前提是运行 sshd 系统服务,请查看它是否运行
$ systemctl status sshd

如果没有运行的话,请执行下述命令行,至于 SSH 端口之类的问题就不做赘述了:

$ sudo systemctl start sshd
$ sudo systemctl enable sshd
现在可以初始化 Gitolite 了:
$ sudo -u gitolite -H gl-setup /tmp/james.pub
 
好了,下面该让我们稍微解释一下 Gitolite 对 Git 服务器的管理方式了。 Gitolite 通过导入用户的 SSH 公匙的方式来实现对 GIT 服务器的用户管理。Gitolite 利用配置文件 /var/lib/gitolite/repositoreis/gitolite-admin.git/config/gitolite.conf 实现了用户权限的控制。非常有意思的是,Gitolite 以 GIT 版本库的形式在管理 gitolite.conf 与所有用户的 SSH 公匙。具体来说,Gitolite 中预设了两个版本库,即 gitolite-admin.git 与 testing.git:
$ sudo ls /var/lib/gitolite/repositories
gitolite-admin.git  testing.git
可能我们已经注意到,版本库目录中的版本库名字均是以 .git 结尾的,这是 Gitolite 的约定。Gitolite 的管理者正是通过 gitolite-admin.git 来管理版本库的,他可以以版本控制的方式管理它。而 Gitolie 会自动根据该版本库中的修改来产生新的配置。好了,让我们的管理者把 gitolite-admin.git 克隆到他的家目录中去吧:
$ cd
$ git clone gitolite@serverIP:gitolite-admin.git
$ cd gitolite-admin
$ cat conf/gitolite.conf
repo    gitolite-admin
        RW+     =   james

repo    testing
        RW+     =   @all
我们很容易看到 gitolite.conf 中奇特的语法。每一个版本库的授权均以 repo 指令开头。repo 后面紧跟的是版本库列表。版本库列表中的版本库名之间用空格分开,版本库名中可以含有相对路径名。根据 Gitolite 的默认规则,repo 后面的版本库名不需要以 .git 为后缀,因为 Gitolite 会自动添加该后缀名。另外,版本库列表里面还可以包括版本库组。版本库组就是一些以空格间隔的版本库名的合集,版本库组名以@开头,例如
@testings testing james/testing
repo @testings
repo 指令也可以紧跟以正则表达式定义的通配符版本库。需要注意通配符版本库在匹配时,会自动在通配符版本库的正则表达式前、后分别加上前缀 ^ 和后缀 $。例如
repo james/.+
要当心的是版本库名中的正则表达式过于简单,就可能引起歧义,让 Gitolite 以为它就是普通版本库名称。为了不必要的麻烦,可在正则表达式的前或后主动加上 ^ 或 $ 符号,例如
repo james/.+$
 
repo 指令后续的几行就是版本库的授权命令列表。每条授权指令有相同的缩进,且以 = 为标记分为前后两段,等号前面的是权限表达式,等号后面的是用户列表。授权指令的语法类似于
perms [regex ...] = user1 [user2 ...]
正如我们所看到的,授权指令中包含一个可选的 regex 列表。regex 列表有正则表达式给出,它们与 repo 所指定的版本库里的分支、标签甚至是文件名或路径进行匹配。具体说来,正则表达式 regex 可能与分支名匹配,也可能与分支组匹配。分支组名以@开头,它是一些有空格间隔的分支名的合集,例如
@mainstream master developing testing
regex 也可能与 refs/tags/ 中的标签名匹配;regex 还可能与版本库中的文件名或文件路径匹配。如果 regex 中的表达式不以 $ 结尾的话,那么它将匹配以该正则表达式开头的任意字符,相当于在表达式后面添加 .*$。如果授权指令中不包含任何 regex 列表,那么该授权将针对由 repo 指定整个的版本库。
 
perms 部分只能出现如下授权之一:-、C、R、RW、RW+、RWC、RW+C、RWD、RW+D、RWCD、RW+CD。它们的具体含义如下:
  • -:不能写入、但是可以读取;
  • C:仅在通配符版本库中可以使用。用于指定谁可以创建和通配符匹配的版本库。
  • R, RW, 和 RW+:R 为只读。RW 为读写权限。RW+ 含义为除了具有读写外,还可以对 rewind 的提交强制 PUSH。
  • RWC, RW+C:只有当授权指令中定义了 regex 列表才可以使用该授权指令。其中 C 的含义是允许创建与 regex 匹配的分支、标签、文件名或者路径。
  • RWD, RW+D:只有当授权指令中定义了 regex 列表才可以使用该授权指令。其中 D 的含义是允许删除与 regex 匹配的分支、标签、文件名或者路径。
  • RWCD, RW+CD:只有当授权指令中定义了 regex 列表才可以使用该授权指令。
Gitolie 中的用户通常是以公匙文件名来指定的,这是 Gitolite 中的用户的表示方法之一。另一种 Gitolite 用户的表示方法就是用户组,用户组的命名以@开头,例如
@myteam james alice
定义了一个名为 @myteam 的用户组,james、alice 都是属于 myteam 这个用户组。Gitolite 中有个特殊的用户组,即@all,用来表示所有的用户。
 
下面给出一个权限控制的示例
@admin james
@myteam james alice
@test alice

@testings james/testing alice/testing

@mainstream master developing

repo    james/.+$
        C                           =   @admin
        R       @mainstream         =   @test
        -                           =   bob
        RW                          =   @myteam bob

repo    testing @testings
        RW+                         =   @admin
        RW      master              =   bob
        RW      developing$         =   alice
        -                           =   bob
        RW      tmp/                =   @all
        RW      refs/tags/v[0-9]    =   alice
这里有一点需要指出,那就是当同一个用户或者组有多个授权时,Gitolite 将采用所有授权的并集。
 
为了将上面的介绍与实际应用相结合,不妨考虑为 Gitolite 增加一个版本库 myproj、两个用户组 @admin 与 @myteam,以及用户 Alice 并授予她 myproj.git 的读写权限与用户 Bob 但只给予 myproj.git 的读权限。先让 Gitolite 的管理者 James 执行下述命令:
$ cd ~/gitolite-admin
$ cp /path/to/alice.pub keydir/
$ cp /path/to/bob.pub keydir/
$ nano -w conf/gitolite.conf
@admin james
@myteam james alice

repo    gitolite-admin
        RW+     =   @admin

repo    testing
        RW+     =   @all

repo    myproj
        RW+     =   @myteam
        RW+CD   =   @admin
        R       =   bob
$ git add conf/gitolite.conf keydir/alice.pub keydir/bob.pub
$ git commit -m 'new user and repo created.'
$ git push origin master
接着再让 James 在自己的主机家目录下创建新项目 myproj 并推至服务器:
$ mkdir -p ~/myproj
$ cd ~/myproj
$ git init
$ echo "hello, Gitolite!" >> hello.txt
$ git add hello.txt
$ git commit -m 'initial commit.'
$ git remote add origin gitolite@serverIP:myproj.git
$ git push origin master
现在试试让 Alice 在自己的主机上克隆并做一次提交
$ cd ~
$ git clone gitolite@serverIP:myproj.git
$ cd myproj
$ echo "hi, I'm Alice." >> hello.txt
$ git add hello.txt
$ git commit  -m 'say hello to Git Server."
$ git push origin master

再来让 Bob 试试 GIT 服务器的情况:

$ cd ~
$ git clone gitolite@serverIP:gitolite-admin.git

正常情况,Bob 无法克隆该仓库;

$ git clone gitolite@serverIP:testing.git
$ cd testing
$ echo 1 > index.txt
$ git add index.txt
$ git commit -m 'write permission for testing repo.'
$ git push origin master

这表明 Bob 拥有 testing.git 的读写权限;再来看

$ cd
$ git clone gitolite@serverIP:myproj.git
$ myproj
$ echo "hello, I'm Bob." >> hello.txt
$ git add hello.txt
$ git commit -m 'say hello to Gitolite.'
$ git push origin master

这表明 Bob 只能读取 myproj 但没有写权限。这几个操作表明 Gitolite 比较完美的控制了用户操作 GIT 服务器的权限。

2、与 gitweb 的整合
 
最初 gitweb 是为 GIT 服务器的 http 协议提供 Web 界面的。这里正是借助这个功能,为 Gitolite 实现同样的功能。同时,Gitolite 也为 gitweb 提供了两个便利:为 gitweb 提供了设置版本库的描述信息途径,可用于在 gitweb 的项目列表页面显示;为 gitweb 自动生成项目的列表文件,避免 gitweb 使用效率低的目录递归搜索查找 Git 版本库列表。
 
安装 gitweb 与 highlight:
$ sudo yum install highlight gitweb
其中 highlight 是为了在网页中查看代码的时候可以高亮代码的语法。查看 gitweb 的配置文件所在的位置:
$ rpm -qc gitweb
/etc/gitweb.conf
/etc/httpd/conf.d/git.conf
/etc/httpd/conf.d/git.conf 是与 Apache 相关的配置。gitweb 本身的配置文件是 /etc/gitweb.conf,下面开始配置 gitweb:
$ sudo nano -w /etc/gitweb.conf
根据需要调整里面的内容,下面这几行的内容必须调整
our $projectroot="/var/lib/gitolite/repositories";
our $projects_list="/var/lib/gitolite/projects.list";
至于语法高亮,自己看着办
# Add highlighting at the end 
$feature{'highlight'}{'default'}= [1];
 
为了能够让 Apache 访问到 Gitolite 目录中的文件,需要将 apache 加入到 gitolite 组中,并修改相关文件的权限
$ sudo usermod -a -G gitolite apache
$ sudo chmod g+r /var/lib/gitolite/projects.list
$ sudo chmod -R g+rx /var/lib/gitolite/repositories
由于 Gitolite 中默认新建文件的权限是 0077,这意味着要让 Apache 访问之后新建版本库,必须对之后新建版本库权限作类似的修改。为了免去这一麻烦,这里利用 Gitolite 的配置文件 ~/.gitolite.rc 来指定新建文件的权限:
$ sudo nano -w /var/lib/gitolite/.gitolite.rc
根据自己的需要修改下面的行
#$REPO_UMASK = 0077; # gets you 'rwx------'
#$REPO_UMASK = 0027; # gets you 'rwxr-x---'
$REPO_UMASK = 0022; # gets you 'rwxr-xr-x'
好了,一切就绪了,重启 Apache 服务:
$ sudo service httpd restart
 
以上配置基本都是在告诉 Apache 一些 GIT 服务器的信息。不过,为了让 gitweb 工作,还需要让 Gitolite 知道哪些仓库启用了 gitweb。这可以通过下面这个例子来了解这个机制,让管理者再次修改 Gitolite 的配置文件
$ cd
$ cd gitolite-admin
$ nano -w conf/gitolite.conf
repo    gitolite-admin
        RW+     =   james

repo    testing
        testing "James" =   "Git repository for testing"
        RW+     =   @all
        R       =   gitweb
$ git add conf/gitolite.conf
$ git commit -m 'gitweb support for Gitolite.'
$ git push origin master

很明显,'R = gitweb' 这一行告诉 Gitolite 版本库 testing.git 启用 gitweb,这样 Gitolite 就会把 testing.git 写入 projects.list 文件;而 'testing "James" = "git repository for testing"' 这一行则是为了在网页中显示 testing 仓库的额外信息,也即仓库的创建者以及仓库的概述。其他版本库启用 gitweb 的设置完全类同,这里就不一一修改了。实际上,版本库的信息的设定也通过如下的命令来完成:

repo    testing
        config gitweb.owner         =   some person's name
        config gitweb.description   =   some description
        config gitweb.category      =   some category 
 
是时候打开网页浏览器开始测试了,在地址栏中输入 http://serverIP/git,正常情况应该出现下图。
 
3、与 git-daemon  的整合
 
最后,让我们利用 git-daemon 为 Gitolite 开启匿名访问功能。首先安装它:
$ sudo yum install git-daemon
需要注意的是,由 Fedora 19 中 git-daemon 的 RPM 包存在问题,详见 https://bugzilla.redhat.com/show_bug.cgi?id=980574。因此,如果要在 Fedora 19 中启动 git-daemon 的服务以配合 Gitolite,那么需要作如下的修改:
$ mv /usr/lib/systemd/system/git.service /usr/lib/systemd/system/git@.service
随后将它按如下方式修改:
$ cat /usr/lib/systemd/system/git@.service
[Unit]
Description=Git Repositories Server Daemon
Documentation=man:git-daemon(1)
Wants=git.socket

[Service]
User=nobody
ExecStart=-/usr/libexec/git-core/git-daemon --base-path=/var/lib/gitolite/repositories --export-all --user-path=public_git --syslog --inetd --verbose
StandardInput=socket
由该段代码可以看到,Fedora 19 中 git-daemon 包并没有创建新的用户组,而是以 nobody 用户启动了系统服务。但是,Gitolite 的目录则是赋予了 gitolite 组:
$ ls -ald /var/lib/gitolite
drwxr-xr-- 5 gitolite gitolite 4096 Jul 29 22:31 /var/lib/gitolite
因此,为了让 git-daemon 能够访问 Gitolite 的家目录,需要将 nobody 加入 gitolite 组并赋予 Gitolite 家目录以可读权限
$ sudo usermod -a -G gitolite nobody
$ sudo chmod g+r -R /var/lib/gitolite/repositories
现在启动 git-daemon 服务并让它随机器启动:
$ sudo systemctl start git.socket
$ sudo systemctl enable git.socket
git-daemon 默认端口是 9418,查看该端口是否打开
$ netstat -nat | grep 9418
如果没有打开的话,请编辑 /etc/sysconfig/iptables:
$ nano -w /etc/sysconfig/iptables
在 Drop 与 Reject 规则之前,增加一行
-A INPUT -p tcp -m conntrack --ctstate NEW -m tcp --dport 9418 -j ACCEPT
重启防火墙:
$ sudo service iptables restart
至此,git-daemon 已经知道 Gitolite 的工作目录了。不过,Gitolite 中的版本库还需要为 git-daemon 自动生成 git-daemon-export-ok 文件, 这便是下面的设置,仍需管理者运行:
$ cd 
$ cd gitolite-admin
$ nano -w conf/gitolite.conf
repo    gitolite-admin
        RW+     =   james

repo    testing
        RW+     =   @all
        R       =   daemon
$ git add conf/gitolite.conf
$ git commit -m 'git daemon support for Gitolite.'
$ git push origin master

'R=daemon' 这一行就是告诉 Gitolite 为 git-daemon 生成 git-daemon-export-ok 文件。

好了,现在让我们做简单的测试:

$ git clone git://serverIP/testing.git
一切正常。

 

Jul 22

LAMP 服务器就绪之后,就可以开始考虑构建网站了,这是 LAMP 应用的一个方面;根据 LAMP 服务提供的 WEB 界面来管理 LAMP 主机则是应用的另一个方面。当然,有 Web 界面的管理工具很多,这类工具在远程主机的控制,特别是在 Headless 主机的控制上发挥着至关重要的作用。下面开始要介绍的是一些依赖与 LAMP 服务的管理工具。

二、与 LAMP 服务相关的管理工具

1、phpMyAdmin 的安装

phpMyAdmin 是 MariaDB 数据库的 Web 界面管理工具。通过它,就能远程管理 MariaDB 的数据库了。由于它已经在 Fedora 的 YUM 仓库之中,它的安装非常容易:

$ sudo yum install phpmyadmin
phpMyAdmin 的配置文件位于如下目录
$ rpm -qc phpMyAdmin
/etc/httpd/conf.d/phpMyAdmin.conf
/etc/phpMyAdmin/config.inc.php
与 Apache 的相关配置文件是 /etc/httpd/conf.d/phpMyAdmin.conf。
 
现在重启 Apache 服务
$ sudo service httpd restart
先作本地测试,这个很容易,通过浏览器访问 http://localhost/phpmyadmin  即可管理 MariaDB 数据库。
 
另一方面,phpMyAdmin 的默认设置是不允许远程主机访问的,为了让其他远程主机也能访问,作如下修改
$ sudo nano -w /etc/httpd/conf.d/phpMyAdmin.conf
Directory /usr/share/phpMyAdmin/>
   <IfModule mod_authz_core.c>
     # Apache 2.4
     <RequireAny>
       Require all granted
     </RequireAny>
   </IfModule>
   <IfModule !mod_authz_core.c>
     # Apache 2.2
     Order Deny,Allow
     Allow from all
   </IfModule>
</Directory>
再次重启 Apache 服务
$ sudo service httpd restart
任找一台能够访问的远程主机,通过在浏览器中输入 http://ipaddr/phpmyadmin 访问后台数据库并管理它。
 
2、Webalizer 
Webalizer 是一种网页日志分析工具,它用比较直观地图形表格来分析 Web 服务器的状态。官方网站地址是 http://www.mrunix.net/webalizer/。由于 Fedora 已经提供了 Webalizer 的 RPM 包,因此,只需执行
$ sudo yum install webalizer
即可完成安装。与 phpMyAdmin 类似,Webalizer 默认不能远程访问,作如下修改
$ sudo nano -w /etc/httpd/conf.d/webalizer.conf
Alias /usage /var/www/usage
<Location /usage>
   # Alternative e.g. "Require ip 192.168.10"
   #Require local
   Require all granted
</Location>
为了修改能够即时生效,需重启 Apache 服务:
$ sudo service httpd restart
注意,此时 Webalizer 并没有工作,需执行
$ sudo webalizer
才行。Webalizer 的使用非常简单,只需在浏览器中输入 http://ipaddr/usage/
 
3、phpsysinfo 的安装
phpsysinfo 是一款简单的工具,它提供了 LAMP 主机的系统信息。它的项目主页在 http://phpsysinfo.sourceforge.net/。由于 Fedora 官方没有提供该 RPM 包,如有需要,可到按下述方法安装它:
$ sudo rpm -ivh http://fedorapeople.org/~easior/fedora/19/i386/doremi-release-19-1.noarch.rpm
$ sudo yum install phpsysinfo

为了让 Apache 服务能够即时认出 phpsysinfo,需重启 Apache 服务:

$ sudo service httpd restart
phpsysinfo 的用法很简单。只需要在网页浏览器中输入 http://ipaddr/phpsysinfo 即可。
 
4. Webmin 的安装
 
Webmin是目前功能最强大的基于Web的 Unix/Linux 系统管理工具。管理员通过浏览器访问Webmin的各种管理功能并完成相应的管理动作。Webmin 让您能够在远程使用支持 HTTPS (SSL 上的 HTTP)协议的 Web 浏览器通过 Web 界面管理您的主机。这在保证了安全性的前提下提供了简单深入的远程管理。它的项目主页在 http://www.webmin.com。由于 Fedora 官方没有提供 Webmin 的 RPM 包,为了方便用户使用它,Webmin 的官方提供了 YUM 源。因此,先做如下设置
$ su -c 'echo > /etc/yum.repos.d/webmin.repo << EOF
[Webmin]
name=Webmin Distribution Neutral
#baseurl=http://download.webmin.com/download/yum
mirrorlist=http://download.webmin.com/download/yum/mirrorlist
enabled=1
gpgcheck=1
gpgkey=http://www.webmin.com/jcameron-key.asc
EOF'
好了,可以直接安装 Webmin 了:
$ sudo yum install webmin
需要注意,由于 Webmin 启用 HTTPS 协议,因此它并没有共用 Apache 的服务端口,而是使用了10000端口,因此需要在防火墙中打开该端口:
$ sudo nano -w /etc/sysconfig/iptables
在里面增加一行
-A INPUT -p tcp -m tcp --dport 10000 -j ACCEPT
保存后,重启 iptables 服务
$ sudo service iptables restart
 
现在可以试试用 Webmin 管理 LAMP 服务器的主机了。打开浏览器,输入 https://ipaddr:10000,通常,Webmin 需要超级用户登录。登录之后,就会出现如下的界面。
 
Webmin 的功能相当强大,大多数操作只需要动动鼠标就能完成,这比 SSH 操作方便的多。而且 Webmin 也提供了 SSH 模块,利用 Web 浏览器同样能够执行 SSH 操作。
 
与 LAMP 相关的 Web 管理工具层出不穷,例如 Nagios、phpVirtualBox 等等。这些工具的介绍恐怕不是短时间之内所能穷尽的,有兴趣的话可自行查找相关资料。后面要介绍的是利用 LAMP 服务建立网站,主要侧重的是如何利用现成的建站软件构建网站。至于利用 LAMP 开发网站,那恐怕是 Web 程序员的事情了。

 

Jul 22

虽然 Fedora 作为服务器来用不是上佳的选择,不过拿来练手倒是上上之选。因为 Fedora 中的大多数 Web 服务除去安全性等方面需要多加注意之外,基本上属于即装即用型的。Fedora 上的 Web 服务器的搭建也有很多选择,而且都是一些非常成熟的组合。反正不能免俗,不妨选择最常用的 LAMP 组合作为 Web 服务器的基础。不过话说回来,物换星移,Fedora 19 以 MariaDB 替换了 MySQL,也算是必然趋势。尽管如此,这些对于普通用户的影响并不大,mysqld 还是那个 mysqld。 作为普通用户,这里主要介绍的是与 LAMP 服务器相关的一些应用。至于 LAMP 服务本身相关的网站开发、优化等内容,暂时没有时间也没有能力触及了。

下面主要的测试环境是 Fedora 19。其他环境中 Web 服务器安装大同小异,很容易自行调整。当然,在开始之前最好关掉 SELinux,具体来说

$ sudo nano -w /etc/sysconfig/selinux
SELINUX=disable

修改完之后需重启机器才能有效。为了免去重启机器,可执行

$ sudo setenforce 0

即可即时生效。

一、LAMP 的安装与测试

1. Apache 服务器的安装

Apache 是世界上非常流行的 Web 服务器软件之一,类似的还有lighttpd、Nginx、Tomcat 等。不过,Apache 功能强大,一直深受建站爱好者的喜爱。它的安装非常容易:

$ sudo yum install httpd

Apache 的配置文件位于 /etc/httpd 目录,其中 /etc/httpd/conf/httpd.conf 是其默认配置文件,默认虚拟主机的目录位于 /var/www/html,与 Apache 相关的 Web 应用的配置目录可能位于 /etc/httpd/conf.d/。下面启动 Apache 服务并让它随机器一起启动:

$ sudo service httpd start
$ sudo chkconfig httpd on

为了看看 Apache 有没有正常工作,先做一下本地测试。打开本地的网页浏览器,在地址栏输入 http://localhost。正常情况应该出现如下的页面:

2. MariaDB 数据库的安装

Linux 中的 SQL 数据库很多,例如 MariaDB(MySQL)、PostgreSQL、SQLite、Firebird 等。不过这里就只安装 MariaDB:

$ sudo yum install mariadb mariadb-server

MariaBD 服务的开启方法与 MySQL 一样:

$ sudo service mysqld start
$ sudo chkconfig mysqld on

实际上,MariaDB 的用法也与 MySQL 别无二致。例如,MariaDB 数据的默认账户是 root,它与 Linux 系统的 root 账户没有什么联系。通常,MariaDB 的默认账户是没有密码的,这对于数据库的管理来说是不安全的。给它设置一个密码,例如toor:

$ sudo mysqladmin -u root password toor

现在尝试在本地登录 MariaDB 数据库:

$ sudo mysql -u root -p

数据库一切正常。

3. 网页开发语言 PHP 的安装

网页开发语言众多,例如PHP、JSP、ASP等。不过在 Linux 下面,PHP 整合的相对好一些:

$ sudo yum install php

测试一下 PHP 是否正常工作?首先,在本地的 /var/www/html 目录新建如下的文件:

$ su -c 'echo > /var/www/html/info.php << EOF

<?php
    phpinfo();
?>
EOF'

接着,在本地浏览器的地址栏中输入 http://localhost/info.php。如果出现如下的页面,就说明 PHP 工作正常!

4. 整合Apache与PHP
 
具体的整合可能涉及到很多优化方面的内容,这里只谈非常常见的几点。
$ sudo nano -w /etc/httpd/conf/httpd.conf
先在
AddType application/x-gzip .gz .tgz
所在行的下面添加
AddType application/x-httpd-php .php .phtml
AddType applicatoin/x-httpd-php-source .phps
接着再将
   DirectoryIndex index.html
改为
    DirectoryIndex index.html index.htm index.php
修改完成后保存退出。
 
为了提升 PHP 安全性,可在 /etc/php.ini 中进行作如下设置
$ sudo nano -w /etc/php.ini
将下面这一行
disable_functions =
修改为:
disable_functions = phpinfo,passthru,exec,system,chroot,scandir,chgrp,chown,shell_exec,proc_open,proc_get_status,ini_alter,ini_alter,ini_restore,dl,pfsockopen,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server

5. 防火墙设置与 LAMP 的远程测试

Fedora 中默认防火墙的安全级别比较高,基本上关闭了所有的服务端口。为了让远程机器能够访问 LAMP 服务器,需要适当调整防火墙设置。Fedora 在程序菜单中提供了防火墙的图形界面工具,不过这里主要介绍防火墙的命令行设置方法。由于 iptables 的规则是有优先次序的,通常需要手动编辑 iptables 的配置文件 /etc/sysconfig/iptables。下面为了简单起见,直接清空防火墙的原先设置,完全重写了所有的 iptables 规则。因此,使用下面这些规则的时候要小心,例如与 SSH 相关的规则没有在里面。关于如何开启 SSH 端口,可自行查阅 iptables 规则的写法。

首先,停止所有的 iptables 服务:

$ sudo service iptables stop
清除所有的 iptables 规则表:
$ sudo iptables -F -t filter
$ sudo iptables -X
设定预设 iptables 规则:
$ sudo iptables -P INPUT DROP
$ sudo iptables -P OUTPUT ACCEPT
接受所有本地回环网络的数据:
$ sudo iptables -A INPUT -i lo -j ACCEPT
接受所有 Established 连接:
$ sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
设置 ICMP 服务(保证 
$ sudo iptables -A INPUT -p icmp -m limit --limit 1/s --limit-burst 10 -j ACCEPT
开启 Apache 服务的端口:
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
开启 MariaDB 服务的端口:
$ sudo iptables -A INPUT -p tcp --dport 3306 -j ACCEPT
最后,保存所有 iptables 的规则并再次启动 iptables 服务
$ sudo service iptables save
$ sudo service iptables start

为了确认本地端口已经正常开启,请执行以下命令

$ netstat -nat

检查相应服务的端口是否被监听。如果一切正常的话,可以开始在远端主机测试 LAMP 服务器了。假设 LAMP 主机的 IP 地址为 ipaddr。首先测试 Apache 服务,打开网页浏览器,在地址栏输入 http://ipaddr 或者 http://ipaddr/info.php。如果出现图或中的页面,就说明 Apache 工作正常;接着测试 MariaDB 服务,请安装 MariaDB 的客户端,然后登录 MariaDB 主机进行测试:

$ sudo yum install mariadb
$ mysql -h http://ipaddr -u root -p
至此,LAMP 服务器的安装配置已经完成,后面将接着介绍它的应用。
Jul 20
我们知道 Gnu PG 是非常重要的加密工具,它可以帮助我们加密数据或者对使用的文件、文本进行签名以确保数据的真实性。Gnu PG 被广泛的应用于电子邮件传递、软件包打包等过程中。下面我们就来谈谈 Gnu PG 在 GIT 中的使用。
 
1、标签、提交等的签名
通常提交源码时,我们直接采用
$ git commit -m 'something added.'
对于这种提交方式,我们无法确认是否本人做了这些修改。为了防止这种情况发生,我们可以尝试
$ git commit -S <gpg-key-id> -m 'something added.' 
其中 <gpg-key-id> 就是用户的Gnu PG 的密匙ID。该命令执行时会提示用户输入该 <gpg-key-id> 的口令,随后对这次提交做了 GPG 签名,如此一来便可确信是本人做了这次递交。类似地情况也可运用到标签上来,例如
$ git tag v1.0 -s -u <gpg-key-id> -m 'tagged with important information.'
如果觉得每次手动指定 Gnu PG 密匙 ID 比较麻烦,可以通过下述方式自动指定
$ git config --global user.signingkey <gpg-key-id>
 
2、push/pull的口令缓存
我们在将版本库的修改同步到远程版本库时,通常需要输入账户与口令。如果版本库中有多次提交需要同步,那么账户、口令就需要输入多次。早期 GIT 版本库同步时,由于没有提供密码的缓存机制,为了免去重复输入账户名与口令,通常直接将密码明文的保存在.git/config文件之中。例如,
$ git remote add origin https://<username>:<password>@github.com/someone/repo
其中 <username> 与 <password> 就是账户与密码。很明显,以明文方式存储隐私信息是非常不可取的。因此新版的 GIT 中提供了新的办法,大体来说有两种:一、利用 git-credential;二、利用 ~/.netrc 或者 ~/.authinfo 等文件实现自动读取隐私信息。
 
credential 机制有点类似于 Gnu PG 代理,它能够缓存用户的密码,例如
$ git config --global credential.helper 'cache --timeout=3600'
如此设置之后,当我们输入完账户密码之后,GIT 就会缓存密码1个小时。实际上,credential 的机制还有好几个,有兴趣的朋友请自行阅读文档
$ man git-credential
 
另一方面,GIT 利用 ~/.netrc 等文件存取账户名与密码的方式与 ftp 的工作方式类似。例如,
$ cat ~/.netrc
machine github.com
  multilinetoken <hashnumber>
  login <username> password <password>
随后,我们便可以执行
$ git push origin master
此时 GIT 会自动读取 ~/.netrc 中账户信息将本地版本库修改同步远程端 GIT 服务器。这样一来,隐私信息的安全完全有赖于 ~/.netrc 文件权限了,通常,会对该文件的权限作如下设置
$ chmod 600 ~/.netrc
 
不过即使是这样,我们可能还是觉得安全性不够。例如用户登录电脑后有事需要离开一段时间,但没有及时开启密码屏保,这就难保 ~/.netrc 的信息不被泄漏。下面就来谈谈进一步的保密措施,那就是用 Gnu PG 加密 ~/.netrc 文件
$ gpg -o ~/.netrc.gpg -er <gpg-key-id> ~/.netrc
随后再对 GIT 做如下配置
$ git config --global credential.helper 'netrc -f ~/.netrc.gpg -d'
为了让 GIT 支持如上的修改,还需要开启 git-credential-netrc。在 Fedora 19 中,该文件位于 /usr/share/doc/git-<version>/contrib/credential/netrc 目录之中。需要将它置于 /usr/libexec/git-core 目录之下,并增加可执行权限
$ sudo cp /usr/share/doc/git-<version>/contrib/credential/netrc/git-credential-netrc /usr/libexec/git-core
$ sudo chmod +x /usr/libexec/git-core/git-credential-netrc
当然,用户也可以试试我的 Fedora 源中重新打包的 GIT。好了,现在再试试远程版本库的同步吧。
 
用 Gnu PG 加密 ~/.netrc 有个问题需要指出,那就是原先 ~/.netrc 的功能并不能被完全拓展到 ~/.netrc.gpg。换而言之,当我们执行 ftp 命令时,~/.netrc.gpg 并不能被解析。因此,我们需要适当分离 ~/.netrc 中内容以确保各个程序能够合理的工作。
 
3、版本库中文件的自动加密/解密
 
通常版本库中不太可能有什么隐私信息,不过随着很多人将 Linux 配置文件制成 GIT 版本库,隐私问题也就随之而来了。有些配置文件,例如 SSH 的私匙文件,再如 Emacs 的 GNUS 与 ERC 等,它们的密码有一部分只能以明文的方式保存的。如果将它们的配置发布到公开的 GIT 版本库中显然不是很合适。那么有没有办法将这些隐私文件以加密的形式保存到远程版本库,但本地工作目录中则仍以解密形式存在呢?答案仍是使用 GPG,主要是利用 GIT 的 filter 机制来配合 GPG 的使用。具体来说是这样的:
$ git config --local filter."gpg".smudge 'gpg -d --batch --no-tty -r <gpg-key-id>'
$ git config --local filter."gpg".clean 'clean = gpg -ea -q --batch --no-tty -r <gpg-key-id>'
$ git config --local diff."gpg".textconv decrypt
接着将需要将解密的文件名列表加入.gitattributes或者.git/info/attributes,例如
/path/to/id_rsa filter=gpg diff=gpg
/path/to/gnus.el filter=gpg diff=gpg
现在你可以尝试将id_rsa、gnus.el加入版本库了,当它们被加入到版本库时,GIT会利用 clean 所指定的方式进行加密。而当它被检出时,GIT 会调用 smudge 进行解密。需要注意的是,整个过程需要预先运行 gpg-agent。
 
用 GIT 管理配置文件的过程中,可能还会碰到一个特殊的文件需要加密,那就是 GIT 本身的配置文件。这个需求仍然与登录密码相关,最直接的例子就是 Github 的 token。很明显,直接加密整个 ~/.gitconfig 文件并不是很好的选择。这里提供一种方法,可以将需要加密的那部分配置分离出来。具体来说就是在 GIT 的配置文件中增加include部分,例如
$ git config --global include.path '~/.gitrepo'
并在 ~/.gitrepo 中加入与隐私相关的部分:
$ nano -w ~/.gitrepo
[github]
      username = <username>
      token = <hashnumber>
至于如何将 ~/.gitconfig、~/.gitrepo 纳入我们的配置文件版本库,这里就不多说。最后就是加密~/.gitrepo文件,这个非常简单。例如,~/.gitrepo 在版本库中的名字gitrepo,下面只需要再在.gitattributes中增加一行
/path/to/gitrepo filter=gpg diff=gpg

 

以上就是关于 GPG 与 GIT 的一些应用,希望对大家有用。
Jun 13

有时使用某个应用程序的时候,你需要非常频繁地使用你的 Gnu PG 密钥,这就意味着你需要多次输入密匙解密口令。相当多的应用程序支持将口令(密码)缓存起来方便用户使用。但是出于安全的目的,却不能让缓存的口令(密码)在多个程序之间交叉使用。不过,Gnu PG 提供了很安全的密码缓存方式,也即 Gnu PG 的代理 gpg-agent。通过它,多个应用程序可以共用 Gnu PG 密匙的解密口令。如果你在使用某个应用程序的时候输入了密匙解密口令,其他应用程序可以在一段时间内不用再请求输入口令也能解密 Gnu PG 密钥。下面就来谈谈如何设置 Gnu PG 的代理。

尽管我们不谈论 Gnu PG 公匙、密匙的生成与使用过程,但是使用 Gnu PG,第一步当然是安装它:
$ sudo yum install gnupg
通常,Gnu PG 程序本身就有代理功能。不过在图形界面下,Gnu PG 的代理功能需要用 pinentry 来开启,所以需要先在 Linux 中安装 pinentry 程序。
$ sudo yum install pinentry-gtk 
现在创建 gpg-agent 的配置文件:
$ cat > ~/.gnupg/gpg-agent.conf << EOF 

# PIN entry Program
#pinentry-program /usr/bin/pinentry-curses
#pinentry-program /usr/bin/pinentry-qt4
#pinentry-program /usr/bin/pinentry-kwallet
pinentry-program /usr/bin/pinentry-gtk-2
# Keyboard control
no-grab
# Cache timeout: 3 hours
default-cache-ttl 10800
#default-cache-ttl-ssh 10800

EOF
这个配置指明了 pinentry 程序、口令缓存的超时时间等等。接着激活 Gnu PG 的代理能力,这只要使用下面这一行即可
$ echo "gpg-agent" >> ~/.gnupg/gpg.conf
这一行告诉 Gnu PG 在需要密码时使用 gpg-agent,但前提是需要 gpg-agent 事先已经工作。运行 gpg-agent 的方法很简单:
$ eval $(gpg-agent --daemon)
停止 gpg-agent 的方法是:
$ pkill -u "$USER" gpg-agent
 
为了让 gpg-agent 的使用更加方便,我们自然希望它能够随机器启动而自动工作,这可通过在 /etc/profile.d/ 中作如下的配置来实现
$ sudo cat > /etc/profile.d/gpg-agent.sh << EOF

#!/bin/sh

envfile="${HOME}/.gnupg/gpg-agent.env"
if test -f "$envfile" && kill -0 $(grep GPG_AGENT_INFO “$envfile" |cut -d: -f 2) 2>/dev/null; then
     eval "$(cat :$envfile")"
else
     eval "$(gpg-agent --daemon --write-env-file "$envfile")"
fi
export GPG_AGENT_INFO # the env file does not contain the export statement

EOF

$ sudo chmod 755 /etc/profile.d/gpg-agent.sh
以上的设置使得每位登录 Linux 的用户自动启用 gpg-agent。一般而言,一个会话只允许开启一个 gpg-agent 进程。关于这一点,我们可以从上面的配置中可以看到。如果我们只希望为某个用户启用 gpg-agent,可在 ~/.xprofile、~/.xsession 或者 ~/.xinitrc 中添加下面这一行,这取决于我们使用的图形界面的启动方式,例如:
$ echo 'eval "$(gpg-agent --daemon)"' >> ~/.xprofile
如果用户不使用图形界面的话,也可以将上面这一行写入 ~/.bash_profile。通过前面这些设置便能自动启动 gpg-agent 了。关于 gpg-agent 的更多设置,请自行参看 gpg-agent 的手册页
$ man gpg-agent
 
实际上,从手册页中可以看到,gpg-agent 还可以作为 ssh-agent,这只需要在命令行 gpg-agent 中增加 --enable-ssh-support 选项即可。下面给出一个自动作为 ssh-agent 与 gpg-agent 的配置:
$ cat >> ~/.bash_profile << EOF

#!/bin/sh

# Start the GnuPG agent and enable OpenSSH agent emulation
gnupginf="${HOME}/.gpg-agent-info"

if pgrep -u "${USER}" gpg-agent >/dev/null 2>&1; then
    eval `cat $gnupginf`
    eval `cut -d= -f1 $gnupginf | xargs echo export`
else
    eval `gpg-agent -s --enable-ssh-support --daemon`
fi 

EOF
 
值得指出的是,Gnome 桌面自身提供的 Gnome-keyring 也整合了 gpg-agent 功能,这取决于 Gnome-keyring 包编译过程有没有开启 gpg-agent 选项。如果我们想禁用 Gnome-keyring 的 gpg-agent 功能,除去修改源码的编译选项之外,还可作如下操作来实现
$ cp /etc/xdg/autostart/gnome-keyring-gpg.desktop ~/.config/autostart/gnome-keyring-gpg.desktop
$ echo "X-GNOME-Autostart-enabled=false" >> ~/.config/autostart/gnome-keyring-gpg.desktop
实际上,上面的操作与如下的半图形化操作相同:
$ gnome-session-properties
在随后出现的图形框中勾选掉 gnome-keyring-gpg 功能。如果只是想临时禁用 Gnome-keyring,可执行
$ sudo pkill gnome-keyring