FreeBSD磁盘组织学习笔记

FreeBSD磁盘组织学习笔记
在FreeBSD中分区与文件系统是一一对应的,它这里的分区和常用的在Windows中的分区的意思不一样(如:MS-DOS分区),在FreeBSD中,将一块硬盘可以最多分成四个slice(片段),每一个slice上又可以分成最多8个分区(partition),这里的一个slice就相当与Windows里面的一个分区看成为一个slice,在FreeBSD中将一个slice分成8个(partition)分区,分别表示为a,b,c,d,e,f,g,h,传统上a,b,c,d分区有特别的意义,如a表示root分区,b表示swap分区,c表示整个slice,d表示整个硬盘。但在FreeBSD-2.0.5 Release后,只需要C定位为整个slice,其他各盘可以互换,但一般还是依照传统。
Slice 其编号是从1到4,Slice编号在设备名后面,并有一个s前缀,从1开始,如da0s1是第一个SCSI磁盘驱动器的第一个Slice,每个磁盘上只能有四个物理Slice,自己可以在物理Slice中使用适当的类型来创建逻辑Slice,这些扩展Slice 编号从5开始,因此ad0s5是第一个IDE磁盘中第一个扩展Slice; Slice“专项指定”物理驱动器,和其他驱动器都包含partitions,那几个partition都是字母从a 到h来标记,如ad1s3e表示第二快IDE磁盘上第三个Slice的第五个partition。
磁盘设备的代码
代码 说明
ad ATAPI (IDE) 磁盘
da SCSI 直接存取磁盘
acd ATAPI (IDE) 光驱
cd SCSI 光驱
fd 软驱

样例磁盘, Slice, 和 Partition 它们的命名
命名 说明
ad0s1a 在首个IDE磁盘(ad0)上的 第一个slice (s1)里的 第一个partition (a)。
da1s2e 在第二个SCSI磁盘(da1)上的 第二个slice(s2)里的 第五个partition(e

一个磁盘的布局
从在系统里的首个IDE磁盘图表可以显示出FreeBSD的见解。假设磁盘大小为4 GB,它里面包含了两个2 GB 大小的slices (但在MS-DOS叫partitions)。 首个slice是一个MS-DOS磁盘叫C:,而第二个slice是FreeBSD配置好的slice。 FreeBSD配置好的slice有三个partitions和另一个交换分区。

关于/proc 文件系统

1. Linux和freebsd下都有/proc 文件系统,它是内存里的一个虚拟的文件系统

2. /proc 文件系统在Linux和freebsd 下的异同
Linux                                                               freebsd
df -h 时不显示                                                df -h 时显示,并占用100%
含有进程及其它系统信息                             只含有进程信息

 

3. /proc文件系统内容解释

/proc 文件系统是一个假的文件系统。它不存在在磁盘某个磁盘上。而是由核心在内存中产生。用于提供关于系统的信息(originally about processes, hence the name)。下面说明一些最重要的文件和目录。 /proc 文件系统在proc man页中有更详细的说明。

/proc/1 
关于进程1的信息目录。每个进程在/proc 下有一个名为其进程号的目录。
/proc/cpuinfo 
处理器信息,如类型、制造商、型号和性能。
/proc/devices 
当前运行的核心配置的设备驱动的列表。
/proc/dma 
显示当前使用的DMA通道。
/proc/filesystems 
核心配置的文件系统。
/proc/interrupts 
列出使用中的中断号,这在硬件冲突的诊断中十分有用。
/proc/ioports 
当前使用的I/O端口。
/proc/kcore 
系统物理内存映象。与物理内存大小完全一样,但不实际占用这么多内存;it is generated on the fly as programs access it. (记住:除非你把它拷贝到什么地方,/proc 下没有任何东西占用任何磁盘空间。)
/proc/kmsg 
核心输出的消息。也被送到syslog 
/proc/ksyms 
核心符号表。
/proc/loadavg 
系统"平均负载";3个没有意义的指示器指出系统当前的工作量。
/proc/meminfo 
存储器使用信息,包括物理内存和swap。
/proc/modules 
当前加载了哪些核心模块。
/proc/net 
网络协议状态信息。
/proc/self 
到查看/proc 的程序的进程目录的符号连接。当2个进程查看/proc 时,是不同的连接。这主要便于程序得到它自己的进程目录。
/proc/stat 
系统的不同状态,such as the number of page faults since the system was booted.
/proc/uptime 
系统启动的时间长度。
/proc/version 
核心版本。

 

相关资料: http://www.ibm.com/developerworks/cn/linux/l-proc.html

问题:不知道freebsd下的系统信息如何方便地得到?

PHP中的错误与异常

1. PHP中的错误与异常时不同的,try 不能捕获到函数中非throw产生的错误,set_error_handler函数可以设置错误处理句柄,set_exception_handler可以设置异常处理句柄,不过,异常一般不这么做,都是用try{}catch(){}来处理的。

2. 不像C语言,函数的返回值可以标识函数是否执行成功,也可以标识可能产生的错误类型,如open函数在打开错误时总返回-1,但是错误原因可能是不同的,只是可以通过errno全局变量来获取详细的错误号,虽然php同样有fopen函数,但是没有类似errno的全局变量(可能是我没有发现,但愿有)。

根分区只读后会产生很多奇怪的问题

 

 1. 卸载一个分区后,df 仍显示该分区,因为根分区只读,卸载操作成功了,但修改根分区下配置文件的操作没有成功,通过strace发现,df是读文件的,好像读的是/etc/mtab

2. /root 的历史命令没有记录,因为根分区只读,而root刚好在根分区,所以history文件无法修改就没有记录

3.  。。。

令人琢磨的 history 命令

大家知道 history命令可以列出最近执行过的命令,而且我们也知道,最近执行过的命令是存放在用户目录下的.bash_history 文件中的;但是有一点令人迷惑,我同时以同一个用户身份打开两个终端,交替在两个终端中执行命令,这时,我们分别在每个终端中使用history命令,显示的都是当前终端里刚执行过的命令,而不是两个终端执行的命令的交叉显示,我们说,执行过的命令是存入文件的,而打开文件,发现里面没有我们刚执行过的命令,这时我们不得不怀疑,刚才执行过的命令并没有立即写history文件,肯定是先缓存起来了,那么什么时候才写文件呢?目前我只知道当exit的时候是要写文件的,其它的时候,如果执行的命令足够多了,会写文件吗?这个还不清楚。

我起初是考虑使用strace 看看history是怎么执行的,但是计算机死活说history不是命令,type history 看看,原来history是内置命令,不是文件,所以strace就不管了,由此也知道了,strace 不能跟踪内置命令,因为strace可以跟踪一个进程(使用进程的pid),如果内置命令也是要产生进程的话,肯定是可以跟踪的,猜想内置命令执行时并不产生一个进程

注意:默认history命令列出很多曾经执行的命令,如果只要后n条,可以history n

 

strace 也能用,直接strace bash进程就行了

关于cookie

关于cookie曾经研究过一些,现在补充一些:

1. 进程cookie的实现
从http协议的角度来讲,进程cookie和文件cookie都是用Set-Cookie 来发送的,其区别就是进程cookie没有设置过期时间,而文件cookie有过期时间,PHPSESSIONID是典型的没有过期时间的cookie,不过,除此之外,我们自己设置cookie时只要不指定过期时间,都是进程cookie的,只保留在内存中,不写入cookie文件,达到重启浏览器session失效的效果。不过,还有一点需要注意,也是我从来没有注意到的,PHPSESSIONID也不是说绝对就是进程cookie的,在php.ini 中有下述设置:

; Lifetime in seconds of cookie or, if 0, until browser is restarted.
session.cookie_lifetime = 10

该设置是指定设置PHPSESSIONID这个cookie时(不影响其它进程cookie的设置是否指定过期时间,0 为不指定,这是正常情况,这样PHPSESSIONID就被设置为进程cookie,如果非0 ,那么发送PHPSESSIONID的Set-Cookie 头时就是含有过期时间的,对于浏览器而言,不管该cookie叫什么名字或起什么作用,只要有过期时间,就是文件cookie(即:写入文件),因为session是要重启浏览器就失效的,所以,我建议将此值设置为0;另外,如果设置的时间比较短而且客户端与服务器的时间差又比较大,可能就无法登陆,因为session刚设置就失效,服务器上的一个将来的时间可能对客户端来说已经是过去的时间了。

2. php发展到4.0 以后,register_globals 一般都设置为off ,所以,我不建议使用session_register();函数,直接使用$_SESSION这个全局变量更好,也方便。

3. 关于PHP加速器eaccelarator默认的编译禁用session的说明:

PHP 资源类型 — stream

PHP 中有一中特殊的变量叫资源,其中一种资源类型叫 stream,这里就说说stream

1. 获取可以使用的流:
print_r(stream_get_wrappers());

2. 注册一个用 PHP 类实现的 URL 封装协议,允许用户实现自定义的协议处理器和流,详细请参看手册,
boolean stream_register_wrapper ( string protocol,  string classname )

3. stream_context_* 类的函数 (还没来及看呢)

关于虚拟主机的配置

Apache的虚拟主机主要分两种:基于ip的虚拟主机和基于域名的虚拟主机

对于单纯的基于ip的虚拟主机来说,配置像这样:

NameVirtualHost 10.10.10.11:80
NameVirtualHost 10.10.10.12:80

#VirtualHost 1
<VirtualHost 10.10.10.11:80>
DocumentRoot "/aaa/"
ServerName domain1
</VirtualHost>

#VirtualHost 2
<VirtualHost 10.10.10.12:80>
DocumentRoot "/bbb/"
ServerName domain2
</VirtualHost>

说明:因为每个ip都配置了虚拟主机,所以只需根据ip就可以判断要访问的是哪个虚拟主机,如果用domain2来访问,而hosts里设置domain2指向10.10.10.11,那么会访问到哪个虚拟主机呢?当然,先根据ip判断,访问 VirtualHost 1了,所以ServerName没有多大用途,师傅说可以作为环境变量(就是说环境变量里会出现ServerName的);或许您会问了,如果用127.0.0.1来访问呢,确实没有给该ip指定使用哪个虚拟主机,这种情况下排在第一个的那个(就是VirtualHost 1)就是默认虚拟主机了,就是说,没有能匹配的上的(用ip和域名匹配,ip优先),就使用默认虚拟主机

 

对于单纯的基于域名的虚拟主机,配置像这样:

#任何ip都是用虚拟主机
NameVirtualHost *:80

#VirtualHost 1
<VirtualHost *:80>
DocumentRoot "/aaa/"
ServerName domain1
</VirtualHost>

#VirtualHost 2
<VirtualHost *:80>
DocumentRoot "/bbb/"
ServerName domain2
</VirtualHost>

说明:这样的话,不管走哪个ip(因为根据ip没法区分),用domain1访问,就访问到VirtualHost 1,用domain2访问,就访问到VirtualHost 2;

对于既有基于ip的虚拟主机也有基于域名的虚拟主机,配置像这样:

#任何ip都是用虚拟主机
NameVirtualHost *:80

#VirtualHost 1
<VirtualHost 10.10.10.11:80>
DocumentRoot "/aaa/"
ServerName domain1
</VirtualHost>

#VirtualHost 2
<VirtualHost 10.10.10.12:80>
DocumentRoot "/bbb/"
ServerName domain2
</VirtualHost>

#VirtualHost 3
<VirtualHost domain3:80>
DocumentRoot "/ccc/"
ServerName domain3
</VirtualHost>

说明:
1. 要注意启动apache时,domain3指向的是哪个ip,因为<VirtualHost domain3:80>里的domain3是要解释成ip的,分析的时候就把这里当作解析成的ip来对待

2. 假设domain3解释为10.10.10.11,如果客户端用domain3指向10.10.10.11来访问,我们发现就有两个10.10.10.11:80的虚拟主机,然后根据ServerName判断,发现#VirtualHost 3是最匹配的一个虚拟主机,于是#VirtualHost 3就是要访问到的虚拟主机;

3. 假设domain3解释为10.10.10.11,如果客户端用domain3指向10.10.10.12来访问,先根据ip判断,只有#VirtualHost 2是匹配的,所以#VirtualHost 2就是要访问到的虚拟主机;

4. 要想只要用domain3访问,都是访问/ccc/目录,那么就要对两个ip都配置ServerName为domain3的虚拟主机;我们想,将#VirtualHost 3改成如下行吗:
#VirtualHost 3
<VirtualHost *:80>
DocumentRoot "/ccc/"
ServerName domain3
</VirtualHost>

答案是:不行;因为做ip匹配的时候,优先选用更精确匹配的一个,显然与另外两个虚拟主机相比,通过任何一个ip访问,* 都不如直接用ip定义的虚拟主机精确,所以这时的#VirtualHost 3只有通过环回地址访问,而且只要通过环回地址访问,使用任何主机名访问的都是#VirtualHost 3;

对于NameVirtualHost的使用
如果某个ip:port 上只设置了一个虚拟主机,那么NameVirtualHost ip:port 可以不写,因为从这个ip:port的访问不需要做任何选择;
如果某个ip:port 上设置了多于一个虚拟主机,那么必须使用指令
NameVirtualHost ip:port ,
否则从该ip:port的访问只访问第一个该ip:port 的虚拟主机(因为它优先,apache启动时会提示的);
如果使用了指令
NameVirtualHost ip:port ,
却没有为该ip:port定义任何虚拟主机,好像不会出现访问到错误的虚拟主机的问题(因为谁也不知道你想干什么,不过apache还是会提示你:[warn] NameVirtualHost ip:port has no VirtualHosts);
如果VirtualHost 指定的虚拟主机没有匹配一个NameVirtualHost 指令,那么该虚拟主机不会被用到(除非他是第一个虚拟主机),这相当于没有NameVirtualHost 指令,即:如果有多个虚拟主机,一定要有NameVirtualHost 指令

注:

虚拟主机中可以缺省很多指令,我曾经只是想给通过不同域名的访问分别记录日志,实际上他们访问的都是相同的东西,所以DocumentRoot指令就可以省略了,里面我只写了三条指令,如:

<VirtualHost *:80 >
        ServerName *
        TransferLog "|rotatelogs /backup/apachelog/%Y%m/access_log.%Y%m%d 86400 480"
        ErrorLog "|/rotatelogs /backup/apachelog/%Y%m/error_log.%Y%m%d 86400 480"
</VirtualHost>


打包大批量文件的方法

对于大批量的文件如果要tar的话,是不能直接:tar -cvf a.tar * 的,因为* 扩展开来太大了,会出现参数太长的错误,一般来讲这种问题都通过xargs命令来解决,如:

ls * | xargs tar -rvf a.tar

注意:
1. 这里用到了tar命令的选项 -r ,是append的意思,但是如果tar文件不存在,也有create的作用
2. -r 选项不能和 -z 选项同时使用,所以需要压缩的话,都tar完之后再gzip

如果不知道 -r 选项,当然还可以 把所有要tar的文件mv到一个新的目录,还得用到xargs命令,不过这时就有点问题了,如:

ls * | xargs mv source target

因为一般情况下我们使用mv时,目标是最后一个参数,所以用xargs传参就有些不合适,但是我man mv 发现可以用选项指定目的地,可以这样写:

ls * | xargs mv –target-directory=/newdir/
然后:tar -zcvf a.tar /newdir

注: 这里的ls * 仅代表数据源的意思,不要直译,可能是find ….或 grep .. 等