├── Archive ├── PHP学习书单整理.md ├── PHP的生命周期.md └── 资料合集.md ├── Backup ├── Cheat Sheets Collection │ ├── Apache’s mod_rewrite.png │ ├── CakePHP-1.2-Cheatsheet.pdf │ ├── HTML Character Entities.png │ ├── HTML.png │ ├── Laravel4-cheat-sheet-A4-webpreview.jpg │ ├── Linux Command Line Cheat Sheet.pdf │ ├── RGB Hex Color Codes.png │ ├── SEO_Web_Developer_Cheat_Sheet.pdf │ ├── asp-cheat-sheet-v1.pdf │ ├── css cheat sheet.png │ ├── eclipse shortcut.jpg │ ├── html5 cheat sheet.jpg │ ├── javascript-cheat-sheet.png │ ├── jquery 1.3 Cheat sheet.png │ ├── linux_command_shelf_pdf_ver1_1.pdf │ ├── mysql-cheat-sheet.png │ ├── php-cheat-sheet.png │ ├── regular expressions cheat sheet.png │ ├── ruby-on-rails-cheat-sheet-v1.pdf │ ├── subversion-cheat-sheet-v1.png │ ├── vim_cheat_sheet_for_programmers_bnw.png │ ├── vim_cheat_sheet_for_programmers_screen.png │ └── world-of-warcraft-cheat-sheet-v1.pdf ├── PHP │ ├── Wordpress.md │ ├── symfony │ │ └── create-your-own-framework-on-top-of-the-symfony2-components │ │ │ ├── 1.md │ │ │ ├── 10.md │ │ │ ├── 11.md │ │ │ ├── 12.md │ │ │ ├── 2.md │ │ │ ├── 3.md │ │ │ ├── 4.md │ │ │ ├── 5.md │ │ │ ├── 6.md │ │ │ ├── 7.md │ │ │ ├── 8.md │ │ │ └── 9.md │ └── 常见开源消息系统.md └── linux │ ├── AWK编程基础.pdf │ ├── Linux_C_HS.chm │ ├── Linux命令图解.pdf │ ├── Linux学习笔记.pdf │ ├── Mac_OSX_shortcuts_CN.pdf │ ├── README.md │ ├── Rsync命令参数详解.doc │ ├── Sed命令学习笔记.pdf │ ├── awk使用手册.pdf │ ├── awk学习思维导图.jpg │ ├── centos │ ├── CentOS系统管理 │ │ ├── Linux 字符界面操作基础 │ │ │ ├── Shell 和命令操作基础.pdf │ │ │ ├── 信息显示命令.pdf │ │ │ ├── 基本网络操作命令.pdf │ │ │ ├── 字符操作界面简介.pdf │ │ │ ├── 文件与目录操作命令.pdf │ │ │ ├── 文件概述.pdf │ │ │ └── 文本处理命令.pdf │ │ ├── Linux 字符界面操作进阶 │ │ │ ├── Shell 变量和 Shell 环境.pdf │ │ │ ├── find.pdf │ │ │ ├── sed 和 awk.pdf │ │ │ ├── 提高工作效率.pdf │ │ │ ├── 文件权限及设置命令.pdf │ │ │ ├── 文件编辑器 vi.pdf │ │ │ ├── 正则表达式基础.pdf │ │ │ ├── 进程管理和作业控制.pdf │ │ │ └── 重定向和管道.pdf │ │ ├── Shell 脚本编程 │ │ │ ├── Shell 脚本示例分析.pdf │ │ │ ├── Shell 脚本简介.pdf │ │ │ ├── 使用特殊环境变量.pdf │ │ │ ├── 分支结构.pdf │ │ │ ├── 子程序结构.pdf │ │ │ ├── 循环结构.pdf │ │ │ ├── 条件测试.pdf │ │ │ └── 深入 Shell 变量操作.pdf │ │ ├── TCPIP 网络配置 │ │ │ ├── 网络测试方法和测试工具.pdf │ │ │ ├── 路由表和静态路由.pdf │ │ │ └── 配置基本网络参数.pdf │ │ ├── 包管理与系统更新 │ │ │ ├── 使用 RPM 管理包.pdf │ │ │ └── 使用 yum 工具更新系统.pdf │ │ ├── 备份与恢复 │ │ │ ├── Linux 下的光盘刻录.pdf │ │ │ ├── 使用 rsync 同步.pdf │ │ │ ├── 使用 rsync 服务.pdf │ │ │ ├── 使用 tar 备份.pdf │ │ │ └── 备份简介.pdf │ │ ├── 守护进程管理 │ │ │ ├── Xinetd 和 TCP Wrapper.pdf │ │ │ ├── 守护进程简介.pdf │ │ │ ├── 安全登录守护进程.pdf │ │ │ ├── 安排周期性任务.pdf │ │ │ ├── 日志系统和系统日志.pdf │ │ │ ├── 时钟同步守护进程.pdf │ │ │ └── 管理守护进程.pdf │ │ ├── 安装 CentOS │ │ │ ├── 安装 Linux 之前的必备知识.pdf │ │ │ ├── 安装后的基本配置.pdf │ │ │ └── 服务器方式安装 CentOS 5.pdf │ │ ├── 文件系统管理 │ │ │ ├── Linux 文件系统概述.pdf │ │ │ ├── ext2-ext3 文件系统管理.pdf │ │ │ ├── 挂装和卸装文件系统.pdf │ │ │ └── 磁盘限额.pdf │ │ ├── 磁盘管理和 LVM 管理 │ │ │ ├── LVM 简介.pdf │ │ │ ├── 创建 LVM 系统.pdf │ │ │ ├── 硬盘相关概念.pdf │ │ │ ├── 磁盘分区工具.pdf │ │ │ └── 维护 LVM 系统.pdf │ │ ├── 系统引导和启动 │ │ │ ├── 单用户模式和修复模式.pdf │ │ │ ├── 系统启动过程.pdf │ │ │ └── 系统引导器.pdf │ │ ├── 系统监控 │ │ │ ├── lsof 工具.pdf │ │ │ ├── psacct 工具.pdf │ │ │ ├── sysstat 工具.pdf │ │ │ └── 系统监视初步.pdf │ │ └── 账户管理 │ │ │ ├── 使用账户管理命令.pdf │ │ │ ├── 口令管理和口令时效.pdf │ │ │ ├── 用户切换和用户状态命令.pdf │ │ │ └── 账户管理概述.pdf │ └── 自定义光盘.md │ ├── linux-training.doc │ ├── linux命令手册.pdf │ ├── rsync安装与配置-完整版.doc │ ├── sed使用手册.pdf │ ├── sed学习思维导图.jpg │ ├── shell语法.txt │ ├── vi.md │ ├── 管理员必备的_linux_系统监控工具.md │ └── 高级bash脚本编程指南.pdf └── README.md /Archive/PHP学习书单整理.md: -------------------------------------------------------------------------------- 1 | # PHP 学习书单整理 2 | 3 | ## 技能类 4 | 5 | * 《Modern PHP》 : PHP 新特性及良好编程习惯; 6 | * 《深入 PHP 面向对象、模式与实践(第三版)》:深入理解 PHP 面向对象,有些章节可以跳过; 7 | * 《图解 HTTP》:HTTP 一定要清楚,这本书通俗易懂; 8 | 9 | ## 概念类 10 | * 《代码大全》:经典书,就是书名有点俗气; 11 | * 《松本行弘的程序世界》:虽然 ruby 创始人写的,但是快乐编程的思想还是值得推广的; 12 | * 《重来》:不多说了; 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Archive/PHP的生命周期.md: -------------------------------------------------------------------------------- 1 | # PHP的生命周期 2 | 3 | PHP 有两种运行模式,WEB 模式和 CLI(命令行)模式。当我们在终端敲入 PHP 这个命令的时候,使用的是 CLI 模式; 4 | 当使用 Nginx 或者别 Web 服务器作为宿主处理一个到来的请求时,会调用 PHP 运行,此时使用的是 WEB 模式。 5 | 6 | 当我们请求一个 PHP 文件时,PHP 为了完成这次请求,会发生5个阶段的生命周期切换: 7 | 8 | 1. 模块初始化(MINIT),即调用 php.ini 中指明的扩展的初始化函数进行初始化工作,如 `mysql` 扩展; 9 | 1. 请求初始化(RINIT),即初始化为执行本次脚本所需要的变量名称和变量值内容的符号表,如`$_SESSION`变量; 10 | 1. 执行该 PHP 脚本; 11 | 1. 请求处理完成(Request Shutdown),按顺序调用各个模块的 RSHUTDOWN 方法,对每个变量调用 unset 函数,如 `unset $_SESSION` 变量; 12 | 1. 关闭模块(Module Shutdown), PHP 调用每个扩展的 MSHUTDOWN 方法,这是各个模块最后一次释放内存的机会。这意味着没有下一个请求了; 13 | 14 | 15 | WEB 模式和 CLI(命令行)模式很相似,区别是:CLI 模式会在每次脚本执行经历完整的 5 个周期,因为你脚本执行完不会有下一个请求;而 WEB 模式为了应对并发,可能采用多线程,因此生命周期 1 和 5 有可能只执行一次,下次请求到来时重复 2 - 4 的生命周期,这样就节省了系统模块初始化所带来的开销。 16 | 17 | Via: http://blog.csdn.net/hguisu/article/details/7377520 -------------------------------------------------------------------------------- /Archive/资料合集.md: -------------------------------------------------------------------------------- 1 | # 资料合集 2 | 3 | 4 | ## 文档类 5 | * https://github.com/bayandin/awesome-awesomeness 6 | * https://github.com/avelino/awesome-go 7 | * https://github.com/markets/awesome-ruby 8 | * https://github.com/TIGERB/easy-tips 9 | * https://github.com/kamranahmedse/design-patterns-for-humans 10 | * https://github.com/dypsilon/frontend-dev-bookmarks 11 | * https://github.com/justjavac/free-programming-books-zh_CN 12 | * https://github.com/mmcgrana/gobyexample 13 | * https://github.com/MiYogurt/MSMindMap 14 | * https://github.com/phodal/booktree 15 | * https://github.com/reactnativecn/react-native-guide 16 | * https://github.com/happen-zhang/symfony2-jobeet-tutorial 17 | 18 | 19 | ## 源码类 20 | * https://github.com/shincoder/homestead-docker 21 | * https://github.com/gin-gonic/gin 22 | * https://github.com/jp7internet/rails-apz 23 | * https://github.com/jp7internet/laravel-apz 24 | * https://github.com/ruanyf/react-demos 25 | * https://github.com/voten-co/voten 26 | * https://github.com/codecasts/spa-starter-kit 27 | * https://github.com/TahaSh/spa-forum 28 | * https://github.com/coderzh/CodeTips 29 | * https://github.com/hoisie/web 30 | * https://github.com/bogiesoft/ticketx 31 | 32 | # 备份 33 | 34 | * https://github.com/pubyun/macdev 35 | * http://devtoolsecrets.com/ 36 | * http://jinlong.github.io/blog/2013/08/29/devtoolsecrets/ 37 | * 前端知识体系:http://knowledge.ecomfe.com/ 38 | * http://html5ify.com/fks/ 39 | * https://github.com/foru17/front-end-collect 40 | * http://usablica.github.io/front-end-frameworks/compare.html 41 | 42 | ## 入门 43 | 44 | * 学习CSS布局 http://zh.learnlayout.com/index.html 45 | * Markdown 语法简体中文版 https://github.com/riku/Markdown-Syntax-CN 46 | * 简单易懂的 OAuth 2.0 https://speakerdeck.com/chitsaou/jian-dan-yi-dong-de-oauth-2-dot-0 47 | * git 学习 http://try.github.io/ 48 | 49 | 50 | ## 推荐 51 | * http://i.linuxtoy.org/docs/guide/ 52 | * https://github.com/dypsilon/frontend-dev-bookmarks 53 | * https://github.com/saberma/ruby-dev-bookmarks 54 | * https://github.com/taobao/nginx-book 55 | * http://stackoverflow.com/questions/194812/list-of-freely-available-programming-books/ 56 | * https://github.com/wonderfo/wonderfogo/wiki 57 | * https://github.com/audreyr/favicon-cheat-sheet 58 | * https://github.com/DaRaFF/jsgamewiki 59 | * https://github.com/JuanitoFatas/Guides 60 | * https://github.com/astaxie/build-web-application-with-golang 61 | * http://github.ibireme.com/github/list/ios/ 62 | * https://github.com/vhf/free-programming-books/blob/master/free-programming-books.md 63 | * https://github.com/kirang89/pycrumbs/blob/master/pycrumbs.md 64 | * https://github.com/jmcunningham/AngularJS-Learning 65 | * http://www.mysqlplus.net/mysql-docs/ 66 | * https://github.com/justjavac/free-programming-books-zh_CN 67 | * http://resrc.io/list/10/list-of-free-programming-books/ 68 | * https://github.com/Thibaut/devdocs 69 | * https://github.com/freebook 、 http://netkiller.github.io/ 70 | * https://github.com/youyudehexie/node123 71 | * http://cpp1x.org/ 72 | * https://github.com/howiehu/vim_tutorials 73 | * https://github.com/zhangxinxu/zxx.lib.css 74 | * https://github.com/mrmrs/colors 75 | * https://github.com/daylerees/colour-schemes 76 | * https://github.com/chriskempson/base16 77 | * https://github.com/qyuhen/book 78 | * https://github.com/greatghoul/remote-working 79 | * https://github.com/avelino/awesome-go 80 | * https://git.oschina.net/itfanr/JavaDesignPattern 81 | * https://github.com/shockerli/Notes 82 | 83 | 84 | ## 导航 85 | * http://www.nav80.com/ 86 | * http://dh.kaifazhe.com/ 87 | * http://www.pm265.com/ 88 | 89 | -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/Apache’s mod_rewrite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/Apache’s mod_rewrite.png -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/CakePHP-1.2-Cheatsheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/CakePHP-1.2-Cheatsheet.pdf -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/HTML Character Entities.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/HTML Character Entities.png -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/HTML.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/HTML.png -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/Laravel4-cheat-sheet-A4-webpreview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/Laravel4-cheat-sheet-A4-webpreview.jpg -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/Linux Command Line Cheat Sheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/Linux Command Line Cheat Sheet.pdf -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/RGB Hex Color Codes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/RGB Hex Color Codes.png -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/SEO_Web_Developer_Cheat_Sheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/SEO_Web_Developer_Cheat_Sheet.pdf -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/asp-cheat-sheet-v1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/asp-cheat-sheet-v1.pdf -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/css cheat sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/css cheat sheet.png -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/eclipse shortcut.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/eclipse shortcut.jpg -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/html5 cheat sheet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/html5 cheat sheet.jpg -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/javascript-cheat-sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/javascript-cheat-sheet.png -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/jquery 1.3 Cheat sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/jquery 1.3 Cheat sheet.png -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/linux_command_shelf_pdf_ver1_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/linux_command_shelf_pdf_ver1_1.pdf -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/mysql-cheat-sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/mysql-cheat-sheet.png -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/php-cheat-sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/php-cheat-sheet.png -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/regular expressions cheat sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/regular expressions cheat sheet.png -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/ruby-on-rails-cheat-sheet-v1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/ruby-on-rails-cheat-sheet-v1.pdf -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/subversion-cheat-sheet-v1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/subversion-cheat-sheet-v1.png -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/vim_cheat_sheet_for_programmers_bnw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/vim_cheat_sheet_for_programmers_bnw.png -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/vim_cheat_sheet_for_programmers_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/vim_cheat_sheet_for_programmers_screen.png -------------------------------------------------------------------------------- /Backup/Cheat Sheets Collection/world-of-warcraft-cheat-sheet-v1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/Cheat Sheets Collection/world-of-warcraft-cheat-sheet-v1.pdf -------------------------------------------------------------------------------- /Backup/PHP/Wordpress.md: -------------------------------------------------------------------------------- 1 | # Wordpress笔记 2 | 3 | ## 工具 4 | * http://wpgear.org/ 5 | * http://pods.io/ 6 | 7 | ## 资料 8 | * http://wzbs.org/ 9 | * http://www.wptherightway.org/ 10 | 11 | ## Theme Framework 12 | * https://github.com/Automattic/_s 13 | * https://github.com/murtaugh/HTML5-Reset-WordPress-Theme 14 | * https://github.com/mattbanks/WordPress-Starter-Theme 15 | * https://github.com/retlehs/roots 16 | * https://github.com/viewportindustries/starkers 17 | * https://github.com/themeskult/wp-svbtle 18 | * https://github.com/somerandomdude/Frank 19 | * https://github.com/drewsymo/Foundation 20 | * https://github.com/320press/wordpress-bootstrap 21 | * https://github.com/leemason/NHP-Theme-Options-Framework 22 | * https://github.com/eddiemachado/bones 23 | * https://github.com/wycks/WP-Skeleton-Theme 24 | * https://github.com/320press/wordpress-foundation 25 | * http://www.gantry-framework.org/download#wordpress 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Backup/PHP/symfony/create-your-own-framework-on-top-of-the-symfony2-components/1.md: -------------------------------------------------------------------------------- 1 | sf2是一系列独立的,解耦的,可复用的,有粘着力的(cohesive)php组件库。可用来解决web开发中的常见问题。 2 | 3 | 您可以用完整的,使用这些组件的sf2框架来替代使用这些底层组件来做开发,亦或使用这些底层组件来创建你自己的框架。这篇文章,我们讨论的是后面一种目的。 4 | 5 | 6 | # 为什么要创建自己的框架? 7 | 8 | 首先为什么要创建自己的框架呢?如果你跟周围的人讨论,每个人都会告诉你重复发明轮子是一件糟糕的事情,你最好选择一个已有的框架,忘掉“创建自己的框架”这种想法。大部分情况,他们是正确的,但是我想到了几个创建自己的框架的好处: 9 | 10 | * 了解更多框架的底层架构,特别是像sf2那种完整框架的内部架构; 11 | * 创建一个能满足你特殊需求的框架(但首先要确定你的需求真的是很特别); 12 | * 因为乐趣而试着写一个框架(为了“学习然后抛弃”的目的); 13 | * 想利用新的开发技术以及最佳实践重构已经存在的项目; 14 | * 向世界证明自己也是可以写出框架的(……但只需那么一点点付出)。 15 | 16 | 我将一步步的,循序渐进的引导你创建一个框架。每一步你得到的都是一个完全能使用的框架。我们将从一个简单的框架开始,然后一点点的给它加功能。最后,你将能得到一个完整的web框架。 17 | 18 | 当然,每一步你都会学到一些新的sf2组件的用法。 19 | 20 | 如果你没有时间看完全文,或者你想快一点开始学习,你也可以看看[Silex](http://silex.sensiolabs.org/)库——一个使用sf2组件写的微框架,它的代码简单,而且也体现出sf2组件的许多用法。 21 | 22 | 许多现代框架都称呼自己为“MVC框架”。在这里我们不讨论MVC,因为sf2组件可以用来创建任何类型的框架,而不仅仅是MVC架构的框架。总之,如果你看过MVC的定义,这个系列只讨论如何创建控制器部分。对于数据模型部分以及视图部分,这得看你的个人爱好(意思是看你喜欢使用什么库或者什么方式来处理Model和View),对我而言,我会让你使用一些第三方的库文件(数据部分比如Doctrine,Propel或者直接使用PDO;视图部分比如Twig)。 23 | 24 | 当创建一个框架的时候,只是为遵循MVC模式并不是一个正确的目的。最主要的目的是要做到“分离关注点”(其实就是我经常说的框架的目的是为了分工,MVC就是一种分工的方式)。事实上这是我认为需要真正关心的,唯一的设计模式。sf2组件都是围绕实现http协议这个基本原则而创建的。同样,我们将要创建的框架应更准确的被描述为http框架或者说是“请求/响应框架”。 25 | 26 | # 开始之前的准备 27 | 28 | 只学习如何创建框架是不够的,你最好按照我们写的例子自己实际操作一下。所以你需要一个较新的php(因为sf2是基于php5.3的所以最起码php的版本不能低于php5.3.0,最好是php5.3.8及其以上),一个web服务器比如apache或者nginx,对php有较好的掌握,并且对面向对象有所了解。 29 | 30 | 准备好了吗?那我们就开始吧! 31 | 32 | # 引导程序(Bootstrapping) 33 | 34 | 在构思我们的框架之前,我们需要谈谈一些规定,比如我们在什么地方保存我们的代码,如何给类命名,如何引用对外部代码的依赖等等。 35 | 36 | 我们先建立一个目录来保存我们的代码: 37 | 38 | ``` 39 | $ mkdir framework 40 | $ cd framework 41 | ``` 42 | 43 | ### 代码规范 44 | 45 | 我们不讨论哪种代码规范更好,只要坚守同一种代码规范就行了,这个系列我们就使用Symfony2的[编码规范](http://symfony.com/doc/current/contributing/code/standards.html)。 46 | 47 | ### 安装组件 48 | 49 | 我们将使用[Composer](https://github.com/huanghua581/laravel/blob/master/composer/00-intro.md)来安装我们需要的sf2组件,它是一个用php做的项目依赖管理器(就有点像gentoo的emerge那种感觉)。首先,将你要使用的组件用composer.json文件列出来: 50 | 51 | ``` 52 | { 53 | "require": { 54 | "symfony/class-loader": "2.1.*" 55 | } 56 | } 57 | ``` 58 | 59 | 这里我们告诉Composer我们需要symfony的class-loader组件,版本为2.1.0及其以上。要安装组件,我们需要下载composer二进制文件并且运行它: 60 | 61 | ``` 62 | $ wget http://getcomposer.org/composer.phar 63 | $ # 或者 64 | $ curl -O http://getcomposer.org/composer.phar 65 | $ # 注:如果是windows,可先直接下载好再放进刚刚简历的目录 66 | $ # 如果用cygwin可以先安装links再使用links http://getcomposer.org/composer.phar下载 67 | 68 | $ php composer.phar install 69 | ``` 70 | 71 | 运行完install命令,你会看见目录下多了一个vendor目录,此目录包含了sf2的ClassLoader代码。 72 | 73 | *虽然我们强烈建议你使用Composer来安装组件,但是你也可以直接使用Git来下载组件压缩包。这都您说了算。* 74 | 75 | ### 命名规则和自动加载 76 | 77 | 我们将自动加载所有的类。如果不使用自动加载,你需要在使用某个类之前自己手工包含类定义文件。不过如果遵守了命名规则,我们可以让php来帮我们做这些痛苦的工作。 78 | 79 | sf2的类命名以及自动加载遵循de-facto标准,[PSR-0](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md)。sf2提供了实现PSR-0标准的组件自动加载器(ClassLoader),大多数情况sf2自动加载器将能为你载入一个项目的所有类。 80 | 81 | 在autoload.php中建立一个自动加载器: 82 | 83 | ``` 84 | register(); 94 | ``` 95 | 96 | 现在你可以在命令行下运行autoload.php,它应该什么都不会做,但也不会报错。 97 | 98 | ``` 99 | $ php autoload.php 100 | ``` 101 | 102 | *Sf官网有关于[自动载入器](http://symfony.com/doc/current/components/class_loader.html)的更多的文档* 103 | 104 | Composer也为安装过的依赖组件创建自动载入器,你可以直接使用载入vendor/.composer/autoloader.php来替代sf的autoloader。 105 | 106 | # 我们的项目 107 | 108 | 与其按自己想象瞎写一个框架,我们不如不断的改进我们的“应用程序”,每次改进都引入一个“概念”。让我们从最简单的一个程序开始: 109 | 110 | ``` 111 | handle($request)->send(); 51 | ``` 52 | 53 | 这便是我们要为我们的框架添加http缓存功能的所有代码,是不是很给力? 54 | 55 | 我们需要通过改变相应头来对缓存策略进行配置。比如要将一个页面缓存10秒,我们需要调用Response::setTtl方法: 56 | 57 | ``` 58 | // example.com/src/Calendar/Controller/LeapYearController.php 59 | 60 | public function indexAction(Request $request, $year) 61 | { 62 | $leapyear = new LeapYear(); 63 | if ($leapyear->isLeapYear($year)) { 64 | $response = new Response('Yep, this is a leap year!'); 65 | } else { 66 | $response = new Response('Nope, this is not a leap year.'); 67 | } 68 | 69 | $response->setTtl(10); 70 | 71 | return $response; 72 | } 73 | ``` 74 | 75 | *如果你跟我一样,喜欢在命令行下面模拟请求来调试代码,你可以轻而易举的使用echo $response;的方式将所有的响应头信息以及内容全部显示出来(如果入口文件是front.php,你可以现在此文件里用类似Request::create(‘/is_leap_year/2012′)的方式模拟一个请求,然后在框架handle了这个请求返回了响应对象之后,不要直接调用响应的send方法,而是直接echo出这个响应对象,你就可以通过命令行下执行php front.php来查看response的详细信息)。* 76 | 77 | 让我们写个随机数来验证我们的缓存功能是否好用: 78 | 79 | ``` 80 | $response = new Response('Yep, this is a leap year! '.rand()); 81 | ``` 82 | 83 | *在你部署代码到投产机的时候,记得使用Symfony的反相代理来提升性能,或者用更加专业的反相代理软件[Varnish](https://www.varnish-cache.org/)。* 84 | 85 | 利用http头信息来管理缓存很好很强大,它既可以使用过期策略,也可以使用验证策略来管理你的缓存。如果你对这些概念不熟悉话,最好先阅读一下Symfony2文档的[http缓存](http://symfony.com/doc/current/book/http_cache.html)部分。 86 | 87 | Response类包含了很多方法来让你方便管理http缓存,setCache方法便是其中最强大的方法之一,它可以通过一个数组来设定所有的缓存参数: 88 | 89 | ``` 90 | $date = date_create_from_format('Y-m-d H:i:s', '2005-10-15 10:00:00'); 91 | 92 | $response->setCache(array( 93 | 'public' => true, 94 | 'etag' => 'abcde', 95 | 'last_modified' => $date, 96 | 'max_age' => 10, 97 | 's_maxage' => 10, 98 | )); 99 | 100 | // it is equivalent to the following code 101 | $response->setPublic(); 102 | $response->setEtag('abcde'); 103 | $response->setLastModified($date); 104 | $response->setMaxAge(10); 105 | $response->setSharedMaxAge(10); 106 | ``` 107 | 108 | 在验证模式下,你可以通过isNotModified方法来判断是否可将响应缓存直接返回,从而节省响应时间。 109 | 110 | ``` 111 | $response->setETag('whatever_you_compute_as_an_etag'); 112 | 113 | if ($response->isNotModified($request)) { 114 | return $response; 115 | } 116 | $response->setContent('The computed content of the response'); 117 | 118 | return $response; 119 | ``` 120 | 121 | 虽然http缓存很给力,但万一你不能缓存整个页面而只是一部分怎么办?比如说页头用户信息?没事,[ESI](http://en.wikipedia.org/wiki/Edge_Side_Includes)(Edge Side Includes)来帮您!它可以用“子请求”的方式生成页面部分缓存,来代替整个页面的缓存。 122 | 123 | ``` 124 | This is the content of your page 125 | 126 | Is 2012 a leap year? 127 | 128 | Some other content 129 | ``` 130 | 131 | 你需要在HttpCache对象里传入ESI对象,来开启HttpCache类对ESI功能的支持,设置以后HttpCache便可以自动识别ESI标签并生成一个子请求。 132 | 133 | ``` 134 | use Symfony\Component\HttpKernel\HttpCache\ESI; 135 | 136 | $framework = new HttpCache($framework, new Store(__DIR__.'/../cache'), new ESI()); 137 | ``` 138 | 139 | *要让ESI正常工作,你需要一个支持ESI的反相代理,比如Symfony2的实现,或者使用Varnish* 140 | 141 | 如果设置了太多的缓存机制,或者太多的ESI标签,你可能非常难看得出那些应该缓存而那些不应该,这个时候你可以将debug设置打开进行调试: 142 | 143 | ``` 144 | $framework = new HttpCache($framework, new Store(__DIR__.'/../cache'), new ESI(), array('debug' => true)); 145 | ``` 146 | 147 | 调试器将会在头信息中加入X-Symfony-Cache信息来表述缓存层都做了些什么: 148 | 149 | ``` 150 | X-Symfony-Cache: GET /is_leap_year/2012: stale, invalid, store 151 | 152 | X-Symfony-Cache: GET /is_leap_year/2012: fresh 153 | ``` 154 | 155 | HttpCache实现了很多功能比如stale-while-revalidatestale-if-error等RFC 5861协议中定义的Http Cache-Control的扩展功能。 156 | 157 | 在一个简单的接口的帮助下,我们的框架可以享受HttpKernel组件的许多功能。Http缓存只是其中的一个重要部分,但已经能让你的框架运行如飞了! 158 | 159 | 英文原文地址:http://fabien.potencier.org/article/59/create-your-own-framework-on-top-of-the-symfony2-components-part-10 -------------------------------------------------------------------------------- /Backup/PHP/symfony/create-your-own-framework-on-top-of-the-symfony2-components/11.md: -------------------------------------------------------------------------------- 1 | 如果你正在使用我们的框架,你或许想让框架支持自定义错误页面。目前,我们可以处理404和500错误,不过此功能都是硬编码在框架里面的。但让错误信息变得可自定义也非常容易:分发一个新事件然后监听它。要做到这点也就意味着监听器(listener)需要调用一个控制器。 2 | 3 | 但要是控制器也发出一个错误怎么办,那不是会发生无限循环调用?应该有更方便的方法是吧。 4 | 5 | 6 | 下面看看HttpKernel类。HttpKernel类是对HttpKernelInterface接口的一个可被广泛使用的,灵活的,可扩展的实现。我们就是用它而不用反反复复的发明轮子。 7 | 8 | 这个类跟我们目前写的类非常的类似:它在一个请求进来的时候,在某些策略点(strategic point)分发事件,并使用控制器分析器来选择某一个控制器去处理请求。它会非常的细心处理各种问题,并且在有问题发生的时候,会有非常棒的回馈。 9 | 10 | 下面是我们的新框架代码: 11 | 12 | ``` 13 | addSubscriber(new HttpKernel\EventListener\RouterListener($matcher)); 50 | 51 | $framework = new Simplex\Framework($dispatcher, $resolver); 52 | 53 | $response = $framework->handle($request); 54 | $response->send(); 55 | ``` 56 | 57 | RouterListener是一个跟我们之前实现的一样逻辑的类:匹配请求的路由,并且根据路由参数为请求生成更多的属性。 58 | 59 | 现在我们的代码既精简,功能又强大,比以前更加的给力了。比如说现在可以利用ExceptionListener监听器来让你的错误处理变得能够配置。 60 | 61 | ``` 62 | $errorHandler = function (HttpKernel\Exception\FlattenException $exception) { 63 | $msg = 'Something went wrong! ('.$exception->getMessage().')'; 64 | 65 | return new Response($msg, $exception->getStatusCode()); 66 | }); 67 | $dispatcher->addSubscriber(new HttpKernel\EventListener\ExceptionListener($errorHandler)); 68 | ``` 69 | 70 | ExceptionListener使用FlattenException来代替抛出Exception,以此让你更加容易地操作和显示异常。它能使用任何有效的控制器作为异常的处理器,所以你可以建立一个错误控制器(ErrorController类)来代替闭包。 71 | 72 | ``` 73 | $listener = new HttpKernel\EventListener\ExceptionListener('Calendar\\Controller\\ErrorController::exceptionAction'); 74 | $dispatcher->addSubscriber($listener); 75 | ``` 76 | 77 | 错误控制器代码如下: 78 | 79 | ``` 80 | getMessage().')'; 94 | 95 | return new Response($msg, $exception->getStatusCode()); 96 | } 97 | } 98 | ``` 99 | 100 | 怎样?轻易得得到一个简洁而又可自定义的错误管理功能!当然,如果你的控制器抛出一个异常,HttpKernel会很好去处理它。 101 | 102 | 在第二章,我们曾经聊过Response::prepare()这个方法,此方法能保证响应是严格遵守http协议的,那如果能在响应发给客户端之前,都调用一次这个方法,那是一个非常好的主意。其实这便是ResponseListener所做的事情: 103 | 104 | ``` 105 | $dispatcher->addSubscriber(new HttpKernel\EventListener\ResponseListener('UTF-8')); 106 | ``` 107 | 108 | 是不是很方便呢?让我们在添加一个新功能,想让响应对象支持响应流(streamed response)功能吗?只用注册一个StreamedResponseListener就行了: 109 | 110 | ``` 111 | $dispatcher->addSubscriber(new HttpKernel\EventListener\StreamedResponseListener()); 112 | ``` 113 | 114 | 然后在你的控制器里返回一个StreamedResponse实例来替代以前的Response实例。 115 | 116 | *请阅读Symfony2组件的Internal这一章,了解更多利用HttpKernel做事件分发的知识点,以及他们是如何改变对请求的处理流程的。* 117 | 118 | 现在让我们在添加一个,可以允许控制器仅返回字符串而非必须返回一个完整的响应对象的监听器: 119 | 120 | ``` 121 | class LeapYearController 122 | { 123 | public function indexAction(Request $request, $year) 124 | { 125 | $leapyear = new LeapYear(); 126 | if ($leapyear->isLeapYear($year)) { 127 | return 'Yep, this is a leap year! '; 128 | } 129 | 130 | return 'Nope, this is not a leap year.'; 131 | } 132 | } 133 | ``` 134 | 135 | 为了实现此功能,我们需要监听内核里面的kernel.view事件,此事件会在控制器刚被调用结束后触发。它的作用是仅在需要的时候,将控制器返回的字符串转化成一个完全的响应对象: 136 | 137 | ``` 138 | getControllerResult(); 153 | 154 | if (is_string($response)) { 155 | $event->setResponse(new Response($response)); 156 | } 157 | } 158 | 159 | public static function getSubscribedEvents() 160 | { 161 | return array('kernel.view' => 'onView'); 162 | } 163 | } 164 | ``` 165 | 166 | 只有当控制器返回不是响应对象的时候,此事件才会被触发,另外如果在此事件上设置了响应对象,便停止了此事件的继续传播。 167 | 168 | 当然别忘记在前端控制器里面注册它。 169 | 170 | ``` 171 | $dispatcher->addSubscriber(new Simplex\StringResponseListener()); 172 | ``` 173 | 174 | *如果你忘记了注册,HttpKernel会抛出一个带有很好错误提示的异常:The controller must return a response (Nope, this is not a leap year. given)..* 175 | 176 | 至此,我们的框架代码是越来越紧凑,而且都是用现成的库组成的。扩展的本质其实就是事件监听+订阅事件。 177 | 178 | 但愿你现在能够理解为什么这看起来那么简单的HttpKernelInterface会这么的强大。它默认实现HttpKernel,能让你感受到很多的很酷的特性,而且能毫不费劲得使用它。又因为HttpKernel是Symfony2以及Silex框架的核心,所以你可以有两全其美的选择:在一个稳固的,持续维护的,并且在许多网站都已验证的地基架构上,做一个可定制的,满足你需求的框架,以及写出做过安全审计而又能很好扩展的代码。 179 | 180 | 英文原文地址:http://fabien.potencier.org/article/60/create-your-own-framework-on-top-of-the-symfony2-components-part-11 -------------------------------------------------------------------------------- /Backup/PHP/symfony/create-your-own-framework-on-top-of-the-symfony2-components/12.md: -------------------------------------------------------------------------------- 1 | 在前一篇教程的最后,我们扩展了Symfony的HttpKernel类,而将Simplex\Framework的代码清空了。让我们把前端控制器的一些代码挪过来: 2 | 3 | ``` 4 | addSubscriber(new HttpKernel\EventListener\RouterListener($matcher)); 24 | $dispatcher->addSubscriber(new HttpKernel\EventListener\ResponseListener('UTF-8')); 25 | 26 | parent::__construct($dispatcher, $resolver); 27 | } 28 | } 29 | ``` 30 | 31 | 这样前端控制器的代码看起来也更加精炼: 32 | 33 | ``` 34 | handle($request)->send(); 48 | ``` 49 | 50 | 如果您能写出一个更加精简的前端控制器,那也意味着你能让一个应用程序轻易拥有更多的前端控制器,不过多个前端控制器有啥好处呢?比如说,你可以让开发环境和投产环境(production,正式线上的环境)拥有不同的配置。在开发环境中,你得打开错误报告并把错误显示出来来方便调试: 51 | 52 | ``` 53 | ini_set('display_errors', 1); 54 | error_reporting(-1); 55 | ``` 56 | 57 | 但是你肯定不想让投产环境也这么设置。所以使用不同的前端控制器可以让你拥有不同的配置环境。 58 | 59 | 将前端控制器的代码移到框架类里面可以让框架更容易配置,但同时也产生了一下一些问题: 60 | 61 | * 因为分发器在框架外无法访问,所以我们无法添加自定义的监听器(一个简单的解决办法是添加一个Framework::getEventDispatcher()方法); 62 | * 我们也无法修改UrlMatcher以及ControllerResolver的实现方式了; 63 | * 我们也无法轻易地测试框架,因为我们无法模拟框架内部的对象; 64 | * 我们无法利用ResponseListener修改charset(一个简单的解决办法是让charset作为构造函数的一个参数)。 65 | 66 | 由于之前我们使用依赖注入,所以当时没有这些问题。所有的依赖对象都是通过参数传递的方式“注入”到构造体里的(举个栗子:事件分发器便是注入在框架对象里面的,所以我们能全面控制他的构造以及配置)。 67 | 68 | 这是否意味着我们将在灵活性,可定制性,易测试性,以及避免在不同的前端控制器里复制黏贴代码这些美好的事情里面做出艰难的决定?答案是否定的,我们还有终极解决方案。利用Symfony2的依赖注入容器(dependency injection container,其实叫做依赖注入服务管理器更贴切一点)即可解决这些问题。 69 | 70 | ``` 71 | { 72 | "require": { 73 | "symfony/class-loader": "2.1.*", 74 | "symfony/http-foundation": "2.1.*", 75 | "symfony/routing": "2.1.*", 76 | "symfony/http-kernel": "2.1.*", 77 | "symfony/event-dispatcher": "2.1.*", 78 | "symfony/dependency-injection": "2.1.*" 79 | }, 80 | "autoload": { 81 | "psr-0": { "Simplex": "src/", "Calendar": "src/" } 82 | } 83 | } 84 | ``` 85 | 86 | 建立一个新文件来描述容器的配置: 87 | 88 | ``` 89 | register('context', 'Symfony\Component\Routing\RequestContext'); 98 | $sc->register('matcher', 'Symfony\Component\Routing\Matcher\UrlMatcher') 99 | ->setArguments(array($routes, new Reference('context'))) 100 | ; 101 | $sc->register('resolver', 'Symfony\Component\HttpKernel\Controller\ControllerResolver'); 102 | 103 | $sc->register('listener.router', 'Symfony\Component\HttpKernel\EventListener\RouterListener') 104 | ->setArguments(array(new Reference('matcher'))) 105 | ; 106 | $sc->register('listener.response', 'Symfony\Component\HttpKernel\EventListener\ResponseListener') 107 | ->setArguments(array('UTF-8')) 108 | ; 109 | $sc->register('listener.exception', 'Symfony\Component\HttpKernel\EventListener\ExceptionListener') 110 | ->setArguments(array('Calendar\\Controller\\ErrorController::exceptionAction')) 111 | ; 112 | $sc->register('dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher') 113 | ->addMethodCall('addSubscriber', array(new Reference('listener.router'))) 114 | ->addMethodCall('addSubscriber', array(new Reference('listener.response'))) 115 | ->addMethodCall('addSubscriber', array(new Reference('listener.exception'))) 116 | ; 117 | $sc->register('framework', 'Simplex\Framework') 118 | ->setArguments(array(new Reference('dispatcher'), new Reference('resolver'))) 119 | ; 120 | 121 | return $sc; 122 | ``` 123 | 124 | 此文件的目的就是描述你需要的对象以及它们依赖的对象。在配置阶段是不会有任何对象被创建的。此文件是一个纯粹的,仅仅对如何创建以及操作对象做静态描述的文件。对象将在您或者容器需要创建它的时候才会被生成。 125 | 126 | 举个栗子,要创建路由监听器,我们只需要告诉Symfony他的类名是Symfony\Component\HttpKernel\EventListener\RouterListeners,以及他需要一个Matcher作为他的依赖组建(new Reference(‘matcher’))。如你所见,每一个对象都被一个唯一的名字表示,此名字让我们能获取相应的对象以及被其他对象所引用。 127 | 128 | *默认情况下,每当你从容器里获取对象的时候,容器都将返回同一个实例。所以利用容器可以用来管理你的“全局”对象。* 129 | 130 | 现在前端控制器只用将一切黏在一块儿: 131 | 132 | ``` 133 | get('framework')->handle($request); 147 | 148 | $response->send(); 149 | ``` 150 | 151 | 因为目前所有的对象都由依赖注入容器来生成了,所以框架代码又回到了之前那最简洁的版本: 152 | 153 | ``` 154 | register('listener.string_response', 'Simplex\StringResponseListener'); 173 | $sc->getDefinition('dispatcher') 174 | ->addMethodCall('addSubscriber', array(new Reference('listener.string_response'))) 175 | ; 176 | ``` 177 | 178 | 除了描述对象,依赖注入容器也可以通过参数来做配置。我们定义一个是否在debug模式的参数: 179 | 180 | ``` 181 | $sc->setParameter('debug', true); 182 | 183 | echo $sc->getParameter('debug'); 184 | ``` 185 | 186 | 所有参数将在定义对象的时候用到。我们可以让charset也能配置: 187 | 188 | ``` 189 | $sc->register('listener.response', 'Symfony\Component\HttpKernel\EventListener\ResponseListener') 190 | ->setArguments(array('%charset%')) 191 | ; 192 | ``` 193 | 194 | 之后,你需要在使用响应监听器之前指定好charset: 195 | 196 | ``` 197 | $sc->setParameter('charset', 'UTF-8'); 198 | ``` 199 | 200 | 参数也可以用在指定路由配置上: 201 | 202 | ``` 203 | $sc->register('matcher', 'Symfony\Component\Routing\Matcher\UrlMatcher') 204 | ->setArguments(array('%routes%', new Reference('context'))) 205 | ; 206 | ``` 207 | 208 | 相应地在前端控制器中添加: 209 | 210 | ``` 211 | $sc->setParameter('routes', include __DIR__.'/../src/app.php'); 212 | ``` 213 | 214 | 相对于整个依赖注入容器的功能来说以上的介绍还只是冰山一角,除了上面说的那些功能,还能覆写已存在的对象定义,甚至将定义转存为php类等等。Symfony的依赖注入容器很好很强大,可以用来管理任意类型的php类。 215 | 216 | 如果你不想在你的框架中使用依赖注入容器,请别冲着哥斯巴达,别用就是了。这是您的框架,不是我的。 217 | 218 | 这文章是此系列的最后一篇了,虽然还有好多好多功能还没有提到,但也希望各位看官能从这些文章学到新姿势,并且开始自己再深入研究Symfony2框架是如何工作的。 219 | 220 | 如果你想了解更多,我强烈建议你读一读Silex微框架的代码,特别是[Application](https://github.com/fabpot/Silex/blob/master/src/Silex/Application.php)类 221 | 222 | 祝大家学得开心,玩得开心,写得开心! 223 | 224 | ~~ 全剧终 ~~ 225 | 226 | 英文原文地址:http://fabien.potencier.org/article/62/create-your-own-framework-on-top-of-the-symfony2-components-part-12 -------------------------------------------------------------------------------- /Backup/PHP/symfony/create-your-own-framework-on-top-of-the-symfony2-components/2.md: -------------------------------------------------------------------------------- 1 | 在开始重构我们的代码之前,我打算先再谈谈为什么您最好使用一个框架来替代用php直接书写这种方式来创建一个应用程序。即使写一个很小的代码片段,使用框架也是一个好主意,而使用sf2组件库来创建一个框架比直接写一个框架更好。 2 | 3 | *这里我不会讨论在有多个开发者共同开发的大项目中,那些经典的或者明显的使用框架的好处。网上已经有很多关于这个话题的资源信息。* 4 | 5 | 即使昨天我们写的“应用程序”非常的简单,但也会遇到很多问题: 6 | 7 | ``` 8 | assertEquals('Hello Fabien', $content); 63 | } 64 | } 65 | ``` 66 | 67 | 如果我们的项目再大一些,我们还会发现更多的问题。如果你非常想知道还有哪些问题,请阅读sf2文档的[《sf2 vs 纯php》](http://symfony.com/doc/current/book/from_flat_php_to_symfony2.html)部分。 68 | 69 | 从这几点来看,如果你还觉得安全性和可测性不是使用框架的好理由,你可以不用继续往下阅读了。 70 | 71 | *当然,使用框架给你带来的不只是安全性和可测试性。请记住你选择的框架必须能够让你更快的写出更好的代码来.* 72 | 73 | # 使用 HttpFoundation 组件迈向面向对象之路 74 | 75 | 写web程序都是有关http交互的,所以我们写框架的基本原则都是围绕着[http协议](http://tools.ietf.org/wg/httpbis/)展开的。 76 | 77 | http协议描述了客户端(比如说浏览器)和服务器端(比如网络服务器)的交互方式。客户端和服务器端的对话是通过良好定义的“消息”——即请求和响应的传递来实现的。客户端向服务器发起一个请求,服务器根据这个请求再向客户端返回一个响应。 78 | 79 | 在php的世界里,请求由全局变量($_GET,$_POST,$_FILE等)来表示,响应又由一些函数来生成(echo,header,setcookie等)。 80 | 81 | 写出更好代码的第一步最好是使用面向对象来实现。这是sf2的HttpFoundation组件的主要目的:利用面向对象层来代替php默认使用的全局变量。 82 | 83 | 要使用此组件,打开composer.js然后修改代码为下面内容: 84 | 85 | ``` 86 | // framework/composer.json 87 | { 88 | "require": { 89 | "symfony/class-loader": "2.1.*", 90 | "symfony/http-foundation": "2.1.*" 91 | } 92 | } 93 | ``` 94 | 95 | 然后运行Composer的update命令: 96 | 97 | ``` 98 | $ php composer.phar update 99 | ``` 100 | 101 | 最后,在autoloader.php文件的最后添加以下代码,让HttpFoundation组件能自动加载: 102 | 103 | ``` 104 | registerNamespace('Symfony\\Component\\HttpFoundation', __DIR__.'/vendor/symfony/http-foundation'); 109 | ``` 110 | 111 | 现在,让我们用请求类(Request class)和响应类(Response class)来重写我们的程序: 112 | 113 | ``` 114 | get('name', 'World'); 126 | 127 | $response = new Response(sprintf('Hello %s', htmlspecialchars($input, ENT_QUOTES, 'UTF-8'))); 128 | 129 | $response->send(); 130 | ``` 131 | 132 | createFromGlobals方法会根据当前php的全局变量生成一个Request对象。 133 | 134 | send方法返回Response对象里的内容到客户端(他会先根据内容发送http头信息)。 135 | 136 | 其实在调用send方法之前,我们应该先调用一下prepare方法($response->prepare($request))来确认发送一个与标准http协议兼容的相应。举个例子,如果客户端对一个页面发送HEAD请求,那么服务器是不应该返回响应正文的(HEAD请求类似GET请求,除了要求服务器只返回头信息)。 137 | 138 | 对比之前的代码,你现在能完全控制HTTP消息。你能创建任何任何你想创建的请求,你也能发送任何你想返回的响应。 139 | 140 | *我们并没有显式设置Content-type为UTF-8,因为Response对象默认发送的就是UTF-8编码的内容。* 141 | 142 | 得益于优雅而简单的api,你能很轻易的通过Request对象获得请求的各种信息: 143 | 144 | ``` 145 | getPathInfo(); 149 | 150 | // 分别得到GET参数或POST参数 151 | $request->query->get('foo'); // GET 152 | $request->request->get('bar', '如何没有bar的默认值'); // POST 153 | 154 | // 得到服务器变量 155 | $request->server->get('HTTP_HOST'); 156 | 157 | // 得到上传文件对象 158 | $request->files->get('foo'); 159 | 160 | // 得到cookie值 161 | $request->cookies->get('PHPSESSID'); 162 | 163 | // 得到http请求头信息 164 | $request->headers->get('host'); 165 | $request->headers->get('content_type'); 166 | 167 | $request->getMethod(); // GET, POST, PUT, DELETE, HEAD 168 | $request->getLanguages(); // 得到客户端接收语言数组 169 | ``` 170 | 171 | 你也能够模拟一个请求: 172 | 173 | ``` 174 | $request = Request::create('/index.php?name=Fabien'); 175 | ``` 176 | 177 | 你也能利用Response对象很轻易的改变响应: 178 | 179 | ``` 180 | setContent('Hello world!'); 185 | $response->setStatusCode(200); 186 | $response->headers->set('Content-Type', 'text/html'); 187 | 188 | // configure the HTTP cache headers 189 | $response->setMaxAge(10); 190 | ``` 191 | 192 | *要debug一个相应对象,使用(string)让其变成一个字符串,他将返回http响应的全部信息(包括头信息和正文)* 193 | 194 | 最后也是最重要的一点,这些类以及sf2组件库其他的类,安全性方面都被一家专门做安全评审的公司[评估过](http://symfony.com/blog/symfony2-security-audit)(这里说的公司应该是指SektionEins,一家德国专门做安全评估的公司),而且作为开源项目就意味着许多志愿程序员已经将许多潜在的安全问题解决了。你上一次给你的框架做专业的安全评估是什么时候? 195 | 即使像获取用户IP这么简单的操作,也会出现安全隐患: 196 | 197 | ``` 198 | getClientIp()) { 223 | // the client is a known one, so give it some more privilege 224 | } 225 | ``` 226 | 227 | 另外还有一个好处:默认情况下它很安全,这里的安全我指的是:$_SERVER['HTTP_X_FORWARDED_FOR']这个参数并不可信,因为在没有代理服务器的情况下,终端用户是可以模仿出这么一个值的。所以,如果你在投产机里使用了这个参数,那么是很容易遭到黑客攻击而让你的服务器被滥用。即使是getClientIp方法也并非那么安全,为了解决刚才所说的情况,你需要显式调用trustProxyData()方法来处理: 228 | 229 | ``` 230 | getClientIp(true)) { 235 | // the client is a known one, so give it some more privilege 236 | } 237 | ``` 238 | 239 | 此刻getClientIp方法在各种情况下都会安全的工作,你能在你所有的项目里使用它,无论你用什么样的服务器配置,他都会安全而正确的工作。这便是使用框架的目的之一,如果你要从头到尾自己琢磨一个框架,这些问题你都得自己去考虑。所以为何不使用一个已经好用的技术呢? 240 | 241 | *如果你想知道关于HttpFoundation组件更多的信息,你可以查看它的[api](http://api.symfony.com/2.0/Symfony/Component/HttpFoundation.html),或者查看sf2网站上写得非常专业的[文档](http://symfony.com/doc/current/components/http_foundation.html)* 242 | 243 | 不管你信不信,我们已经写好我们的第一个框架了。如果你愿意的话你也可不必再继续往下阅读,因为使用sf2的HttpFoundation组件已经能让你写出更好更适合测试的代码了,另外它也能让你的代码写得更快,因为那些每次开发都需要注意的问题它都已经帮你解决了。 244 | 245 | 事实上,像Drupal等一些项目已经开始采用HttpFoundation组件了(从第8个版本开始)。如果这个组件能在这些项目里正常运行,那么它也可以在你的项目里正常运行。所以……不要重复发明轮子。 246 | 247 | 我差点忘了还有一个使用HttpFoundation组件的好处:它会让你在那些使用过它的项目和框架中有更好的互相操作性(interoperability)(目前这样的项目有Symfony2, Drupal 8, phpBB 4, Silex, Midgard CMS, Zikula …)。 248 | 249 | 英文原文地址:http://fabien.potencier.org/article/51/create-your-own-framework-on-top-of-the-symfony2-components-part-2 -------------------------------------------------------------------------------- /Backup/PHP/symfony/create-your-own-framework-on-top-of-the-symfony2-components/3.md: -------------------------------------------------------------------------------- 1 | 直到现在,我们的应用程序还只有一个页面,非常简单。为了再增加一点点乐趣,我们再添加一个“再见”页面。 2 | 3 | ``` 4 | send(); 17 | ``` 18 | 19 | 如你所见,这段代码跟我们第一个页面的代码写法都差不多。让我们把相同的代码提取出来,这样我们就可以让这段代码在所有要创建的页面里共享了。对于创建我们“真正的”框架来说,代码共享听起来是个不错的想法! 20 | 21 | 以php的方式来完成上面目标的重构,就是创建一个包含文件: 22 | 23 | ``` 24 | get('name', 'World'); 47 | 48 | $response->setContent(sprintf('Hello %s', htmlspecialchars($input, ENT_QUOTES, 'UTF-8'))); 49 | $response->send(); 50 | ``` 51 | 52 | 以及我们的“再见”页: 53 | 54 | ``` 55 | setContent('Goodbye!'); 62 | $response->send(); 63 | ``` 64 | 65 | 这样我们已将公共代码挪到了单独的文件,但这样做感觉上还是不够好,是吧?首先,我们每个页面代码依然还存在共同的send()方法,其次我们的页面代码任然看起来不像模版代码,而且我们依然不能很好的测试这段代码。 66 | 67 | 再其次,添加一个新的页面,意味着我们要添加一个新的php脚本文件,并且此文件是通过url完全暴露给终端用户的(http://example.com/bye.php),php脚本文件名和客户端url是完全直接相互映射的,这是因为请求的调度工作完全是由web服务器直接完成的。但为了灵活性,把调度工作直接交给我们自己的代码来做似乎是一个更好的想法。将所有的请求交给一个php脚本来做路由处理的话,这个想法是很容易实现的。 68 | 69 | *只暴露一个脚本给终端用户这种方式,是一种叫“前端控制器(front controller)”的设计模式。* 70 | 71 | 这个文件如下所示: 72 | 73 | ``` 74 | __DIR__.'/hello.php', 88 | '/bye' => __DIR__.'/bye.php', 89 | ); 90 | 91 | $path = $request->getPathInfo(); 92 | if (isset($map[$path])) { 93 | require $map[$path]; 94 | } else { 95 | $response->setStatusCode(404); 96 | $response->setContent('Not Found'); 97 | } 98 | 99 | $response->send(); 100 | ``` 101 | 102 | 经过改造后的新页面代码,举个例子,hello.php,应该是这个样子: 103 | 104 | ``` 105 | get('name', 'World'); 110 | $response->setContent(sprintf('Hello %s', htmlspecialchars($input, ENT_QUOTES, 'UTF-8'))); 111 | ``` 112 | 113 | 在front.php文件中,$map定义了url路径和相关php页面脚本路径的对应关系。 114 | 115 | 这么做还有一个好处是,如果用户输入了一个$map里未定义的url,我们可以返回一个自定义的404页面。现在你可以用代码完全控制你的网站了。 116 | 117 | 你现在必须使用front.php来访问一些页面: 118 | 119 | * http://example.com/front.php/hello?name=Fabien 120 | * http://example.com/front.php/bye 121 | 122 | /hello和/bye是页面的路径 123 | 124 | *大部分web服务器,比如nginx和apache,都有改写url的功能,可以将前段控制器脚本从url里面去掉,比如可以让用户直接输入http://example.com/hello?name=Fabien来进入上面的连接,这样看起来url干净了许多。* 125 | 126 | 能实现上面功能的诀窍便是使用Request::getPathInfo()方法,此方法将返回不包括前段控制器文件名,但包含它的子目录路径的路径信息。 127 | 128 | *你甚至都不用建立一个web服务器来做测试,你只用将Request::createFromGlobals()方法替换成比如Request::create(‘/hello?name=Fabien’),你就可以模拟任何请求了。* 129 | 130 | 目前所有的请求都是通过front.php来访问的,所以我们可以将其他php文件挪到web目录的外面去,以达到保护其他代码的作用。 131 | 132 | ``` 133 | example.com 134 | composer.json 135 | src 136 | autoload.php 137 | pages 138 | hello.php 139 | bye.php 140 | vendor 141 | web 142 | front.php 143 | ``` 144 | 145 | 现在,更改一下web服务器的配置,把访问的根目录设置到web目录下,这样web目录外面的代码,客户端就不能直接访问到了。 146 | 147 | *更改目录结构以后,有些包含路径是需要手工去调整的,这些就留给读者自己去修改了* 148 | 149 | 最后一个被重复写过多次的代码是Response::setContent()方法。我们可以把所有的页面代码变成直接echo出来的模版代码,这样我们就可以在前段控制器脚本中直接调用setContent方法了: 150 | 151 | ``` 152 | getPathInfo(); 159 | if (isset($map[$path])) { 160 | ob_start(); 161 | include $map[$path]; 162 | $response->setContent(ob_get_clean()); 163 | } else { 164 | $response->setStatusCode(404); 165 | $response->setContent('Not Found'); 166 | } 167 | 168 | // ... 169 | ``` 170 | 171 | hello.php也需要修改成模版页: 172 | 173 | 174 | 175 | ``` 176 | get('name', 'World') ?> 177 | 178 | Hello 179 | ``` 180 | 181 | 最终我们得到了我们今天的框架代码: 182 | 183 | ``` 184 | __DIR__.'/../src/pages/hello.php', 198 | '/bye' => __DIR__.'/../src/pages/bye.php', 199 | ); 200 | 201 | $path = $request->getPathInfo(); 202 | if (isset($map[$path])) { 203 | ob_start(); 204 | include $map[$path]; 205 | $response->setContent(ob_get_clean()); 206 | } else { 207 | $response->setStatusCode(404); 208 | $response->setContent('Not Found'); 209 | } 210 | 211 | $response->send(); 212 | ``` 213 | 214 | 要在添加一个新页面,目前只需要两步完成:在$map变量里面添加一个映射,然后在src/pages/目录添加一个模版页面。在模版文件里面,通过$request对象获得请求参数,然后利用$response变量,修改响应内容。 215 | 216 | *如果你决定在此停止阅读,你最好是把map的映射关系表提取出来放在单独的文件里面。* 217 | 218 | 英文原文地址:http://fabien.potencier.org/article/52/create-your-own-framework-on-top-of-the-symfony2-components-part-3 -------------------------------------------------------------------------------- /Backup/PHP/symfony/create-your-own-framework-on-top-of-the-symfony2-components/4.md: -------------------------------------------------------------------------------- 1 | 在开始我们今天的话题前,我们先重构一下我们的框架,让我们的模板文件更加易读: 2 | 3 | ``` 4 | 'hello', 17 | '/bye' => 'bye', 18 | ); 19 | 20 | $path = $request->getPathInfo(); 21 | if (isset($map[$path])) { 22 | ob_start(); 23 | extract($request->query->all(), EXTR_SKIP); 24 | include sprintf(__DIR__.'/../src/pages/%s.php', $map[$path]); 25 | $response = new Response(ob_get_clean()); 26 | } else { 27 | $response = new Response('Not Found', 404); 28 | } 29 | 30 | $response->send(); 31 | ``` 32 | 33 | 由于我们将请求里面的get参数解压(extract)出来了,我们就可以简化模板代码: 34 | 35 | 36 | ``` 37 | Hello 38 | ``` 39 | 40 | 现在我们的代码将可以以更好的状态来添加新的功能了。 41 | 42 | 任何一个网站都有一个重要的要素,那就是他们的url的形式。多亏了有$map变量这个映射表,我们将url以及跟他关联的响应这两部分代码从我们的代码里面解耦出来了,但目前还是不够灵活。举个例子,如果你想动态生成url,并将url中的一个部分来代替get参数: 43 | 44 | ``` 45 | # 之前 46 | /hello?name=Fabien 47 | 48 | # 之后 49 | /hello/Fabien 50 | ``` 51 | 52 | 想添加这个功能?请使用sf2的路由组件吧。如同以往,现在composer.json文件里面添加它,然后执行Composer的update命令安装它。 53 | 54 | ``` 55 | { 56 | "require": { 57 | "symfony/class-loader": "2.1.*", 58 | "symfony/http-foundation": "2.1.*", 59 | "symfony/routing": "2.1.*" 60 | } 61 | } 62 | ``` 63 | 64 | 现在开始,我们开始使用composer的autoloader,来代替我们之前所用的sf2自己的autoloader。删除之前写得autoload.php文件,然后把front.php引用它的代码改成引用composer的autoloader: 65 | 66 | ``` 67 | add('hello', new Route('/hello/{name}', array('name' => 'World'))); 92 | $routes->add('bye', new Route('/bye')); 93 | ``` 94 | 95 | 每一条路由规则都由一个名字(hello)以及一个Route实例来定义,而一条路由实例又由一条路由规则(/hello/{name})以及默认值数组(array(‘name’ => ‘World’))来定义。 96 | 97 | *请阅读官方[文档](http://symfony.com/doc/current/components/routing.html)——最近就会上线——学会路由组件其他更多功能,比如url生成器,属性限制,http方法限制,yaml,xml配置载入器,规则转储为php文件甚至apache的url重写规则来获取性能上的提升,以及其他更多功能。* 98 | 99 | 基于RouteCollection实例里存储的信息,UrlMatch对象可实现对url的匹配: 100 | 101 | ``` 102 | use Symfony\Component\Routing\RequestContext; 103 | use Symfony\Component\Routing\Matcher\UrlMatcher; 104 | 105 | $context = new RequestContext(); 106 | $context->fromRequest($request); 107 | $matcher = new UrlMatcher($routes, $context); 108 | 109 | $attributes = $matcher->match($request->getPathInfo()); 110 | ``` 111 | 112 | match方法接受请求路径为参数,然后返回相关的路由属性数组(注意路由的名字已经自动赋值给_route属性了): 113 | 114 | ``` 115 | print_r($matcher->match('/bye')); 116 | array ( 117 | '_route' => 'bye', 118 | ); 119 | 120 | print_r($matcher->match('/hello/Fabien')); 121 | array ( 122 | 'name' => 'Fabien', 123 | '_route' => 'hello', 124 | ); 125 | 126 | print_r($matcher->match('/hello')); 127 | array ( 128 | 'name' => 'World', 129 | '_route' => 'hello', 130 | ); 131 | ``` 132 | 133 | *我们并不严格要求要使用$context参数,但在真正的项目中最好还是加上,因为需要他来匹配http方法以及其他属性(你可以定义一个url只能用http的GET方法访问,不使用context而只传pathinfo参数,是做不到这一点的,所以作者说最好还是使用context。但实际上我认为context的存在让api看上去不舒服,因为第一时间很难判断context的作用是什么,为什么需要这个参数,以及思考:既然已经使用了context,为什么还需要单独传入pathinfo)。* 134 | 135 | 如果匹配器找不到任何一个匹配规则,他会抛出一个意外: 136 | 137 | ``` 138 | $matcher->match('/not-found'); 139 | 140 | // throws a Symfony\Component\Routing\Exception\ResourceNotFoundException 141 | ``` 142 | 143 | 利用上面的知识,我们将框架代码重写一下: 144 | 145 | ``` 146 | fromRequest($request); 161 | $matcher = new Routing\Matcher\UrlMatcher($routes, $context); 162 | 163 | try { 164 | extract($matcher->match($request->getPathInfo()), EXTR_SKIP); 165 | ob_start(); 166 | include sprintf(__DIR__.'/../src/pages/%s.php', $_route); 167 | 168 | $response = new Response(ob_get_clean()); 169 | } catch (Routing\Exception\ResourceNotFoundException $e) { 170 | $response = new Response('Not Found', 404); 171 | } catch (Exception $e) { 172 | $response = new Response('An error occurred', 500); 173 | } 174 | 175 | $response->send(); 176 | ``` 177 | 178 | 此段代码改进以下一些事情: 179 | 180 | * 使用route名字作为模板的文件名 181 | * 500错误也可以进行控制和管理了 182 | * 解压后的请求变量让我们的模板文件代码简单许多 183 | 184 | 185 | ``` 186 | Hello 187 | ``` 188 | 189 | * 路由管理被单独分配到一个文件里面 190 | 191 | ``` 192 | add('hello', new Routing\Route('/hello/{name}', array('name' => 'World'))); 200 | $routes->add('bye', new Routing\Route('/bye')); 201 | 202 | return $routes; 203 | ``` 204 | 205 | 现在我们的框架(front.php里的代码)和配置文件(所有都在app.php文件里配置)有了很明确的分工。 206 | 207 | 我们用不到30行的代码便写好了我们新的框架,比之前那个更灵活更强大了。 208 | 209 | 使用路由组件还有一个很大的好处:利用路由规则生成url的功能。如果你使用路由组件来匹配你的url,又使用路由组件来生成你的url,那么你像更换某个路由的规则,可毫无顾忌对系统的影响。想知道如何利用这个功能生成链接?小菜一碟: 210 | 211 | ``` 212 | use Symfony\Component\Routing; 213 | 214 | $generator = new Routing\Generator\UrlGenerator($routes, $context); 215 | 216 | echo $generator->generate('hello', array('name' => 'Fabien')); 217 | // outputs /hello/Fabien 218 | ``` 219 | 220 | 代码非常明了,根本不用再重新说明过程了;然后,也多亏了有context你甚至可以生成全路径: 221 | 222 | ``` 223 | echo $generator->generate('hello', array('name' => 'Fabien'), true); 224 | // outputs something like http://example.com/somewhere/hello/Fabien 225 | ``` 226 | 227 | *是否在关注路由的性能问题?基于你指定的路由规则,你可以创建一个被强力优化过的匹配类,来代替之前的UrlMatcher():* 228 | 229 | ``` 230 | $dumper = new Routing\Matcher\Dumper\PhpMatcherDumper($routes); 231 | 232 | echo $dumper->dump(); 233 | ``` 234 | 235 | 还不满足?你还可以将路由规则转储为apache的重写规则: 236 | 237 | ``` 238 | $dumper = new Routing\Matcher\Dumper\ApacheMatcherDumper($routes); 239 | 240 | echo $dumper->dump(); 241 | ``` 242 | 243 | 任何前端控制器框架,或者说单点入口框架,都会面对路由器性能问题,这个问题甚至被php之父作为“反对使用框架”的论点之一。但事实上,如果一个项目有几十个甚至上百个路由规则,路由器性能的确是一个头痛的问题。sf2的路由转存组件将路由转存为apache的url改写规则,将本来php就不擅长的路由工作交给特别擅长此工作的web服务器,的确是个很靠谱的创新。对性能要求较高的同学可以考虑尝试一下。另外我想既然apache的改写能做,nginx的改写规则也应该不远了。 244 | 245 | 英文原文地址:http://fabien.potencier.org/article/53/create-your-own-framework-on-top-of-the-symfony2-components-part-4 -------------------------------------------------------------------------------- /Backup/PHP/symfony/create-your-own-framework-on-top-of-the-symfony2-components/5.md: -------------------------------------------------------------------------------- 1 | 细心的读者可能已经发现,之前我们“硬编码”了一些代码在模板文件里面(比如说之前的$input = $request->get('name', 'World')这种逻辑代码)。像目前我们编写的这些小页面,问题倒也不大。但如果你想写更多的逻辑代码,那你只能把它们写在模板文件里面,这是非常不好的做法,特别是对于我们本来就是为了达到分工这个目的而做这个框架的,所以更不能这么搞。 2 | 3 | 为了把逻辑代码从模板文件里面分离出来,我们再加一个“控制器”层。控制器的主要作用是根据得到的客户端请求,生成相应的响应内容。 4 | 5 | 修改模板渲染代码如下: 6 | 7 | ``` 8 | attributes->add($matcher->match($request->getPathInfo())); 16 | $response = call_user_func('render_template', $request); 17 | } catch (Routing\Exception\ResourceNotFoundException $e) { 18 | $response = new Response('Not Found', 404); 19 | } catch (Exception $e) { 20 | $response = new Response('An error occurred', 500); 21 | } 22 | ``` 23 | 24 | 目前模板渲染已经交给了外部的函数处理(这里是render_template()函数),我们需要把url里面带的参数解析出来,并作为参数传递给这个函数。我们可以这么做,但是我们可以利用Request类的另外一个叫属性的功能:Request类的属性可以让你添加其他的信息,而且这些信息不一定非要跟请求的数据有直接的联系。 25 | 26 | 现在我们开始写render_template()函数了,让它作为一个没有其他任何逻辑代码的通用控制器。为了让我们之前写的模板代码还是能如之前一样工作,我们还是将请求对象的属性值都“解压”(利用php的extract函数)出来: 27 | 28 | ``` 29 | function render_template($request) 30 | { 31 | extract($request->attributes->all(), EXTR_SKIP); 32 | ob_start(); 33 | include sprintf(__DIR__.'/../src/pages/%s.php', $_route); 34 | 35 | return new Response(ob_get_clean()); 36 | } 37 | ``` 38 | 39 | 由于这里我们用render_template作为call_user_func函数的一个参数,它也完全可以由任何合法的php回调函数来代替。这便可以随意让我们使用函数,或者匿名函数,甚至类方法来做回调函数。 40 | 41 | 为了使用方便,我们把每个路由规则都加上控制器属性: 42 | 43 | ``` 44 | $routes->add('hello', new Routing\Route('/hello/{name}', array( 45 | 'name' => 'World', 46 | '_controller' => 'render_template', 47 | ))); 48 | 49 | try { 50 | $request->attributes->add($matcher->match($request->getPathInfo())); 51 | $response = call_user_func($request->attributes->get('_controller'), $request); 52 | } catch (Routing\Exception\ResourceNotFoundException $e) { 53 | $response = new Response('Not Found', 404); 54 | } catch (Exception $e) { 55 | $response = new Response('An error occurred', 500); 56 | } 57 | ``` 58 | 59 | 这样你就可以将任何控制器函数和路由规则联系起来了。当然,在控制器代码里面,你还是可以使用写好的render_template方法: 60 | 61 | ``` 62 | $routes->add('hello', new Routing\Route('/hello/{name}', array( 63 | 'name' => 'World', 64 | '_controller' => function ($request) { 65 | return render_template($request); 66 | } 67 | ))); 68 | ``` 69 | 70 | 这样做会更加灵活,因为你可以在生成模板之前以及之后对Response对象进行修改,你甚至可以传更多的参数给模板: 71 | 72 | ``` 73 | $routes->add('hello', new Routing\Route('/hello/{name}', array( 74 | 'name' => 'World', 75 | '_controller' => function ($request) { 76 | // $foo will be available in the template 77 | $request->attributes->set('foo', 'bar'); 78 | 79 | $response = render_template($request); 80 | 81 | // change some header 82 | $response->headers->set('Content-Type', 'text/plain'); 83 | 84 | return $response; 85 | } 86 | ))); 87 | ``` 88 | 89 | 以下是更新改进过后的框架代码: 90 | 91 | ``` 92 | attributes->all(), EXTR_SKIP); 105 | ob_start(); 106 | include sprintf(__DIR__.'/../src/pages/%s.php', $_route); 107 | 108 | return new Response(ob_get_clean()); 109 | } 110 | 111 | $request = Request::createFromGlobals(); 112 | $routes = include __DIR__.'/../src/app.php'; 113 | 114 | $context = new Routing\RequestContext(); 115 | $context->fromRequest($request); 116 | $matcher = new Routing\Matcher\UrlMatcher($routes, $context); 117 | 118 | try { 119 | $request->attributes->add($matcher->match($request->getPathInfo())); 120 | $response = call_user_func($request->attributes->get('_controller'), $request); 121 | } catch (Routing\Exception\ResourceNotFoundException $e) { 122 | $response = new Response('Not Found', 404); 123 | } catch (Exception $e) { 124 | $response = new Response('An error occurred', 500); 125 | } 126 | 127 | $response->send(); 128 | ``` 129 | 130 | 为庆祝我们有一个新框架的诞生,让我们再创建一个新的,带较多逻辑的程序。我们的新程序只有一个页面,告诉我们某一年是不是闰年。如果访问/is_leap_year,我们会被告知今年是不是闰年,当然你也可以指定查询特定的年份,比如/is_leap_year/2009。我们的框架不用做太大的修改,只用在app.php文件里进行点修改: 131 | 132 | ``` 133 | add('leap_year', new Routing\Route('/is_leap_year/{year}', array( 150 | 'year' => null, 151 | '_controller' => function ($request) { 152 | if (is_leap_year($request->attributes->get('year'))) { 153 | return new Response('Yep, this is a leap year!'); 154 | } 155 | 156 | return new Response('Nope, this is not a leap year.'); 157 | } 158 | ))); 159 | 160 | return $routes; 161 | ``` 162 | 163 | is_leap_year()函数会告知我们某一年是不是闰年,如果传入参数,那么就检查今年是不是闰年,然后根据它返回的结果,我们能分别创造出不同的响应结果。 164 | 165 | 一如往常,如果你在此打算停止继续往下阅读了并且打算开始使用当前的框架,那你最好能利用这框架创建一个简单的网站,比如那些有趣的“单页”网站(“单页”网站,one-page website,是指一种一个网站就一个页面的网站,读者们可以点击单页网站的链接参观参观,的确非常“有趣”,它们比起今天做的判断是否闰年的功能还要简单n倍……很蛋疼)。 166 | 167 | 英文原文地址:http://fabien.potencier.org/article/54/create-your-own-framework-on-top-of-the-symfony2-components-part-5 -------------------------------------------------------------------------------- /Backup/PHP/symfony/create-your-own-framework-on-top-of-the-symfony2-components/6.md: -------------------------------------------------------------------------------- 1 | 可能你觉得我们的框架已经非常的稳定了,但其实我们仍然可以继续改进它。 2 | 3 | 目前,我们所有的例子,都是以面向过程的方式实现的,但是别忘了,我们的控制器可以是任何一种合法的php回调函数。让我们把控制器改写成一个类: 4 | 5 | ``` 6 | class LeapYearController 7 | { 8 | public function indexAction($request) 9 | { 10 | if (is_leap_year($request->attributes->get('year'))) { 11 | return new Response('Yep, this is a leap year!'); 12 | } 13 | 14 | return new Response('Nope, this is not a leap year.'); 15 | } 16 | } 17 | ``` 18 | 19 | 再修改相应的路由配置: 20 | 21 | ``` 22 | $routes->add('leap_year', new Routing\Route('/is_leap_year/{year}', array( 23 | 'year' => null, 24 | '_controller' => array(new LeapYearController(), 'indexAction'), 25 | ))); 26 | ``` 27 | 28 | 当你使用这种方法创建更多的新页面的时候,你会觉得更加的合理和直观,但是这种方式也有一个副作用:LeapYearController对象总是会被创建,无论当前的url是不是跟leap_year相匹配。这样做非常糟糕,因为性能受到很大影响。无论什么样的请求发送到服务器,所有的控制器类都会初始化一个对象。如果控制器会按照指定的路由匹配规则“迟载入(lazy-loaded)”,性能将会好很多。 29 | 30 | 要解决这个问题,我们再安装一个“Http核心(HttpKernel)”组件: 31 | 32 | ``` 33 | { 34 | "require": { 35 | "symfony/class-loader": "2.1.*", 36 | "symfony/http-foundation": "2.1.*", 37 | "symfony/routing": "2.1.*", 38 | "symfony/http-kernel": "2.1.*" 39 | } 40 | } 41 | ``` 42 | 43 | HttpKernel组件有许多有意思的功能,但目前我们需要的是“控制器分解器(controller resolver)”。根据传过来的请求对象,controller resolver知道那一个控制器将要被执行,以及将要传给它什么参数。所有的controller resolver需要实现以下接口: 44 | 45 | ``` 46 | namespace Symfony\Component\HttpKernel\Controller; 47 | 48 | interface ControllerResolverInterface 49 | { 50 | function getController(Request $request); 51 | 52 | function getArguments(Request $request, $controller); 53 | } 54 | ``` 55 | 56 | getController()方法实现依赖跟之前同样的方式:_controller属性必然是跟某个请求对应关联的。除了php内置的回调函数方式,getController()也支持像"class::method"这样的字符串作为合法的回调函数。 57 | 58 | ``` 59 | $routes->add('leap_year', new Routing\Route('/is_leap_year/{year}', array( 60 | 'year' => null, 61 | '_controller' => 'LeapYearController::indexAction', 62 | ))); 63 | ``` 64 | 65 | 要让这段代码生效,我们要让框架代码使用HttpKernel组件的控制器分析器: 66 | 67 | ``` 68 | use Symfony\Component\HttpKernel; 69 | 70 | $resolver = new HttpKernel\Controller\ControllerResolver(); 71 | 72 | $controller = $resolver->getController($request); 73 | $arguments = $resolver->getArguments($request, $controller); 74 | 75 | $response = call_user_func_array($controller, $arguments); 76 | ``` 77 | 78 | *Controller resolver还有一个好处是,它将会为你合理的处理错误,比如说,如果你忘记了给路由规则设定_controller属性。* 79 | 80 | 现在我们来看看控制器所需要的参数是怎么被猜测出来的。getArguments()方法将使用php的[反射功能](http://php.net/reflection)来决定什么样的参数才需要传给控制器。 81 | 82 | indexAction()方法需要一个Request对象作为参数。getArguments()知道如何根据参数类型(type-hint)来传入正确的参数: 83 | 84 | ``` 85 | public function indexAction(Request $request) 86 | 87 | // 如果没有限定参数类型是Request类型,那么参数就不会被正确传递 88 | // 所以以下代码不会正常运作 89 | public function indexAction($request) 90 | ``` 91 | 92 | 更有意思的是,getArguments()方法可以传递任何请求对象的属性值,只要参数的名字跟属性名称一样就行: 93 | 94 | ``` 95 | public function indexAction($year) 96 | ``` 97 | 98 | 你甚至可以在传入属性指的同时也传入请求对象(因为已经通过参数类型和参数名称做好了匹配,所以参数顺序无所谓) 99 | 100 | ``` 101 | public function indexAction(Request $request, $year) 102 | 103 | public function indexAction($year, Request $request) 104 | ``` 105 | 106 | 最后,你可以使用方法参数默认值,来给一个请求的可选属性设置默认值: 107 | 108 | ``` 109 | public function indexAction($year = 2012) 110 | ``` 111 | 112 | 让我们就把year参数传递给控制器: 113 | 114 | ``` 115 | class LeapYearController 116 | { 117 | public function indexAction($year) 118 | { 119 | if (is_leap_year($year)) { 120 | return new Response('Yep, this is a leap year!'); 121 | } 122 | 123 | return new Response('Nope, this is not a leap year.'); 124 | } 125 | } 126 | ``` 127 | 128 | 控制器分离器还有验证控制器回调函数以及其参数的功能,如果出现问题,它将抛出一个详细的意外来解释发生了什么错误(比如控制器类不存在,控制器方法不存在,某个参数没有相应的请求属性)。 129 | 130 | *默认的控制器分解器已经非常的灵活,你可能会想怎么可能还有人去实现另外一个分解器(为什么需要提供一个接口)?举两个例子:在sf2里,getController()功能得到了进一步强化,让其可实现将[控制器作为服务](http://symfony.com/doc/current/cookbook/controller/service.html),而在FrameworkExtraBundle里,getArguments()方法也得到了增强,让请求参数自动转化为对象。* 131 | 132 | 让我们最后整理一下我们的新框架: 133 | 134 | ``` 135 | attributes->all()); 149 | ob_start(); 150 | include sprintf(__DIR__.'/../src/pages/%s.php', $_route); 151 | 152 | return new Response(ob_get_clean()); 153 | } 154 | 155 | $request = Request::createFromGlobals(); 156 | $routes = include __DIR__.'/../src/app.php'; 157 | 158 | $context = new Routing\RequestContext(); 159 | $context->fromRequest($request); 160 | $matcher = new Routing\Matcher\UrlMatcher($routes, $context); 161 | $resolver = new HttpKernel\Controller\ControllerResolver(); 162 | 163 | try { 164 | $request->attributes->add($matcher->match($request->getPathInfo())); 165 | 166 | $controller = $resolver->getController($request); 167 | $arguments = $resolver->getArguments($request, $controller); 168 | 169 | $response = call_user_func_array($controller, $arguments); 170 | } catch (Routing\Exception\ResourceNotFoundException $e) { 171 | $response = new Response('Not Found', 404); 172 | } catch (Exception $e) { 173 | $response = new Response('An error occurred', 500); 174 | } 175 | 176 | $response->send(); 177 | ``` 178 | 179 | 现在我们框架现在更加的健壮,更加的灵活,而且实现它仍然没有超过40行代码。 180 | 181 | 英文原文地址:http://fabien.potencier.org/article/55/create-your-own-framework-on-top-of-the-symfony2-components-part-6 -------------------------------------------------------------------------------- /Backup/PHP/symfony/create-your-own-framework-on-top-of-the-symfony2-components/7.md: -------------------------------------------------------------------------------- 1 | 目前我们的框架还有一个不足之处:当我们要创建新的网站的时候,我们都需要将front.php的代码复制一份。虽然40行代码并不是很多,但是如果我们能将这些代码写成一个合适的类,将会更给力一些,比如更好的复用性以及更好的可测试性。 2 | 3 | 更进一步研究你会发现,front.php包含一个输入,即一个请求Request,以及一个输出,即一个相应Response。我们的框架将遵循一个简单的原则:生成与请求相关联的响应。 4 | 5 | 因为Symfony2本身php5.3的支持,所以我们可以为框架设置一个自己的命名空间:`Simplex`。 6 | 7 | 将处理请求的逻辑代码移动到我们的框架类中: 8 | 9 | ``` 10 | matcher = $matcher; 30 | $this->resolver = $resolver; 31 | } 32 | 33 | public function handle(Request $request) 34 | { 35 | try { 36 | $request->attributes->add($this->matcher->match($request->getPathInfo())); 37 | 38 | $controller = $this->resolver->getController($request); 39 | $arguments = $this->resolver->getArguments($request, $controller); 40 | 41 | return call_user_func_array($controller, $arguments); 42 | } catch (ResourceNotFoundException $e) { 43 | return new Response('Not Found', 404); 44 | } catch (\Exception $e) { 45 | return new Response('An error occurred', 500); 46 | } 47 | } 48 | } 49 | ``` 50 | 51 | 相应的我们也需要更新一下front.php的代码: 52 | 53 | ``` 54 | fromRequest($request); 65 | $matcher = new Routing\Matcher\UrlMatcher($routes, $context); 66 | $resolver = new HttpKernel\Controller\ControllerResolver(); 67 | 68 | $framework = new Simplex\Framework($matcher, $resolver); 69 | $response = $framework->handle($request); 70 | 71 | $response->send(); 72 | ``` 73 | 74 | 让我们把除了路由定义的代码挪到另外一个命名空间Calendar下,以完成我们对重构代码的继续封装: 75 | 76 | 为了让在Simplex以及Calendar这两个命名空间下的代码文件能够自动加载,我们需要更新一下composer.json文件: 77 | 78 | ``` 79 | { 80 | "require": { 81 | "symfony/class-loader": "2.1.*", 82 | "symfony/http-foundation": "2.1.*", 83 | "symfony/routing": "2.1.*", 84 | "symfony/http-kernel": "2.1.*" 85 | }, 86 | "autoload": { 87 | "psr-0": { "Simplex": "src/", "Calendar": "src/" } 88 | } 89 | } 90 | ``` 91 | 92 | *为了让自动加载生效,需要运行php composer.phar update。* 93 | 94 | 将控制器代码挪到Calendar\Controller\LeapYearController: 95 | 96 | ``` 97 | isLeapYear($year)) { 113 | return new Response('Yep, this is a leap year!'); 114 | } 115 | 116 | return new Response('Nope, this is not a leap year.'); 117 | } 118 | } 119 | ``` 120 | 121 | 然后把is_leap_year()方法挪到它应该存在的类中: 122 | 123 | ``` 124 | add('leap_year', new Routing\Route('/is_leap_year/{year}', array( 147 | 'year' => null, 148 | '_controller' => 'Calendar\\Controller\\LeapYearController::indexAction', 149 | ))); 150 | ``` 151 | 152 | 最终,我们得到一个新的目录结构: 153 | 154 | ``` 155 | example.com 156 | composer.json 157 | src 158 | app.php 159 | Simplex 160 | Framework.php 161 | Calendar 162 | Controller 163 | LeapYearController.php 164 | Model 165 | LeapYear.php 166 | vendor 167 | web 168 | front.php 169 | ``` 170 | 171 | 没错!我们的应用程序目前有4个不同的部分,而且每一个部分都有自己特有的责任: 172 | 173 | * web/front.php:前段控制器,这是唯一一处没有被封装的php代码文件,并且唯一与客户端交互的接口(它接受请求并发送响应),并且提供了初始化框架的代码模版(boil-plate,这个单词很有意思,来源于印刷工业,指的是不能拆卸的一整块印刷母板,你可以想成是活字印刷发明之前用来印书的东西); 174 | * src/Simplex:可供复用的框架代码,作为处理请求的抽象化接口(另外,他使你的控制器/模板文件更容易测试,更多信息请看下一章); 175 | * src/Calendar:我们程序的特定代码(指一个程序的具体实现); 176 | * src/app.php:程序配置/框架自定义。 177 | 178 | 英文原文地址:http://fabien.potencier.org/article/56/create-your-own-framework-on-top-of-the-symfony2-components-part-7 -------------------------------------------------------------------------------- /Backup/PHP/symfony/create-your-own-framework-on-top-of-the-symfony2-components/8.md: -------------------------------------------------------------------------------- 1 | 一些细心的读者已经发现,前一章完成的框架里还存在难以发现却很严重的bug。创建框架,你必须得保证它能像当初设计的那样工作,否则的话使用它做出来的程序都会出现它导致的问题。当然好消息是:如果你修改了一个bug,你就等于修改了一大堆(使用它的)的应用程序。 2 | 3 | 今天我们的任务是,利用PHPUnit来为我们的框架写一些单元测试。首先创建一个[PHPUnit](http://www.phpunit.de/manual/current/en/index.html)的配置文件example.com/phpunit.xml.dist: 4 | 5 | ``` 6 | 7 | 8 | 19 | 20 | 21 | ./tests 22 | 23 | 24 | 25 | ``` 26 | 27 | 此配置定义了PHPUnit大部分设置很好的默认选项;更有趣的是,自动加载器将会用来启动测试,而所有的测试都将放在example.com/tests/目录。 28 | 29 | 现在,让我们写一个“资源无法找到”的响应的测试。为了防止要测试的对象的依赖组件对测试的影响,我们打算使用[test doubles](http://www.phpunit.de/manual/current/en/test-doubles.html)(对于test doubles我自己的理解是,在测试某一个组件的时候,有可能这个组件需要其他组件才能工作,比如方向盘。当然为了测试方向盘能否正常工作,不见得非要把方向盘装车上,若有专门的仪器可以模拟真实的环境也可以测试)。如果我们的组件都依赖于接口而不是实际的类,我们将很容易使用模拟环境(test doubles)来做测试。还好Symfony2的核心组件都提供了这样的接口,比如url匹配器以及控制器解析器。让我们修改一下框架来使用这些接口: 30 | 31 | ``` 32 | matcher = $matcher; 51 | $this->resolver = $resolver; 52 | } 53 | 54 | // ... 55 | } 56 | ``` 57 | 58 | 我们现在便可以写我们的第一个测试了: 59 | 60 | ``` 61 | getFrameworkForException(new ResourceNotFoundException()); 76 | 77 | $response = $framework->handle(new Request()); 78 | 79 | $this->assertEquals(404, $response->getStatusCode()); 80 | } 81 | 82 | protected function getFrameworkForException($exception) 83 | { 84 | $matcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface'); 85 | $matcher 86 | ->expects($this->once()) 87 | ->method('match') 88 | ->will($this->throwException($exception)) 89 | ; 90 | $resolver = $this->getMock('Symfony\Component\HttpKernel\Controller\ControllerResolverInterface'); 91 | 92 | return new Framework($matcher, $resolver); 93 | } 94 | } 95 | ``` 96 | 97 | 此测试模拟了一个不匹配任何路由规则的请求,接着match()方法将产生ResourceNotFoundException的意外。我们将测试我们的框架类能否将此意外转变成一个404相应。 98 | 99 | 执行测试程序非常简单: 100 | 101 | ``` 102 | $ phpunit 103 | ``` 104 | 105 | *我将不会详细解释代码执行的细节,因为这不是本章的重点,但如果你实在被这些代码搞的崩溃,我强烈推荐你们看看PHPUnit关于[test doubles](http://www.phpunit.de/manual/current/en/test-doubles.html)的文档* 106 | 107 | 执行完上面的命令,你应该能看到一条绿色背景提示(在windows下面应该是看不到的,绿色背景的提示表示测试很OK),如果没有,说明你的框架代码可能有问题哦。 108 | 109 | 添加测试控制器抛出的异常的代码也是so easy的事情: 110 | 111 | ``` 112 | public function testErrorHandling() 113 | { 114 | $framework = $this->getFrameworkForException(new \RuntimeException()); 115 | 116 | $response = $framework->handle(new Request()); 117 | 118 | $this->assertEquals(500, $response->getStatusCode()); 119 | } 120 | ``` 121 | 122 | 最后很重要的一步,添加一个返回正常相应的测试: 123 | 124 | ``` 125 | use Symfony\Component\HttpFoundation\Response; 126 | use Symfony\Component\HttpKernel\Controller\ControllerResolver; 127 | 128 | public function testControllerResponse() 129 | { 130 | $matcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface'); 131 | $matcher 132 | ->expects($this->once()) 133 | ->method('match') 134 | ->will($this->returnValue(array( 135 | '_route' => 'foo', 136 | 'name' => 'Fabien', 137 | '_controller' => function ($name) { 138 | return new Response('Hello '.$name); 139 | } 140 | ))) 141 | ; 142 | $resolver = new ControllerResolver(); 143 | 144 | $framework = new Framework($matcher, $resolver); 145 | 146 | $response = $framework->handle(new Request()); 147 | 148 | $this->assertEquals(200, $response->getStatusCode()); 149 | $this->assertContains('Hello Fabien', $response->getContent()); 150 | } 151 | ``` 152 | 153 | 在此测试中,我们模拟了一个能匹配的路由,并返回了一个简单的控制器。我们测试了框架返回的相应代码是否200,并且相应内容是否是我们期待的那样工作。 154 | 155 | 要查看此测试代码是否测试了所有的运行事例(也就是代码测试率,即测试运行过的代码行数占整个代码行数的比率),请使用PHPUnit的代码测试率功能(你需要安装php的[XDebug](http://xdebug.org/)插件): 156 | 157 | ``` 158 | $ phpunit --coverage-html=cov/ 159 | ``` 160 | 161 | 在浏览器中打开example.com/cov/src_Simplex_Framework.php.html,检查所有关于框架类的代码是不是都是绿色的(绿色的代码表示这些它们已经被测试过了)。 162 | 163 | 得益于我们写的面向对象的代码,我们能够写出能测试全部使用事例的框架测试代码。test doubles测试可以保证我们测试的是只自己的代码而不是Symfony2的。 164 | 165 | 现在我们(又一次)对自己的代码充满信心,我们可以安心的考虑我们接下来要加什么功能了。 166 | 167 | 英文原文地址:http://fabien.potencier.org/article/57/create-your-own-framework-on-top-of-the-symfony2-components-part-8 -------------------------------------------------------------------------------- /Backup/PHP/symfony/create-your-own-framework-on-top-of-the-symfony2-components/9.md: -------------------------------------------------------------------------------- 1 | 我们的框架依然缺少作为好框架必备的一个特点:扩展性。拥有扩展性意味着,开发者可以很方便的通过拦截(hook)的方式,修改请求被处理的过程。 2 | 3 | 我们说的拦截是什么东西呢?验证或者缓存就是两个例子(其实请求的处理就像通过一层层的筛子。比如访问一个需要做登陆验证的url,那么我们可以设计这么一个筛子,它将判断请求来源是否已登陆,如果没有登录请求将被拦截住,转向登录页面。如果一个url设计为可以被缓存,一个请求过来以后,缓存筛子判断这个url是否已经被缓存,如果是,这个筛子直接拦截此次请求不继续往下处理,而是直接把缓存的内容发送出去)。为了灵活性,拦截程序必须是即插即用型(plug and play)的。根据不同的需求,你所“注册”的拦截程序肯定有别于其他拦截程序。许多软件都有类似的概念,比如说Wordpress或者Drupal。在一些语言里,甚至会有相关的标准。比如Ruby的[Rack](http://rack.rubyforge.org/)和Python的[WSGI](http://www.python.org/dev/peps/pep-0333/#middleware-components-that-play-both-sides)。 4 | 5 | 因为在PHP里面没有相关的标准,我们将使用著名的设计模式“观察者模式”,来将各种拦截模块连接到我们的框架中。sf2的事件调度(EventDispatcher)组件为此模式做了一个轻量级的实现。 6 | 7 | ``` 8 | { 9 | "require": { 10 | "symfony/class-loader": "2.1.*", 11 | "symfony/http-foundation": "2.1.*", 12 | "symfony/routing": "2.1.*", 13 | "symfony/http-kernel": "2.1.*", 14 | "symfony/event-dispatcher": "2.1.*" 15 | }, 16 | "autoload": { 17 | "psr-0": { "Simplex": "src/", "Calendar": "src/" } 18 | } 19 | } 20 | ``` 21 | 22 | 此模块如何工作呢?作为此组件的核心的调度器,将对每一个连接过它的监听器(listener)做出事件提醒。或者这么说:你的代码将在某个事件发生的时候调用调度器,而调度器将提醒每一个监听器刚刚发生了什么事件,每个监听器收到消息后,将对此事件做出自己的不同处理行为。 23 | 24 | 举一个例子,让我们透明的为每一个响应都添加google的网站访问分析代码GA。 25 | 26 | 要达成此目的,我们得让框架在返回相应对象之前做一次事件分发: 27 | 28 | ``` 29 | matcher = $matcher; 51 | $this->resolver = $resolver; 52 | $this->dispatcher = $dispatcher; 53 | } 54 | 55 | public function handle(Request $request) 56 | { 57 | try { 58 | $request->attributes->add($this->matcher->match($request->getPathInfo())); 59 | 60 | $controller = $this->resolver->getController($request); 61 | $arguments = $this->resolver->getArguments($request, $controller); 62 | 63 | $response = call_user_func_array($controller, $arguments); 64 | } catch (ResourceNotFoundException $e) { 65 | $response = new Response('Not Found', 404); 66 | } catch (\Exception $e) { 67 | $response = new Response('An error occurred', 500); 68 | } 69 | 70 | // dispatch a response event 71 | $this->dispatcher->dispatch('response', new ResponseEvent($response, $request)); 72 | 73 | return $response; 74 | } 75 | } 76 | ``` 77 | 78 | 框架每次处理请求的时候,都将分发一个类型为ResponseEvent的事件: 79 | 80 | ``` 81 | response = $response; 99 | $this->request = $request; 100 | } 101 | 102 | public function getResponse() 103 | { 104 | return $this->response; 105 | } 106 | 107 | public function getRequest() 108 | { 109 | return $this->request; 110 | } 111 | } 112 | ``` 113 | 114 | 最后一步我们将创建分发器,并为此添加一个监听器: 115 | 116 | ``` 117 | addListener('response', function (Simplex\ResponseEvent $event) { 129 | $response = $event->getResponse(); 130 | 131 | if ($response->isRedirection() 132 | || ($response->headers->has('Content-Type') && false === strpos($response->headers->get('Content-Type'), 'html')) 133 | || 'html' !== $event->getRequest()->getRequestFormat() 134 | ) { 135 | return; 136 | } 137 | 138 | $response->setContent($response->getContent().'GA CODE'); 139 | }); 140 | 141 | $framework = new Simplex\Framework($dispatcher, $matcher, $resolver); 142 | $response = $framework->handle($request); 143 | 144 | $response->send(); 145 | ``` 146 | 147 | *上面代码只是为了说明怎么加代码,若要真的添加GA代码你得自己把真实的代码写上去(而且用这种方式添加GA在真正实践中也不是一个好方法,像GA这种HTML代码,直接放在布局文件中更好)。* 148 | 149 | 如你所见,addListener()方法把将response事件和一个php回调函数联系在了一起。事件的名字必须跟dispatch()方法里提到的事件名字一样。 150 | 151 | 在监听代码中,我们只为不跳转的响应添加GA代码,而且响应的类型必须是html类型(此代码演示了操作请求或者响应对象是多么的手到擒来的事情)。 152 | 153 | 让我们在为同样的事件添加另外一个监听者,此监听者检查响应是否有Content-length头,没有便添加一个: 154 | 155 | ``` 156 | $dispatcher->addListener('response', function (Simplex\ResponseEvent $event) { 157 | $response = $event->getResponse(); 158 | $headers = $response->headers; 159 | 160 | if (!$headers->has('Content-Length') && !$headers->has('Transfer-Encoding')) { 161 | $headers->set('Content-Length', strlen($response->getContent())); 162 | } 163 | }); 164 | ``` 165 | 166 | 添加监听者时需要注意添加的顺序,否则你有可能会得到错误的Content-length值。监听者添加顺序很重要,但从默认设置来说,所有的监听者都是一样的优先级,值为0。要想让某个监听者优先执行,可以将优先级设置为一个正数,也可以为低优先级的监听控件设置优先级为负数。比如说设置content-length的监听控件,我们可以设置它为-255,表示最后执行。 167 | 168 | ``` 169 | $dispatcher->addListener('response', function (Simplex\ResponseEvent $event) { 170 | $response = $event->getResponse(); 171 | $headers = $response->headers; 172 | 173 | if (!$headers->has('Content-Length') && !$headers->has('Transfer-Encoding')) { 174 | $headers->set('Content-Length', strlen($response->getContent())); 175 | } 176 | }, -255); 177 | ``` 178 | 179 | *当你创建框架的时候,请仔细思考如何设计优先级(比如给内部监听控件预留一些优先级数),以及为此做好文档* 180 | 181 | 让我们将代码重构一下,把GA监听控件放在属于他自己的类里: 182 | 183 | ``` 184 | getResponse(); 195 | 196 | if ($response->isRedirection() 197 | || ($response->headers->has('Content-Type') && false === strpos($response->headers->get('Content-Type'), 'html')) 198 | || 'html' !== $event->getRequest()->getRequestFormat() 199 | ) { 200 | return; 201 | } 202 | 203 | $response->setContent($response->getContent().'GA CODE'); 204 | } 205 | } 206 | ``` 207 | 208 | 其他的监听也做同样处理: 209 | 210 | ``` 211 | getResponse(); 222 | $headers = $response->headers; 223 | 224 | if (!$headers->has('Content-Length') && !$headers->has('Transfer-Encoding')) { 225 | $headers->set('Content-Length', strlen($response->getContent())); 226 | } 227 | } 228 | } 229 | ``` 230 | 231 | 如此以来我们的前端控制器代码可改成如下样子: 232 | 233 | ``` 234 | $dispatcher = new EventDispatcher(); 235 | $dispatcher->addListener('response', array(new Simplex\ContentLengthListener(), 'onResponse'), -255); 236 | $dispatcher->addListener('response', array(new Simplex\GoogleListener(), 'onResponse')); 237 | ``` 238 | 239 | 虽然相关代码已被漂亮的封装起来了,但依然还残留一个小问题:优先级相关的代码被硬编码在了前段控制器里,而不是又监听器自己来控制。每一个应用程序里你都得自己记着设置合适的优先级。除此之外,监听器所绑定的事件名字也暴露在前段控制器里,这意味着如果我们要重构监听器时,所有相关的应用程序都得所相应的修改。当然,有一个办法可以解决这个问题,使用订阅的方式来代替监听的方式: 240 | 241 | ``` 242 | $dispatcher = new EventDispatcher(); 243 | $dispatcher->addSubscriber(new Simplex\ContentLengthListener()); 244 | $dispatcher->addSubscriber(new Simplex\GoogleListener()); 245 | ``` 246 | 247 | “订阅者”知道所有的事件,并且可通过getSubscribedEvents()方法给分发器传递信息。让我们看看新版本的GA监听器: 248 | 249 | ``` 250 | 'onResponse'); 265 | } 266 | } 267 | ``` 268 | 269 | 以及新版Content-length监听器: 270 | 271 | ``` 272 | array('onResponse', -255)); 287 | } 288 | } 289 | ``` 290 | 291 | *一个订阅者可以拥有多个监听者,以及处理多种事件* 292 | 293 | 为了让框架更加的灵活,不要犹豫,给框架多添加点事件吧,当然为了让框架功能更给力,添加更多的监听器那也是必须的,直到你感觉合适了位置,然后我们可以更进一步改进我们的代码。 294 | 295 | 英文原文地址:http://fabien.potencier.org/article/58/create-your-own-framework-on-top-of-the-symfony2-components-part-9 -------------------------------------------------------------------------------- /Backup/PHP/常见开源消息系统.md: -------------------------------------------------------------------------------- 1 | # 常见开源消息系统 2 | 3 | 消息系统的作用:异步处理、削减峰值、减少组件之间的耦合。 4 | 5 | 选择消息系统根据业务需要需要考虑以下几个方面: 6 | 7 | * 是否持久化 8 | * 吞吐能力 9 | * 高可用 10 | * 分布式扩展能力 11 | * 兼容现有协议 12 | * 易于维护 13 | * 其他,如消息丢失和重复的处理 14 | * 避免单点故障 15 | * 负载均衡 16 | 17 | ## 常见消息系统协议: 18 | 19 | 1. STOMP 20 | 2. AMQP 21 | 3. 类似 MEMCACHE 的协议 22 | 4. HTTP 23 | 5. 自定格式 24 | 25 | **1、2 是不错的可选开源组件:** 26 | 27 | ### 1. Kafka/MetaQ: 广泛用于 Linkedin 内部 (类似有 Java 版本的国产 MetaQ) 28 | 29 | 由于优先考虑吞吐,更加适合大数据量的消息收集和处理,比如日志分析、用户行为信息实时报表、集群状态信息收集和分析。 30 | 31 | * 优先考虑持久化的设计,依靠 page cache 管理内存 32 | * 高吞吐 112MB/s 11K msgs/s (比 beanstalkd >70x 吞吐能力) 33 | * 支持异步复制 34 | * 高可用、基于 Zookeeper 的集群设计、支持消费者失效后重新负载均衡 35 | * Kafka 提供 PHP 类库 36 | * 支持 ganglia JMX 监控 37 | * 需要策略避免重复消息, 消费者更新 Zookeeper 的 offset 的方式 (MetaQ 已经提供了几种方式避免消息重复) 38 | * MetaQ 提供 HTTP 接口 39 | 40 | http://www.mail-archive.com/kafka-users@incubator.apache.org/msg02082.html 41 | https://github.com/neophenix/StateOfTheMQ/blob/master/state_of_the_mq.pdf?raw=true 42 | http://s.urge.omniti.net/i/content/slides/Surge2012-ErikOnen_Kafka_Messaging-Paradigms.pdf 43 | http://research.microsoft.com/en-us/um/people/srikanth/netdb11/netdb11papers/netdb11-final12.pdf 44 | http://dirlt.com/kafka.html 45 | http://dirlt.com/index.html 46 | http://wiki.secondlife.com/wiki/Message_Queue_Evaluation_Notes 47 | 48 | ### 2. NSQ – Golang 49 | 50 | 无中心设计、节点自动注册和发现。可以考虑作为内部通讯框架的基础。 51 | 52 | https://github.com/bitly/nsq 53 | 54 | * 追求简单部署 55 | * 追求高可用、避免单点故障、无中心设计 56 | * 确保消息送达 57 | * 生产者消费者自动发现、消费者连接所有生产者、向消费者推的模式 58 | * 提供 HTTP 接口 59 | 60 | https://speakerdeck.com/snakes/nsq-nyc-golang-meetup 61 | https://github.com/davegardnerisme/nsqphp 62 | http://www.davegardner.me.uk/blog/tag/nsq/ 63 | 64 | ### 3. Beanstalkd 65 | 66 | * 支持持久化 binlog 设计,重启消息不丢失 67 | * 一般 68 | * 无高可用设计 69 | * 和 memcached 一样的分布式扩展方式 70 | * 各种类库 71 | * 有 Web 管理工具 72 | * 支持同步调用,等待返回 73 | * 只有类似 Memcache TCP ASCII 协议, 单文件部署 74 | * 支持消息优先级 75 | * 9K jobs/s 入队列 5K jobs/s 出队列 76 | * 单点故障 77 | * 无主从同步复制机制 78 | * 最好单机多实例部署 79 | 80 | https://github.com/kr/beanstalkd/wiki/Tools 81 | https://github.com/pda/pheanstalk 82 | 83 | ### 4. Redis 84 | 85 | * 需要自己封装 Pub/Sub 86 | * 基于 Redis 的复制高可用 87 | 88 | ### 其他常见开源消息系统: 89 | 90 | #### ZeroMQ: 轻量级基础消息库 91 | 92 | 只适合不需要持久化的场景、需要自己封装 93 | 94 | * 不支持持久化,只提供消息分发, 性能最好 95 | * 无 Broker 设计, 无中心故障 96 | 97 | #### RabbitMQ 98 | 99 | * 2500 job/s 入队列 1300 job/s 出队列 100 | * 适合小消息 101 | * 分布式无单点设计 102 | * 底层为 Erlang 实现 103 | 104 | 有评论: RabbitMQ could not enqueue/dequeue fast enough. 105 | https://blogs.vmware.com/vfabric/2013/04/how-fast-is-a-rabbit-basic-rabbitmq-performance-benchmarks.html 106 | 107 | #### RESTMQ 108 | 109 | http://restmq.com/ 110 | 111 | #### MemcacheQ 112 | 113 | http://memcachedb.org/memcacheq/ 114 | 115 | #### HTTPSQS 116 | 117 | https://code.google.com/p/httpsqs/ 118 | 119 | #### Gearman 120 | 121 | http://gearman.org/presentations 122 | https://code.google.com/p/shard-query/ 123 | 124 | #### Kestrel 125 | 126 | http://robey.github.io/kestrel/ 127 | http://robey.github.io/kestrel/docs/guide.html 128 | 129 | #### HornetQ 130 | 131 | 性能差不考虑[3] 132 | 133 | #### Resque 134 | 135 | 3800 jobs/s 入队列 300 jobs/s 出队列 136 | https://github.com/blog/542-introducing-resque 137 | 基于 Redis 的消息队列 138 | 139 | #### Starling 140 | 141 | https://github.com/starling/starling 142 | 143 | #### SquirrelMQ 144 | 145 | https://code.google.com/p/squirrel-message-queue/ 146 | 147 | #### Sparrow – Ruby 148 | 149 | https://code.google.com/p/sparrow/ 150 | 151 | #### Apache ActiveMQ 152 | 153 | ActiveMQ crashed constantly under load. 154 | 155 | #### STOMP HTTP 协议 156 | 157 | http://stomp.github.io/stomp-specification-1.2.html 158 | 159 | ## 参考: 160 | 161 | http://hiramchirino.com/stomp-benchmark/ec2-c1.xlarge/index.html 162 | https://blog.serverdensity.com/queueing-mongodb-using-mongodb/ 163 | [3] http://x-aeon.com/wp/2013/04/10/a-quick-message-queue-benchmark-activemq-rabbitmq-hornetq-qpid-apollo/ 164 | https://news.ycombinator.com/item?id=5531192 165 | http://www.javaplex.com/blog/high-performance-message-queues-get-reviewed/ 166 | http://adam.heroku.com/past/2010/4/24/beanstalkasimpleandfastqueueingbackend/ 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /Backup/linux/AWK编程基础.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/AWK编程基础.pdf -------------------------------------------------------------------------------- /Backup/linux/Linux_C_HS.chm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/Linux_C_HS.chm -------------------------------------------------------------------------------- /Backup/linux/Linux命令图解.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/Linux命令图解.pdf -------------------------------------------------------------------------------- /Backup/linux/Linux学习笔记.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/Linux学习笔记.pdf -------------------------------------------------------------------------------- /Backup/linux/Mac_OSX_shortcuts_CN.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/Mac_OSX_shortcuts_CN.pdf -------------------------------------------------------------------------------- /Backup/linux/README.md: -------------------------------------------------------------------------------- 1 | # 学习资料 2 | 3 | * [Linux运维趋势](http://os.51cto.com/art/201011/233915.htm) 4 | * http://bbs.linuxtone.org/thread-22436-1-1.html 5 | * http://distrowatch.com/ 6 | 7 | 8 | ## 工具 9 | * http://docs.linuxtone.org/ 10 | * http://soft.vpser.net/ 11 | * http://www.server-world.info/en/ 12 | 13 | ## 镜像 14 | * 阿里云:https://mirrors.aliyun.com/ 15 | * 网易开源镜像站:http://mirrors.163.com/ 16 | * 搜狐开源镜像站:http://mirrors.sohu.com/ 17 | * 北京交通大学:http://mirror.bjtu.edu.cn/cn/ 18 | * 兰州大学:http://mirror.lzu.edu.cn/ 19 | * 北京理工大学:http://mirror.bit.edu.cn/web/ 20 | * 中国科技大学:http://mirrors.ustc.edu.cn/ 、 http://ubuntu.uestc.edu.cn/ 21 | * 清华大学开源镜像网站 : http://mirrors.tuna.tsinghua.edu.cn/ 22 | * 电子科技大学 : http://mirrors.stuhome.net/ 23 | * 天津大学开源软件镜像站 : http://mirror.tju.edu.cn/ 24 | * 厦门大学:http://mirrors.xmu.edu.cn/ 25 | * 上海交通大学:http://ftp.sjtu.edu.cn/ 26 | * 西南大学:http://linux.swu.edu.cn/swudownload/ 27 | * 泰安移动:http://mirrors.ta139.com/ 28 | * 东北大学:http://mirror.neu.edu.cn/ 29 | * 浙江大学:http://mirrors.zju.edu.cn/ 30 | * 东软信息学院:http://mirrors.neusoft.edu.cn/ 31 | * 哈尔滨工业大学: http://run.hit.edu.cn/ 32 | * 大连理工大学: http://mirror.dlut.edu.cn/ 33 | * 中国互联网信息中心:http://mirrors.cnnic.cn 34 | * 西南大学:http://linux.swu.edu.cn/swudownload/Distributions/ 35 | * 首都在线科技股份有限公司:http://mirrors.yun-idc.com/ 36 | 37 | ### Debian 38 | * http://www.dotdeb.org/instructions/ 39 | * http://dotdeb.90g.org/ 40 | * http://mirror.pcbeta.com/packman/debian/ 41 | -------------------------------------------------------------------------------- /Backup/linux/Rsync命令参数详解.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/Rsync命令参数详解.doc -------------------------------------------------------------------------------- /Backup/linux/Sed命令学习笔记.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/Sed命令学习笔记.pdf -------------------------------------------------------------------------------- /Backup/linux/awk使用手册.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/awk使用手册.pdf -------------------------------------------------------------------------------- /Backup/linux/awk学习思维导图.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/awk学习思维导图.jpg -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作基础/Shell 和命令操作基础.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作基础/Shell 和命令操作基础.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作基础/信息显示命令.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作基础/信息显示命令.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作基础/基本网络操作命令.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作基础/基本网络操作命令.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作基础/字符操作界面简介.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作基础/字符操作界面简介.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作基础/文件与目录操作命令.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作基础/文件与目录操作命令.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作基础/文件概述.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作基础/文件概述.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作基础/文本处理命令.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作基础/文本处理命令.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/Shell 变量和 Shell 环境.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/Shell 变量和 Shell 环境.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/find.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/find.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/sed 和 awk.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/sed 和 awk.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/提高工作效率.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/提高工作效率.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/文件权限及设置命令.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/文件权限及设置命令.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/文件编辑器 vi.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/文件编辑器 vi.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/正则表达式基础.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/正则表达式基础.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/进程管理和作业控制.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/进程管理和作业控制.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/重定向和管道.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Linux 字符界面操作进阶/重定向和管道.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Shell 脚本编程/Shell 脚本示例分析.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Shell 脚本编程/Shell 脚本示例分析.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Shell 脚本编程/Shell 脚本简介.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Shell 脚本编程/Shell 脚本简介.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Shell 脚本编程/使用特殊环境变量.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Shell 脚本编程/使用特殊环境变量.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Shell 脚本编程/分支结构.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Shell 脚本编程/分支结构.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Shell 脚本编程/子程序结构.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Shell 脚本编程/子程序结构.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Shell 脚本编程/循环结构.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Shell 脚本编程/循环结构.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Shell 脚本编程/条件测试.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Shell 脚本编程/条件测试.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/Shell 脚本编程/深入 Shell 变量操作.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/Shell 脚本编程/深入 Shell 变量操作.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/TCPIP 网络配置/网络测试方法和测试工具.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/TCPIP 网络配置/网络测试方法和测试工具.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/TCPIP 网络配置/路由表和静态路由.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/TCPIP 网络配置/路由表和静态路由.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/TCPIP 网络配置/配置基本网络参数.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/TCPIP 网络配置/配置基本网络参数.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/包管理与系统更新/使用 RPM 管理包.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/包管理与系统更新/使用 RPM 管理包.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/包管理与系统更新/使用 yum 工具更新系统.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/包管理与系统更新/使用 yum 工具更新系统.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/备份与恢复/Linux 下的光盘刻录.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/备份与恢复/Linux 下的光盘刻录.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/备份与恢复/使用 rsync 同步.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/备份与恢复/使用 rsync 同步.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/备份与恢复/使用 rsync 服务.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/备份与恢复/使用 rsync 服务.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/备份与恢复/使用 tar 备份.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/备份与恢复/使用 tar 备份.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/备份与恢复/备份简介.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/备份与恢复/备份简介.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/守护进程管理/Xinetd 和 TCP Wrapper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/守护进程管理/Xinetd 和 TCP Wrapper.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/守护进程管理/守护进程简介.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/守护进程管理/守护进程简介.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/守护进程管理/安全登录守护进程.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/守护进程管理/安全登录守护进程.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/守护进程管理/安排周期性任务.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/守护进程管理/安排周期性任务.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/守护进程管理/日志系统和系统日志.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/守护进程管理/日志系统和系统日志.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/守护进程管理/时钟同步守护进程.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/守护进程管理/时钟同步守护进程.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/守护进程管理/管理守护进程.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/守护进程管理/管理守护进程.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/安装 CentOS/安装 Linux 之前的必备知识.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/安装 CentOS/安装 Linux 之前的必备知识.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/安装 CentOS/安装后的基本配置.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/安装 CentOS/安装后的基本配置.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/安装 CentOS/服务器方式安装 CentOS 5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/安装 CentOS/服务器方式安装 CentOS 5.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/文件系统管理/Linux 文件系统概述.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/文件系统管理/Linux 文件系统概述.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/文件系统管理/ext2-ext3 文件系统管理.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/文件系统管理/ext2-ext3 文件系统管理.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/文件系统管理/挂装和卸装文件系统.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/文件系统管理/挂装和卸装文件系统.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/文件系统管理/磁盘限额.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/文件系统管理/磁盘限额.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/磁盘管理和 LVM 管理/LVM 简介.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/磁盘管理和 LVM 管理/LVM 简介.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/磁盘管理和 LVM 管理/创建 LVM 系统.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/磁盘管理和 LVM 管理/创建 LVM 系统.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/磁盘管理和 LVM 管理/硬盘相关概念.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/磁盘管理和 LVM 管理/硬盘相关概念.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/磁盘管理和 LVM 管理/磁盘分区工具.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/磁盘管理和 LVM 管理/磁盘分区工具.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/磁盘管理和 LVM 管理/维护 LVM 系统.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/磁盘管理和 LVM 管理/维护 LVM 系统.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/系统引导和启动/单用户模式和修复模式.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/系统引导和启动/单用户模式和修复模式.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/系统引导和启动/系统启动过程.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/系统引导和启动/系统启动过程.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/系统引导和启动/系统引导器.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/系统引导和启动/系统引导器.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/系统监控/lsof 工具.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/系统监控/lsof 工具.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/系统监控/psacct 工具.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/系统监控/psacct 工具.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/系统监控/sysstat 工具.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/系统监控/sysstat 工具.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/系统监控/系统监视初步.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/系统监控/系统监视初步.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/账户管理/使用账户管理命令.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/账户管理/使用账户管理命令.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/账户管理/口令管理和口令时效.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/账户管理/口令管理和口令时效.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/账户管理/用户切换和用户状态命令.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/账户管理/用户切换和用户状态命令.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/CentOS系统管理/账户管理/账户管理概述.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/centos/CentOS系统管理/账户管理/账户管理概述.pdf -------------------------------------------------------------------------------- /Backup/linux/centos/自定义光盘.md: -------------------------------------------------------------------------------- 1 | # 自定义光盘 CentOS 6.4 mini 2 | 3 | ## 参考 4 | * http://xlogin.blog.51cto.com/3473583/1261632 5 | * http://blog.csdn.net/zhangrenfang/article/details/10160025 6 | * http://hi.baidu.com/higkoo/item/936544870a684f55e63d19b1 7 | * http://yuanbor.blog.163.com/blog/static/5667462020132148935577/ 8 | * http://my.oschina.net/laudor/blog/69239 9 | * http://blog.csdn.net/e421083458/article/details/7981706 10 | * http://blog.csdn.net/hncomputer/article/details/7269874 11 | * http://blog.chinaunix.net/uid-25471613-id-3153675.html 12 | * http://blog.csdn.net/kakane/article/details/7715800 13 | 14 | ## 导入库 15 | rpm -Uvh http://dl.iuscommunity.org/pub/ius/stable/CentOS/6/x86_64/epel-release-6-5.noarch.rpm 16 | rpm -Uvh http://dl.iuscommunity.org/pub/ius/stable/CentOS/6/x86_64/ius-release-1.0-11.ius.centos6.noarch.rpm 17 | rpm -Uvh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm 18 | 19 | 定制步骤: 20 | 1、安装一个干净的操作系统.包括基本的系统和所需要的工具等. 21 | 比如:对于http,mysql等软件,建议使用编译的方式安装, 然后打包放进去,可以减少许多依赖包的麻烦. 22 | 2、安装系统后,收集系统已安装的软件包,使用脚本统一转存到一个目录中. 23 | 3、在安装光盘复制images镜像,从光盘启动centos安装所需的文件等. 24 | 4、定义自己的kickstart安装脚本. 25 | 5、按照之前转存的软件(rpm)包, 重新生成光盘的report信息. 26 | 6、打包生成ISO文件,及MD5效验码. 27 | 28 | 光盘结构介绍: 29 | * isolinux目录存放光盘启动时的安装界面 30 | * images目录包括了必要的启动映像文件 31 | * CentOS目录存放安装软件包及信息 32 | * .discinfo文件是安装价质的识别信息 33 | 34 | ## ISO 镜像 35 | 1.yum -y install rsync 36 | 37 | ### 挂载光盘,使用脚本拷贝相关软件包到/ISO/Packages目录下 38 | 2.mkdir /mnt/cdrom 39 | 3.mount /dev/cdrom /mnt/cdrom 40 | 4./usr/bin/rsync -a --exclude=Packages/ --exclude=repodata/ /mnt/cdrom/ /ISO/ 41 | 5.mkdir -p /ISO/{Packages,repodata} 42 | 43 | 44 | 6.vi copy.sh 45 | ` 46 | #!/bin/bash 47 | cd /root 48 | awk '/安装/{print $2}' install.log | sed 's/^*://g' >package.txt 49 | DVD='/mnt/cdrom/Packages' 50 | PACKDIR='/root/package.txt' 51 | NEW_DVD='/ISO/Packages' 52 | while read LINE 53 | do 54 | cp ${DVD}/${LINE}*.rpm /${NEW_DVD} || echo "$LINE don't cp......." 55 | done < package.txt 56 | rm -f package.txt 57 | ` 58 | 59 | 7.chmod +x copy.sh 60 | 8../copy.sh 61 | 9.ll /ISO/Packages/ |wc -l 62 | 63 | ### 定制kickstart安装脚本ks.cfg,并修改/ISO/isolinux/isolinux.cfg文件,默认isolinux.cfg的权限为444,只能读,无法修改 64 | 10.cd /ISO 65 | 11.cp ~/anaconda-ks.cfg isolinux/ks.cfg 66 | ### 修改 ks.cfg isolinux.cfg 67 | 68 | ### 部署 LNMP 69 | 70 | ### 安装anaconda repodata createrepo mkisofs等工具,执行createrepo程序生成repodata下的comps.xml文件 71 | 12.yum -y install anaconda repodata createrepo mkisofs rsync 72 | 13.cp /mnt/cdrom/repodata/*-minimal-x86_64.xml /ISO/repodata/minimal-x86_64.xml 73 | 14.createrepo -g repodata/minimal-x86_64.xml . 74 | 15.declare -x discinfo=`head -1 .discinfo` 75 | 16.mv /ISO/repodata/*minimal-x86_64.xml /ISO/repodata/minimal-x86_64.xml 76 | 17.createrepo -u "media://$discinfo" -g repodata/minimal-x86_64.xml . 77 | 78 | ### 使用mkisofs命令生成ISO文件 79 | 18.mkisofs -o CentOS-6.4_64.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -R -J -v -T /ISO/ 80 | 81 | ### 生成ISO文件MD5值 82 | 19./usr/bin/implantisomd5 /ISO/CentOS-6.4_64.iso 83 | 84 | ## 创建一个Kickstart安装脚本 85 | 86 | 在CentOS安装完成后,会在root用户的家目录中自动生成一个 /root/anaconda-ks.cfg 配置文件。这个就是Kickstart的安装脚本了。如果需要克隆当前的服务器,完全可以拷贝出来在另一台机子上重复使用。 87 | 也可以直接调用Kickstart配置程序来生成安装脚本。进入CentOS系统,“应用程序”->“系统工具”下找到Kickstart。按需调用相应的程序,具体如下: 88 | 1.Basic Configuration (基本设置)可以指定root密码、默认语言、键盘设置以及时区等。还可以选择安装系统时的界面(text mode)。以加快安装进程的速度。 89 | 2.Installation Method (安装方式)选择是安装全新操作系统还是升级。不推荐使用Kickstart升级操作系统,因为在升级的过程中会出现很多的交互选项,会比较麻烦。还可以指定安装源(如:CD-ROM、NFS、FTP、HTTP或本地磁盘) 90 | 3.Boot Loader Options (启动选项)修改启动选项的设置,一般使用默认的就可以了。 91 | 4.Partition Information (分区设置)如果你的服务器上有SAN存储器,需要谨慎操作此选项。在默认情况下,Kickstart脚本会尝试清除SAN存储器中的内容,并将新操作系统安装在上面。 92 | Network Configuration (网络设置)Kickstart默认不会修改网络接口。因为IP地址每台机子都是唯一的。具体需要怎么做,笔者稍候会作出解答^_^。 93 | 5.Authentication (认证)Kickstart默认使用shadow文件进行密码认证。对于大型系统的部署,可能会用到专用的认证系统。Kickstart支持NIS,LDAP,Kerberos,SMB 和Name Switch Cache。 94 | 6.Firewall Configuration (防火墙设置)可以设置防火墙和SELinux。如果你不喜欢SELinux直接禁用就可以了。如果是最小化安装,建议禁用防火墙稍候再设置。 95 | 7.Display Configuration (显示设置)如果是服务器的话,直接text mode就可以了。 96 | 8.Package Selection (安装包选择)指定CentOS预安装的软件包。 97 | 9.Pre-installation Script (预执行脚本) 和 Post-installation Script (延迟执行脚本)定义bash、Perl或Python脚本以供安装脚本使用。 98 | 99 | **备注:由于centos6.x系统无法在--nochroot环境下挂载,只能在%post下挂载,挂载方式跟在真实linux环境下一致,命令和挂载路径也一致。** 100 | -------------------------------------------------------------------------------- /Backup/linux/linux-training.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/linux-training.doc -------------------------------------------------------------------------------- /Backup/linux/linux命令手册.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/linux命令手册.pdf -------------------------------------------------------------------------------- /Backup/linux/rsync安装与配置-完整版.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/rsync安装与配置-完整版.doc -------------------------------------------------------------------------------- /Backup/linux/sed使用手册.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/sed使用手册.pdf -------------------------------------------------------------------------------- /Backup/linux/sed学习思维导图.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/sed学习思维导图.jpg -------------------------------------------------------------------------------- /Backup/linux/shell语法.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/shell语法.txt -------------------------------------------------------------------------------- /Backup/linux/vi.md: -------------------------------------------------------------------------------- 1 | # vi基本命令 2 | 3 | ## 光标命令 4 | 5 | * 左 `h` 上 `j` 下 `k` 右 `l` 6 | * `nG` n为行数,该命令即时使光标跳到指定行,n为空,光标跳到文件最后一行。 7 | * `Ctrl+G` 光标所在位置的行数和列数报告 8 | * `w,b` 使光标向前或向后跳过一个单词 9 | 10 | ## 编辑命令 11 | 12 | * `(n)dd` 删除 13 | * `(n)yy` 复制 14 | * `i` 光标前插入 15 | * `a` 当前字母后插入 16 | * `r` 在当前光标处替换 17 | * `cw` 替换光标所在处的单词(从光标开始处) 18 | * `dw` 删除光标所在处的单词 19 | * `x` 删除(右) 20 | * `X` 删除(左) 21 | * `u` 撤销 22 | * `.` 重复上次操作 23 | * `o` 插入新行 24 | * `J` 合并两行 25 | * `A` 行尾 26 | 27 | ## 查找命令 28 | 29 | * `f` 查找 30 | * `/` 查找 31 | 32 | ## 复制粘贴命令 33 | 34 | * `(n)yy` 拷贝n行到剪切板 35 | * `p` 粘贴(后) 36 | * `P` 粘贴(当前) 37 | 38 | # vi选项设置 39 | 40 | vi是个强大的编辑器,他不仅能用来处理我们平时的文本工作,还能用来写程式文件。在用vi进行程式编辑时,他能实现语法加亮显示、自动缩进、括号匹配等编辑功能。为控制不同的编辑功能,vi 提供了非常多内部选项。 41 | 42 | 利用 :set 命令能设置选项。基本语法为: 43 | 44 | `:set option` 设置选项 option 45 | 46 | 常见的功能选项包括: 47 | 48 | * `autoindent` 设置该选项,则正文自动缩进 49 | * `ignorecase` 设置该选项,则忽略规则表达式中大小写字母的差别 50 | * `number` 设置该选项,则显示正文行号 51 | * `ruler` 设置该选项,则在屏幕底部显示光标所在行、列的位置 52 | * `tabstop` 设置按 Tab 键跳过的空格数。例如:set tabstop=n,n默认值为8 53 | 54 | ## 语法加亮显示 55 | 56 | `:syntax on` 57 | 58 | 该命令在vi中打开语法加亮显示的功能。这样以后在输入的字符中,vi就会自动的识别出关键字,字符串及其他的一些语法元素,并以不同的颜色来显示出来。 59 | 60 | ## 自动缩进 61 | 62 | 在vi中自动缩进的选项一般有以下的几种: 63 | 64 | * `autoindent` : 在这种缩进形式中,新增加的行和前一行有相同的缩进形式。 65 | * `smartindent` : 在这种缩进模式中,每一行都和前一行有相同的缩进量,同时能够正确的识别出{和},当遇见右花括号(}),则取消了缩进形式。此外还增加了识别C语言关键字的功能。如果一行是以#开头的,那么这种格式将会被特别对待而不采用缩进格式。这种缩进格式强于autoindent。 66 | * `cindent`:这是C语言的缩进形式,采用这样的缩进方式的程式语言有:C,C++,Java等。当采用这种缩进格式时,vi就会自动的采用标准的C语言形式。这种缩进格式强于smartindent。 67 | 68 | 能用如下命令进行缩进形式的设置: 69 | 70 | * `:set autoindent(ai)` 71 | * `:set smartindent(si)` 72 | * `:set cindent(ci) ` 73 | 74 | ## 显示行号 75 | * `:set number(nu)` 显示行号 76 | * `:set nonumber (nonu)` 不显示行号 77 | 78 | 在每个用户的目录下,都有一个vi的设置文件".vimrc"(没有的话能自己创建)。 79 | 用户能编辑他,输入以上命令,使这些设置在每次vi时都有效。例如:在.vimrc文件中加入如下设置行: 80 | 81 | * `set nu` #显示行号 82 | * `set nonu` #不显示行号 83 | * `set ic` #查找时不考虑大小写 84 | * `set noic` #查找时考虑大小写 85 | * `set smartindent` #自动缩进 86 | * `syntax on` #语法加亮 87 | 88 | 89 | --------------- 90 | 91 | # vi的工作模式 (详解) 92 | 93 | 编辑模式: 用户能利用一些预先定义的按键来移动光标、删除文字、复制或粘贴文字等。`l` 是向右移动光标,相当于向右箭头键,`k` 是向下移动光标,相当于向下箭头键。 94 | 95 | 当用户在编辑模式下键入 `i`, `a`, `o` 等命令之后,可进入插入模式; 96 | 键入 : 可进入命名模式。 97 | 98 | 在插入模式下,用户随后输入的,除 `Esc` 之外的所有字符均将被看成是插入到编辑缓冲区中的字符。按 `Esc` 之后,从插入模式转换到编辑模式。 99 | 100 | 在命令模式,Vi 将把光标挪到屏幕的最下方,并在第一个字符的位置显示一个 :(冒号)。 101 | 这时,用户就能键入一些命令。这些命令可用来保存文件、读取文件内容、执行 Shell 命令、设置 Vi 参数、以正则表达式的方式查找字符串或替换字符串等。 102 | 103 | 104 | ## 编辑模式 105 | 106 | 移动光标要对正文内容进行修改,首先必须把光标移动到指定位置。移动光标的最简单的方式是按键盘的上、下、左、右箭头键。除了这种最原始的方法之外,用户还能利用 vi 提供的众多字符组合键,在正文中移动光标,迅速到达指定的行或列,实现定位。例如: 107 | 108 | * `k`、`j`、`h`、`l` 功能分别等同于上、下、左、右箭头键 109 | * `Ctrl+b` 在文件中向上移动一页(相当于 PageUp 键) 110 | * `Ctrl+f` 在文件中向下移动一页(相当于 PageDown 键) 111 | * `H` 将光标移到屏幕的最上行(Highest) 112 | * `nH` 将光标移到屏幕的第 n 行 113 | * `2H` 将光标移到屏幕的第 2 行 114 | * `M` 将光标移到屏幕的中间(Middle) 115 | * `L` 将光标移到屏幕的最下行(Lowest) 116 | * `nL` 将光标移到屏幕的倒数第 n 行 117 | * `3L` 将光标移到屏幕的倒数第 3 行 118 | * `w` 在指定行内右移光标,到下一个字的开头 119 | * `e` 在指定行内右移光标,到一个字的末尾 120 | * `b` 在指定行内左移光标,到前一个字的开头 121 | * `0` 数字0,左移光标,到本行的开头 122 | * `$` 右移光标,到本行的末尾 123 | * `^` 移动光标,到本行的第一个非空字符 124 | 125 | 替换和删除将光标定位于文件内指定位置后,能用其他字符来替换光标所指向的字符,或从当前光标位置删除一个或多 126 | 个字符。例如: 127 | 128 | * `rc` 用 c 替换光标所指向的当前字符 129 | * `nrc` 用 c 替换光标所指向的前 n 个字符 130 | * `5rc` 用 c 替换光标所指向的前 5 个字符 131 | * `x` 删除光标所指向的当前字符 132 | * `nx` 删除光标所指向的前 n 个字符 133 | * `3x` 删除光标所指向的前 3 个字符 134 | * `dw` 删除光标右侧的字 135 | * `ndw` 删除光标右侧的 n 个字 136 | * `3dw` 删除光标右侧的 3 个字 137 | * `db` 删除光标左侧的字 138 | * `ndb` 删除光标左侧的 n 个字 139 | * `5db` 删除光标左侧的 5 个字 140 | * `dd` 删除光标所在行,并去除空隙 141 | * `ndd` 删除 n 行内容,并去除空隙 142 | * `3dd` 删除 3 行内容,并去除空隙 143 | 144 | 粘贴和复制从正文中删除的内容(如字符、字或行)并没有真正丢失,而是被剪切并复制到了一个内存缓冲区中。用户可 145 | 将其粘贴到正文中的指定位置。完成这一操作的命令是: 146 | 147 | * `p` 小写字母 p,将缓冲区的内容粘贴到光标的后面 148 | * `P` 大写字母 P,将缓冲区的内容粘贴到光标的前面 149 | 150 | 如果缓冲区的内容是字符或字,直接粘贴在光标的前面或后面;如果缓冲区的内容为整行正文,则粘贴在当前 151 | 光标所在行的上一行或下一行。 152 | 153 | *注意上述两个命令中字母的大小写。vi 编辑器经常以一对大、小写字母(如 p 和 P)来提供一对相似的功能 154 | 。 155 | 通常,小写命令在光标的后面进行操作,大写命令在光标的前面进行操作。* 156 | 157 | 有时需要复制一段正文到新位置,同时保留原有位置的内容。这种情况下,首先应当把指定内容复制(而不是 158 | 剪切)到内存缓冲区。完成这一操作的命令是: 159 | 160 | * `yy` 复制当前行到内存缓冲区 161 | * `nyy` 复制 n 行内容到内存缓冲区 162 | * `5yy` 复制 5 行内容到内存缓冲区 163 | 164 | 搜索字符串和许多先进的编辑器相同,vi 提供了强大的字符串搜索功能。要查找文件中指定字或短语出现的位置,能 165 | 用 vi 直接进行搜索,而不必以手工方式进行。搜索方法是: 166 | 167 | 键入字符 / ,后面跟以要搜索的字符串,然后按回车键。编辑程式执行正向搜索(即朝文件末尾方向),并在找到指定字符串后,将光标停到该字符串的开头;键入 n 命令能继续执行搜索,找出这一字符串下次出现的位置。用字符 ? 取代 / ,能实现反向搜索(朝文件开头方向)。例如: 168 | 169 | * `/str1` 正向搜索字符串 str1 170 | * `n` 继续搜索,找出 str1 字符串下次出现的位置 171 | * `?str2` 反向搜索字符串 str2 172 | 173 | 无论搜索方向怎么,当到达文件末尾或开头时,搜索工作会循环到文件的另一端并继续执行。 174 | 175 | 撤销和重复在编辑文件的过程中,为消除某个错误的编辑命令造成的后果,能用撤消命令。另外,如果用户希望在新 176 | 的光标位置重复前面执行过的编辑命令,可用重复命令。 177 | 178 | * `u` 撤消前一条命令的结果 179 | * `.` 重复最后一条修改正文的命令 180 | 181 | 文本选中vi 可进入到一种成为 Visual 的模式,在该模式下,用户能用光标移动命令可视地选择文本,然后再执行其他编辑操作,例如删除、复制等。 182 | 183 | * `v` 字符选中命令 184 | * `V` 行选中命令 185 | 186 | ## 插入模式 187 | 188 | 进入插入模式在编辑模式下正确定位光标之后,可用以下命令转换到插入模式: 189 | 190 | * `i` 在光标左侧输入正文 191 | * `a` 在光标右侧输入正文 192 | * `o` 在光标所在行的下一行增添新行 193 | * `O` 在光标所在行的上一行增添新行 194 | * `I` 在光标所在行的开头输入正文 195 | * `A` 在光标所在行的末尾输入正文 196 | 197 | 上面介绍了几种转换到插入模式的简单方法。另外更有一些命令,他们允许在进入插入模式之前首先删去一段 198 | 正文,从而实现正文的替换。这些命令包括: 199 | 200 | * `s` 用输入的正文替换光标所指向的字符 201 | * `ns` 用输入的正文替换光标右侧 n 个字符 202 | * `cw` 用输入的正文替换光标右侧的字 203 | * `ncw` 用输入的正文替换光标右侧的 n 个字 204 | * `cb` 用输入的正文替换光标左侧的字 205 | * `ncb` 用输入的正文替换光标左侧的 n 个字 206 | * `cd` 用输入的正文替换光标的所在行 207 | * `ncd` 用输入的正文替换光标下面的 n 行 208 | * `c$` 用输入的正文替换从光标开始到本行末尾的所有字符 209 | * `c0` 用输入的正文替换从本行开头到光标的所有字符 210 | 211 | 退出插入模式退出插入模式的方法是,按 `ESC` 键或组合键 `Ctrl+[` 。 212 | 213 | ## 命令模式 214 | 215 | *命令模式在 vi 的命令模式下,能使用复杂的命令。在编辑模式下键入“:”,光标就跳到屏幕最后一行,并在那里显示冒号,此时已进入命令模式。命令模式又称“末行模式”,用户输入的内容均显示在屏幕的最后一行,按回车键,vi 执行命令。* 216 | 217 | 退出命令在编辑模式下能用 ZZ 命令退出 vi 编辑程式,该命令保存对正文所作的修改,覆盖原始文件。如果只需要退出编辑程式,而不打算保存编辑的内容,可用下面的命令: 218 | 219 | * `:q` 在未作修改的情况下退出 220 | * `:q!` 放弃所有修改,退出编辑程式 221 | 222 | 行号和文件编辑中的每一行正文都有自己的行号,用下列命令能移动光标到指定行: 223 | 224 | * `:n` 将光标移到第 n 行 225 | 226 | 命令模式下,能规定命令操作的行号范围。数值用来指定绝对行号;字符“.”表示光标所在行的行号;字符 227 | 符“$”表示正文最后一行的行号;简单的表达式,例如“.+5”表示当前行往下的第 5 行。例如: 228 | 229 | * `:345` 将光标移到第 345 行 230 | * `:345w file` 将第 345 行写入 file 文件 231 | * `:3,5w file` 将第 3 行至第 5 行写入 file 文件 232 | * `:1,.w file` 将第 1 行至当前行写入 file 文件 233 | * `:.,$w file` 将当前行至最后一行写入 file 文件 234 | * `:.,.+5w file` 从当前行开始将 6 行内容写入 file 文件 235 | * `:1,$w file` 将所有内容写入 file 文件,相当于 :w file 命令 236 | 237 | 在命令模式下,允许从文件中读取正文,或将正文写入文件。例如: 238 | 239 | * `:w` 将编辑的内容写入原始文件,用来保存编辑的中间结果 240 | * `:wq` 将编辑的内容写入原始文件并退出编辑程式(相当于 ZZ 命令) 241 | * `:w file` 将编辑的内容写入 file 文件,保持原有文件的内容不变 242 | * `:a,bw file` 将第 a 行至第 b 行的内容写入 file 文件 243 | * `:r file` 读取 file 文件的内容,插入当前光标所在行的后面 244 | * `:e file` 编辑新文件 file 代替原有内容 245 | * `:f file` 将当前文件重命名为 file 246 | * `:f` 打印当前文件名称和状态,如文件的行数、光标所在的行号等 247 | 248 | 字符串搜索给出一个字符串,能通过搜索该字符串到达指定行。如果希望进行正向搜索,将待搜索的字符串置于两个“ 249 | /”之间;如果希望反向搜索,则将字符串放在两个“?”之间。例如: 250 | 251 | * `:/str/` 正向搜索,将光标移到下一个包含字符串 str 的行 252 | * `:?str?` 反向搜索,将光标移到上一个包含字符串 str 的行 253 | * `:/str/w file` 正向搜索,并将第一个包含字符串 str 的行写入 file 文件 254 | * `:/str1/,/str2/w file` 正向搜索,并将包含字符串 str1 的行至包含字符串 str2 的行写入 file 文件 255 | 256 | 正文替换利用 :s 命令能实现字符串的替换。具体的用法包括: 257 | 258 | * `:s/str1/str2/` 用字符串 str2 替换行中首次出现的字符串 str1 259 | * `:s/str1/str2/g` 用字符串 str2 替换行中所有出现的字符串 str1 260 | * `:.,$ s/str1/str2/g` 用字符串 str2 替换正文当前行到末尾所有出现的字符串 str1 261 | * `:1,$ s/str1/str2/g` 用字符串 str2 替换正文中所有出现的字符串 str1 262 | * `:g/str1/s//str2/g` 功能同上 263 | 264 | 从上述替换命令能看到:g 放在命令末尾,表示对搜索字符串的每次出现进行替换;不加 g,表示只对搜索 265 | 字符串的首次出现进行替换;g 放在命令开头,表示对正文中所有包含搜索字符串的行进行替换操作。 266 | 267 | 删除正文在命令模式下,同样能删除正文中的内容。例如: 268 | 269 | * `:d` 删除光标所在行 270 | * `:3d` 删除 3 行 271 | * `:.,$d` 删除当前行至正文的末尾 272 | * `:/str1/,/str2/d` 删除从字符串 str1 到 str2 的所有行 273 | 274 | 恢复文件vi 在编辑某个文件时,会另外生成一个临时文件,这个文件的名称通常以 . 开头,并以 .swp 结尾。 275 | vi 在正常退出时,该文件被删除,若意外退出,而没有保存文件的最新修改内容,则能使用恢复命令: 276 | 277 | * `:recover` 恢复文件 278 | 279 | 也能在启动 vi 时利用 -r 选项。 280 | 281 | 选项设置为控制不同的编辑功能,vi 提供了非常多内部选项。利用 :set 命令能设置选项。基本语法为: 282 | 283 | * `:set option` 设置选项 option 284 | 285 | 常见的功能选项包括: 286 | 287 | * `autoindent` 设置该选项,则正文自动缩进 288 | * `ignorecase` 设置该选项,则忽略规则表达式中大小写字母的差别 289 | * `number` 设置该选项,则显示正文行号 290 | * `ruler` 设置该选项,则在屏幕底部显示光标所在行、列的位置 291 | * `tabstop` 设置按 Tab 键跳过的空格数。例如 :set tabstop=n,n 默认值为 8 292 | * `mk` 将选项保存在当前目录的 .exrc 文件中 -------------------------------------------------------------------------------- /Backup/linux/管理员必备的_linux_系统监控工具.md: -------------------------------------------------------------------------------- 1 | #管理员必备的 Linux 系统监控工具 2 | 3 | 需要监控 Linux 服务器系统性能吗?尝试下面这些系统内置或附件的工具吧。大多数 Linux 发行版本都装备了大量的监控工具,这些工具提供了能用作取得相关信息和系统活动的量度指标。 4 | 你能使用这些工具发现造成性能问题可能原因,这些原因包括: 5 | 6 | 1. 找出瓶颈 7 | 2. 硬盘(存储)瓶颈 8 | 3. CPU 及内存瓶颈 9 | 4. 网络瓶颈 10 | 11 | 下面开始介绍找出这些原因的工具。当然,这份列表只是所有监控工具当中很小的一部分。 12 | 13 | ##1: top - 进程活动 14 | top 提供一个当前运行系统实时动态的视图,也就是正在运行进程。在默认情况下,显示系统中 CPU 使用率最高的任务,并每 5 秒钟刷新一次。 15 | 16 | ##2: vmstat -系统活动、硬件及系统信息 17 | 使用 vmstat 命令可以得到关于进程、内存、内存分页、堵塞 IO、traps 及 CPU 活动的信息。 18 | 19 | ##3: w - 显示谁已登录,他们正在做什么? 20 | w 命令显示系统当前用户及其运行进程的信息。 21 | 22 | ##4:uptime - 告诉系统已经运行了多久? 23 | uptime 命令过去只显示系统运行多久。现在,可以显示系统运行多久、当前有多少的用户登录、在过去的 1,5,15 分钟里平均负载时多少。 24 | 25 | ##5:ps - 显示进程 26 | ps 命令显示当前运行进程的快照。使用-A 或-e 显示所有进程。ps 与 top 非常相似,但 ps 提供更多的信息。 27 | 28 | ##6: free - 内存使用情况 29 | free 命令显示系统中空闲的、已用的物理内存及 swap 内存,及被内核使用的 buffer。 30 | 31 | ##7: iostat - CPU 平均负载,硬盘活动 32 | iostat 命令可报告中央处理器(CPU)的统计信息,各种设备、分区及网络文件系统输入/输出的统计信息。 33 | 34 | ##8: sar - 搜集和报告系统活动 35 | sar 命令用来搜集、报告和储存系统活动信息。 36 | 37 | ##9:mpstat - 多处理器使用率 38 | mpstat 命令可以显示所有可用处理器的使用情况,处理器编号从 0 开始。mpstat -P ALL 显示每个处理器的平均使用率。 39 | 40 | #10: pmap - 进程的内存使用 41 | pmap 命令可以显示进程的内存映射,使用这个命令可以找出造成内存瓶颈的原因。 42 | 本文介绍找出这些性能问题原因的工具。当然,这份列表只是所有监控工具当中很小的一部分。 43 | 44 | ##11:netstat - 网络相关信息 45 | netstat 可以显示网络链接、路由表信息、接口统计信息、伪装链接和多播成员(multicast memberships) 46 | 47 | ##12:ss - 网络相关信息 48 | ss 命令用来显示网络套接字信息,它允许显示类似 netstat 一样的信息。 49 | 50 | ##13: iptraf - 网络实时信息 51 | iptraf 是一个可交互式的 IP 网络监控工具。它可以生成多种网络统计信息包括: TCP 信息、UDP 数量、ICMP 和 OSPF 信息、以太网负载信息、节点状态、IP 校验错误等。 52 | 53 | ##14:tcpdump:详细的网络流量分析 54 | tcpdump 是一个简单网络流量转储工具,然而要使用好需要对 TCP/IP 协议非常熟悉。 55 | 56 | ##15:strace - 系统调用 57 | 追踪系统调用和型号,这对于调试 Web 服务器和其他服务器非常有用。了解怎样追踪进程和他功能。 58 | 59 | ##16:/proc 文件系统 - 各种内核信息 60 | /proc 目录下文件提供了很多不同硬件设备和内核的详细信息。 61 | 62 | ##17:Nagios - 服务器及网络监控 63 | Nagios 是一款非常流行的系统及网络监控软件。你可以轻松监控所有的主机、网络设备及服务。它能在发生故障和重新恢复后发送警讯。 64 | 65 | ##18:Cacti - 基于 Web 的监控工具 66 | Cacti 是一套完成的网络图形化解决方案,基于 RRDTool 的资料存储和图形化功能。Cacti 提供一个快速的轮询器、进阶的图形化模板、多种数据采集方法和用户管理功能。这些功能都拥有非常友好易用的界面,确保可以部署在一个包含数百台设备的复杂网络中。它提供关于网络、CPU、内存、已登录用户、Apache、DNS 等信息。 67 | 68 | ##19:KDE System Guard 69 | KSysguard 是在 KDE 桌面下一个网络化的系统监控工具。这个工具可以通过 SSH 会话运行。它提供很多功能,例如可以监控本机和远程主机的客户端/服务器架构,前端图形界面使用所谓传感器得到信息并展现出来。传感器返回的可以是一个简单的数值或是一组表格的信息。针对不同的信息类型,提供一个或多个显示。这些显示被组织多个工作表中,可以工作表可以独体储存和加载。所以,KSysguard 不只是一个简单的任务管理器,还是一个可以控制多台服务器的强大工具。 70 | 71 | ##20:Gnome System Monitor 72 | System Monitor 可以显示系统基本信息、监控系统进程、系统资源及文件系统使用率。你也可以使用 System Monitor 监控和修改系统行为。尽管没有 KDE System Guard 功能强大,但其提供的基本信息对于入门用户还是非常有用的。 73 | -------------------------------------------------------------------------------- /Backup/linux/高级bash脚本编程指南.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myxiaoao/backup-files/f59558aa0b2ced173e5160d5334211efd53b9bd2/Backup/linux/高级bash脚本编程指南.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Just do it !!! 2 | 3 | Keep It Simple, Stupid . 4 | --------------------------------------------------------------------------------