p:first-child, #write > ul:first-child, #write > ol:first-child, #write > pre:first-child, #write > blockquote:first-child, #write > div:first-child, #write > table:first-child { margin-top: 30px; }
img { max-width: 100%; }
input, button, select, textarea { color: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; font-size: inherit; line-height: inherit; font-family: inherit; }
input[type="checkbox"], input[type="radio"] { line-height: normal; padding: 0px; }
::before, ::after, * { box-sizing: border-box; }
#write p, #write h1, #write h2, #write h3, #write h4, #write h5, #write h6, #write div, #write pre { width: inherit; }
#write p, #write h1, #write h2, #write h3, #write h4, #write h5, #write h6 { position: relative; }
h1 { font-size: 2rem; }
p { -webkit-margin-before: 1rem; -webkit-margin-after: 1rem; -webkit-margin-start: 0px; -webkit-margin-end: 0px; }
.mathjax-block { margin-top: 0px; margin-bottom: 0px; -webkit-margin-before: 0rem; -webkit-margin-after: 0rem; }
.hidden { display: none; }
.md-blockmeta { color: rgb(204, 204, 204); font-weight: bold; font-style: italic; }
a { cursor: pointer; }
#write input[type="checkbox"] { cursor: pointer; width: inherit; height: inherit; margin: 4px 0px 0px; }
tr { page-break-inside: avoid; page-break-after: auto; }
thead { display: table-header-group; }
table { border-collapse: collapse; border-spacing: 0px; width: 100%; overflow: auto; page-break-inside: auto; text-align: left; }
table.md-table td { min-width: 80px; }
.CodeMirror-gutters { border-right-width: 0px; background-color: inherit; }
.CodeMirror { text-align: left; }
.CodeMirror-placeholder { opacity: 0.3; }
.CodeMirror pre { padding: 0px 4px; }
.CodeMirror-lines { padding: 0px; }
div.hr:focus { cursor: none; }
pre { white-space: pre-wrap; }
.CodeMirror-gutters { margin-right: 4px; }
.md-fences, pre.md-fences { font-size: 0.9rem; display: block; page-break-inside: avoid; text-align: left; overflow: visible; white-space: pre; position: relative !important; background: inherit; }
.md-fences .CodeMirror.CodeMirror-wrap { top: -1.6em; margin-bottom: -1.6em; }
.md-fences.mock-cm { white-space: pre-wrap; }
.show-fences-line-number pre.md-fences { padding-left: 0px; }
.show-fences-line-number pre.md-fences.mock-cm { padding-left: 40px; }
.footnotes { color: rgb(136, 136, 136); font-size: 0.9rem; padding-top: 1em; padding-bottom: 1em; }
.footnotes + .footnotes { margin-top: -1em; }
.md-reset { margin: 0px; padding: 0px; border: 0px; outline: 0px; vertical-align: top; text-decoration: none; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 1rem; text-shadow: none; float: none; position: static; width: auto; height: auto; white-space: nowrap; cursor: inherit; -webkit-tap-highlight-color: transparent; line-height: normal; font-weight: normal; text-align: left; box-sizing: content-box; direction: ltr; background: transparent; }
li div { padding-top: 0px; }
blockquote { margin: 1rem 0px; }
li p, li .mathjax-block { margin: 0.5rem 0px; }
li { margin: 0px; position: relative; }
blockquote > :last-child { margin-bottom: 0px; }
blockquote > :first-child { margin-top: 0px; }
.footnotes-area { color: rgb(136, 136, 136); margin-top: 0.714rem; padding-bottom: 0.143rem; }
@media print {
html, body { height: 100%; }
.typora-export * { -webkit-print-color-adjust: exact; }
h1, h2, h3, h4, h5, h6 { page-break-after: avoid; orphans: 2; }
p { orphans: 4; }
html.blink-to-pdf { font-size: 13px; }
.typora-export #write { padding-left: 1cm; padding-right: 1cm; }
.typora-export #write::after { height: 0px; }
@page { margin: 20mm 0mm; }
}
.footnote-line { margin-top: 0.714em; font-size: 0.7em; }
a img, img a { cursor: pointer; }
#write pre.md-meta-block { font-size: 0.8rem; min-height: 2.86rem; white-space: pre-wrap; display: block; background: rgb(204, 204, 204); }
p > .md-image:only-child { display: inline-block; width: 100%; text-align: center; }
#write .MathJax_Display { margin: 0.8em 0px 0px; }
.mathjax-block { white-space: pre; overflow: hidden; width: 100%; }
p + .mathjax-block { margin-top: -1.143rem; }
.mathjax-block:not(:empty)::after { display: none; }
[contenteditable="true"]:active, [contenteditable="true"]:focus { outline: none; box-shadow: none; }
.task-list { list-style-type: none; }
.task-list-item { position: relative; padding-left: 1em; }
.task-list-item input { position: absolute; top: 0px; left: 0px; }
.math { font-size: 1rem; }
.md-toc { min-height: 3.58rem; position: relative; font-size: 0.9rem; border-radius: 10px; }
.md-toc-content { position: relative; margin-left: 0px; }
.md-toc::after, .md-toc-content::after { display: none; }
.md-toc-item { display: block; color: rgb(65, 131, 196); text-decoration: none; }
.md-toc-inner:hover { text-decoration: underline; }
.md-toc-inner { display: inline-block; cursor: pointer; }
.md-toc-h1 .md-toc-inner { margin-left: 0px; font-weight: bold; }
.md-toc-h2 .md-toc-inner { margin-left: 2em; }
.md-toc-h3 .md-toc-inner { margin-left: 4em; }
.md-toc-h4 .md-toc-inner { margin-left: 6em; }
.md-toc-h5 .md-toc-inner { margin-left: 8em; }
.md-toc-h6 .md-toc-inner { margin-left: 10em; }
@media screen and (max-width: 48em) {
.md-toc-h3 .md-toc-inner { margin-left: 3.5em; }
.md-toc-h4 .md-toc-inner { margin-left: 5em; }
.md-toc-h5 .md-toc-inner { margin-left: 6.5em; }
.md-toc-h6 .md-toc-inner { margin-left: 8em; }
}
a.md-toc-inner { color: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; text-decoration: inherit; line-height: inherit; }
.footnote-line a:not(.reversefootnote) { color: inherit; }
.md-attr { display: none; }
.md-fn-count::after { content: "."; }
.md-tag { opacity: 0.5; }
code { text-align: left; }
h1 .md-tag, h2 .md-tag, h3 .md-tag, h4 .md-tag, h5 .md-tag, h6 .md-tag { font-weight: initial; opacity: 0.35; }
a.md-header-anchor.md-print-anchor { border: none !important; display: inline-block !important; position: absolute !important; width: 1px !important; right: 0px !important; outline: none !important; text-decoration: initial !important; text-shadow: initial !important; background: transparent !important; }
.md-inline-math .MathJax_SVG .noError { display: none !important; }
.mathjax-block .MathJax_SVG_Display { text-align: center; margin: 1em 0em; position: relative; text-indent: 0px; max-width: none; max-height: none; min-width: 0px; min-height: 0px; width: 100%; display: block !important; }
.MathJax_SVG_Display, .md-inline-math .MathJax_SVG_Display { width: auto; margin: inherit; display: inline-block !important; }
.MathJax_SVG .MJX-monospace { font-family: monospace; }
.MathJax_SVG .MJX-sans-serif { font-family: sans-serif; }
.MathJax_SVG { display: inline; font-style: normal; font-weight: normal; line-height: normal; zoom: 90%; text-indent: 0px; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border: 0px; padding: 0px; margin: 0px; }
.MathJax_SVG * { transition: none; }
@font-face { font-family: Merriweather; font-style: normal; font-weight: 300; src: local("Merriweather Light"), local("Merriweather-Light"), url("file:///C:/Users/Administrator/AppData/Roaming/Typora/themes/pixyll/Merriweather-Light.ttf"); }
@font-face { font-family: Merriweather; font-style: normal; font-weight: 900; src: local("Merriweather Heavy"), local("Merriweather-Heavy"), url("file:///C:/Users/Administrator/AppData/Roaming/Typora/themes/pixyll/Merriweather-Bold.ttf"); }
@font-face { font-family: Merriweather; font-style: italic; font-weight: 300; src: local("Merriweather Light Italic"), local("Merriweather-LightItalic"), url("file:///C:/Users/Administrator/AppData/Roaming/Typora/themes/pixyll/Merriweather-LightItalic.ttf"); }
@font-face { font-family: Merriweather; font-style: italic; font-weight: 900; src: local("Merriweather Heavy Italic"), local("Merriweather-HeavyItalic"), url("file:///C:/Users/Administrator/AppData/Roaming/Typora/themes/pixyll/Merriweather-HeavyItalic.ttf"); }
@font-face { font-family: Lato; font-style: normal; font-weight: 300; src: local("Lato Light"), local("Lato-Light"), url("file:///C:/Users/Administrator/AppData/Roaming/Typora/themes/pixyll/Lato-Light.ttf"); }
@font-face { font-family: Lato; font-style: normal; font-weight: 900; src: local("Lato Black"), local("Lato-Blcak"), url("file:///C:/Users/Administrator/AppData/Roaming/Typora/themes/pixyll/Lato-Black.ttf"); }
@font-face { font-family: Lato; font-style: normal; font-weight: bold; src: local("Lato Black"), local("Lato-Blcak"), url("file:///C:/Users/Administrator/AppData/Roaming/Typora/themes/pixyll/Lato-Black.ttf"); }
@font-face { font-family: Lato; font-style: italic; font-weight: 900; src: local("Lato BlackItalic"), local("Lato-BlackItalic"), url("file:///C:/Users/Administrator/AppData/Roaming/Typora/themes/pixyll/Lato-BlackItalic.ttf"); }
@font-face { font-family: Lato; font-style: italic; font-weight: bold; src: local("Lato BlackItalic"), local("Lato-BlackItalic"), url("file:///C:/Users/Administrator/AppData/Roaming/Typora/themes/pixyll/Lato-BlackItalic.ttf"); }
h1, .h1, .f1 { font-size: 2rem; line-height: 2.5rem; }
h2, .h2, .f2 { font-size: 1.5rem; line-height: 2rem; }
h3, .h3, .f3 { font-size: 1.25rem; line-height: 1.5rem; }
p, .p, .f4, h4, h5, h6, dl, ol, ul, pre[cid], div[cid], #typora-source { font-size: 1.125rem; line-height: 1.5rem; }
h4 { font-size: 1.13rem; }
body { font-family: Merriweather, 'PT Serif', Georgia, 'Times New Roman', STSong, serif; line-height: 1.5rem; font-weight: 400; }
#write { max-width: 854px; }
img { width: auto; max-width: 100%; }
body { font-size: 1.5rem; box-sizing: border-box; }
.md-table-edit { padding-top: 4px; background: rgb(237, 237, 237); }
table { width: 100%; font-size: 1.125rem; }
table > thead > tr > th, table > thead > tr > td, table > tbody > tr > th, table > tbody > tr > td, table > tfoot > tr > th, table > tfoot > tr > td { padding: 12px; line-height: 1.2; vertical-align: top; border-top-width: 1px; border-top-style: solid; border-top-color: rgb(51, 51, 51); }
table > thead > tr > th { vertical-align: bottom; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: rgb(51, 51, 51); }
table > caption + thead > tr:first-child > th, table > caption + thead > tr:first-child > td, table > colgroup + thead > tr:first-child > th, table > colgroup + thead > tr:first-child > td, table > thead:first-child > tr:first-child > th, table > thead:first-child > tr:first-child > td { border-top-width: 0px; }
table > tbody + tbody { border-top-width: 2px; border-top-style: solid; border-top-color: rgb(51, 51, 51); }
p { font-weight: 300; line-height: 1.5; color: rgb(51, 51, 51); }
abbr { border-bottom-width: 1px; border-bottom-color: black; border-bottom-style: dotted; cursor: help; }
pre, code { font-family: Menlo, Monaco, 'Courier New', monospace; }
code, pre.md-fences { color: rgb(122, 122, 122); }
.md-fences .CodeMirror.CodeMirror-wrap { top: -1.5em; margin-bottom: -1.5em; }
pre.md-fences { padding: 1.125em; margin-bottom: 0.88em; font-size: 1rem; border: 1px solid rgb(122, 122, 122); }
blockquote { padding: 1.33em; font-style: italic; border-left-width: 5px; border-left-style: solid; border-left-color: rgb(122, 122, 122); }
blockquote footer { font-size: 0.85rem; font-style: normal; color: rgb(122, 122, 122); border-color: transparent; background-color: rgb(255, 255, 255); }
h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6 { font-family: Lato, 'Helvetica Neue', Helvetica, sans-serif; font-weight: 900; line-height: 1.2; margin: 1em 0px 0.5em; }
@media screen and (min-width: 48em) {
.h1, h1 { font-size: 3.25rem; }
.h2, h2 { font-size: 2.298rem; }
.h3, h3 { font-size: 1.625rem; }
.h4, h4 { font-size: 1.3rem; }
#write > h4.md-focus::before, #write > h5.md-focus::before, #write > h6.md-focus::before { top: 1px; }
.p, p, li { font-size: 1.25rem; line-height: 1.8; }
table { font-size: 1.25rem; }
}
@media (max-width: 48em) {
blockquote { margin-left: 1rem; margin-right: 0px; padding: 0.5em; }
.h1, h1 { font-size: 2.827rem; }
.h2, h2 { font-size: 1.999rem; }
.h3, h3 { font-size: 1.413rem; }
.h4, h4 { font-size: 1.3rem; }
}
@media screen and (min-width: 64em) {
.h1, h1 { font-size: 4.498rem; }
.h2, h2 { font-size: 2.29rem; }
.h3, h3 { font-size: 1.9rem; }
.h4, h4 { font-size: 1.591rem; }
#write > h4.md-focus::before { top: 4px; }
}
a { color: rgb(70, 63, 92); text-decoration: underline; }
#write { padding-top: 2rem; }
#write::after { height: 8rem; }
#write pre.md-meta-block { min-height: 35px; padding: 2000px 1em 10px 0px; white-space: pre; border-width: 0px 1000px; border-left-color: rgb(248, 248, 248); border-left-style: solid; margin: -2010px -1000px 2em; border-right-color: rgb(248, 248, 248); border-right-style: solid; line-height: 1.5em; color: rgb(122, 122, 122); font-family: Lato, 'Helvetica Neue', Helvetica, sans-serif; font-weight: 300; clear: both; font-size: 1.125rem; background-color: rgb(250, 250, 250); }
.md-image > .md-meta { color: rgb(70, 63, 92); }
.footnotes { font-size: 1.1rem; }
.md-tag { font-family: Lato, 'Helvetica Neue', Helvetica, sans-serif; }
.code-tooltip { background: white; }
.code-tooltip-content { font-size: 1.1rem; }
.task-list { padding-left: 0px; }
.task-list-item { padding-left: 34px; }
.task-list-item input { width: 1.25rem; height: 1.25rem; display: block; -webkit-appearance: initial; top: -2px; }
.task-list-item input:focus { outline: none; box-shadow: none; }
.task-list-item input::before { border: 1px solid rgb(85, 85, 85); border-radius: 1.5rem; width: 1.5rem; height: 1.5rem; content: " "; transition: background-color 200ms ease-in-out; display: block; background: rgb(255, 255, 255); }
.task-list-item input:checked::before, .task-list-item input[checked]::before { border-width: 2px; display: inline-block; transition: background-color 200ms ease-in-out; background: rgb(51, 51, 51); }
.task-list-item input:checked::after, .task-list-item input[checked]::after { opacity: 1; }
.task-list-item input::after { transition: opacity 0.05s ease-in-out; transform: rotate(-45deg); position: absolute; top: 0.4375rem; left: 0.28125rem; width: 0.9375rem; height: 0.5rem; border-width: 0px 0px 3px 3px; border-bottom-style: solid; border-left-style: solid; border-bottom-color: rgb(255, 255, 255); border-left-color: rgb(255, 255, 255); content: " "; opacity: 0; }
.md-tag { color: inherit; }
.md-toc:focus .md-toc-content { margin-top: 19px; }
#outline-dropmenu { font-size: 1rem !important; background-color: white; }
#outline-content li, #outline-content ul { font-size: 1rem !important; }
.outline-title { line-height: inherit; margin-top: 10px; }
.outline-expander { width: 18px; }
.outline-expander::before { content: "+"; font-family: inherit; color: rgb(108, 108, 108); font-size: 1.5rem; top: 0.1rem; }
.outline-expander:hover::before { content: "+"; }
.outline-item-open > .outline-item > .outline-expander::before { content: "-"; }
#typora-source { font-family: Courier, monospace; color: rgb(106, 106, 106); }
.os-windows #typora-source { font-family: inherit; }
.cm-s-typora-default .cm-header, .cm-s-typora-default .cm-property, .CodeMirror.cm-s-typora-default div.CodeMirror-cursor { color: rgb(66, 139, 202); }
.cm-s-typora-default .cm-atom, .cm-s-typora-default .cm-number { color: rgb(119, 119, 119); }
-->
Linux Baisc
LinuxHistoryUserful link用户管理手动创建用户修改root密码LDAPldapaddldapsearchldapdeleteldappasswdldapmodifyfindCPIO文件系统创建文件系统InodeBlock大小文件描述符FDuevent修改superblock文件类型管道Suid和StickyI/O重定向集群文件系统内核相关可重入内核系统调用内核线程进程与线程进程管理I/O模型系统时间和用户时间MMAPIPCModulesNotes硬件相关Bios磁盘相关RAID系统启动流程GPT分区结构inittabRedhat RC启动脚本系统初始化脚本rc.sysinitGRUBgrub的安装制作Initrd编译操作系统安装linux&&windows双系统重启后强制fsck软件安装VIM环境修改VIM配置Cygwin相关基础编程Bash通配符:正则表达式Read隐藏密码Trap变量作用域Stack vs HeapThe StackThe HeapStack vs Heap Pros and ConsStackHeap链接库shell下个进制转换证书与加密openssl使用openssl查看信息证书类型证书转换部分脚本内容产生随机数的几种方法产生sha512的密码包管理RPMYUM源码安装网络相关Bridge&&802.1qPortMaplsoftcpdump主机arp&route配置网卡网卡Bonding检查网络状态vmstatHTTP Client服务相关curlrsyslogdNTPtimezonekillall邮件服务器虚拟化ESXI网卡安全相关使用urandom替代randomTipsMVC
History
Kernel version:
- RHEL5 2.6.18
- RHEL6 2.6.32
- RHEL7 3.10
Bootup:
- RHEL5 systemV格式系统初始化程序
- RHEL6 upstart event-driven startup, 类似并行启动,无需东等,进程间使用dbus通信
- RHEL7 systemd 完全使用并行初始化的过程, 参考 OS x
ChangeLog:
- ifconfig deprecated from RHEL6, you must use
ip a
to check the Virtual IPs, and useip -s link
show link statistics
- the old way to do virtual IPs was setup something like ifcfg-eth0:1. Now, just add to ifcfg-eth0, IPADDR2=., IPADDR3=.. But these don.t show up in .ifconfig
Userful link
SourceForge: http://www.sourceforge.org
sliceshare PPT 分享: http://www.slideshare.net
wordpress: http://www.wordpress.com
google code: http://code.google.com
用户管理
手动创建用户
用vim编辑/etc/passwd ,为新用户增加一个新行。
如果要创建新组,用vim 编辑/etc/group 。
用mkdir 产生用户的主目录。
将/etc/skel 中的文件复制到新的主目录中。
用chown 和chmod 修改所有者和权限。 -R选项是最有用的。
#cd /home/newusername #chown -R username.group . #chmod -R go=u,go-w . #chmod go= .
用passwd设定口令。
最后一步设定完口令,这个帐户就能用了。
/etc/passwd:
用户名:x:UID:基本组ID:comment信息:HOME:默认shell
/etc/shadow文件的格式:
UserName:加密的密码:最近一次密码修改时间:最短使用期限:最长使用期限:警告区间:非活动区间:帐号的过期期限:预留段
sp_namp - pointer to null-terminated user name
sp_pwdp - pointer to null-terminated password
sp_lstchg - days since Jan 1, 1970 password was last changed
sp_min - days before which password may not be changed
sp_max - days after which password must be changed
sp_warn - days before password is to expire that user is warned of pending password expiration
sp_inact - days after password expires that account is considered inactive and disabled
sp_expire - days since Jan 1, 1970 when account will be disabled
sp_flag - reserved for future use
修改root密码
密码改为root01
sed -i s/'^root:.*:\(.*\):\(.*\):\(.*\):\(.*\):\(.*\):\(.*\):\(.*\)'/"root:\$1\$3UEVsYK.\$bUg14pg\/vHYYUgR7hxzL.1:\1:\2:\3:\4:\5:\6:\7"/ /etc/shadow
echo nsadm|passwd --stdin root
LDAP
ldapadd
-x 进行简单认证
-D 用来绑定服务器的DN
-h 目录服务的地址
-w 绑定DN的密码
-f 使用ldif文件进行条目添加的文件
eg
ldapadd -x -D "cn=root,dc=starxing,dc=com" -w secret -f /root/test.ldif
ldapadd -x -D "cn=root,dc=starxing,dc=com" -w secret (这样写就是在命令行添加条目)
ldapsearch
-x 进行简单认证
-D 用来绑定服务器的DN
-w 绑定DN的密码
-b 指定要查询的根节点
-H 制定要查询的服务器
eg.
ldapsearch -x -D "cn=root,dc=starxing,dc=com" -w secret -b "dc=starxing,dc=com"
使用简单认证,用 "cn=root,dc=starxing,dc=com" 进行绑定,要查询的根是 "dc=starxing,dc=com"。这样会把绑定的用户能访问"dc=starxing,dc=com"下的所有数据显示出来。
ldapsearch -x -W -D "cn=administrator,cn=users,dc=osdn,dc=zzti,dc=edu,dc=cn" -b "cn=administrator,cn=users,dc=osdn,dc=zzti,dc=edu,dc=cn" -h troy.osdn.zzti.edu.cn
ldapsearch -b "dc=canon-is,dc=jp" -H ldaps://192.168.0.92:636
ldapdelete
ldapdelete -x -D "cn=Manager,dc=test,dc=com" -w secret "uid=test1,ou=People,dc=test,dc=com"
ldapdelete -x -D 'cn=root,dc=it,dc=com' -w secert 'uid=zyx,dc=it,dc=com'
这样就可以删除'uid=zyx,dc=it,dc=com'记录了,应该注意一点,如果o或ou中有成员是不能删除的。
ldappasswd
-x 进行简单认证
-D 用来绑定服务器的DN
-w 绑定DN的密码
-S 提示的输入密码
-s pass 把密码设置为pass
-a pass 设置old passwd为pass
-A 提示的设置old passwd
-H 是指要绑定的服务器
-I 使用sasl会话方式
eg.
#ldappasswd -x -D 'cm=root,dc=it,dc=com' -w secret 'uid=zyx,dc=it,dc=com' -S
New password:
Re-enter new password:
就可以更改密码了,如果原来记录中没有密码,将会自动生成一个userPassword。
ldapmodify
-a 添加新的条目.缺省的是修改存在的条目.
-C 自动追踪引用.
-c 出错后继续执行程序并不中止.缺省情况下出错的立即停止.比如如果你的ldif 文
件内的某个条目在数据库内并不存在,缺省情况下程序立即退出,但如果使用了该参数,程
序忽略该错误继续执行.
-n 用于调试到服务器的通讯.但并不实际执行搜索.服务器关闭时,返回错误;服务器
打开时,常和-v 参数一起测试到服务器是否是一条通路.
-v 运行在详细模块.在标准输出中打出一些比较详细的信息.比如:连接到服务器的
ip 地址和端口号等.
-M[M] 打开manage DSA IT 控制. -MM 把该控制设置为重要的.
-f file 从文件内读取条目的修改信息而不是从标准输入读取.
-x 使用简单认证.
-D binddn 指定搜索的用户名(一般为一dn 值).
-W 指定了该参数,系统将弹出一提示入用户的密码.它和-w 参数相对使用.
-w bindpasswd 直接指定用户的密码. 它和-W 参数相对使用.
-H ldapuri 指定连接到服务器uri(ip 地址和端口号,常见格式为
ldap://hostname:port).如果使用了-H 就不能使用-h 和-p 参数.
-h ldaphost 指定要连接的主机的名称/ip 地址.它和-p 一起使用.
-p ldapport 指定要连接目录服务器的端口号.它和-h 一起使用.
如果使用了-h 和-p 参数就不能使用-H 参数.
-Z[Z] 使用StartTLS 扩展操作.如果使用-ZZ,命令强制使用StartTLS 握手成功.
-V 启用证书认证功能,目录服务器使用客户端证书进行身份验证,必须与-ZZ 强制启用
TLS 方式配合使用,并且匿名绑定到目录服务器.
-e 设置客户端证书文件,例: -e cert/client.crt
-E 设置客户端证书私钥文件,例: -E cert/client.key
eg
ldapmodify -x -D "cn=root,dc=it,dc=com" -W -f modify.ldif
将modify.ldif中的记录更新原有的记录。
find
-name "文件名称": 支持使用globbing
*
?
[]
[^]
-iname "文件名称":查找时不区分字符大小写 -user UserName: 根据属主查找
-group GroupName: 根据属组查找 -uid UID
-gid GID -nouser:查找没有属主的文件;
-nogroup: 查找没有属组的文件; 组合条件:
-a: 与,同时满足
-o: 或,
-not, !:非,取反 非A,并且 非B: 非(A或B) -not ( -user hadoop -o -iname "*.txt" ) 非A,或 非B: 非(A且B) -type: 根据文件类型查找
f: 普通文件
d: 目录
b: 块设备
c: 字符设备
l: 符号链接文件
p: 命名管道
s: 套接字 -size: 根据文件大小查找
-size [+|-]#Unit
例如:-size +2M
常用单位:k, M, G #: (#-1)<x<=# 根据时间戳查找:
以天为单位(time):
-atime [+|-]#
+: 表示(#+1)天之外被访问过;
-: 表示#天之内被访问过;
无符号:表示短于(#+1)> x >=#天的时间段被访问过;
-mtime
-ctime 以分钟为单位(min):
-amin [+|-]#
-mmin
-cmin
根据权限查找:
-perm [+|-]MODE
MODE:精确匹配
+MODE: 任何一类用户的任何一位权限匹配;常用于查找某类用户的某特定权限是否存在;
-MODE: 每类用户的指定要检查的权限位都匹配; 文件权限:644
-perm 600: 否
-perm +222:
-perm +002
-perm -444
find与xargs 在使用find命令的-exec选项处理匹配到的文件时, find命令将所有匹配到的文件一起传递给exec执行。但有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现 溢出错误。错误信息通常是“参数列太长”或“参数列溢出”。这就是xargs命令的用处所在,特别是与find命令一起使用。
find命令把匹配到的文件传递给xargs命令,而xargs命令每次只获取一部分文件而不是全部,不像-exec选项那样。这样它可以先处理最先获取的一部分文件,然后是下一批,并如此继续下去。
在有些系统中,使用-exec选项会为处理每一个匹配到的文件而发起一个相应的进程,并非将匹配到的文件全部作为参数一次执行;这样在有些情况下就会出现进程过多,系统性能下降的问题,因而效率不高;
而使用xargs命令则只有一个进程。另外,在使用xargs命令时,究竟是一次获取所有的参数,还是分批取得参数,以及每一次获取参数的数目都会根据该命令的选项及系统内核中相应的可调参数来确定。
CPIO
【命令格式】
cpio [option][destination-directory]
【常用选项】
i:使用copy-in模式,还原归档文件或列出归档文件中的文件列表。
o:使用copy-out模式,建立归档文件。
p:使用copy-pass模式,将文件直接复制到目的目录。
c:使用老式的ASCII归档模式。如果需要跨平台使用,应该使用老式的ASCII归档格式。
d:创建需要的目录。如果文件不处于同一目录中,应该使用此选项。
v:显示处理过程的详细信息。
t:显示归档文件中的文件列表。
m:保持文件的时间戳记。
H:使用指定的格式归档文件
常常与find命令一同使用
制作归档文件
find -print | cpio -ov >../backup.cpio
查看CPIO内容
cpio -tv <backup.cpio
文件系统
文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统.
创建文件系统
预留block空间
Reserving some number of filesystem blocks for use by privileged processes is done to avoid filesystem fragmentation, and to allow system daemons, such as syslogd(8), to continue to function correctly after non-privileged processes are prevented from writing to the filesystem
Inode
文件类型
与文件相关的硬链接个数
以字节为单位的文件长度
设备标识符
在文件系统中表示文件的索引节点号
文件拥有者的UID
文件的用户组ID
几个时间戳, 表示索引节点状态改变的时间, 最后访问时间及最后修改时间
访问权限和文件模式.
inode 0 is used as a NULL value, to indicate that there is no inode.
indoe 1 is used to keep track of any bad blocks on the disk; it is essentially a hidden file containing the bad blocks. Those bad blocks which are recorded using e2fsck –c
indoe 2 is used by the root directory which indicates starting of File system inodes
Block大小
1k, 最大单一档案限制 16GB, 最大文件系统总容量2TB
2k, 最大单一档案限制 256GB, 最大文件系统总容量8TB
4k, 最大单一档案限制2TB, 最大文件系统总容量16TB
文件描述符FD
文件描述符:文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。
uevent
Udev的工作是依赖于sysfs文件系统的,所以从内核版本2.6之后才开始支持udev。它基本可以替代2.4之后的devfs。
调用过程是内核空间通过netlinksocket跟用户空间交互,kenerl调用kobject-uevent()函数给用户空间发送netLink message来通知用户空间。
在用户空间,udev是启动一个守护进程叫做udevd(使用ps指令可以查看). 当uevent到达用户空间时,用户空间通过inotify的功能通知udevd。Udevd获得硬件更新信息,然后再根据/etc/udev.conf 以及/etc/udev/rules.d/* 下的规则进行设备定义,udev语法可以参考链接。
PS1. 可以模拟一个uevent的动作echo add > /sys/class/net/eth0/uevent来出发一个uevent消息。
PS2. /etc/udev/rules.d/中的70-persistent-net.rules文件生成,是通过在/lib/udev/write_net_rules脚本来生成。
修改superblock
破坏superblock, 由于有boot sector的存在, 所以需要seek响应的位数
dd if=/dev/zero of=/dev/sda6 bs=1 count=1024 seek=1024
修复superblock
e2fsck -b 32768 /dev/sda6
文件类型
管道
管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入,常说的管道多是指无名管道,无名管道只能用于具有亲缘关系的进程之间,这是它与有名管道的最大区别。
文件描述符
文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统.
文件描述符的有效范围是 0 到 OPEN_MAX。一般来说,每个进程最多可以打开 64 个文件(0 — 63)
进程上下文
这些代码从可执行文件载入到进程的地址空间执行。一般程序在用户空间执行当一个程序调用了系统调用或者触发了某个异常,它就陷入了内核空间。此时,我们称内核“代表进程执行”并处于进程上下文。在此上下文中current宏是有效的。除非在此间隙有更高优先级的进程需要执行并由调度器做出了相应调整,否则在内核退出的时候,程序恢复在用户空间继续执行。
Suid和Sticky
s :当文件被执行时,把该文件的UID或GID赋予执行进程的UID(用户ID)或GID(组ID)。
t:设置标志位(留在内存,不被换出)。如果该文件是目录,在该目录中的文件只能被超级用户、目录拥有者或文件属主删除。如果它是可执行文件,在该文件执行后,指向其正文段(程序的代码)的指针仍留在内存。这样再次执行它时,系统就能更快地装入该文件。
目录的S属性使得在该目录下创建的任何文件及目录属于该目录所拥有的组。
I/O重定向
INPUT:标准输入,stdin, 0 OUPUT: 标准输出,stdout, 1 标准错误:stderr, 2
输入重定向:<, <<
<: 输入重定向
<< EOF: 此处创建文件, Here Document
常用于在脚本中创建文件或生成菜单
输出重定向:>, >>
>: 覆盖输出
>>: 追加输出
set -C:禁止使用覆盖重定向至已经存在的文件;
set +C: 关闭上述特性;
>|:在-C特性下,强制使用覆盖重定向;
/dev/null: bit bucket,位桶
同时重定标准输出和错误输出:
COMMAND > /path/to/outfile 2> /path/to/errfile
COMMAND &> /path/to/somefile
COMMAND > /path/to/somefile 2>&1
集群文件系统
集群文件系统有GFS2(Redhat),OCFS2(Oracle)
内核相关
2.6之前的内核发布分为稳定版和测试版, 偶数次代表稳定版本, 奇次则不同.
可重入内核
reentrant: 若干个进程可以同时在内核态下执行. 当然在单处理器系统上只有一个进程在真正的运行
系统调用
open(path, flag, mode): 打开一个文件
flock(): 可以让进程在整个文件或部分文件上对I/O操作实施同步.
read(fd,buf,count), write(): 系统调用总是从文件指针的当前位置开始读或者写. 默认offset为0. Read()可以指定buf, 即指定进程地址空间中缓冲区的地址.
close(fd): 关闭文件
rename(oldpath,newpath): 修改文件名称
unlink(pathname): 修改文件链接的名字. 当一个文件的链接数为0, 则该文件被删除.
内核线程
是运行在内核态的特权进程. 它们以内核态运行在内核空间, 不予用户直接交互, 并且在系统启动时创建, 在系统关闭时关闭.
进程与线程
为了让内核管理进程, 每个进程都由一个进程描述符(process descriptor)表示. 当内核暂停一个进程的执行时, 就把几个处理器寄存器相关的内容保存在进程描述符中.
程序计数器(PC)和栈指针(SP)
通用寄存器
浮点寄存器
包含CPU状态信息的处理器控制寄存器(处理器状态字, processor status word)
用来跟踪进程对RAM访问的内存管理寄存器.
线程是进程的子单位, 在linux系统中并不支持原生态的线程, linux把所有线程当做进程来对待, 只不过将其当做轻量级进程来对待, LWP: light weight process. Linux 自身的线程库不同, 有内核自带的也有红帽提供的. Linux中的进程与线程响应I/O调用时的机制却是相同的
对于进程而言, 指令执行流是串行执行的. 而有了线程之后, 指令可以并行执行
进程切换需要保留现场, 以及还原现场. 保留指令指针, 数据要加载到CPU的缓存中. CPU的寄存器也要重置. 线程间切换, 由于数据共享, 则无需进行CPU的缓存清空
CPU的存储器是寄存器
32位CPU有4个32位的通用寄存器EAX、EBX、ECX和EDX。对低16位数据的存取,不会影响高16位的数据。这些低16位寄存器分别命名为:AX、BX、CX和DX,它和先前的CPU中的寄存器相一致。
4个16位寄存器又可分割成8个独立的8位寄存器(AX:AH-AL、BX:BH-BL、CX:CH-CL、DX:DH-DL),每个寄存器都有自己的名称,可独立存取。程序员可利用数据寄存器的这种“可分可合”的特性,灵活地处理字/字节的信息
CPU 忙等/闲等, 忙等不切换(使用自旋锁, spin lock), 闲等上下文切换
进程管理
使用命令 pmap -x 可以查看进程的内存占用信息; lsof -a -p 可以查看一个进程打开的文件信息。ps -Lf 可以查看进程的线程数。
另外procfs也是一个分析进程结构的好地方。procfs是一个虚拟的文件系统,它把系统中正在运行的进程都显现在/proc/目录下。
I/O模型
SELECT() 每次将所有的I/O请求的文件描述符扫一遍, 然后再将整个数据结构输给用户空间. 最多只支持1024个IO请求. 当内核发现有完成的IO调用后, 返回将所有内容返回
select的几大缺点:
(1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
(2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
(3)select支持的文件描述符数量太小了,默认是1024
poll()没有上限限制, 但是性能跟select()差不多
五种I/O模型
1 . Blocking I/O: blocked all the way
2 . nonblocking I/O: if no data in buffer
3 . I/O multiplexing(select and poll): blocked separately in wait and copy
4 . Singal Driven I/O(SIGIO): nonblocked in wait but blocked in copy(signaled when I/O can be initiated) (epoll())
5 . asynchornous I/O(aio): nonblocked all the way(singaled when I/O is complete)
Synchronous I/O: 引起请求进程阻塞, 直到I/O完成
Asynchronous I/O:不导致请求进程阻塞
系统时间和用户时间
系统调用, 内核运行的时间成为系统时间. 用户空间内占用的时间, 称为用户时间.
pointer_size
系统指针大小, 32位的系统指针大小通常为32bytes, 64位系统通常大小为64bytes.
MMAP
系统调用mmap()可以将某文件映射至内存(进程空间),如此可以把对文件的操作转为对内存的操作,以此避免更多的lseek()与read()、write()操作,这点对于大文件或者频繁访问的文件而言尤其受益。
1、 Linux采用了投机取巧的分配策略,用到时,才分配物理内存。也就是说进程调用brk()或mmap()时,只是占用了虚拟地址空间,并没有真正占用物理内存。这也正是free –m中used并不意味着消耗的全都是物理内存。 2、 mmap()通过指定标志(flag) MAP_ANONYMOUS来表明该映射是匿名内存映射,此时可以忽略fd,可将它设置为-1。如果不支持MAP_ANONYMOUS标志的类unix系统,可以映射至特殊设备文件/dev/zero实现匿名内存映射。 3、 调用mmap()时就决定了映射大小,不能再增加。换句话说,映射不能改变文件的大小。反过来,由文件被映射部分,而不是由文件大小来决定进程可访问内存空间范围(映射时,指定offset最好是内存页面大小的整数倍)。 4、通常使用mmap()的三种情况.提高I/O效率、匿名内存映射、共享内存进程通信。
mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。
当使用mmap映射文件到进程后,就可以直接操作这段虚拟地址进行文件的读写等操作,不必再调用read,write等系统调用.但需注意,直接对该段内存写时不会写入超过当前文件大小的内容.
采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据:一次从输入文件到共享内存区,另一次从共享内存区到输出文件。
使用命令 pmap -x 可以查看进程的内存占用信息; lsof -a -p 可以查看一个进程打开的文件信息。ps -Lf 可以查看进程的线程数。
另外procfs也是一个分析进程结构的好地方。procfs是一个虚拟的文件系统,它把系统中正在运行的进程都显现在/proc/目录下。
IPC
(1) 半双工Unix管道 (2) FIFOs(命名管道) (3) 消息队列 (4) 信号量 (5) 共享内存 (6) 网络Socket
Modules
Linux的内核: 单内核, 支持动态装载和卸载
模块: /lib/modules/KERNEL_VERSION/
查看PCI设备的命令
lspci
查看当前内核装载的模块
lsmod
查看某模块的详细信息
modinfo MOD_NAME
动态卸载某模块
modprobe -r MOD_NAME
rmmod MOD_NAME
动态装载某模块
modprobe MOD_NAME
insmod /path/to/module_file
Notes
不要对内核进行升级操作: 多版本内核可以并存, 因此,建议执行安装操作
硬件相关
Bios
BIOS芯片是主板上一块长方型或正方型芯片,在微机的发展初期,BIOS都存放在ROM(Read Only Memory,只读存储器)中。ROM内部的资料是在ROM的制造工序中,在工厂里用特殊的方法被烧录进去的,其中的内容只能读不能改,一旦烧录进去,用户只能验证写入的资料是否正确,不能再作任何修改。如果发现资料有任何错误,则只有舍弃不用。EPROM(Erasable Programmable ROM,可擦除可编程ROM)芯片可重复擦除和写入,解决了PROM芯片只能写入一次的弊端。EPROM芯片有一个很明显的特征,在其正面的陶瓷封装上,开有一个玻璃窗口,透过该窗口,可以看到其内部的集成电路,紫外线透过该孔照射内部芯片就可以擦除其内的数据,完成芯片擦除的操作要用到EPROM擦除器。EPROM内资料的写入要用专用的编程器,并且往芯片中写内容时必须要加一定的编程电压(VPP=12—24V,随不同的芯片型号而定)。EPROM的型号是以27开头的,如27C020(8*256K)是一片2M Bits容量的EPROM芯片。EPROM芯片在写入资料后,还要以不透光的贴纸或胶布把窗口封住,以免受到周围的紫外线照射而使资料受损。由EPROM操作的不便,后来出的主板上BIOS ROM芯片大部分都采用EEPROM(Electrically Erasable Programmable ROM,电可擦除可编程ROM。
BIOS中主要存放: ● 自诊断程序:通过读取CMOS RAM中的内容识别硬件配置,并对其进行自检和初始化; ● CMOS设置程序:引导过程中,用特殊热键启动,进行设置后,存入CMOS RAM中; ● 系统自举装载程序:在自检成功后将磁盘相对0道0扇区上的引导程序装入内存,让其运行以装入DOS系统; ● 主要I/O设备的驱动程序和中断服务: 由于BIOS直接和系统硬件资源打交道,因此总是针对某一类型的硬件系统,而各种硬件系统又各有不同,所以存在各种不同种类的BIOS,随着硬件技术的发展,同一种BIOS也先后出现了不同的版本,新版本的BIOS比起老版本来说,功能更强。
程序员可以通过INT5, INT13等中断的访问直接调用BIOS中断例程.
POST: Power on self test
磁盘相关
磁盘的识别机制
1 . Centos 5
IDE硬盘 -hd[abc..]#
SATA、SCSI、USB、SAS - sd[abc...]#
2 .Centos 6、7
IDE、SATA、SCSI、USB、SAS -sd[abc...] 查看内核中的主次设备号映射
cat /proc/devices
现在的 Linux 内核允许多个驱动共享一个主设备号,但更多的设备都遵循一个驱动对一个主设备号的原则
次设备号的主要用途
1、区分设备驱动程序控制的实际设备; 2、区分不同用途的设备 (misc 系列设备) 3、区分块设备的分区 (partition)
RAID
Level: 仅用于标识磁盘组合方式的不同 raid0, raid1, raid5, raid10, raid50, jbod
raid0: 至少需要两块磁盘,没有容错能力,读写性能都提升,100%
raid1: 至少需要两块磁盘,镜像,硬件容错能力,读性能提升,写性能下降,50%
raid4: 至少需要三块磁盘,允许一块盘出错,读写性能提升,(n-1)/n
raid5: 至少需要三块磁盘,允许一块盘出错,读写性能提升,(n-1)/n
raid6: 至少需要四块磁盘,允许两块盘出错,读写性能提升,(n-2)/n
raid10: 至少需要四块磁盘,允许不同组内各坏一块盘,读写性能提升,50% raid01
系统启动流程
POST --> BIOS(boot sequence) --> MBR (bootloader) --> Kernel (initrd, initramfs) --> /sbin/init (/etc/inittab)
init:
SysV init: /etc/inittab
upstart: /etc/inittab, /etc/init/*.conf
SystemD: OS X
1 .POST: 加电自检, ROM中的代码, CPU看到的存储存储空间为ROM+RAM, CPU寻找ROM要实现自举. 开机首先寻找ROM的地址, 主板商和CPU商约定俗成
2 .MBR:第0个扇区, 446bytes boot loader 64partition table 2: SA(标示是否有操作系统) bootloader要自行识别kernel所在磁盘的文件系统, kernel文件只能放在基本磁盘分区上, 最多放在raid1上, bootloader要在 /目录被挂载前找到vmlinux内核, 为找寻一个临时入口, bootloader会直接访问/vmlinuz将其作为根目录访问, vmlinuz会自解压到内存中, kernel自行进行初始化
3 .initrd帮助内核初始化, initrd是一个根文件系统, rd:ramdisk 将内存模拟成磁盘使用, 建立临时根,寻找模块使用/lib/module
4 ./sbin/init: /etc/rc.d/rc.sysinit脚本
GPT分区结构
GPT磁盘是指使用GUID分区表的磁盘。是源自EFI标准的一种较新的磁盘分区表结构的标准。与普遍使用的主引导记录(MBR)分区方案相比,GPT提供了更加灵活的磁盘分区机制。
在GPT分区表的最开头(LBA0),处于兼容性考虑仍然存储了一份传统的MBR,用来防止不支持GPT的硬盘管理工具错误识别并破坏硬盘中的数据,这个MBR也叫做保护MBR。
GPT分区表分为4个区域:GPT头、分区表、GPT分区、备份区。
- GPT头:起始于磁盘的 LBA1,通常也只占用这个单一扇区。其作用是定义分区表的位置和大小。GPT头还包含头和分区表的校验和,这样就可以及时发现错误。
- 分区表:分区表区域包含分区表项。这个区域由GPT头定义,一般占用磁盘LBA2~LBA33扇区。分区表中的每个分区项由起始地址、结束地址、类型值、名字、属性标志、GUID值组成。分区表建立后,128位的GUID对系统来说是唯一的。
- GPT分区:最大的区域,由分配给分区的扇区组成。这个区域的起始和结束地址由GPT头定义。
- 备份区:备份区域位于磁盘的尾部,包含GPT头和分区表的备份。它占用GPT结束扇区和EFI结束扇区之间的33个扇区。其中最后一个扇区用来备份1号扇区的EFI信息,其余的32个扇区用来备份LBA2~LBA33扇区的分区表
inittab
/sbin/init的配置文件:
每行定义一种操作:
id: 操作的ID
runlevels: 在哪些级别下执行此操作
action: 动作
initdefault: 设置默认运行级别,无需定义操作
sysinit:指定系统初始化脚本
si::sysinit:/etc/rc.d/rc.sysinit
wait: 等待系统切换至此级别时运行一次;
ctrlaltdel: 定义组合键被按下时要运行的命令;
respawn: 当指定操作进程被关闭时立即再启动一次;
tty1:2345:respawn:/sbin/mingetty tty1
process: 操作 /etc/inittab中定义的操作:
设定默认运行级别
指定系统运行的初始化脚本
启动指定级别下的要启动的服务,并关闭需要停止的服务
定义CtrlAltDel组合的动作
初始化字符终端
启动图开终端
Redhat RC启动脚本
对于Redhat来说,执行的顺序为:
①/etc/rc.d/rc.sysinit # 由init执行的第一个脚本
②/etc/rc.d/rc $RUNLEVEL # $RUNLEVEL为缺省的运行模式
③/etc/rc.d/rc .local # RUNLEVEL为2、3、5时运行
④/etc/rc.d/rc.serial # $RUNLEVEL为1、3时初始化串口
/sbin/mingetty # 等待用户登录
系统初始化脚本rc.sysinit
系统初始化脚本/etc/rc.d/rc.sysinit
设置主机名
打印文本欢迎信息
激活SELinux和udev
激活swap
挂载/etc/fstab定义的本地文件系统
检测根文件系统并对其以读写方式重新挂载
设置系统时钟
装载键盘映射
根据/etc/sysctl.conf设置内核参数
激活RAID和LVM设备
清理操作
GRUB
GRand Unified Bootloader
1st stage: 位于MBR中,为了引导2nd stage 1.5 stage: 位于boot基本磁盘分区中,为识别内核文件所在的文件系统提供文件系统识别扩展 2nd stage: 位于boot基本磁盘分区中,GRUB的引导程序
boot分区大小:
CentOS5: 100M
CentOS6: 200M
grub接口:
title: 操作系统或内核的标题
root: 设定内核文件所在的分区为grub的根
kernel: 定义要使用的内核文件,后面可附加传递给内核的启动参数
initrd: 指定为内核提供额外驱动等功能的ram disk或ram fs文件
init的级别1的表示方式:
1, s, single, S
单用户模式几乎不会启动任何服务,且不需要用户登录;但是会执行/etc/rc.d/rc.sysinit脚本;
如是连/etc/rc.d/rc.sysinit文件也不加载,则传递 emergency
grub.conf配置文件语法:
default=#: 指定默认启动的内核或OS;
timeout=#: 等待用户选择要启动的内核或OS的时长,单位为秒;
splashimage=/path/to/splashimage_file: 指定使用的背景图片
hiddenmenu: 隐藏菜单
title
root (hd0,0)
(Device, Part)
Device表示方式: 在grub中,统统以hd开头,并紧跟一个数字做各磁盘设备的标记,从0开始编号
Part表示方式:代表分区,从0开始编号
kernel
指定内核文件及传递给内核的参数
参数:ro root=/path/to/DEVICE quiet
initrd
文件:通常为cpio归档,并使用gzip压缩;通常以.img作为文件名后缀;
查看runlevel
runlevel
who -r
grub的安装
第一种方式
grub> root (hd#,#)
grub> setup (hd#)
grub> quit
第二种方式
chroot /mnt/sysimage
grub-install --root-directory=/ /dev/sda
制作Initrd
command mkinitrd
mkinitrd [-v] [--with=模块名称] initrd档名 核心版本
选项与参数:
-v :显示 mkinitrd 的运行过程
--with=模块名称:模块名称指的是模块的名字而已,不需要填写档名。举例来说,
目前核心版本的 ext3 文件系统模块为底下的档名:
/lib/modules/$(uname -r)/kernel/fs/ext3/ext3.ko
那你应该要写成: --with=ext3 就好了 (省略 .ko)
initrd档名:你所要创建的 initrd 档名,尽量取有意义又好记的名字。
核心版本 :某一个核心的版本,如果是目前的核心则是『 $(uname -r) 』
编译操作系统
HOST: 宿主机
Target: 目标机
基于HOST制作一个简单的可启动的Linux:
1、给目标磁盘分区
两个:
宿主机上:/dev/sdb1, /dev/sdb2
/dev/sdb1 挂载至 /mnt/boot
/dev/sdb2 挂载至 /mnt/sysroot
2、安装grub至目标磁盘
# grub-install --root-directory=/mnt /dev/sdb
3、复制内核和initrd文件
# cp /boot/vmlinuz-VERSION /mnt/boot/vmlinuz
# cp /boot/initramfs-VERSION.img /mnt/boot/initramfs.img
4、创建目标主机的根文件系统
# mkdir -pv /mnt/sysroot/{etc/rc.d, usr, var, proc, sys, dev, lib, lib64, bin, sbin, boot, srv, mnt, media, home, root}
接着去移植bash等至目标主机的根文件系统;
5、为grub提供配置文件
# vim /mnt/boot/grub/grub.conf
default=0
timeout=5
title MageEdu Little Linux
root (hd0,0)
kernel /vmlinuz ro root=/dev/sda2 quiet selinux=0 init=/bin/bash
initrd /initramfs.img
安装linux&&windows双系统
要先安装windows在给linux系统分区后安装linux. 因为windows的boot loader在安装时会覆盖原有的MBR内容, 导致linux无法被引导. 其次Windows并不支持安装在扩展分区上面.
Grub本身还可以监测到windows的存在,并且给与正确的配置
重启后强制fsck
touch /forcefsck
软件安装
RPM搜索站点:
RPM Find RPM
VIM环境
修改VIM配置
set ts=4
set sw=4
set expandtab
set autoindent
VIM粘贴模式
set paste
Cygwin相关
cygwin安装apt-cyg
svn --force export http://apt-cyg.googlecode.com/svn/trunk/ /bin/
chmod +x /bin/apt-cyg
Syntax:
"apt-cyg install <package names>" to install packages
"apt-cyg remove <package names>" to remove packages
"apt-cyg update" to update setup.ini
"apt-cyg show" to show installed packages
"apt-cyg find <pattern(s)>" to find packages matching patterns
"apt-cyg describe <pattern(s)>" to describe packages matching patterns
"apt-cyg packageof <commands or files>" to locate parent packages
restore_cyg_ssh.sh
#!/bin/bash
editrights -u cyg_server -a SeCreateTokenPrivilege
editrights -u cyg_server -a SeTcbPrivilege
editrights -u cyg_server -a SeAssignPrimaryTokenPrivilege
editrights -u cyg_server -a SeServiceLogonRight
ls editrights -u Administrator -a SeCreateTokenPrivilege
editrights -u Administrator -a SeTcbPrivilege
editrights -u Administrator -a SeAssignPrimaryTokenPrivilege
editrights -u Administrator -a SeServiceLogonRight
net start sshd
mintty主题
BoldAsFont=-1
Locale=C
Charset=GBK
Printer=Foxit Reader PDF Printer
Transparency=medium
Columns=100
Rows=59
BackspaceSendsBS=yes
DeleteSendsDEL=yes
MiddleClickAction=void
RightClickAction=paste
Scrollbar=none
CursorType=underscore
Term=xterm
ForegroundColour=248,248,242
BackgroundColour=39,40,34
CursorColour=253,157,79
Black=39,40,34
BoldBlack=117,113,94
Red=249,38,114
BoldRed=204,6,78
Green=166,226,46
BoldGreen=122,172,24
Yellow=244,191,117
BoldYellow=240,169,69
Blue=102,217,239
BoldBlue=33,199,233
Magenta=174,129,255
BoldMagenta=126,51,255
Cyan=161,239,228
BoldCyan=95,227,210
White=248,248,242
BoldWhite=249,248,245
基础编程
Bash
通配符:
*: 匹配任意长度的任意字符
abc, abb, abm, xab, ab
ab*
*ab
*ab*:
?:匹配任意单个字符
[]: 匹配指定字符范围内的任意单个字符
[xyz]
[a-z]
[A-Z]
[0-9]
[0-9a-zA-Z]
[[:upper:]] 所有大写字母
[[:lower:]]
[[:alpha:]]
[[:digit:]]
[[:alnum:]]
[[:space:]]
[[:punct:]]
[^]: 匹配指定字符范围外的任意单个字符
[^0-9], [^[:digit:]]
交互式登录: su -
/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
非交互时登录: su
~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh
正则表达式
基本正则表达式和扩展正则表达式
基本正则表式的元字符:grep -E
字符匹配:
.: 任意单个字符
[]: 指定范围内的任意单个字符
[0-9], [[:digit:]]
[a-z], [[:lower:]]
[A-Z], [[:upper:]]
[[:alpha:]]
[[:alnum:]]
[[:space:]]
[[:punct:]]
[^]:指定范围外的任意单个字符
次数匹配:用来指定匹配其前面的字符的次数
*: 任意次
例子:x*y, xxy, xy, y,
.*: 匹配任意长度的任意字符
\?: 0次或1次
x\?y, xy, y, xxy 贪婪模式:尽可能的长的去匹配字符;
\{m\}: 匹配m次
\{m,n\}:
\{m,\}: 至少m次;
\{0,n\}:至多n次;
位置锚定:用于指定字符出现的位置
^: 锚定行首
^Char
$: 锚定行尾
char$
^$: 空白行 \<char: 锚定词首,\bchar
char\>: 锚定词尾,char\b
分组:
\(\)
\(ab\)*xy
引用:
\1: 后向引用,引用前面的第一个左括号以及与之对应的右括号中的模式所匹配到的内容
\2
...
\(a.b\)xy\1: a6bxya6b,
He like his lover.
She love her liker.
He love his lover.
She like her liker.
Read隐藏密码
read -s -p "Please input your pgsql User password:" PGPASSWORD
stty -echo
read pw
stty echo
Trap
trap "Clear_Temp;exit" SIGINT SIGQUIT SIGHUP
变量作用域
变量作用域:变量能够被使用的代码范围. 变量被声明的位置决定了其作用域:
查找次序:
内层函数
外层函数
主程序
bash解释器内置环境变量
Stack vs Heap
So far we have seen how to declare basic type variables such as int
, double
, etc, and complex types such as arrays and structs. The way we have been declaring them so far, with a syntax that is like other languages such as MATLAB, Python, etc, puts these variables on the stack in C.
The Stack
What is the stack? It's a special region of your computer's memory that stores temporary variables created by each function (including the main()
function). The stack is a "LIFO" (last in, first out) data structure, that is managed and optimized by the CPU quite closely. Every time a function declares a new variable, it is "pushed" onto the stack. Then every time a function exits, all of the variables pushed onto the stack by that function, are freed (that is to say, they are deleted). Once a stack variable is freed, that region of memory becomes available for other stack variables.
The advantage of using the stack to store variables, is that memory is managed for you. You don't have to allocate memory by hand, or free it once you don't need it any more. What's more, because the CPU organizes stack memory so efficiently, reading from and writing to stack variables is very fast.
A key to understanding the stack is the notion that when a function exits, all of its variables are popped off of the stack (and hence lost forever). Thus stack variables are local in nature. This is related to a concept we saw earlier known as variable scope, or local vs global variables. A common bug in C programming is attempting to access a variable that was created on the stack inside some function, from a place in your program outside of that function (i.e. after that function has exited).
Another feature of the stack to keep in mind, is that there is a limit (varies with OS) on the size of variables that can be store on the stack. This is not the case for variables allocated on the heap.
To summarize the stack:
- the stack grows and shrinks as functions push and pop local variables
- there is no need to manage the memory yourself, variables are allocated and freed automatically
- the stack has size limits
- stack variables only exist while the function that created them, is running
The Heap
The heap is a region of your computer's memory that is not managed automatically for you, and is not as tightly managed by the CPU. It is a more free-floating region of memory (and is larger). To allocate memory on the heap, you must use malloc()
or calloc()
, which are built-in C functions. Once you have allocated memory on the heap, you are responsible for using free()
to deallocate that memory once you don't need it any more. If you fail to do this, your program will have what is known as a memory leak. That is, memory on the heap will still be set aside (and won't be available to other processes). As we will see in the debugging section, there is a tool called valgrind
that can help you detect memory leaks.
Unlike the stack, the heap does not have size restrictions on variable size (apart from the obvious physical limitations of your computer). Heap memory is slightly slower to be read from and written to, because one has to usepointers to access memory on the heap. We will talk about pointers shortly.
Unlike the stack, variables created on the heap are accessible by any function, anywhere in your program. Heap variables are essentially global in scope.
Stack vs Heap Pros and Cons
Stack
- very fast access
- don't have to explicitly de-allocate variables
- space is managed efficiently by CPU, memory will not become fragmented
- local variables only
- limit on stack size (OS-dependent)
- variables cannot be resized
Heap
- variables can be accessed globally
- no limit on memory size
- (relatively) slower access
- no guaranteed efficient use of space, memory may become fragmented over time as blocks of memory are allocated, then freed
- you must manage memory (you're in charge of allocating and freeing variables)
- variables can be resized using
realloc()
链接库
库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。
本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库有两种:静态库(**.a、.lib)和动态库(.so、.dll)。 windows上对应的是.lib .dll linux上对应的是.a .so**
gcc -c hellospeak.cpp
会将hellospeak.cpp 选项 -c 用来告诉编译器编译源代码但不要执行链接,输出结果为对象文件。文件默认名与源码文件名相同,只是将其后缀变为 .o。例如,上面的命令将编译源码文件hellospeak.cpp 并生成对象文件 hellospeak.o;
将上述两个源码文件连接成一个单一的可执行程序:
gcc hellospeak.cpp speak.cpp -o hellospeak
如果没有-o和后面参数,编译器默认采用默认的a.out. 本例中就会生成hellospeak这样的可执行程序
编译的四个过程
1 . 预处理(Pre-processing)
在该阶段, 编译器将C源代码中的包含的头文件如stdio.h编译进来, 用户可以使用gcc -E 选项查看
2 . 编译阶段(Compiling)
第二步进行的是编译阶段,在这个阶段中,Gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,Gcc把代码翻译成汇编语言.
用户可以使用”-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
3 . 汇编阶段(Assembling)
汇编阶段是把编译阶段生成的".s"文件转成二进制目标代码. 选项为 -c
4 . 链接阶段(Link)
将编译输出文件hello.o链接成最终可执行文件.
静态库
之所以成为【静态库】,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。静态库文件为.a
静态库对函数库的链接是放在编译时期完成的
程序在运行时与函数库没有关系, 方便移植
浪费资源和空间, 因为所有相关的目标文件与牵涉到函数库被链接合成一个可执行文件
shell下个进制转换
一、16进制转换成10进制
printf %d 0xF
15
或者
echo $((16#F))
15
二、10进制转换成16进制
printf %x 15
f
或者
echo "obase=16;15"|bc
F
三、10进制转换成8进制
printf %o 9
11
四、8进制转换成10进制
echo $((8#11))
9
五、同理二进制转换成10进制
echo $((2#111))
7
六、10进制转换成二进制
echo "obase=2;15"|bc
1111
证书与加密
openssl
使用openssl查看信息
查看私钥
openssl rsa -noout -text -in private.key
查看CSR
openssl req -noout -text -in myserver.csr
查看证书
openssl x509 -noout -text -in ca.crt
查看证书链
openssl verify selfsign.crt
openssl verify -CAfile ca.crt myserver.crt
将pem证书转成windows可以使用的pfx格式
openssl pkcs12 -export -in /etc/pki/CA/newcerts/01.pem -inkey /etc/pki/CA/private/user1.key -out /etc/pki/CA/private/user1.pfx -chain -CAfile /etc/pki/CA/certs/chain.crt
openssl pkcs12 -export -out user.pfx -inkey /etc/pki/CA/pricate/cakey.pem -in /etc/pki/CA/cacert.pem -certfile ca-chain.pem
使用openssl s_client测试连接
openssl s_client -connect server.example.com:443 -ign_eof -cipher "DHE-RSA-CAMELLIA256-SHA" - no_comp -msg 2> /dev/null echo -e "GET / HTTP/1.0\n"|openssl s_client -showcerts -connect 135.27.213.164:443 2>/dev/null
证书类型
Certificate
-----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----
RSA private key (PKCS#1)
-----BEGIN RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----
RSA public key (PKCS#1)
-----BEGIN RSA PUBLIC KEY----- ... -----END RSA PUBLIC KEY-----
RSA private key (PKCS#8, key )
-----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----
RSA public key (PKCS#8)
-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----
RSA private key (PKCS#8, key)
-----BEGIN ENCRYPTED PRIVATE KEY----- ... -----END ENCRYPTED PRIVATE KEY----- openssl中有如下后缀名的文件
.key格式:私有的密钥
.crt格式:证书文件,certificate的缩写
.csr格式:证书签名请求(证书请求文件),含有公钥信息,certificate signing request的缩写
.crl格式:证书吊销列表,Certificate Revocation List的缩写
.pem格式:用于导出,导入证书时候的证书的格式,有证书开头,结尾的格式 常用证书协议
x509v3: IETF的证书标准
x.500:目录的标准
SCEP: 简单证书申请协议,用http来进行申请,数据有PKCS#7封装,数据其实格式也是PKCS#10的
PKCS#7: 是封装数据的标准,可以放置证书和一些请求信息
PKCS#10: 用于离线证书申请的证书申请的数据格式,注意数据包是使用PKCS#7封装这个数据
PKCS#12: 用于一个单一文件中交换公共和私有对象,就是公钥,私钥和证书,这些信息进行打包,加密放在存储目录中,CISCO放在NVRAM中,用户可以导出,以防证书服务器挂掉可以进行相应恢复。思科是.p12,微软是.pfx 1.带有私钥的证书
由Public Key Cryptography Standards #12,PKCS#12标准定义,包含了公钥和私钥的二进制格式的证书形式,以pfx作为证书文件后缀名。 2.二进制编码的证书
证书中没有私钥,DER 编码二进制格式的证书文件,以cer作为证书文件后缀名。 3.Base64编码的证书
证书中没有私钥,BASE64 编码格式的证书文件,也是以cer作为证书文件后缀名。
证书转换
DER转换为PEM
openssl x509 -inform der -in CA.crt -out CA.pem
x509转换为pfx
openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt
PKCS12到PEM转换
openssl pkcs12 -nocerts -nodes -in cert.p12 -out private.pem
验证
openssl pkcs12 -clcerts -nokeys -in cert.p12 -out cert.pem
从PFX格式文件中提取私钥格式文件
openssl pkcs12 -in mycert.pfx -nocerts -nodes -out mycert.key
转换pem到DER格式
openssl x509 -in Cert.pem -inform PEM -out cert.der -outform DER
转换pem到PKCS#12
openssl pkcs12 -export -in Cert.pem -out Cert.p12 -inkey key.pem
转换PKCS#12到pem
openssl pkcs12 -in sun59.p12 -out sun59.pem
部分脚本内容
产生私钥
openssl genrsa -des3 -passout pass:1234 -out /etc/pki/CA/private/cakey.pem 2048
自签证书
openssl req -new -x509 -passin pass:1234 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cacert.pem -days 3655 -subj "/C=CN/ST=BJ/L=BJ/O=Centos/OU=Linux Department/CN=centos.example.com"
产生CSR
openssl req -new -passin pass:1234 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/newcerts/client1.csr -subj "/C=CN/ST=LN/L=SY/O=Client1/OU=IT Department/CN=client1.example.com" openssl req -new -passin pass:1234 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/newcerts/server.csr -subj "/C=CN/ST=LN/L=DL/O=Server/OU=Operation System Department/CN=server.example.com"
签发证书
openssl x509 -req -in /etc/pki/CA/newcerts/client1.csr -CA /etc/pki/CA/cacert.pem -CAkey /etc/pki/CA/private/cakey.pem -CAcreateserial -passin pass:1234 -out /etc/pki/CA/certs/client1.crt openssl x509 -req -in /etc/pki/CA/newcerts/server.csr -CA /etc/pki/CA/cacert.pem -CAkey /etc/pki/CA/private/cakey.pem -CAcreateserial -passin pass:1234 -out /etc/pki/CA/certs/server.crt
签V3证书
openssl ca -extensions v3_ca -passin pass:1234 -in /etc/pki/CA/newcerts/client1.csr -config ./ca.config -days 300 -out /etc/pki/CA/certs/client1.crt -batch
产生随机数的几种方法
第一种: date +%s | sha256sum | base64 | head -c 10
解释: date +%s -- 当前时间戳
date +%s | sha256sum -- 对时间戳求hash值 (也可以使用md5sum)
date +%s | sha256sum | base64 -- 对hash值进行基于base64的编码
date +%s | sha256sum | base64 | head -c 10 -- 取前10个字符做为密码 第二种: tr -cd '*,+\-\.a-zA-z0-9' < /dev/urandom | head -c 10
解释: tr -cd '*,+\-\.a-zA-z0-9' < /dev/urandom -- 从/dev/urandom读取,并去掉非",*+-\.\-a-zA-Z0-9"这类字符
tr -cd '*,+\-\.a-zA-z0-9' < /dev/urandom | head -c 10 -- 取前10个字符 第三种: openssl rand 100 | base64 | head -c 10
解释: openssl rand 100 -- 利用系统openssl随机产生100个字节随机字符
openssl rand 100 | base64 -- 产生随机字符用base64编码
openssl rand 100 | base64 | head -c 10 -- 取前10个字符 第四种: date +%s | md5sum | head -c 10
解释: date +%s -- 得到当前时间戳
date +%s | md5sum -- 对时间戳求md5值,md5sum是128位hash值,sha256sum是256hash值
date +%s | md5sum | head -c 10 -- 取前10个字符,这里还可以对hash值求base64编码
产生sha512的密码
python -c 'import crypt; print crypt.crypt("nsadm", "$6$QvoUYKM/")'
也可以使用grub-crypt
grub-crypt --md5|--sha-256|--sha-512
openssl 只支持Up_front这种形式的
Up_front:
means SSL handshakes immediately follow up with TCP handshakes
Upgraded:
TLSstarted after a command at theapplication protocol level like tlsstart
You can do this for by adding -starttlsthe_name_of_the_protocol to this openssl s_clientcommand.
-starttls protocol
send the protocol-specific message(s) toswitch to TLS for communication. protocol is a keyword for the intendedprotocol. Currently, the only supported keywords are "smtp","pop3", "imap", "ftp", "xmpp","xmpp-server", and "irc."
包管理
获取rpm包的途径: 1、发行商的光盘或站点服务器
以CentOS为例:
http://mirrors.163.com
http://mirrors.sohu.com
2、http://rpmfind.net 3、http://rpm.pbone.net
RPM
rpm -ivh h:hash, 以#的个数显示安装进度,一个#表示2%的进度
--test:仅测试, 不真正执行安装过程
rpm -e --nodeps
查看所有已经安装的包: rpm -qa
查看包的描述信息: rpm -qi
查看某单个包是否安装: rpm -q package_name
查询包安装之后再当前系统生成的文件列表: rpm -ql package_name
查看某文件是哪个包安装生成的: rpm -qf /path/to/somefile
查询包安装后生成的帮助文档: rpm -qd package_name
查询包安装后生成的配置文件: rpm -qc package_name
查询包相关的脚本: rpm -q --scripts package_name
脚本有四类:
preinstall: 安装前脚本
postinstall: 安装后脚本
preuninstall: 卸载前脚本
postuninstall: 卸载后脚本
rpm包管理: 校验, 查看包安装后生成的文件是否被修改过:
rpm -V package_name
S file Size differs
M Mode differs (includes permissions and file type)
5 digest (formerly MD5 sum) differs
D Device major/minor number mismatch
L readLink(2) path mismatch
U User ownership differs
G Group ownership differs
T mTime differs
P caPabilities differ
rpm检验来源合法性和软件包完整性
包完整性: md5|sha1 通过单向加密机制
来源合法性: 通过公钥加密机制(RSA)
导入制作者的公钥, rpm --import /path/to/pgp-key-file
检查:rpm -K /path/to/package_file
rpm --checksig /path/to/package_file
--nosignature: 不检查来源合法性
--nodigest: 不检查完整性
rpm包数据库重建
重建:
rpm --initdb: 初始化
如果事先不存在一个数据库,则新建之;
rpm --rebuilddb: 重建
直接重建数据库,会覆盖原有的库;
YUM
yum配置宏
$releasever: 程序的版本,对Yum而言指的是redhat-release版本;只替换为主版本号,如RedHat 6.5,则替换为6;
$arch: 系统架构
$basearch: 系统基本架构,如i686,i586等的基本架构为i386;
$YUM0-9: 在系统中定义的环境变量,可以在yum中使用
获取当前系统相应宏替换结果的办法
# python
Python 2.6.6 (r266:84292, Nov 22 2013, 12:16:22)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import yum,pprint
>>> yb = yum.YumBase()
>>> pprint.pprint(yb.conf.yumvar,width=1)
Loaded plugins: fastestmirror, refresh-packagekit
{'arch': 'ia32e',
'basearch': 'x86_64',
'releasever': '6',
'uuid': 'ea249181-2f82-4c40-8c42-d51b3fce319a'}
>>> quit()
可以使用createrepo创建yum仓库, createrepo
源码安装
前提:准备好开发环境 编译过程:
./configure
make
make install
输出:
头文件
库文件
二进制程序
man文档
网络相关
Bridge&&802.1q
VLAN内核管理工具vconfig, TAP/TUN设备管理工具tunctl.
创建/删除Bridge
brctl addbr [BRIDGE NAME]
brctl delbr [BRIDGE NAME]
attach/detach设备到Bridge:
brctl addif [BRIDGE NAME][DEVICE NAME]
brctl delif [BRIDGE NAME][DEVICE NAME]
查看Bridge
brctl show
创建/删除VLAN设备
vconfig add [Parent Device Name][VLAN ID]
vconfig rem [VLAN DEVICE NAME]
设置VLAN设备flag
vconfig set_flag [VLAN DEVICE NAME][FLAG][VLAN]
设置VLAN设备qos
vconfig set_egress_map [VLAN DEVICE NAME] [SKB_PRIORITY] [VLAN_QOS]
vconfig set_ingress_map [VLAN DEVICE NAME] [SKB_PRIORITY] [VLAN_QOS]
查看VLAN设备情况
cat /proc/net/vlan/[VLAN DEVICE NAME]
创建VETH设备
ip link add link [DEVICE NAME] type veth
创建/删除TAP设备
tunctl -p [TAP DEVICE NAME]
tunctl -d [TAP DEVICE NAME]
查询系统所有二层设备, 包括VETH/TAP设备
ip link show
删除普通二层设备
ip link delete [DEVICE NAME] type [TYPE]
PortMap
Remote Procedure Call, RPC. 当一个RPC服务器启动时,会选择一个空闲的端口并在上面监听(每次启动的端口号各不相同), 同时它作为一个可用的服务会在portmap进程注册. 一个RPC服务器对应唯一一个RPC程序号,RPC服务器告诉portmap进程它在哪个端口号上监听连接请求和为哪个RPC程序号提供服务. 经过这个过程, portmap进程就知道了每一个已注册的PRC服务器所用的Internet端口号,而且还知道哪个程序号在这个端口上是可用的. portmap进程维护着一张RPC程序号到Internet端口号之间的映射表,它的字段包括程序号,版本号,所用协议,端口号和服务名, portmap进程通过这张映射表来提供程序号-端口号之间的转化功能
lsof
Lsof是遵从Unix哲学的典范,它只完成一个功能,并且做的相当完美――它可以列出某个进程打开的所有文件信息。打开的文件可能是普通的文件、目录、NFS文件、块文件、字符文件、共享库、常规管道、命名管道、符号链接、Socket流、网络Socket、UNIX域Socket,以及其它更多类型。因为“一切皆文件”乃为Unix系统的重要哲学思想之一,因此可以想象lsof命令的重要地位。
lsof输出各列信息的意义如下:
COMMAND:进程的名称 PID:进程标识符
USER:进程所有者
FD:文件描述符,应用程序通过文件描述符识别该文件。如cwd、txt等 TYPE:文件类型,如DIR、REG等
DEVICE:指定磁盘的名称
SIZE:文件的大小
NODE:索引节点(文件在磁盘上的标识)
NAME:打开文件的确切名称
FD 列中的文件描述符cwd 值表示应用程序的当前工作目录,这是该应用程序启动的目录,除非它本身对这个目录进行更改,txt 类型的文件是程序代码,如应用程序二进制文件本身或共享库,如上列表中显示的 /sbin/init 程序。
其次数值表示应用程序的文件描述符,这是打开该文件时返回的一个整数。如上的最后一行文件/dev/initctl,其文件描述符为 10。u 表示该文件被打开并处于读取/写入模式,而不是只读 ® 或只写 (w) 模式。同时还有大写 的W 表示该应用程序具有对整个文件的写锁。该文件描述符用于确保每次只能打开一个应用程序实例。初始打开每个应用程序时,都具有三个文件描述符,从 0 到 2,分别表示标准输入、输出和错误流。所以大多数应用程序所打开的文件的 FD 都是从 3 开始。
与 FD 列相比,Type 列则比较直观。文件和目录分别称为 REG 和 DIR。而CHR 和 BLK,分别表示字符和块设备;或者 UNIX、FIFO 和 IPv4,分别表示 UNIX 域套接字、先进先出 (FIFO) 队列和网际协议 (IP) 套接字。
lsof语法格式
lsof [options] filename
lsof /path/to/somefile:显示打开指定文件的所有进程之列表
lsof -c string:显示其COMMAND列中包含指定字符(string)的进程所有打开的文件;此选项可以重复使用,以指定多个模式;
lsof -p PID:查看该进程打开了哪些文件;进程号前可以使用脱字符“^”取反;
lsof -u USERNAME:显示指定用户的进程打开的文件;用户名前可以使用脱字符“^”取反,如"lsof -u ^root"则用于显示非root用户打开的所有文件;
lsof -g GID:显示归属gid的进程情况
lsof +d /DIR/:显示指定目录下被进程打开的文件
lsof +D /DIR/:基本功能同上,但lsof会对指定目录进行递归查找,注意这个参数要比grep版本慢:
lsof -a:按“与”组合多个条件,如lsof -a -c apache -u apache
lsof -N:列出所有NFS(网络文件系统)文件
lsof -d FD:显示指定文件描述符的相关进程;也可以为描述符指定一个范围,如0-2表示0,1,2三个文件描述符;另外,-d还支持其它很多特殊值,如:
mem: 列出所有内存映射文件;
mmap:显示所有内存映射设备;
txt:列出所有加载在内存中并正在执行的进程,包含code和data;
cwd:正在访问当前目录的进程列表; lsof -n:不反解IP至HOSTNAME
lsof -i:用以显示符合条件的进程情况
lsof -i[46] [protocol][@hostname|hostaddr][:service|port]
46:IPv4或IPv6
protocol:TCP or UDP
hostname:Internet host name
hostaddr:IPv4地址
service:/etc/service中的服务名称(可以不只一个)
port:端口号 (可以不只一个)
查看系统目前正在被打开的文件(一般是log文件)
lsof -Pn|grep "[0-9]w.*REG"|awk '{print $NF}'
查看系统正在侦听状态的进程
lsof -Pn |grep LISTEN
查看被删除的文件
lsof -Pn |grep deleted
对于应用程序而言,当进程打开了某个文件时,只要该进程保持打开该文件,即使将其删除,它依然存在于磁盘中。这意味着,进程并不知道文件已经被删除,它仍然可以向打开该文件时提供给它的文件描述符进行读取和写入。除了该进程之外,这个文件是不可见的,因为已经删除了其相应的目录索引节点。
如果文件被删除,则可以将相应的文件描述符中的内容保存出来
eg. cat /proc/1283/fd/2 >/var/log/messages
查看正在被修改的文件大小排序
lsof -Pn|egrep "[0-9]u.*REG|[0-9]w.*REG"|awk '{print $7" "$9}'|sort -rnu|head -20
查看网络活动
lsof -i @192.168.48.1
查看端口状态
lsof -i :22
查看正在读写的文件
lsof -Pn|grep "[0-9][ruw] .*REG "|awk '{print substr($4,length($4),1)" "$9" "$7}'|grep -v "/proc/"|sort -u
tcpdump
Syntax:
tcpdump [options] [Protocol] [Direction] [Host(s)] [Value] [Logical Operations] [Other expression]
常用选项:
常用选项:
-i any : Listen on all interfaces just to see if you're seeing any traffic. -n : Don't resolve hostnames. -nn : Don't resolve hostnames or port names. -X : Show the packet's contents in both hex and ASCII. -XX : Same as -X, but also shows the ethernet header. -v, -vv, -vvv : Increase the amount of packet information you get back. -c # : Only get x number of packets and then stop. -s : Define the snaplength (size) of the capture in bytes. Use -s0 to get everything, unless you are intentionally capturing less. -S : Print absolute sequence numbers. -e : Get the ethernet header as well. -q : Show less protocol information. -E : Decrypt IPSEC traffic by providing an encryption key. -A :Display Captured Packets in ASCII -w /path/to/some_file : Capture the packets and write into a file -r /path/from/some_file : Reading the packets from a saved file -tttt : Capture packets with proper readable timestamp
Protocol:
ether, fddi, ip, arp, rarp, decnet, lat, sca, moprc, mopdl, tcp and udp. 若没有定义协议,则所有协议都会被捕获
Direction(流向)
src, dst, src and dst, src or dst
若未指定则是src or dst
Hosts(主机)
net, port, host, portrange. 若未指定主机类型,则host为缺省值
Logical Operations:
and &&; or ||; not !
主机arp&route
清空arp表
arp -n|awk '/^[1-9]/ {print "arp -d "$1}' | sh
配置网卡
Bonding的模式7种方式:
#define BOND_MODE_ROUNDROBIN 0 (balance-rr模式)网卡的负载均衡模式
#define BOND_MODE_ACTIVEBACKUP 1 (active-backup模式)网卡的容错模式
#define BOND_MODE_XOR 2 (balance-xor模式)需要交换机支持
#define BOND_MODE_BROADCAST 3 (broadcast模式)
#define BOND_MODE_8023AD 4 (IEEE 802.3ad动态链路聚合模式)需要交换机支持
#define BOND_MODE_TLB 5 自适应传输负载均衡模式
#define BOND_MODE_ALB 6 网卡虚拟化方式
网卡Bonding
网卡绑定mode共有七种(0~6) bond0、bond1、bond2、bond3、bond4、bond5、bond6等7种,其中常用的有三种: mode=0:平衡负载模式,有自动备援,但需要”Switch”支援及设定。 mode=1:自动备援模式,其中一条线若断线,其他线路将会自动备援。 mode=6:平衡负载模式,有自动备援,不必”Switch”支援及设定。
需要说明的是如果想做成mode 0的负载均衡,仅仅设置这里options bond0 miimon=100 mode=0是不够的,与网卡相连的交换机必须做特殊配置(这两个端口应该采取聚合方式),因为做bonding的这两块网卡是使用同一个MAC地址.从原理分析一下(bond运行在mode 0下) mode 0下bond所绑定的网卡的IP都被修改成相同的mac地址,如果这些网卡都被接在同一个交换机,那么交换机的arp表里这个mac地址对应的端口就有多个,那么交换机接受到发往这个mac地址的包应该往哪个端口转发呢?正常情况下mac地址是全球唯一的,一个mac地址对应多个端口肯定使交换机迷惑了。所以 mode0下的bond如果连接到交换机,交换机这几个端口应该采取聚合方式(cisco称为 ethernetchannel,foundry称为portgroup),因为交换机做了聚合后,聚合下的几个端口也被捆绑成一个mac地址.我们的解 决办法是,两个网卡接入不同的交换机即可。 mode6模式下无需配置交换机,因为做bonding的这两块网卡是使用不同的MAC地址。
七种bond模式说明: 第一种模式:mod=0 ,即:(balance-rr) Round-robin policy(平衡轮循环策略) 特点:传输数据包顺序是依次传输(即:第1个包走eth0,下一个包就走eth1….一直循环下去,直到最后一个传输完毕),此模式提供负载平衡和容错能力;但是我们知道如果一个连接或者会话的数据包从不同的接口发出的话,中途再经过不同的链路,在客户端很有可能会出现数据包无序到达的问题,而无序到达的数据包需要重新要求被发送,这样网络的吞吐量就会下降 第二种模式:mod=1,即: (active-backup) Active-backup policy(主-备份策略) 特点:只有一个设备处于活动状态,当一个宕掉另一个马上由备份转换为主设备。mac地址是外部可见得,从外面看来,bond的MAC地址是唯一的,以避免switch(交换机)发生混乱。此模式只提供了容错能力;由此可见此算法的优点是可以提供高网络连接的可用性,但是它的资源利用率较低,只有一个接口处于工作状态,在有 N 个网络接口的情况下,资源利用率为1/N 第三种模式:mod=2,即:(balance-xor) XOR policy(平衡策略) 特点:基于指定的传输HASH策略传输数据包。缺省的策略是:(源MAC地址 XOR 目标MAC地址) % slave数量。其他的传输策略可以通过xmit_hash_policy选项指定,此模式提供负载平衡和容错能力 第四种模式:mod=3,即:broadcast(广播策略) 特点:在每个slave接口上传输每个数据包,此模式提供了容错能力 第五种模式:mod=4,即:(802.3ad) IEEE 802.3ad Dynamic link aggregation(IEEE 802.3ad 动态链接聚合) 特点:创建一个聚合组,它们共享同样的速率和双工设定。根据802.3ad规范将多个slave工作在同一个激活的聚合体下。 外出流量的slave选举是基于传输hash策略,该策略可以通过xmit_hash_policy选项从缺省的XOR策略改变到其他策略。需要注意的 是,并不是所有的传输策略都是802.3ad适应的,尤其考虑到在802.3ad标准43.2.4章节提及的包乱序问题。不同的实现可能会有不同的适应性。
必要条件: 条件1:ethtool支持获取每个slave的速率和双工设定 条件2:switch(交换机)支持IEEE 802.3ad Dynamic link aggregation 条件3:大多数switch(交换机)需要经过特定配置才能支持802.3ad模式
第六种模式:mod=5,即:(balance-tlb) Adaptive transmit load balancing(适配器传输负载均衡) 特点:不需要任何特别的switch(交换机)支持的通道bonding。在每个slave上根据当前的负载(根据速度计算)分配外出流量。如果正在接受数据的slave出故障了,另一个slave接管失败的slave的MAC地址。 该模式的必要条件:ethtool支持获取每个slave的速率
第七种模式:mod=6,即:(balance-alb) Adaptive load balancing(适配器适应性负载均衡) 特点:该模式包含了balance-tlb模式,同时加上针对IPV4流量的接收负载均衡(receive load balance, rlb),而且不需要任何switch(交换机)的支持。接收负载均衡是通过ARP协商实现的。bonding驱动截获本机发送的ARP应答,并把源硬件地址改写为bond中某个slave的唯一硬件地址,从而使得不同的对端使用不同的硬件地址进行通信。 来自服务器端的接收流量也会被均衡。当本机发送ARP请求时,bonding驱动把对端的IP信息从ARP包中复制并保存下来。当ARP应答从对端到达 时,bonding驱动把它的硬件地址提取出来,并发起一个ARP应答给bond中的某个slave。使用ARP协商进行负载均衡的一个问题是:每次广播 ARP请求时都会使用bond的硬件地址,因此对端学习到这个硬件地址后,接收流量将会全部流向当前的slave。这个问题可以通过给所有的对端发送更新 (ARP应答)来解决,应答中包含他们独一无二的硬件地址,从而导致流量重新分布。当新的slave加入到bond中时,或者某个未激活的slave重新 激活时,接收流量也要重新分布。接收的负载被顺序地分布(round robin)在bond中最高速的slave上 当某个链路被重新接上,或者一个新的slave加入到bond中,接收流量在所有当前激活的slave中全部重新分配,通过使用指定的MAC地址给每个 client发起ARP应答。下面介绍的updelay参数必须被设置为某个大于等于switch(交换机)转发延时的值,从而保证发往对端的ARP应答 不会被switch(交换机)阻截。
必要条件: 条件1:ethtool支持获取每个slave的速率; 条件2:底层驱动支持设置某个设备的硬件地址,从而使得总是有个slave(curr_active_slave)使用bond的硬件地址,同时保证每个 bond 中的slave都有一个唯一的硬件地址。如果curr_active_slave出故障,它的硬件地址将会被新选出来的 curr_active_slave接管 其实mod=6与mod=0的区别:mod=6,先把eth0流量占满,再占eth1,….ethX;而mod=0的话,会发现2个口的流量都很稳定,基本一样的带宽。而mod=6,会发现第一个口流量很高,第2个口只占了小部分流量
miimon 监视网络链接的频度,单位是毫秒,我们设置的是200毫秒。 max_bonds 配置的bond口个数 mode bond模式,主要有以下几种,在一般的实际应用中,0和1用的比较多,
DEVICE="eth0"
USERCTL=no
ONBOOT=yes
MASTER=bond0
SLAVE=yes
BOOTPROTO=none DEVICE="eth1"
USERCTL=no
ONBOOT=yes
MASTER=bond0
SLAVE=yes
BOOTPROTO=none DEVICE="bond0"
BOOTPROTO="static"
MTU="1500"
ONBOOT="yes"
BONDING_OPTS='mode=1 miimon=100 primary=eth0'
IPADDR=192.168.48.131
NETMASK=255.255.255.0
GATEWAY=192.168.48.130
DNS1=192.168.48.130
检查网络状态
vmstat
vmstat:
procs
r: 运行或等待CPU时间片的进程的个数
b: 被阻塞(通常为等待IO完成)的进程队列的长度 memory
swpd: 从物理内存交换至swap中的数据量
free: 未使用物理内存大小
buffer: buffer空间大小,通常与缓存写操作相关
cache: cache空间大小,通常与缓存读操作相关 swap
si: swap in, 数据进入swap中的数据量,通常是速率,kb/s
so: swap out, 数据离开swap的数据量, io
bi: block in,从块设备读入的数据量,通常是速率,kb/s
bo: block out, 保存至块设备中的数据量,通常是速率,kb/s system
in: 中断发生速率,每秒的中断数;
cs: context switch, 上下文切换,进程切换,速率,通常为每秒钟切换的次数 cpu
us
sy
id
wa
st # vmstat [delay [counts]]
-s: 显示内存统计数据
HTTP Client
服务相关
curl
curl命令选项:
--cacert <file> CA证书 (SSL)
--capath <directory> CA目录 (made using c_rehash) to verify peer against (SSL)
--compressed 要求返回是压缩的形势 (using deflate or gzip)
--connect-timeout <seconds> 设置最大请求时间
-H/--header <line>自定义头信息传递给服务器
-i/--include 输出时包括protocol头信息
-I/--head 只显示文档信息
--interface <interface> 使用指定网络接口/地址
-s/--silent静音模式。不输出任何东西
-u/--user <user[:password]>设置服务器的用户和密码
-p/--proxytunnel 使用HTTP代理
rsyslogd
Rsyslog是syslogd的多线程增强版,提供三种传输方式:
- UDP
- TCP
- RELP
UDP配置
$ModLoad imudp
$UDPServerRun 514
$AllowedSender UDP, 192.168.48.0/24
$template Remote,"/var/log/syslog/%fromhost-ip%/%fromhost-ip%_%$YEAR%-%$MONTH%-%$DAY%.log"
:fromhost-ip, !isequal, "127.0.0.1" ?Remote
TCP配置
$ModLoad imtcp
$InputTCPServerRun 514
$AllowedSender TCP, 192.168.48.0/24
$template Remote,"/var/log/syslog/%fromhost-ip%/%fromhost-ip%_%$YEAR%-%$MONTH%-%$DAY%.log"
:fromhost-ip, !isequal, "127.0.0.1" ?Remote
RELP传输
$ModLoad imrelp # 加载相应模块
$InputRELPServerRun 20514 # 监听端口
$template Remote,"/var/log/syslog/%fromhost-ip%/%fromhost-ip%_%$YEAR%-%$MONTH%-%$DAY%.log"
:fromhost-ip, !isequal, "127.0.0.1" ?Remote
Client端
$ActionQueueType LinkedList # use asynchronous processing
$ActionQueueFileName srvrfwd # set file name, also enables disk mode
$ActionResumeRetryCount -1 # infinite retries on insert failure
$ActionQueueSaveOnShutdown on # save in-memory data if rsyslog shuts down
*.* :omrelp:192.168.48.130:20514
###其他场景
*.* @@192.168.48.131
NTP
Troubleshooting
[root@ausyd-WFO-ACR2 ~]# ntpq -np
remote refid st t when poll reach delay offset jitter
==============================================================================
*129.224.76.34 192.61.61.44 4 u 85 128 377 197.869 -13.437 39.879
129.221.132.42 129.224.76.34 5 u 69 128 377 294.079 -22.477 32.765
192.207.98.31 129.224.76.34 5 u 81 128 377 0.292 -15.927 38.265 [root@ausyd-WFO-ACR2 ~]# ntpq -i
ntpq> ass ind assID status conf reach auth condition last_event cnt
===========================================================
1 11563 9624 yes yes none sys.peer reachable 2
2 11564 9024 yes yes none reject reachable 2
3 11565 9024 yes yes none reject reachable 2
ntpq> rv 11563
assID=11563 status=9624 reach, conf, sel_sys.peer, 2 events, event_reach,
srcadr=timehost1, srcport=123, dstadr=172.24.202.112, dstport=123,
leap=00, stratum=4, precision=-6, rootdelay=65.140,
rootdispersion=78.842, refid=192.61.61.44, reach=377, unreach=0,
hmode=3, pmode=4, hpoll=7, ppoll=7, flash=00 ok, keyid=0, ttl=0,
offset=-13.437, delay=197.869, dispersion=22.047, jitter=47.972,
reftime=da377f63.1cdc0478 Wed, Jan 6 2016 11:56:19.112,
org=da378161.8cbb3fdc Wed, Jan 6 2016 12:04:49.549,
rec=da378161.bb9b8835 Wed, Jan 6 2016 12:04:49.732,
xmt=da378161.88e539d7 Wed, Jan 6 2016 12:04:49.534,
filtdelay= 198.09 197.98 198.19 203.75 198.44 199.54 203.07 197.87,
filtoffset= -84.06 -79.58 -73.02 -69.69 -15.91 -18.38 -12.31 -13.44,
filtdisp= 15.63 17.58 19.48 21.39 23.29 24.25 25.20 26.19
timezone
mv /usr/share/zoneinfo/[时区文件] /etc/localtime
killall
#测试服务是否在线
killall -0 nginx
echo $?
If sig is 0, then no signal is sent, but error checking is still performed.
邮件服务器
rhel5: sendmail
rhel6: postfix
SMTP: Simple Mail Transfer Protocol 无法实现用户认证
ESMTP: 实现检测, 无法进行认证
POP3: Post Office Protocol, 邮局协议3
IMAP4: Internet Mail Access Protocol, IMAP4功能比POP3强大,但是IMAP3更加消耗资源
UUCP: Unix to Unix Copy: Unix主机复制文件的协议
SMTP本身可以实现传输路由的功能, C/S架构 sendmail, smtpd(TCP:25)
邮件传输: MT
邮件投递: MD
邮件用户: MU
MUA: Mail User Agent 邮件用户代理. 用于编写邮件的工具. eg: outlook
lmtp: local mail transfer protocol 本地邮件传输协议
OP
虚拟化
ESXI网卡
1、vsphere中的Esxi中的操作系统称作 HypervCentersor ,是基于Redhat Linux的改良规约版本,大部 分bash还是能够使用的,只是网络资源都是由 HypervCentersor 操作系统管理的,因此无法使用ifconfig之类的命令操作。
2、NIC teaming 指的是多个物理网卡合并成一个网络界面来给单台的设备(比如Exsi)使用,可以保证在一个网卡出问题的时候,系统能够通过另外的网卡继续常规任务。
3、Esxi中的网络,物理网卡称作 vmnic0 ,虚拟交换机则是vSwitch0 开始编号的,默认系统会创建一个vSwitch0的交换机,每个交换机可以由一片或者多片vmnic组成。
4、Esxi中的虚拟交换机是通过端口组(Port Group)进行逻辑区分的,不同的端口组具有不同的功能,Esxi具有三个端口组分别用于不同的功能: ①主控台(Service Console):用于连接到Esxi主机的通讯接口,必须拥有一个IP地址,通称为 vswif,第一个主控台端口就是 vswif0。 ②ESXi内核(VMKernel):用于Esxi高级功能,比如vMotion,HA,FT(Fault Tolerance)等,通称为 vmk,第一个就是 vmk0. ③虚拟机通讯端口组(Virtual Machine):用于给虚拟机进行通讯的端口。这些端口可能连接到几台相连的虚拟交互机上,也可能连接到真实的物理交换机上面。
5、vSwitch和物理网卡的关系 一个vSwitch至少需要一个物理网卡,但是一个vSwitch上可以同时有3中端口组,多个vSwitch无法使用同一个物理网卡,就是这样的对应关系。
6、VLAN组件 VLAN的观念和虚拟机或物理机无关,主要是划分网络以及安全上相关的服务,要让vSphere支持vlan,必须让物理设备支持vlan才可以,可以在创建端口组的时候,在属性里面设置 VLAN 号。
7、VM上面的网卡 ①vlance网卡,在没有安装vmware tool的主机上的网卡,只有基本的联网功能,无更多的配置。 ②vmxnet网卡,安装vmware tool之后,vm中的网卡就变成了 vmxnet 网卡,这是一个高性能的网卡,具有更多的配置选项。`
安全相关
使用urandom替代random
urandom是通过算法产生伪随机数的工具,由于使用random产生随机数会消耗大量的时间,很多时候为了方便产生key使用以下方式替换
mv /dev/{random,random.bak}
ln -s /dev/urandom /dev/random
Tips
记录make&&make install 日志
make >& LOG_make &;tailf LOG_make
make install >& LOG_install &;tailf LOG_install
MVC
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构
MVC架构: Controller,Model和View各自独立,一个流行的开源实现是Apache Structs框架;目今,设计优良的Web应用程序通常用相就的技术实现相应的功能,比如: 1、Servlet用于实现应用逻辑; 2、JSP用于内容展示; 3、标签库和JSP扩展语言用于替换在JSP内部嵌入Java代码,进而降低了HTML维护的复杂度; 4、MVC框架用于实现展示和应用逻辑的分离;