首先准备基本软件:
perl:http://www.activestate.com/activeperl/downloads
本人使用的:ActivePerl-5.16.3.1603-MSWin32-x86-296746.msi
awstats:http://sourceforge.net/projects/awstats/
本人使用的:awstats-7.0.exe
cronolog:http://cronolog.org/download/index.html
本人使用的:cronolog-1.6.1-win32.zip
jawstats http://www.jawstats.com/downloadhttp://www.jawstats.com/add-ons
本人使用的:jawstats-0.7beta.zip+中文语言包http://www.jawstats.com/src/languagepack.zip
安装perl,awstats
复制 cronolog.exe 到 apache 的 bin 目录
修改apache配置文件,在httpd.conf末尾加上
Alias /awstatsclasses "D:/Program Files/AWStats/wwwroot/classes/"
Alias /awstatscss "D:/Program Files/AWStats/wwwroot/css/"
Alias /awstatsicons "D:/Program Files/AWStats/wwwroot/icon/"
ScriptAlias /awstats/ "D:/Program Files/AWStats/wwwroot/cgi-bin/"
后面路径为awstats的安装目录的对应路径根据自己目录进行配置
由于我的svn采用的ssl,所以修改ssl的配置文件\conf\extra\httpd-ssl.conf
在文件末尾改为:
CustomLog "|bin/cronolog.exe logs/svn_%y%m%d.log" "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{SVN-ACTION}e\"" env=SVN-ACTION
重启apache如果正常启动说明配置没有问题
然后配置awstats,找到\AWStats\wwwroot\cgi-bin
复制awstats.model.conf为awstats.svn.demo.com.conf
文件中有几个注意点:
LogFile="xx\svn_%YY%MM%DD.log" 路径为上面ssl里面配置的svnlog的绝对路径,svn_%YY%MM%DD.log文件名设置为这个
LogFormat = "%host %other %logname %time1 %methodurl %code %bytesd %refererquot %uaquot" 主要增加了%uaquot,虽然现在没用,作为稍后的扩展功能
SiteDomain="svn.demo.cn" 生成为文件名的一部分
HostAliases="demo.cn svn.demo.com 127.0.0.1 localhost" 主机的相关别名
DirData="D:/awstats_data" 生成的日志文件路径
主要就这几个重点
尝试用awstats生成统计日志
首先检查apachelogs下是否生成了svn_%y%m%d.log,如果没有生成,访问以下svn触发一下
然后:cmd到perl的bin目录,然后perl "D:\Program Files\AWStats\wwwroot\cgi-bin\awstats.pl" -update -config=svn.demo.com
如果正常生成会出现下面这样类似的样子
如果不正常,根据提示进行调整。
下面开始配置jawstats
解压jawstats-0.7beta.zip到apache的root下改名为jawstats,然后将语言包覆盖到languages下
然后复制config.dist.php为config.php
$sDefaultLanguage = "zh-cn"; //改为中文
$sConfigDefaultView = "thismonth.all";
$bConfigChangeSites = true;
$bConfigUpdateSites = true;
$sUpdateSiteFilename = "xml_update.php";
// individual site configuration
$aConfig["svn.demo.com"] = array( //域名很关键用于查找日志文件,要与DirData中生成文件的域名一致
"statspath" => "D:/awstats_data/", //日志文件夹
"statsname" => "svn[MM][YYYY].txt", //不加域名,与日志文件一致
"updatepath" => "D:/Program Files/AWStats/wwwroot/cgi-bin/awstats.pl", //awstats.pl 完整路径
"siteurl" => "http:/svn.demo.com",
"sitename" => "svn",
"theme" => "default",
"fadespeed" => 250,
"password" => "demo", //更新密码
"includes" => "",
"language" => "zh-cn" //改为中文
);
Linux 系统初始化NOR FLash芯片及驱动 韩大卫@吉林师范大学 本文旨在解析linux系统下, Nor Flash芯片的初始化大致过程, 和cfi标准类型的Flash芯片在linux系统中的底层驱动何如实现, 如何找到并调用其提供的write/read/ioctl实现函数. 在明确了上述关系后, 可用通过一个用户层的程序, 向Nor Flash芯片指定分区位置写入指定程序, 比如写入linux elf文件, 实现更新系统内核, 写入uboot, 更新引导程序, 写入 “hello ,world!”, 使得系统崩溃掉(这样做的后果是需要将Nor Flash芯片从目标板中取下来, 用烧录器烧入正确的文件后再焊到板子上). 关于linux如何在Nor FLash上建立分区, 请参考博文 <<linux下建立NOR Flash分区>> 内核启动时, 在arch具体CPU子目录下, 如 mips/cavium-octeon, nor flashd 的初始化过程如下: 在arch/mips/cavium-octeon/flash_setup.c late_initcall(flash_init); static struct map_info flash_map; static int __init flash_init(void) { union cvmx_mio_boot_reg_cfgx region_cfg; region_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(0)); if (region_cfg.s.en) { /* 初始化一个全局数据结构 flash_map, 定义其名为”octeon_nor0” */ flash_map.name = "octeon_nor0"; flash_map.phys = region_cfg.s.base << 16; flash_map.size = 0x1fc00000 - flash_map.phys; flash_map.bankwidth = 1; flash_map.virt = ioremap(flash_map.phys, flash_map.size); pr_notice("Bootbus flash: Setting flash for %luMB flash at " "0x%08llx\n", flash_map.size >> 20, flash_map.phys); simple_map_init(&flash_map); //调用名为cfi_probe 的驱动, 说明该CPU支持CFI标准的flash操作 mymtd = do_map_probe("cfi_probe", &flash_map); if (mymtd) { mymtd->owner = THIS_MODULE; #ifdef CONFIG_MTD_PARTITIONS nr_parts = parse_mtd_partitions(mymtd, part_probe_types, &parts, 0); if (nr_parts > 0) add_mtd_partitions(mymtd, parts, nr_parts); else add_mtd_device(mymtd); #else add_mtd_device(mymtd); #endif } else { pr_err("Failed to register MTD device for flash\n"); } } return 0; } late_initcall(flash_init); do_map_probe() 会找到并调用指定name的probe函数,定义在drivers/mtd/chips/chipreg.c 中, struct mtd_info *do_map_probe(const char *name, struct map_info *map) { struct mtd_chip_driver *drv; struct mtd_info *ret; //获取指定name的驱动 drv = get_mtd_chip_driver(name); if (!drv && !request_module("%s", name)) drv = get_mtd_chip_driver(name); if (!drv) return NULL; //成功获取指定的驱动器后, 调用其probe()函数, 实现对芯片的探测 ret = drv->probe(map); module_put(drv->module); if (ret) return ret; return NULL; } get_mtd_chip_driver()定义: static struct mtd_chip_driver *get_mtd_chip_driver (const char *name) { struct list_head *pos; struct mtd_chip_driver *ret = NULL, *this; spin_lock(&chip_drvs_lock); //遍历MTD芯片驱动器链表chip_drvs_list list_for_each(pos, &chip_drvs_list) { this = list_entry(pos, typeof(*this), list); //当当前节点name等于指定name时, 返回链表中节点指针, 退出遍历 if (!strcmp(this->name, name)) { ret = this; break; } } if (ret && !try_module_get(ret->module)) ret = NULL; spin_unlock(&chip_drvs_lock); return ret; } 总的来说, get_mtd_chip_driver(name)函数作用是遍历所有MTD芯片的驱动链表-chip_drvs_list, 并返回驱动名为name的驱动器. 在获取了驱动后, 开始调用该驱动的probe()函数, 实现探测功能. 在drivers/mtd/chips/cfi_probe.c 中, 实现了cfi标准的驱动, module_init(cfi_probe_init); late_initcall(flash_init)是在module_init(cfi_probe_init)执行之后才执行的, (注: late_initcall()优先级为7, module_init()优先级为6, 数值越低优先级越高) 这样确保了当cfi_probe驱动器添加到chip_drvs_list后, flash init才在chip_drvs_list中寻找cfi_probe的驱动, 进而调用cfi_probe驱动器的probe()函数. static int __init cfi_probe_init(void) { //将名为”cfi_probe”的驱动器添加到芯片驱动链表中 register_mtd_chip_driver(&cfi_chipdrv); return 0; } register_mtd_chip_driver()定义在drivers/mtd/chips/chipreg.c void register_mtd_chip_driver(struct mtd_chip_driver *drv) { spin_lock(&chip_drvs_lock); //向MTD芯片驱动链表chip_drvs_list中添加自己的驱动 list_add(&drv->list, &chip_drvs_list); spin_unlock(&chip_drvs_lock); } cfi_chipdrv 定义为: static struct mtd_chip_driver cfi_chipdrv = { .probe = cfi_probe, .name = "cfi_probe", .module = THIS_MODULE }; struct mtd_info *cfi_probe(struct map_info *map) { //使用gen_probe.c中的函数, cfi_chip_probe数据结构实现探测 return mtd_do_chip_probe(map, &cfi_chip_probe); } 在此看到, 在上面flash_init()中, do_map_probe()在获取了cfi_probe()的驱动后, 调用的探测函数 ret = drv->probe(map) 实际上是间接使用了mtd_do_chip_probe(), 并传入了自定义的数据结构: cfi_chip_probe cfi_chip_probe 定义为: static struct chip_probe cfi_chip_probe = { .name = "CFI", .probe_chip = cfi_probe_chip }; mtd_do_chip_probe()函数定义在 drivers/mtd/chips/gen_probe.c 中: struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp) { struct mtd_info *mtd = NULL; struct cfi_private *cfi; cfi = genprobe_ident_chips(map, cp); if (!cfi) return NULL; map->fldrv_priv = cfi; /* OK we liked it. Now find a driver for the command set it talks */ mtd = check_cmd_set(map, 1); /* First the primary cmdset */ if (!mtd) mtd = check_cmd_set(map, 0); /* Then the secondary */ if (mtd) { if (mtd->size > map->size) { printk(KERN_WARNING "Reducing visibility of %ldKiB chip to %ldKiB\n", (unsigned long)mtd->size >> 10, (unsigned long)map->size >> 10); mtd->size = map->size; } return mtd; } printk(KERN_WARNING"gen_probe: No supported Vendor Command Set found\n"); kfree(cfi->cfiq); kfree(cfi); map->fldrv_priv = NULL; return NULL; } EXPORT_SYMBOL(mtd_do_chip_probe); genprobe_ident_chips()函数定义如下: static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp) { struct cfi_private cfi; struct cfi_private *retcfi; unsigned long *chip_map; int i, j, mapsize; int max_chips; memset(&cfi, 0, sizeof(cfi)); /* 在genprobe_new_chip()中调用了cfi_chip_probe数据结构内的函数:cp->probe_chip(map, 0, NULL, cfi)), 得到返回值0 ,则直接退出, 并返回NULL. */ if (!genprobe_new_chip(map, cp, &cfi)) { return NULL; } … } 在drivers/mtd/chips/cfi_probe.c 中: static int __xipram cfi_probe_chip(struct map_info *map, __u32 base, unsigned long *chip_map, struct cfi_private *cfi) { int i; if ((base + 0) >= map->size) { printk(KERN_NOTICE "Probe at base[0x00](0x%08lx) past the end of the map(0x%08lx)\n", (unsigned long)base, map->size -1); return 0; } if ((base + 0xff) >= map->size) { printk(KERN_NOTICE "Probe at base[0x55](0x%08lx) past the end of the map(0x%08lx)\n", (unsigned long)base + 0x55, map->size -1); return 0; } xip_disable(); if (!cfi_qry_mode_on(base, map, cfi)) { xip_enable(base, map, cfi); return 0; } /* 由于在mtd_do_chip_probe()没有执行到genprobe_ident_chips()的cfi.numchips = 1, 故在此进入if,并执行return语句.后面代码可以忽略.