2010年3月30日星期二

crablfs

http://crablfs.sourceforge.net/sysadm_zh_CN.html#toc1
http://crablfs.sourceforge.net/

ERC使用简介(转)

http://emacser.com/erc.htm
http://jianlee.ylinux.org/Computer/Emacs/erc.html#sec4
突然想找几个 erlang的irc 玩玩, 找两个探讨一下. 用emacs的好处凸显出来, 这很简单

ERC使用简介(转)

转:http://emacser.com/erc.htm
突然想找几个 erlang的irc 玩玩, 找两个探讨一下. 用emacs的好处凸显出来, 这很简单

man 小常识一则

passwd(5)

该格式说明需查阅特定的手册页(后面简称“man”)。括号中的数字指定 man 中特定的章节。比如 passwd 有两个手册页。根据 LFS 安装说明,这两个手册页将会位于/usr/share/man/man1/passwd.1 /usr/share/man/man5/passwd.5。每个手册页都有不同的内容。本书使用 passwd(5) 来指代 /usr/share/man/man5/passwd.5man passwd 会显示它能匹配“passwd” 的第一个手册页,即 /usr/share/man/man1/passwd.1。在此例中,若要读取该手册页,则需要运行 man 5 passwd 来读取你想要指定的手册。需要说明的是绝大部分手册不存在多个相同的手册名,因此 man <程序名> 基本就足够了。

什么是proc文件系统(转)

转:http://hi.baidu.com/ʫչ/blog/item/ee07f13612d7d0300b55a96a.html
什么是proc文件系统 |linux /proc目录介绍|proc中文手册

proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。用户和应用程序可以通过proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是动态从系统内核读出所需信息并提交的。它的目录结构如下:

目录名称 目录内容
apm 高级电源管理信息
cmdline 内核命令行
Cpuinfo 关于Cpu信息
Devices 可以用到的设备(块设备/字符设备)
Dma 使用的DMA通道
Filesystems 支持的文件系统
Interrupts 中断的使用
Ioports I/O端口的使用
Kcore 内核核心印象
Kmsg 内核消息
Ksyms 内核符号表
Loadavg 负载均衡
Locks 内核锁
Meminfo 内存信息
Misc 杂项
Modules 加载模块列表
Mounts 加载的文件系统
Partitions 系统识别的分区表
Rtc 实时时钟
Slabinfo Slab池信息
Stat 全面统计状态表
Swaps 对换空间的利用情况
Version 内核版本
Uptime 系统正常运行时间

并不是所有这些目录在你的系统中都有,这取决于你的内核配置和装载的模块。另外,在/proc下还有三个很重要的目录:net,scsi和 sys。Sys目录是可写的,可以通过它来访问或修改内核的参数(见下一部分),而net和scsi则依赖于内核配置。例如,如果系统不支持scsi,则 scsi目录不存在。

除了以上介绍的这些,还有的是一些以数字命名的目录,它们是进程目录。系统中当前运行的每一个进程都有对应的一个目录在/proc下,以进程的 PID号为目录名,它们是读取进程信息的接口。而self目录则是读取进程本身的信息接口,是一个link。Proc文件系统的名字就是由之而起。进程目录的结构如下:

目录名称 目录内容
Cmdline 命令行参数
Environ 环境变量值
Fd 一个包含所有文件描述符的目录
Mem 进程的内存被利用情况
Stat 进程状态
Status 进程当前状态,以可读的方式显示出来
Cwd 当前工作目录的链接
Exe 指向该进程的执行命令文件
Maps 内存映象
Statm 进程内存状态信息
Root 链接此进程的root目录

用户如果要查看系统信息,可以用cat命令。例如:

# cat /proc/interrupts
CPU0
0: 8728810 XT-PIC timer
1: 895 XT-PIC keyboard
2: 0 XT-PIC cascade
3: 531695 XT-PIC aha152x
4: 2014133 XT-PIC serial
5: 44401 XT-PIC pcnet_cs
8: 2 XT-PIC rtc
11: 8 XT-PIC i82365
12: 182918 XT-PIC Mouse
13: 1 XT-PIC fpu PS/2
14: 1232265 XT-PIC ide0
15: 7 XT-PIC ide1
NMI: 0

用户还可以实现修改内核参数。在/proc文件系统中有一个有趣的目录:/proc/sys。它不仅提供了内核信息,而且可以通过它修改内核参数,来优化你的系统。但是你必须很小心,因为可能会造成系统崩溃。最好是先找一台无关紧要的机子,调试成功后再应用到你的系统上。

要改变内核的参数,只要用vi编辑或echo参数重定向到文件中即可。下面有一个例子:

# cat /proc/sys/fs/file-max
4096
# echo 8192 >; /proc/sys/fs/file-max
# cat /proc/sys/fs/file-max
8192

如果你优化了参数,则可以把它们写成添加到文件rc.local中,使它在系统启动时自动完成修改。

/proc文件系统中网络参数

在/proc/sys/net/ipv4/目录下,包含的是和tcp/ip协议相关的各种参数,下面我们就对这些网络参数加以详细的说明。

ip_forward 参数类型:BOOLEAN
0 - 关闭(默认值)
not 0 - 打开ip转发

在网络本地接口之间转发数据报。该参数非常特殊,对该参数的修改将导致其它所有相关配置参数恢复其默认值(对于主机参阅RFC1122,对于路由器参见RFC1812)

ip_default_ttl 参数类型:INTEGER
默认值为 64 。表示IP数据报的Time To Live值。

ip_no_pmtu_disc 参数类型:BOOLEAN
关闭路径MTU探测,默认值为FALSE

ipfrag_high_thresh 参数类型:整型
用来组装分段的IP包的最大内存量。当ipfrag_high_thresh数量的内存被分配来用来组装IP包,则IP分片处理器将丢弃数据报直到ipfrag_low_thresh数量的内存被用来组装IP包。

ipfrag_low_thresh 参数类型:整型
参见ipfrag_high_thresh。

ipfrag_time 参数类型:整型
保存一个IP分片在内存中的时间。

inet_peer_threshold 参数类型:整型
INET对端存储器某个合适值,当超过该阀值条目将被丢弃。该阀值同样决定生存时间以及废物收集通过的时间间隔。条目越多﹐存活期越低﹐GC 间隔越短

inet_peer_minttl 参数类型:整型
条目的最低存活期。在重组端必须要有足够的碎片(fragment)存活期。这个最低存活期必须保证缓冲池容积是否少于 inet_peer_threshold。该值以 jiffies为单位测量。

inet_peer_maxttl 参数类型:整型
条目的最大存活期。在此期限到达之后﹐如果缓冲池没有耗尽压力的话(例如﹐缓冲池中的条目数目非常少)﹐不使用的条目将会超时。该值以 jiffies为单位测量。

inet_peer_gc_mintime 参数类型:整型
废物收集(GC)通过的最短间隔。这个间隔会影响到缓冲池中内存的高压力。 该值以 jiffies为单位测量。

inet_peer_gc_maxtime 参数类型:整型
废物收集(GC)通过的最大间隔,这个间隔会影响到缓冲池中内存的低压力。 该值以 jiffies为单位测量。

tcp_syn_retries 参数类型:整型
对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃。不应该大于255,默认值是5,对应于180秒左右。

tcp_synack_retries 参数类型:整型
对于远端的连接请求SYN,内核会发送SYN + ACK数据报,以确认收到上一个 SYN连接请求包。这是所谓的三次握手( threeway handshake)机制的第二个步骤。这里决定内核在放弃连接之前所送出的 SYN+ ACK 数目。

tcp_keepalive_time 参数类型:整型
当keepalive打开的情况下,TCP发送keepalive消息的频率,默认值是2个小时。

tcp_keepalive_probes 参数类型:整型
TCP发送keepalive探测以确定该连接已经断开的次数,默认值是9。

tcp_keepalive_interval 参数类型:整型
探测消息发送的频率,乘以tcp_keepalive_probes就得到对于从开始探测以来没有响应的连接杀除的时间。默认值为75秒,也就是没有活动的连接将在大约11分钟以后将被丢弃。

tcp_retries1 参数类型:整型
当出现可疑情况而必须向网络层报告这个可疑状况之前﹐需要进行多少次重试。最低的 RFC 数值是 3 ﹐这也是默认值﹐根据RTO的值大约在3秒 - 8分钟之间。

tcp_retries2 参数类型:整型
在丢弃激活的TCP连接之前﹐需要进行多少次重试。RFC1122规定,该值必须大于100秒。默认值为15,根据RTO的值来决定,相当于13-30分钟,

tcp_orphan_retries 参数类型:整型
在近端丢弃TCP连接之前﹐要进行多少次重试。默认值是 7 个﹐相当于 50秒 - 16分钟﹐视 RTO 而定。如果您的系统是负载很大的 web服务器﹐那么也许需要降低该值﹐这类 sockets 可能会耗费大量的资源。另外参的考 tcp_max_orphans 。

tcp_fin_timeout 参数类型:整型
对于本端断开的socket连接,TCP保持在FIN-WAIT-2状态的时间。对方可能会断开连接或一直不结束连接或不可预料的进程死亡。默认值为 60 秒。过去在2.2版本的内核中是 180 秒。您可以设置该值﹐但需要注意﹐如果您的机器为负载很重的web服务器﹐您可能要冒内存被大量无效数据报填满的风险﹐FIN-WAIT-2 sockets 的危险性低于 FIN-WAIT-1 ﹐因为它们最多只吃 1.5K 的内存﹐但是它们存在时间更长。另外参考 tcp_max_orphans。

tcp_max_tw_buckets 参数类型:整型
系统在同时所处理的最大timewait sockets 数目。如果超过此数的话﹐time-wait socket 会被立即砍除并且显示警告信息。之所以要设定这个限制﹐纯粹为了抵御那些简单的 DoS 攻击﹐千万不要人为的降低这个限制﹐不过﹐如果网络条件需要比默认值更多﹐则可以提高它 (或许还要增加内存)。

tcp_tw_recycle 参数类型:布尔
打开快速 TIME-WAIT sockets 回收。默认值是1。除非得到技术专家的建议或要求﹐请不要随意修改这个值。

tcp_max_orphans 参数类型:整型
系统所能处理不属于任何进程的TCP sockets最大数量。假如超过这个数量﹐那么不属于任何进程的连接会被立即reset,并同时显示警告信息。之所以要设定这个限制﹐纯粹为了抵御那些简单的 DoS 攻击﹐千万不要依赖这个或是人为的降低这个限制

tcp_abort_on_overflow 参数类型:布尔
当守护进程太忙而不能接受新的连接,就象对方发送reset消息,默认值是false。这意味着当溢出的原因是因为一个偶然的猝发,那么连接将恢复状态。只有在你确信守护进程真的不能完成连接请求时才打开该选项,该选项会影响客户的使用。

tcp_syncookies 参数类型:整型
只有在内核编译时选择了CONFIG_SYNCOOKIES时才会发生作用。当出现syn等候队列出现溢出时象对方发送syncookies。目的是为了防止syn flood攻击。默认值是false。

注意:该选项千万不能用于那些没有收到攻击的高负载服务器,如果在日志中出现synflood消息,但是调查发现没有收到synflood攻击,而是合法用户的连接负载过高的原因,你应该调整其它参数来提高服务器性能。参考: tcp_max_syn_backlog, tcp_synack_retries, tcp_abort_on_overflow.

syncookie严重的违背TCP协议,不允许使用TCP扩展,可能对某些服务导致严重的性能影响(如SMTP转发)。

tcp_stdurg 参数类型:整型
使用 TCP urg pointer 字段中的主机请求解释功能。大部份的主机都使用老旧的 BSD解释,因此如果您在 Linux 打开它﹐或会导致不能和它们正确沟通。默认值为为﹕FALSE

tcp_max_syn_backlog 参数类型:整型
对于那些依然还未获得客户端确认的连接请求﹐需要保存在队列中最大数目。对于超过 128Mb 内存的系统﹐默认值是 1024 ﹐低于 128Mb 的则为 128。如果服务器经常出现过载﹐可以尝试增加这个数字。警告﹗假如您将此值设为大于 1024﹐最好修改 include/net/tcp.h 里面的 TCP_SYNQ_HSIZE ﹐以保持 TCP_SYNQ_HSIZE*16<= tcp_max_syn_backlog ﹐并且编进核心之内。

tcp_window_scaling 参数类型:布尔
正常来说,TCP/IP 可以接受最大到65535字节的 windows。对于宽带网络,该值可能是不够的,通过调整该参数有助于提高宽带服务器性能。

tcp_timestamps 参数类型:布尔
Timestamps 用在其它一些东西中﹐可以防范那些伪造的 sequence 号码。一条1G的宽带线路或许会重遇到带 out-of-line数值的旧sequence 号码(假如它是由于上次产生的)。Timestamp 会让它知道这是个 '旧封包'。

tcp_sack 参数类型:布尔
使用 Selective ACK﹐它可以用来查找特定的遗失的数据报--- 因此有助于快速恢复状态。

tcp_fack 参数类型:布尔
打开FACK拥塞避免和快速重传功能。

tcp_dsack 参数类型:布尔
允许TCP发送"两个完全相同"的SACK。

tcp_ecn 参数类型:布尔
打开TCP的直接拥塞通告功能。

tcp_reordering 参数类型:整型
TCP流中重排序的数据报最大数量默认值是 3 。

tcp_retrans_collapse 参数类型:布尔
对于某些有bug的打印机提供针对其bug的兼容性。

tcp_wmem - 三个整数的向量: min, default, max
min:为TCP socket预留用于发送缓冲的内存最小值。每个tcp socket都可以在建议以后都可以使用它。默认值为4K。

default:为TCP socket预留用于发送缓冲的内存数量,默认情况下该值会影响其它协议使用的net.core.wmem_default 值,一般要低于net.core.wmem_default的值。默认值为16K。

max: 用于TCP socket发送缓冲的内存最大值。该值不会影响net.core.wmem_max,今天选择参数SO_SNDBUF则不受该值影响。默认值为128K。

tcp_rmem - 三个整数的向量: min, default, max
min:为TCP socket预留用于接收缓冲的内存数量,即使在内存出现紧张情况下tcp socket都至少会有这么多数量的内存用于接收缓冲,默认值为8K。

default:为TCP socket预留用于接收缓冲的内存数量,默认情况下该值影响其它协议使用的 net.core.wmem_default 值。该值决定了在tcp_adv_win_scale、tcp_app_win和 tcp_app_win:0是默认值情况下,tcp 窗口大小为65535。

max:用于TCP socket接收缓冲的内存最大值。该值不会影响 net.core.wmem_max,今天选择参数 SO_SNDBUF则不受该值影响。默认值为 128K。默认值为87380*2 bytes。

tcp_mem - 三个整数的向量: low, pressure, high
low:当TCP使用了低于该值的内存页面数时,TCP不会考虑释放内存。

pressure:当TCP使用了超过该值的内存页面数量时,TCP试图稳定其内存使用,进入pressure模式,当内存消耗低于low值时则退出pressure状态。

high:允许所有tcp sockets用于排队缓冲数据报的页面量。

一般情况下这些值是在系统启动时根据系统内存数量计算得到的。

tcp_app_win - 整数

保留max(window/2^tcp_app_win, mss)数量的窗口由于应用缓冲。当为0时表示不需要缓冲。默认值是31。

tcp_adv_win_scale - 整数
计算缓冲开销bytes/2^tcp_adv_win_scale(如果tcp_adv_win_scale >; 0)或者bytes- bytes/2^(-tcp_adv_win_scale)(如果tcp_adv_win_scale <= 0),默认值为2。

ip_local_port_range - 两个整数
定于TCP和UDP使用的本地端口范围,第一个数是开始,第二个数是最后端口号,默认值依赖于系统中可用的内存数:
>; 128Mb 32768-61000
< style="line-height: normal;">该值决定了活动连接的数量,也就是系统可以并发的连接数

icmp_echo_ignore_all - 布尔类型
icmp_echo_ignore_broadcasts - 布尔类型
如果任何一个设置为true(>;0)则系统将忽略所有发送给自己的ICMP ECHO请求或那些广播地址的请求。

icmp_destunreach_rate - 整数
icmp_paramprob_rate - 整数
icmp_timeexceed_rate - 整数
icmp_echoreply_rate - 整数(not enabled per default)
限制发向特定目标的ICMP数据报的最大速率。0表示没有任何限制,否则表示jiffies数据单位中允许发送的个数。

icmp_ignore_bogus_error_responses - 布尔类型
某些路由器违背RFC1122标准,其对广播帧发送伪造的响应来应答。这种违背行为通常会被以告警的方式记录在系统日志中。如果该选项设置为True,内核不会记录这种警告信息。默认值为False。

(1) Jiffie: 内核使用的内部时间单位,在i386系统上大小为1/100s,在Alpha中为1/1024S。在/usr/include/asm/param.h中的HZ定义有特定系统的值。

conf/interface/*:
conf/all/*是特定的,用来修改所有接口的设置,is special and changes the settings for all interfaces.
Change special settings per interface.

log_martians - 布尔类型
记录带有不允许的地址的数据报到内核日志中。

accept_redirects - 布尔类型
收发接收ICMP重定向消息。对于主机来说默认为True,对于用作路由器时默认值为False。

forwarding - 布尔类型
在该接口打开转发功能

mc_forwarding - 布尔类型
是否进行多播路由。只有内核编译有CONFIG_MROUTE并且有路由服务程序在运行该参数才有效。

proxy_arp - 布尔类型
打开proxy arp功能。

shared_media - 布尔类型
发送(路由器)或接收(主机) RFC1620 共享媒体重定向。覆盖ip_secure_redirects的值。默认为True。

secure_redirects - 布尔类型
仅仅接收发给默认网关列表中网关的ICMP重定向消息,默认值是TRUE。

send_redirects - 布尔类型
如果是router,发送重定向消息,默认值是TRUE

bootp_relay - 布尔类型
接收源地址为0.b.c.d,目的地址不是本机的数据报。用来支持BOOTP转发服务进程,该进程将捕获并转发该包。默认为False,目前还没有实现。

accept_source_route - 布尔类型
接收带有SRR选项的数据报。对于主机来说默认为False,对于用作路由器时默认值为True。

rp_filter 参数类型
1 - 通过反向路径回溯进行源地址验证(在RFC1812中定义)。对于单穴主机和stub网络路由器推荐使用该选项。
0 - 不通过反向路径回溯进行源地址验证。
默认值为0。某些发布在启动时自动将其打开

读spawn-fcgi 心得

c 属于一知半解, 当看到 execl("/bin/sh", "sh", "-c", b, (char *)NULL);时
就没了头绪, request 是怎么传到 php-cgi 的. 一头雾水
又仔细看了下代码:
if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
close(FCGI_LISTENSOCK_FILENO);
dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
close(fcgi_fd);
}
原来 是把fcgi_fd 端口号打给了STDIN_FILENO(输入), 我靠

一些配置

echo "1024 61000" > /proc/sys/net/ipv4/ip_local_port_range
echo "5" > /proc/sys/net/ipv4/tcp_fin_timeout

Top命令中Load Average的含义(转)

转:http://g.51cto.com/mike/41914
top命令中load average显示的是最近1分钟、5分钟和15分钟的系统平均负载。系统平均负载表示
  系统平均负载被定义为在特定时间间隔内运行队列中(在CPU上运行或者等待运行多少进程)的平均进程树。如果一个进程满足以下条件则其就会 位于运行队列中:
  - 它没有在等待I/O操作的结果
  - 它没有主动进入等待状态(也就是没有调用'wait')
  - 没有被停止(例如:等待终止)

2010年3月29日星期一

SOCKET返回值递增之线程与进程的讨论(转)

转:http://www.cppblog.com/prayer/archive/2009/01/21/72425.html

C, Erlang, Java and Go Web Server performance test(转)

转:http://timyang.net/category/programming/

taskset -pc 1-7 12345 指定某个进程 只使用 1-7 的cpu

fork source exec区别差异(转)

转:http://www.diybl.com/course/6_system/linux/Linuxjs/20090312/160872.html
* 这个对理解线程的环境相当有用,知道什么时候应该用fork,exec
* 部分来自网上, 有部分是自己添加了注解…


fork
使用 fork 方式运行 script 时, 就是让 shell(parent process) 产生一个 child
process 去执行该 script, 当 child process 结束后, 会返回 parent process,
但 parent process 的环境是不会因 child process 的改变而改变的.

source
使用 source 方式运行 script 时, 就是让 script 在当前 process 内执行, 而不
是产生一个 child process 来执行. 由于所有执行结果均于当前 process 内完成,
若 script 的环境有所改变, 当然也会改变当前 process 环境了.

exec
使用 exec 方式运行script时, 它和 source 一样, 也是让 script 在当前process
内执行, 但是 process 内的原代码剩下部分将被终止. 同样, process 内的环境随
script 改变而改变.结论:通常如果我们执行时,都是默认为fork的。大家可以通过 pstree命令看看关于父子进程的关系。如上,如果想让父进程得到子进程的环境变量,就是source方式了


* fork ( /directory/script.sh)

fork是最普通的, 就是直接在脚本里面用/directory/script.sh来调用script.sh 这个脚本.

运行的时候开一个sub-shell执行调用的脚本,sub-shell执行的时候, parent-shell 还在。

sub-shell执行完毕后返回parent-shell. sub-shell从parent-shell继承环境变量.但是sub-shell中的环境变量不会带回parent-shell

*
exec (exec /directory/script.sh)

exec与fork不同,不需要新开一个sub-shell来执行被调用的脚本. 被调用的脚本与父脚本在同一个shell内执行。但是使用exec调用一个新脚本以后, 父脚本中exec行之后的内容就不会再执行了。这是exec和source的区别

*
source (source /directory/script.sh)

与 fork的区别是不新开一个sub-shell来执行被调用的脚本,而是在同一个shell中执行. 所以被调用的脚本中声明的变量和环境变量, 都可以在主脚本中得到和使用.


可以通过下面这两个脚本来体会三种调用方式的不同:

1.sh

#!/bin/bash

A=B
echo "PID for 1.sh before exec/source/fork:$$"
export A
echo "1.sh: \$A is $A"
case $1 in
exec)
echo "using exec…"
exec ./2.sh ;;
source)
echo "using source…"
. ./2.sh ;;
*)
echo "using fork by default…"
./2.sh ;;
esac
echo "PID for 1.sh after exec/source/fork:$$"
echo "1.sh: \$A is $A"

2.sh

#!/bin/bash

echo "PID for 2.sh: $$"
echo "2.sh get \$A=$A from 1.sh"
A=C
export A
echo "2.sh: \$A is $A"





执行情况:

$ ./1.sh
PID for 1.sh before exec/source/fork:5845364
1http://msnpiki.msnfanatic.com/index.php/Main_Page-->
after exec/source/fork:5845364
1.sh: $A is B
$ ./1.sh exec
PID for 1.sh before exec/source/fork:5562668
1.sh: $A is B
using exec…
PID for 2.sh: 5562668
2.sh get $A=B from 1.sh
2.sh: $A is C
$ ./1.sh source
PID for 1.sh before exec/source/fork:5156894
1.sh: $A is B
using source…
PID for 2.sh: 5156894
2.sh get $A=B from 1.sh
2.sh: $A is C
PID for 1.sh after exec/source/fork:5156894
1.sh: $A is C
$

env 命令(转)

转:http://study.chyangwa.com/IT/AIX/aixcmds2/env.htm
env 命令


用途

显示当前环境或者为命令的执行设置环境。

语法

显示多个环境变量

env [ -i | - ] [Name=Value ]... [Command [ Argument ... ] ]

显示单个环境变量

env [Name]

描述

env 命令允许您显示您的当前环境或者在一个被改变了的环境下运行一个指定的命令。

如果没有标志或者参数被指定,env 命令会显示您的当前环境,每行显示一个 Name=Value 对。

标志

-i 忽略继承的环境,调用由 Command 参数指定的命令,在 Name=Value 参数指定的环境下。
参数

Name=Value 您可以在通过指定一个或多个 Name=Value 参数来在当前环境的一种修改版本下运行您的命令。使用 -i 标志,如果您想用指定的 Name =Value 参数代替整个当前环境的话。在其他情况下,环境的改变只有在指定命令正在运行时才有效。
命令 Command 参数有一个可选的 Argument 变量。如果指定的命令是一种 Korn shell 特殊内置命令,结果就是不被指定的。Korn shell 内置命令在 ksh 命令中描述。
退出状态

如果 Command 参数被指定,env 命令的退出状态就是由 Command 参数指定的命令的退出状态。否则,env 命令用下列值中的一个来退出:

0 env 成功完成。
1-125 在 env 命令中发生了一个错误。
126 由 Command 参数指定的命令被发现了,但是不能被调用。
127 由 Command 参数指定的命令未被发现。
示例

要想改变 TZ 环境变量(在 date 命令正运行时),请输入:
TZ=MST7MDT date
OR

env TZ=MST7MDT date
每个这种命令都会显示以山地时间显示的时间和当前日期。给出的两个命令是等价的。date 命令被完成时,TZ 环境变量的以前的值重新生效。

要想在只包含为 PATH、 IDIR、 和 LIBDIR 环境变量定义的环境中运行 make 命令,请输入:
env -i PATH=$PATH IDIR=/$HOME/include LIBDIR=/$HOME/lib make
您必须指定 PATH 环境变量,这样 shell 就能找到 make 命令。当 make 命令被完成时,前面的环境就会生效。

文件

/usr/bin/env 包含了 env 命令。

Linux中su命令使用详解(转)

 转:http://linux.chinaitlab.com/command/38068.html
  1.作用
  
  u的作用是变更为其它使用者的身份,超级用户除外,需要键入该使用者的密码。
  
  2.格式
  
  u [选项]... [-] [USER [ARG]...]
  
  3.主要参数
  
  -f , --fast:不必读启动文件(如 csh.cshrc 等),仅用于csh或tcsh两种Shell。
  
  -l , --login:加了这个参数之后,就好像是重新登陆为该使用者一样,大部分环境变量(例如HOME、SHELL和USER等)都是以该使用者(USER)为主,并且工作目录也会改变。如果没有指定USER,缺省情况是root。
  
  -m, -p ,--preserve-environment:执行su时不改变环境变数。
  
  -c command:变更账号为USER的使用者,并执行指令(command)后再变回原来使用者。
  
  USER:欲变更的使用者账号,ARG传入新的Shell参数。

理解 chroot(转)

转:http://www.ibm.com/developerworks/cn/linux/l-cn-chroot/

理解 chroot

通过编写 chroot 来认识 chroot 发挥的作用和它带来的好处

developerWorks
文档选项
将打印机的版面设置成横向打印模式

打印本页

将此页作为电子邮件发送

将此页作为电子邮件发送

样例代码


级别: 初级

王 华东 (wstoneh@126.com), 自由职业者

2009 年 7 月 09 日

chroot 在 Linux 系统中发挥了根目录的切换工作,同时带来了系统的安全性等好处。本文通过编写 chroot 来理解 chroot 的作用和好处,这不仅有助于更好的使用 chroot,同时加深了对 Linix 系统初始 RAM 磁盘工作的认识。

什么是 chroot

chroot,即 change root directory (更改 root 目录)。在 linux 系统中,系统默认的目录结构都是以 `/`,即是以根 (root) 开始的。而在使用 chroot 之后,系统的目录结构将以指定的位置作为 `/` 位置。


图 1. Linux 系统的目录结构
Linux 系统的目录结构




回页首


为何使用 chroot

在经过 chroot 之后,系统读取到的目录和文件将不在是旧系统根下的而是新根下(即被指定的新的位置)的目录结构和文件,因此它带来的好处大致有以下3个:

  1. 增加了系统的安全性,限制了用户的权力;

    在经过 chroot 之后,在新根下将访问不到旧系统的根目录结构和文件,这样就增强了系统的安全性。这个一般是在登录 (login) 前使用 chroot,以此达到用户不能访问一些特定的文件。

  2. 建立一个与原系统隔离的系统目录结构,方便用户的开发;

    使用 chroot 后,系统读取的是新根下的目录和文件,这是一个与原系统根下文件不相关的目录结构。在这个新的环境中,可以用来测试软件的静态编译以及一些与系统不相关的独立开发。

  3. 切换系统的根目录位置,引导 Linux 系统启动以及急救系统等。

    chroot 的作用就是切换系统的根位置,而这个作用最为明显的是在系统初始引导磁盘的处理过程中使用,从初始 RAM 磁盘 (initrd) 切换系统的根位置并执行真正的 init。另外,当系统出现一些问题时,我们也可以使用 chroot 来切换到一个临时的系统。





回页首


chroot 的使用

为了更好的理解 chroot 发挥的作用,我们将尝试指定一个特定的位置进行根目录切换。但是由于在经过 chroot 之后,系统读取到的 bin/ 等与系统相关目录将不再是旧系统根目录下的,而是切换后新根下的目录结构和文件,因此我们有必要准备一些目录结构以及必要的文件。

清单 1. 准备切换的目录结构

busybox

Busybox 被称为是嵌入式 Linux 中的瑞士军刀。Busybox 包含了许多有用的命令,如 cat、find 等,但是它的体积却非常的小。


$ pwd
/home/wstone/Build/work
$ tree .
.
|-- bin
| |-- ash -> busybox
| |-- bash
| `-- busybox
|-- etc
`-- newhome

这里使用了静态编译后的 busybox 来提供必要的命令,使用静态编译仅是为了避免动态库文件的拷贝。当然我们也可以拷贝旧系统的下的命令到新的目录结构中使用,但是那些命令通常是动态编译的,这就意味着我们不得不拷贝相关的动态库文件到相应的目录结构中。同时这里的 bash 也非真正的 Bourne Again shell,而是一个执行 ash 的 shell 脚本。在清单 2中,展示了位于旧系统中的 chroot 命令的使用。需要注意的是在使用 chroot 时,要求拥有相关的操作权限。


清单 2. 位于系统中的 chroot 的使用
$ pwd
/home/wstone/Build/work

# chroot .
# pwd
/

# ls
ash: ls: not found

# busybox ls
bin etc newhome

3 directories, 3 files


我们可以看到当前路径(/home/wstone/Build/work/),在经过 chroot 后转变成了 `/` 目录,同时从新根下读取了与系统相关的目录结构。使用 ls 命令失败是由于我们创建的测试目录结构中并没有包含命令 ls,但是我们成功的使用了 busybox 中的 ls。以上看到的只是 chroot 的一种使用方式,其实标准的 chroot (Coreutils - GNU core utilities 提供的 chroot)使用方式有2种:


清单 3. 标准 chroot 的2种使用方式
[1] chroot NEWROOT [COMMAND...]
[2] chroot OPTION


刚才我们使用的是方式[2]。这将在没有给定环境时,默认执行 `/bin/sh`,但是当给定环境后,将运行 `${SHELL} –i`,即与环境相同的可交互的 shell。我们的目录结构中并没有包含sh,显然清单 2中的 chroot 运行了 `${SHELL} –i`。当然我们也可以在进行切换时指定需要的命令,即使用方式[1]。

清单 4. chroot 另一种方式的使用


# chroot . /bin/ash
#

清单 4 中,尝试了在经过 chroot 后,执行新目录结构下的 ash shell。不得不说的是,如果新根下的目录结构和文件准备的够充分,那么一个新的简单的 Linux 系统就可以使用了。其实更为常见的是在初始 RAM 磁盘 (initrd)中使用 chroot,以此来执行系统的 init清单 5 中,展示的是在 Linux 2.4 内核 initrd 中使用 chroot。


清单 5. 在 Linux 2.4 内核 initrd 中使用 chroot 的示例
mount /dev/hda1 /new-root
cd /new-root
pivot_root . old-root
exec chroot . /sbin/init dev/console 2>&1
umount /old-root


由于 Linux 内核的升级,initrd 处理机制和格式发生了变化,在 Linux 2.6 内核 initrd 中不能再使用 pivot_root,因此一般也不再使用 chroot,而是选择使用 busybox 提供的 switch_root 或者 klibc 提供的 run-init 进行根目录的切换。(这并不是说不能在 Linux 2.6内核 initrd 中使用 chroot,选择 switch_root 或 run-init 仅是出于习惯和方便的考虑。)但是实质上,它们仅是将 chroot 的功能进行了封装,以此更加方便简单的切换根目录。


清单 6. 在 Linux 2.6 内核 initrd 中 chroot 的使用
[1] find -xdev / -exec rm '{}' ';
[2] cd /newmount; mount --move . /; chroot .


switch_root 和 run-init 完成了类似清单 6中的功能,删除 rootfs 的全部内容以释放空间,以及挂载新的根文件系统并进行切换。在 busybox 和 klibc中也有提供 chroot 命令,只是功能上与 Coreutils (GNU core utilities) 包含的 chroot 有稍许差异。





回页首


编写一个 chroot

上面介绍了 chroot 及其使用,但是编写一个简单的 chroot 并不复杂,下面我们就尝试编写chroot 以此来更好的认识 chroot 的处理过程,先编写一个粗略的 chroot 然后再完善它的功能。chroot 的编写涉及了2个函数,chroot() 以及 chdir(),它们都包含在 unistd.h 头文件中。


清单 7. 编写 chroot 涉及的2个函数
#include 
int chroot(const char *path);
int chdir(const char *path);


chroot() 将切换参数 path 所指位置为根目录 (/),chdir() 用来将当前的工作目录改变成以参数path 所指的目录。以此我们可以编写一个非常粗略的 `chroot`。


清单 8. 粗略的 `chroot`
#include 

int main(int argc, char *argv[])
{
chroot(".");
chdir("/");

char *arrays[]={"ash",NULL};
execvp("ash", arrays);

return 0;
}


这个粗略的 `chroot` 仅能切换当前位置为根目录,同时默认执行 ash shell,不包含任何的错误处理及警告。编写并保存代码为 test.c。在清单 9 中,展示了这个粗略 `chroot` 的使用情况,成功的进行了根目录的切换。


清单 9. 粗略 `chroot` 的使用
$ gcc -Wall test.c -o test

# ./test
# ls
ash: ls: not found

# busybox ls
bin etc newhome test test.c


下面给出功能将近完整的 chroot ,加上了一些错误处理并新增了可执行指定命令的功能。当在没有给出 chroot 切换后要执行的命令时,默认执行 `/bin/sh`,同时检测环境以确认使用何种 shell。


清单 10. 功能完整的 chroot
#include 
#include
#include

int main(int argc, char *argv[])
{
if(argc<2){
printf("Usage: chroot NEWROOT [COMMAND...] \n");
return 1;
}

printf("newroot = %s\n", argv[1]);
if(chroot(argv[1])) {
perror("chroot");
return 1;
}

if(chdir("/")) {
perror("chdir");
return 1;
}

if(argc == 2) {
argv[0] = getenv("SHELL");
if(!argv[0])
argv[0] = (char *)"/bin/sh";

argv[1] = (char *) "-i";
argv[2] = NULL;
} else {
argv += 2;
}

execvp (argv[0], argv);
printf("chroot: cannot run command `%s`\n", *argv);

return 0;
}


保存以上代码为 newchroot.c 文件,编译后运行测试其功能。最后要指出的是,本文中的 `chroot` 并没有使用静态编译。如果有必要(如,在 initrd 中使用 chroot),chroot 应该使用静态编译,若是使用动态编译,那么要拷贝相关的动态库文件到相应目录结构中。


清单 11. `newchroot` 的测试
$ gcc -Wall newchroot.c -o newchroot

# ./newchroot . /bin/ash
newroot = .
#







回页首


结束语

在 Linux 系统初始引导的过程中,通常都有使用 chroot。但是 chroot 的好处不仅于此,它还增加了系统的安全性等。而通过本文后半部分对 chroot 的认识,我相信读者可以更好的发挥chroot 的作用。

UNIX Domain Socket IPC(转)

转:http://docs.huihoo.com/c/linux-c-programming/ch37s04.html
UNIX Domain Socket IPC

socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket。虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIX Domain Socket用于IPC更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。UNIX Domain Socket也提供面向流和面向数据包两种API接口,类似于TCP和UDP,但是面向消息的UNIX Domain Socket也是可靠的,消息既不会丢失也不会顺序错乱。

UNIX Domain Socket是全双工的,API接口语义丰富,相比其它IPC机制有明显的优越性,目前已成为使用最广泛的IPC机制,比如X Window服务器和GUI程序之间就是通过UNIX Domain Socket通讯的。

使用UNIX Domain Socket的过程和网络socket十分相似,也要先调用socket()创建一个socket文件描述符,address family指定为AF_UNIX,type可以选择SOCK_DGRAM或SOCK_STREAM,protocol参数仍然指定为0即可。

UNIX Domain Socket与网络socket编程最明显的不同在于地址格式不同,用结构体sockaddr_un表示,网络编程的socket地址是IP地址加端口号,而UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径,这个socket文件由bind()调用创建,如果调用bind()时该文件已存在,则bind()错误返回。

以下程序将UNIX Domain socket绑定到一个地址。

#include
#include
#include
#include
#include

int main(void)
{
int fd, size;
struct sockaddr_un un;

memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
strcpy(un.sun_path, "foo.socket");
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
perror("socket error");
exit(1);
}
size = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);
if (bind(fd, (struct sockaddr *)&un, size) < 0) {
perror("bind error");
exit(1);
}
printf("UNIX domain socket bound\n");
exit(0);
}
注意程序中的offsetof宏,它在stddef.h头文件中定义:

#define offsetof(TYPE, MEMBER) ((int)&((TYPE *)0)->MEMBER)
offsetof(struct sockaddr_un, sun_path)就是取sockaddr_un结构体的sun_path成员在结构体中的偏移,也就是从结构体的第几个字节开始是sun_path成员。想一想,这个宏是如何实现这一功能的?

该程序的运行结果如下。

$ ./a.out
UNIX domain socket bound
$ ls -l foo.socket
srwxrwxr-x 1 user 0 Aug 22 12:43 foo.socket
$ ./a.out
bind error: Address already in use
$ rm foo.socket
$ ./a.out
UNIX domain socket bound
以下是服务器的listen模块,与网络socket编程类似,在bind之后要listen,表示通过bind的地址(也就是socket文件)提供服务。

#include
#include
#include
#include

#define QLEN 10

/*
* Create a server endpoint of a connection.
* Returns fd if all OK, <0 on error.
*/
int serv_listen(const char *name)
{
int fd, len, err, rval;
struct sockaddr_un un;

/* create a UNIX domain stream socket */
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
return(-1);
unlink(name); /* in case it already exists */

/* fill in socket address structure */
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
strcpy(un.sun_path, name);
len = offsetof(struct sockaddr_un, sun_path) + strlen(name);

/* bind the name to the descriptor */
if (bind(fd, (struct sockaddr *)&un, len) < 0) {
rval = -2;
goto errout;
}
if (listen(fd, QLEN) < 0) { /* tell kernel we're a server */
rval = -3;
goto errout;
}
return(fd);

errout:
err = errno;
close(fd);
errno = err;
return(rval);
}
以下是服务器的accept模块,通过accept得到客户端地址也应该是一个socket文件,如果不是socket文件就返回错误码,如果是socket文件,在建立连接后这个文件就没有用了,调用unlink把它删掉,通过传出参数uidptr返回客户端程序的user id。

#include
#include
#include
#include
#include

int serv_accept(int listenfd, uid_t *uidptr)
{
int clifd, len, err, rval;
time_t staletime;
struct sockaddr_un un;
struct stat statbuf;

len = sizeof(un);
if ((clifd = accept(listenfd, (struct sockaddr *)&un, &len)) < 0)
return(-1); /* often errno=EINTR, if signal caught */

/* obtain the client's uid from its calling address */
len -= offsetof(struct sockaddr_un, sun_path); /* len of pathname */
un.sun_path[len] = 0; /* null terminate */

if (stat(un.sun_path, &statbuf) < 0) {
rval = -2;
goto errout;
}

if (S_ISSOCK(statbuf.st_mode) == 0) {
rval = -3; /* not a socket */
goto errout;
}

if (uidptr != NULL)
*uidptr = statbuf.st_uid; /* return uid of caller */
unlink(un.sun_path); /* we're done with pathname now */
return(clifd);

errout:
err = errno;
close(clifd);
errno = err;
return(rval);
}
以下是客户端的connect模块,与网络socket编程不同的是,UNIX Domain Socket客户端一般要显式调用bind函数,而不依赖系统自动分配的地址。客户端bind一个自己指定的socket文件名的好处是,该文件名可以包含客户端的pid以便服务器区分不同的客户端。

#include
#include
#include
#include
#include
#include

#define CLI_PATH "/var/tmp/" /* +5 for pid = 14 chars */

/*
* Create a client endpoint and connect to a server.
* Returns fd if all OK, <0 on error.
*/
int cli_conn(const char *name)
{
int fd, len, err, rval;
struct sockaddr_un un;

/* create a UNIX domain stream socket */
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
return(-1);

/* fill socket address structure with our address */
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
sprintf(un.sun_path, "%s%05d", CLI_PATH, getpid());
len = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);

unlink(un.sun_path); /* in case it already exists */
if (bind(fd, (struct sockaddr *)&un, len) < 0) {
rval = -2;
goto errout;
}

/* fill socket address structure with server's address */
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
strcpy(un.sun_path, name);
len = offsetof(struct sockaddr_un, sun_path) + strlen(name);
if (connect(fd, (struct sockaddr *)&un, len) < 0) {
rval = -4;
goto errout;
}
return(fd);

errout:
err = errno;
close(fd);
errno = err;
return(rval);
}
下面是自己动手时间,请利用以上模块编写完整的客户端/服务器通讯的程序。

UNIX中getopt()使用心得(转)

转:http://www.diybl.com/course/3_program/c++/cppjs/20090205/154853.html
getopt()是UNIX中分析命令行参数的一个函数,很多论坛上有关于它用法的一些讲解,但其描述语言总会令初学者迷茫不堪,
这个函数的代码我也没有看到,只是通过一些输入输出来大概认识它。以下就是我自己的一些心得,希望对大家的使用有所帮助。

表头文件
#include

函数原型
int getopt(int argc, char * const argv[], const char* optstring)

函数说明
参数argc和argv是由main()传递的参数个数和内容,argc计算参数的个数是以空格为分隔符的;
参数optstring则表示欲处理的选项字符串,optstring选项字符串可能有以下三种格式的字符:
1.单个字符,表示选项
2.单个字符后接一个冒号:表示该选项后必须跟一个参数。参数紧跟在选项后或者以空格隔开。该参数的指针赋给optarg
3 单个字符后跟两个冒号,表示该选项后必须跟一个参数。参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。(这个特性是GNU的扩张)。
举例:optstring="a:b::cd",表示选项a还跟有参数,可能以空格隔开,选项b后还跟有参数,直接接在选项后面,选项c,d均无参数。
补充一点,该函数判断是选项或是参数,依据是字符(串)是否是以-开头,如-ab中,-a为选项,b则为参数

其他说明
此函数影响的全局变量有四个
extern char *optarg; //选项的参数指针
extern int optind, //下一次调用getopt的时,从optind存储的位置处重新开始检查选项。
extern int opterr, //当opterr=0时,getopt不向stderr输出错误信息。
extern int optopt; //当命令行选项字符不包括在optstring中或者选项缺少必要的参数时,该选项存储在optopt中,getopt返回'?’、

返回值
(1)如果选项和optstring中的某一个选项匹配,则返回该选项对应的值
(2)如果不匹配,则返回?
(3)全部分析结束,返回-1

读者可能尚存的疑问:
(1)可带参数的选项后面的参数有两个或两个以上时,optargv的值是什么?
(2)可带参数的选项后面的参数不存在时,optargv的值是多少?
(3)不带参数的选项后有一个或者多个参数时,optargv的值是什么?
以上问题的答案是:
(1)optargv只会取选项后面所跟的第一个字符(串),而忽略其后所有的参数
(2)此时该选项对函数来说不可识别,optargv自然也为NULL
注意,如果此时直接接另一个选项,会把该选项当作是前一个前项的参数处理
(3)对这些参数函数不予处理,optargv的值仍为NULL


下面我们通过一个具体的例子来说明上述结论

源代码:
==============================================================================================================
#include
#include

int main(int argc, char**argv)
{
int ch;
opterr=0; // no printed errors
while((ch=getopt(argc,argv,"a:b:c::d"))!=-1)
switch(ch){
case 'a':
printf("when the option is a, optind=%d, optargv=%s, optopt=%d\n", optind, optargv, optopt);
break;
case 'b':
printf("when the option is b, optind=%d, optargv=%s, optopt=%d\n", optind, optargv, optopt);
break;
case 'c':
printf("when the option is c, optind=%d, optargv=%s, optopt=%d\n", optind, optargv, optopt);
break;
case 'd';
printf("when the option is d, optind=%d, optargv=%s, optopt=%d\n", optind, optargv, optopt);
break;
default:
printf("other options, optind=%d, optargv=%s, optopt=%c\n", optind, optargv, optopt);
}
}
==============================================================================================================

输出:
=====================================================================
input: $./func -aaaa -b bbb -cccc -c ccc -d ddd -e eee

output: when the option is a, optind=2, optargv=aaa, optopt=?
when the option is b, optind=4, optargv=bbb, optopt=?
when the option is c, optind=5, optargv=ccc, optopt=?
when the option is d, optind=6, optargv=(null), optopt=?
other options, optind=8, optargv=(null), optopt=?
other options, optind=10, optargv=(null), optopt=e
===================================================================

2010年3月26日星期五

aqmp 测试用例

http://github.com/pieterh/amqp-testsuite

arch yaourt安装(转)

转:http://wiki.archlinux.org/index.php/Yaourt_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)
Contents [hide]
1 安装 Yaourt
2 简便的安装
3 PKGBUILD 安装
4 使用 Yaourt
4.1 查找并调用pacman安装软件包=
安装 Yaourt
Yet AnOther User Repository Tool.Yaourt is a community-contributed wrapper for pacman which adds seamless access to the AUR, allowing and automating package compilation and installation from your choice of the 8000+ PKGBUILDs in the AUR, in addition to the many thousands of available Arch binary packages. Yaourt uses the same exact syntax as pacman, which saves you from relearning an entirely new method of system maintenance, but also adds new options. Yaourt expands the power and simplicity of pacman by adding even more useful features and provides pleasing, colorized output, interactive search mode, and much more.
Yaourt是archlinux方便使用的关键部件之一,但没有被整合到系统安装中的工具。建议在装完系统重启之后,更新完pacman和基本系统之后,就安装这个工具。 安装方法有下面两种:建议使用第一种,如果要体验AUR的操作过程和使用方法,建议使用第二种方法安装。
简便的安装
最简单安装Yaourt的方式是添加Yaourt源至您的 /etc/pacman.conf:
i686架构:
[archlinuxfr]
Server = http://repo.archlinux.fr/i686
x86-64架构:
[archlinuxfr]
Server = http://repo.archlinux.fr/x86_64
同步并安装:
pacman -S yaourt
下面过程并非必须:如果您乐意,可以创建自己的命令的别名通过添加至~/.bashrc: 用nano打开~/.bashrc(或者用其他编辑器)。添加如下别名:
alias p="pacman"
alias y="yaourt"
保存并使用source命令
source ~/.bashrc
PKGBUILD 安装
传统安装Yaourt的方式是通过AUR,用这种方式安装Yaourt,你就有机会了解到AUR(和PKGBUILD)是如何工作的。
打开网页浏览器并访问yaourt AUR page
下载Yaourt的tarball包。 tarball
解压tarball
tar zxvf yaourt.tar.gz
切换至新的目录
cd yaourt
这时候;确认您已经检查了PKGBUILD和yaourt.intall 的内容! 别担心,它们并不是很复杂,仅仅是看一下而已。如果你觉得某些可疑的东西,到irc上或者论坛上询问一下。
more yaourt.install
more PKGBUILD
如果一切正常,我们已经准备好来构建软件包了。
makepkg PKGBUILD
这一过程结束后,您讲会看到一些新的文件和目录。您应该对那些以*.pkg.tar.gz的后缀名的文件感兴趣(在这特定的情况下;yaourt-0.9.2-i686.pkg.tar.gz)
现在是时候用pacman来安装yaourt了。一定要用实际的软件包名字,而不是 拷贝这如下一行“
pacman -U yaourt-0.9.2-i686.pkg.tar.gz
恭喜!您已经成功的安装了Yaourt!请记住,对于大多数的AUR里面的PKGBUILDS, 您都可以用类似上面的方式来安装。
使用 Yaourt
查找并调用pacman安装软件包=
yaourt可用于查找软件包(包括core extra community aur的软件包,pacman只能查找非aur的软件包),假设我们要安装opera-china-qt3(opera中文版,主要解决了opera的中文字体问题)。但我们只记得opera名称,使用yaourt可以查找和这名称相关的软件包。opera-china-qt3位于aur中,需要用这种方式来安装。下面三条命令任选其一即可。
yaourt opera
yaourt opera-china
yaourt -S opera-china-qt3 (如果名称知道,可用这条命令直接安装位于aur中的该软件)
查找结果会有好多个相关项,按提示,输入所要的软件的数字序号,按enter继续,根据提示,可以选择编辑或者不编辑PKGBUILDS文件,根据提示,最后完成安装。

请访问 yaourt man page 以获取更多信息。

2010年3月25日星期四

tbml 文件格式

淘宝旺铺的模板

IANA

其中包括 端口号

 IANA(The Internet Assigned Numbers Authority,互联网数字分配机构)是负责协调一些使Internet正常运作的机构。同时,由于Internet已经成为一个全球范围的不受集权控制的全球网络,为了使网络在全球范围内协调,存在对互联网一些关键的部分达成技术共识的需要,而这就是IANA的任务。
  更准确地说,IANA分配和维护在互联网技术标准(或者称为协议)中的唯一编码和数值系统。
  IANA的所有任务可以大致分为三个类型:
  一、域名。IANA管理DNS域名根和.int,.arpa域名以及IDN(国际化域名)资源。
  二、数字资源。IANA协调全球IP和AS(自治系统)号并将它们提供给各区域Internet注册机构。
  三、协议分配。IANA与各标准化组织一同管理协议编号系统。
  IANA是全球最早的Internet机构之一,其历史可以追溯到1970年。今天,IANA被负责协调IANA责任范围的非营利机构ICANN(Internet Corporation for Assigned Names and Numbers,互联网名称与数字地址分配机构)掌管。

让服务器自动从Hg版本库中下载代码(转)

转:http://www.neatstudio.com/show-1107-1.shtml
工具介绍: 让服务器自动从Hg版本库中下载代码

首页 > Software >
Submitted by gouki on 2010, February 20, 11:20 AM. Software
javascript:void(0)
以前,为了保证本地的代码与服务器一样,一般都是采用sVN+分支,审核并最后推送到服务器的。当然,也有服务器从svn服务器拉数据的时候。当然这样配置起来是有点繁琐,但还算能用。
shawphy推荐的这个工具,感觉好象不错。如果有兴趣,大家可以尝试尝试。
以下就是shawphy写的文章:让服务器自动从Hg版本库中下载代码

每次写完代码,提交到版本库,测试可以执行不会冲突,推到远端代码仓库。之后要发布的话,还要通过FTP上传到服务器上,FTP速度又不很理想,严重影响工作效率。

有没有解决之道?有!

直接让服务器从代码仓库中下载代码不就行了么?代码仓库中已经包含最新代码了,让服务器从代码仓库的服务器远程下载代码,方便快捷全自动!

而且,现在用的是hg,而不是svn。svn有个问题,提交的代码可能是未完成的半成品导致程序无法执行。而hg的好处是半成品可以提交在本地,阶段性成果完成后再往远端代码仓库中提交。

下面就以使用BitBucket为例,其他服务大同小异。

编译 hg
首先需要在服务器端编译一份 hg ,编译起来还是很方便的,直接从官网下载一份源码,解压缩后make && make install 一下就行了。他源码包里的README里就这么写的。

Mercurial/Hg 下载地址

第一次clone
第一次使用需要先clone一份代码仓库到本地,以后就可以简单的使用pull命令获取更新了。
所以第一次使用需要 hg clone <你的仓库地址>
仓库地址可以在 BitBucket里的项目里找到。

编写 PHP
然后在服务器端写一个文件up.php,放在需要更新的目录下面, 如下代码:

passthru("/< hg命令行工具的绝对地址>/hg pull -u https://<你的用户名>:<你的密码>@<你的代码仓库地址>");
以我的空间为例,就是:

passthru("/home/shawphy/bin/hg pull -u https://shawphy:******@bitbucket.org/shawphy/test/");
其中最关键的一步是要把密码也写在URL里,否则的话就得用popen()函数来处理密码交互了,比较麻烦。

这样,只要访问这个php文件,就能更新这个网站了。

配置Hook
然后,只需要在 BitBucket 项目管理中,Admin标签里,右边Additional options/settings面板下找到Services,点进去。然后添加一个POST服务,URL地址就填写你那个PHP文件的地址就可以了。

这样就能实现往代码仓库中提交代码后,网站服务器自动下载并更新代码了。

其他
如果要自己搭建的服务器上配置的话,参考 Hg 官方Wiki

BusyBox 简化嵌入式 Linux 系统(转)

转:http://www.ibm.com/developerworks/cn/linux/l-busybox/

BusyBox 简化嵌入式 Linux 系统

为小环境准备的一个小工具包


文档选项
将打印机的版面设置成横向打印模式

打印本页

将此页作为电子邮件发送

将此页作为电子邮件发送


级别: 初级

M. Tim Jones (mtj@mtjones.com), 咨询工程师, Emulex

2006 年 9 月 11 日

BusyBox 是很多标准 Linux® 工具的一个单个可执行实现。BusyBox 包含了一些简单的工具,例如 cat 和 echo,还包含了一些更大、更复杂的工具,例如 grep、find、mount 以及 telnet(不过它的选项比传统的版本要少);有些人将 BusyBox 称为 Linux 工具里的瑞士军刀。本文将探索 BusyBox 的目标,它是如何工作的,以及为什么它对于内存有限的环境来说是如此重要。

BusyBox 的诞生

BusyBox 最初是由 Bruce Perens 在 1996 年为 Debian GNU/Linux 安装盘编写的。其目标是在一张软盘上创建一个可引导的 GNU/Linux 系统,这可以用作安装盘和急救盘。一张软盘可以保存大约 1.4-1.7MB 的内容,因此这里没有多少空间留给 Linux 内核以及相关的用户应用程序使用。

BusyBox 许可证
BusyBox 是按照 GNU General Public License(GPL)许可证发行的。这意味着如果我们在一个项目中使用 BusyBox,就必须遵守这个许可证。我们可以在 BusyBox Web 站点(请参看本文后面 参考资料 一节的内容)上看到这个许可证的内容。BusyBox 团队似乎正忙于监视违反这个许可证的情况。实际上,他们维护了一个 “Hall of Shame” 页面来说明违反者的情况。

BusyBox 揭露了这样一个事实:很多标准 Linux 工具都可以共享很多共同的元素。例如,很多基于文件的工具(比如 grep find)都需要在目录中搜索文件的代码。当这些工具被合并到一个可执行程序中时,它们就可以共享这些相同的元素,这样可以产生更小的可执行程序。实际上,BusyBox 可以将大约 3.5MB 的工具包装成大约 200KB 大小。这就为可引导的磁盘和使用 Linux 的嵌入式设备提供了更多功能。我们可以对 2.4 和 2.6 版本的 Linux 内核使用 BusyBox。

BusyBox 是如何工作的?

为了让一个可执行程序看起来就像是很多可执行程序一样,BusyBox 为传递给 C 的 main 函数的参数开发了一个很少使用的特性。回想一下 C 语言的 main 函数的定义如下:

POSIX 环境
尽管 BusyBox 的目标 是提供一个相当完整的 POSIX(可移植操作系统接口)环境,这是一个期望,而不是一种需求。这些工具虽然并不完整,但是它们提供了我们期望的主要功能。

清单 1. C 的 main 函数
int main( int argc, char *argv[] )

在这个定义中,argc 是传递进来的参数的个数(参数数量),而 argv 是一个字符串数组,代表从命令行传递进来的参数(参数向量)。argv 的索引 0 是从命令行调用的程序名。

清单 2 给出的这个简单 C 程序展示了 BusyBox 的调用。它只简单地打印 argv 向量的内容。


清单 2. BusyBox 使用 argv[0] 来确定调用哪个应用程序
// test.c
#include

int main( int argc, char *argv[] )
{
int i;

for (i = 0 ; i <>

调用这个程序会显示所调用的第一个参数是该程序的名字。我们可以对这个可执行程序重新进行命名,此时再调用就会得到该程序的新名字。另外,我们可以创建一个到可执行程序的符号链接,在执行这个符号链接时,就可以看到这个符号链接的名字。


清单 3. 在使用新命令更新 BusyBox 之后的命令测试
$ gcc -Wall -o test test.c
$ ./test arg1 arg2
argv[0] = ./test
argv[1] = arg1
argv[2] = arg2

$ mv test newtest
$ ./newtest arg1
argv[0] = ./newtest
argv[1] = arg1

$ ln -s newtest linktest
$ ./linktest arg
argv[0] = ./linktest
argv[1] = arg

BusyBox 使用了符号链接以便使一个可执行程序看起来像很多程序一样。对于 BusyBox 中包含的每个工具来说,都会这样创建一个符号链接,这样就可以使用这些符号链接来调用 BusyBox 了。BusyBox 然后可以通过 argv[0] 来调用内部工具。





回页首


配置并编译 BusyBox

我们可以从 BusyBox 的 Web 站点上下载最新版本的 BusyBox(请参看 参考资料 一节的内容)。与大部分开放源码程序一样,它是以一个压缩的 tarball 形式发布的,我们可以使用清单 4 给出的命令将其转换成源代码树。(如果我们下载的版本不是 1.1.1,那就请在这个命令中使用适当的版本号以及特定于这个版本号的命令。)


清单 4. 展开 BusyBox
$ tar xvfz busybox-1.1.1.tar.gz
$

结果会生成一个目录,名为 busybox-1.1.1,其中包含了 BusyBox 的源代码。要编译默认的配置(其中包含了几乎所有的内容,并禁用了调试功能),请使用 defconfig make 目标:

BusyBox 源代码树
BusyBox 的源代码树组织得很好。这些工具都基于它们的用途进行了分类,并存储在单独的子目录中。例如,网络工具和守护进程(如 httpdifconfig等)都在 ./networking 目录中;标准的模块工具(包括 insmodrmmod lsmod)都在 ./modutils 目录中;编辑器(例如 vi 和流编辑器,如 awk sed)都在 ./editors 目录中。makefile 配置、编译和安装所使用的各个文档都在这个目录树的根目录中。

清单 5. 编译默认的 BusyBox 配置
$ cd busybox-1.1.1
$ make defconfig
$ make
$

结果是一个相当大的 BusyBox 映像,不过这只是开始使用它的最简单的方法。我们可以直接调用这个新映像,这会产生一个简单的 Help 页面,里面包括当前配置的命令。要对这个映像进行测试,我们也可以对一个命令调用 BusyBox 来执行,如清单 6 所示。


清单 6. 展示 BusyBox 命令的执行和 BusyBox 中的 ash shell
$ ./busybox pwd
/usr/local/src/busybox-1.1.1
$ ./busybox ash
/usr/local/src/busybox-1.1.1 $ pwd
/usr/local/src/busybox-1.1.1
/usr/local/src/busybox-1.1.1 $ exit
$

在这个例子中,我们调用了 pwd(打印工作目录)命令,使用 BusyBox 进入了 ash shell,并在 ash 中调用了 pwd





回页首


手工配置

如果您正在构建一个具有特殊需求的嵌入式设备,那就可以手工使用 menuconfig make 目标来配置 BusyBox 的内容。如果您熟悉 Linux 内核的编译过程,就会注意到 menuconfig 与配置 Linux 内核的内容所使用的目标相同。实际上,它们都采用了相同的基于 ncurses 的应用程序。

使用手工配置,我们可以指定在最终的 BusyBox 映像中包含的命令。我们也可以对 BusyBox 环境进行配置,例如包括对 NSA(美国国家安全代理)的安全增强 Linux(SELinux),指定要使用的编译器(用来在嵌入式环境中进行交叉编译)以及 BusyBox 应该静态编译还是动态编译。图 1 给出了 menuconfig 的主界面。在这里我们应该可以看到可以为 BusyBox 配置的不同类型的应用程序(applet)。


图 1. 使用 menuconfig 配置 BusyBox
使用 menuconfig 配置 BusyBox
多体系结构支持
可以简单地为 BusyBox 指定交叉编译器意味着我们可以为很多体系结构编译 BusyBox。要为您的目标体系结构编译 BusyBox,我们需要一个交叉编译器和一个已经为特定目标体系结构编译好的 C 库(uClibc 或 glibc)。

要手工配置 BusyBox,请使用下面的命令:


清单 7. 手工配置 BusyBox
$ make menuconfig
$ make
$

这为我们提供了可以调用的 BusyBox 的二进制文件。下一个步骤是围绕 BusyBox 构建一个环境,包括将标准 Linux 命令重定向到 BusyBox 二进制文件的符号链接。我们可以使用下面的命令简单地完成这个过程:


清单 8. 构建 BusyBox 环境
$ make install
$

默认情况下,这会创建一个新的本地子目录 _install,其中包含了基本的 Linux 环境。在这个根目录中,您会找到一个链接到 BusyBox 的 linuxrc 程序。这个 linuxrc 程序在构建安装盘或急救盘(允许提前进行模块化的引导)时非常有用。同样是在这个根目录中,还有一个包含操作系统二进制文件的 /sbin 子目录。还有一个包含用户二进制文件的 /bin 目录。在构建软盘发行版或嵌入式初始 RAM 磁盘时,我们可以将这个 _install 目录迁移到目标环境中。我们还可以使用 make 程序的 PREFIX 选项将安装目录重定向到其他位置。例如,下面的代码就使用 /tmp/newtarget 根目录来安装这些符号链接,而不是使用 ./_install 目录:


清单 9. 将符号链接安装到另外一个目录中
$ make PREFIX=/tmp/newtarget install
$

使用 install make 目标创建的符号链接都来自于 busybox.links 文件。这个文件是在编译 BusyBox 时创建的,它包含了已经配置的命令清单。在执行 install 时,就会检查 busybox.links 文件确定要创建的符号链接。

到 BusyBox 的命令行链接也可以使用 BusyBox 在运行时动态创建。CONFIG_FEATURE_INSTALLER 选项就可以启用这个特性,在运行时可以这样执行:


清单 10. 在运行时创建命令链接
$ ./busybox --install -s
$

-s 选项强制创建这些符号链接(否则就创建硬链接)。这个选项要求系统中存在 /proc 文件系统。





回页首


BusyBox 编译选项

BusyBox 包括了几个编译选项,可以帮助为我们编译和调试正确的 BusyBox。


表 1. 为 BusyBox 提供的几个 make 选项
make 目标说明
help显示 make 选项的完整列表
defconfig启用默认的(通用)配置
allnoconfig禁用所有的应用程序(空配置)
allyesconfig启用所有的应用程序(完整配置)
allbareconfig启用所有的应用程序,但是不包括子特性
config基于文本的配置工具
menuconfigN-curses(基于菜单的)配置工具
all编译 BusyBox 二进制文件和文档(./docs)
busybox编译 BusyBox 二进制文件
clean清除源代码树
distclean彻底清除源代码树
sizes显示所启用的应用程序的文本/数据大小

在定义配置时,我们只需要输入 make 就可以真正编译 BusyBox 二进制文件。例如,要为所有的应用程序编译 BusyBox,我们可以执行下面的命令:


清单 11. 编译 BusyBox 二进制程序
$ make allyesconfig
$ make
$





回页首


压缩 BusyBox

如果您非常关心对 BusyBox 映像的压缩,就需要记住两件事情:

  1. 永远不要编译为静态二进制文件(这会将所有需要的库都包含到映像文件中)。相反,如果我们是编译为一个共享映像,那么它会使用其他应用程序使用的库(例如 /lib/libc.so.X)。
  2. 使用 uClibc 进行编译,这是一个对大小进行过优化的 C 库,它是为嵌入式系统开发的;而不要使用标准的 glibc (GNU C 库)来编译。




回页首


BusyBox 命令中支持的选项

BusyBox 中的命令并不支持所有可用选项,不过这些命令都包含了常用的选项。如果我们需要知道一个命令可以支持哪些选项,可以使用 --help 选项来调用这个命令,如清单 12 所示。


清单 12. 使用 --help 选项调用命令
$ ./busybox wc --help
BusyBox v1.1.1 (2006.04.09-15:27+0000) multi-call binary

Usage: wc [OPTION]... [FILE]...

Print line, word, and byte counts for each FILE, and a total line if
more than one FILE is specified. With no FILE, read standard input.

Options:
-c print the byte counts
-l print the newline counts
-L print the length of the longest line
-w print the word counts

$

这些特定的数据只有在启用了 CONFIG_FEATURE_VERBOSE_USAGE 选项时才可以使用。如果没有这个选项,我们就无法获得这些详细数据,但是这样可以节省大约 13 KB 的空间。





回页首


向 BusyBox 中添加新命令

向 BusyBox 添加一个新命令非常简单,这是因为它具有良好定义的体系结构。第一个步骤是为新命令的源代码选择一个位置。我们要根据命令的类型(网络,shell 等)来选择位置,并与其他命令保持一致。这一点非常重要,因为这个新命令最终会在 menuconfig 的配置菜单中出现(在下面的例子中,是 Miscellaneous Utilities 菜单)。

对于这个例子来说,我将这个新命令称为 newcmd,并将它放到了 ./miscutils 目录中。这个新命令的源代码如清单 13 所示。


清单 13. 集成到 BusyBox 中的新命令的源代码

#include "busybox.h"

int newcmd_main( int argc, char *argv[] )
{
int i;

printf("newcmd called:\n");

for (i = 0 ; i <>

接下来,我们要将这个新命令的源代码添加到所选子目录中的 Makefile.in 中。在本例中,我更新了 ./miscutils/Makefile.in 文件。请按照字母顺序来添加新命令,以便维持与现有命令的一致性:


清单 14. 将命令添加到 Makefile.in 中
MISCUTILS-$(CONFIG_MT)          += mt.o
MISCUTILS-$(CONFIG_NEWCMD) += newcmd.o
MISCUTILS-$(CONFIG_RUNLEVEL) += runlevel.o

接下来再次更新 ./miscutils 目录中的配置文件,以便让新命令在配置过程中是可见的。这个文件名为 Config.in,新命令是按照字母顺序添加的:


清单 15. 将命令添加到 Config.in 中
config CONFIG_NEWCMD
bool "newcmd"
default n
help
newcmd is a new test command.

这个结构定义了一个新配置项(通过 config 关键字)以及一个配置选项(CONFIG_NEWCMD)。新命令可以启用,也可以禁用,因此我们对配置的菜单属性使用了 bool (Boolean)值。这个命令默认是禁用的(n 表示 No),我们可以最后放上一个简短的 Help 描述。在源代码树的 ./scripts/config/Kconfig-language.txt 文件中,我们可以看到配置语法的完整文法。

接下来需要更新 ./include/applets.h 文件,使其包含这个新命令。将下面这行内容添加到这个文件中,记住要按照字母顺序。维护这个次序非常重要,否则我们的命令就会找不到。


清单 16. 将命令添加到 applets.h 中
USE_NEWCMD(APPLET(newcmd, newcmd_main, _BB_DIR_USER_BIN, _BB_SUID_NEVER))

这定义了命令名(newcmd),它在 Busybox 源代码中的函数名(newcmd_main),应该在哪里会为这个新命令创建链接(在这种情况中,它在 /usr/bin 目录中),最后这个命令是否有权设置用户 id(在本例中是 no)。

倒数第二个步骤是向 ./include/usage.h 文件中添加详细的帮助信息。正如您可以从这个文件的例子中看到的一样,使用信息可能非常详细。在本例中,我只添加了一点信息,这样就可以编译这个新命令了:


清单 17. 向 usage.h 添加帮助信息
#define newcmd_trivial_usage "None"
#define newcmd_full_usage "None"

最后一个步骤是启用新命令(通过 make menuconfig,然后在 Miscellaneous Utilities 菜单中启用这个选项)然后使用 make 来编译 BusyBox。

使用新的 BusyBox,我们可以对这个新命令进行测试,如清单 18 所示。


清单 18. 测试新命令
$ ./busybox newcmd arg1
newcmd called:
arg[0] = newcmd
arg[1] = arg1
$ ./busybox newcmd --help
BusyBox v1.1.1 (2006.04.12-13:47+0000) multi-call binary

Usage: newcmd None

None

就是这样!BusyBox 开发人员开发了一个优秀但非常容易扩展的工具。





回页首


结束语

BusyBox 是为构建内存有限的嵌入式系统和基于软盘系统的一个优秀工具。BusyBox 通过将很多必需的工具放入一个可执行程序,并让它们可以共享代码中相同的部分,从而对它们的大小进行了很大程度的缩减,BusyBox 对于嵌入式系统来说是一个非常有用的工具,因此值得我们花一些时间进行探索。



参考资料

学习
  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文

  • uClibc glibc 一个精简内存需求的替代品。尽管它需要的资源比 glibc 少,但是将应用程序移植到 uClibc 上通常只需要重新编译即可。

  • Open Group 站点上的 POSIX FAQ 可以帮助我们学习更多有关 POSIX 的知识。这个规范的第 3 部分详细介绍了 shell 和工具的相关内容。

  • LinuxTiny 是用来减少 2.6 版本的 Linux 内核对内存和磁盘需求的一系列补丁,它只有 2MB 大小的 RAM。如果您对精简 2.6 版本的 Linux 内核感兴趣,请尝试一下 Matt Mackall 所开发的这个工具。

  • developerWorks Linux 专区 可以找到为 Linux 开发人员准备的更多资源。

  • 随时关注 developerWorks 技术事件和网络广播

获得产品和技术
  • 下载 BusyBox 的最新版本。我们可以找到最新的新闻、勘误以及使用并改进 BusyBox 的教程。

  • 订购免费的 SEK for Linux,这有两张 DVD,包括最新的 IBM for Linux 的试用软件,包括 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere®。

  • 在您的下一个开发项目中采用 IBM 试用软件,这可以从 developerWorks 上直接下载。


讨论