关于rsyslog的几个测试

测试目的

如果syslog函数的调用并发很大的话,可能会因为syslogd消费太慢而阻塞;本实验观察其阻塞的几个决定因素:

1. 未消费报文数超过多少个会阻塞

2. 报文的长度允许最大多大

3. 如果报文数为超过最大值,则数据超过多少会阻塞

测试平台

ubuntu12

测试1:

1. kill -19 syslogd-pid

2. i=1; while :; do ((i++)); logger a; done

结论: 默认值为10, 可以通过修改net.unix.max_dgram_qlen来调的更大一些;

注意: 修改net.unix.max_dgram_qlen 后需要重启进程才能生效,或者kill rsyslogd (rsyslogd会自己重启的)

 

测试2:

1. while [ i < 65536 ]; do ((i++)); echo -n a>>a.txt; done

2. while :; do logger <a.txt; done

发现一条日志重复了64次,说明,单个数据包的最大数据量为1k; 但是,很有可能是logger程序故意做了这种1k的切割(通过logger的源代码确认了一下,是这样的); 使用PHP的syslog函数来写日志,只截取了其中2k的数据记录进去了,其它的就给丢弃了,不过,这个也可能是PHP给做了2k的限制; 看了下PHP的源码,没有做这样的限制,或许unix数据报的报文大小就是2k的限制了,不过,这个也太小了,难道unixsocket可以显式定义数据报的大小?

 

测试3:

创建了一个200字节的文件,并且把net.unix.max_dgram_qlen 修改为1000,kill -19 syslogd_pid 后,使用logger写了1000次文件后才阻塞,说明还是受到了net.unix.max_dgram_qlen的限制,而没有收到一个buffer的限制。猜测,难道没有这么一个buffer?

 (后测试发现写入84k的数据就开始阻塞了)

=======================

关于丢数据的问题

rsyslog的日志中发现如下日志:

Jan 1 21:19:44 phpor-VirtualBox rsyslogd-2177: imuxsock begins to drop messages from pid 2297 due to rate-limiting

 

 

一种有趣的死锁

死锁步骤

1. 使用sudo把syslogd给pause掉,就是: sudo kill -19 syslogd-pid

2. 使用logger写一些日志,自然是写不进去的,一般写10条就够了

3. 在使用sudo让syslogd继续运行: sudo kill -18 syslogd-pid

 

现象:

发现第三步怎么也执行不了,不知道卡死在什么地方了; 使用strace跟踪一下吧: strace sudo kill -18 syslog-pid; 发现没有权限,自然还要对strace使用sudo执行,于是: sudo  strace sudo kill -18 syslog-pid ; 什么也没看见,继续卡死。

问题原因:

因为syslogd的buffer已经写满了,sudo是要写日志的,阻塞在了写日志的地方了; 于是就不好玩了,关机吧!

但是关机也是要写日志的呀,关机也关不了了,只能断电了

xhprof 的实现机制

缘起

正文

1. 下载xhprof源代码: http://pecl.php.net/package/xhprof

2. 参看: xhprof-x.x.x/extention/xhprof.c 中函数:hp_begin

说明: xhprof 代理了zend的一些函数,在这些函数的开始和结束记录所关心的信息

 

linux中的shadow文件以及所采用的加密算法

转自: http://www.wzzjla.com/Html/201209/500.html

 

在现在的linux和unix系统中,用户的密码都保存在shadow文件中,因为密码关系到系统的安全,所以只有root用户才有读shadow文件的权限。shadow中存放的内容是有着一定的格式的,看如下例子:

root:$1$v2wT9rQF$XSpGgoB93STC4EFSlgpjg1:14181:0:99999:7:::

冒号是分割符,分别代表着,每个字段分别代表着:

:用户名

:密码hash值

:密码修改距离1970年1月1日的时间

:密码将被允许修改之前的天数(0 表示“可在任何时间修改”)

:系统将强制用户修改为新密码之前的天数(1 表示“永远都不能修改”)

:密码过期之前,用户将被警告过期的天数(-1 表示“没有警告”)

:密码过期之后,系统自动禁用帐户的天数(-1 表示“永远不会禁用”)

:该帐户被禁用的天数(-1 表示“该帐户被启用”)

:保留供将来使用

在hash值那一栏,两个”$”符号之间的数字代表不同的加密算法,系统不同所使用的算法也不尽相同。第二个”$”符号之后的字符串就是salt值,加密的时候需要用到(好像是取每八个字符的每个字符的低7个bit位(取得的结果为01串)),然后得到8*7=56个bit位,然后用一定的规则反复加密(我不知道是什么规则),返回指向包含13个可打印的ASCII码字符([a-zA-Z0-9./])的指针,通常取前两位作为salt位,

数字和所使用的加密算法对应关系:

1: MD5 ,(22位)

2a: Blowfish, 只在有一部分linux分支中使用的加密方法

5: SHA-256  (43位)

6: SHA-512   (86位)

后面两种加密算法只在glibc2.7版本之后才支持。

第3个”$”后面的字符串就是加密后的密文了(应该是截取了加密密文中的某一段)

以下是crypt文档的部分内容:

The glibc2 version of  this  function  supports  additional  encryption
algorithms.

If  salt is a character string starting with the characters “$id$” fol‐
lowed by a string terminated by “$”:

$id$salt$encrypted

then instead of using the DES machine,  id  identifies  the  encryption
method  used  and  this  then  determines  how the rest of the password
string is interpreted.  The following values of id are supported:

ID  | Method
─────────────────────────────────────────────────────────
1   | MD5
2a  | Blowfish (not in mainline glibc; added in some
| Linux distributions)
5   | SHA-256 (since glibc 2.7)
6   | SHA-512 (since glibc 2.7)

So   $5$salt$encrypted   is   an   SHA-256   encoded    password    and
$6$salt$encrypted is an SHA-512 encoded one.

“salt” stands for the up to 16 characters following “$id$” in the salt.
The encrypted part of the password string is the actual computed  pass‐
word.  The size of this string is fixed:

MD5     | 22 characters
SHA-256 | 43 characters
SHA-512 | 86 characters

The  characters  in  “salt”  and  “encrypted”  are  drawn  from the set
[a–zA–Z0–9./].  In the MD5 and SHA implementations the  entire  key  is
significant (instead of only the first 8 bytes in DES).

PHP中关于max_execution_time的实现机制

PHP中的 max_execution_time 是通过setitimer来实现的:

文件: Zend/zend_execute_API.c

 

说明: 当程序执行到最大时间时,将会收到一个SIGPROF的信号,PHP处理了这个信号,至于哪些时间计算到最大执行时间中,且看setitimer的文档:

SYNOPSIS
#include <sys/time.h>

int getitimer(int which, struct itimerval *value);
int setitimer(int which, const struct itimerval *restrict value,
struct itimerval *restrict ovalue);

DESCRIPTION
The getitimer() function shall store the current value of the timer specified by which into the structure pointed to by value. The setitimer() function shall set the timer specified by which to the value specified in the structure pointed to by value, and if ovalue is not a null pointer, store the previous value of the timer in the structure pointed to by ovalue.

A timer value is defined by the itimerval structure, specified in <sys/time.h>. If it_value is non-zero, it shall indicate
the time to the next timer expiration. If it_interval is non-zero, it shall specify a value to be used in reloading
it_value when the timer expires. Setting it_value to 0 shall disable a timer, regardless of the value of it_interval. Setting it_interval to 0 shall disable a timer after its next expiration (assuming it_value is nonzero).

Implementations may place limitations on the granularity of timer values. For each interval timer, if the requested timer value requires a finer granularity than the implementation supports, the actual timer value shall be rounded up to the next supported value.

An XSI-conforming implementation provides each process with at least three interval timers, which are indicated by the which argument:

ITIMER_REAL
Decrements in real time. A SIGALRM signal is delivered when this timer expires.

ITIMER_VIRTUAL
Decrements in process virtual time. It runs only when the process is executing. A SIGVTALRM signal is delivered when it expires.

ITIMER_PROF
Decrements both in process virtual time and when the system is running on behalf of the process. It is designed to be used by interpreters in statistically profiling the execution of interpreted programs. Each time the ITIMER_PROF

timer expires, the SIGPROF signal is delivered.

The interaction between setitimer() and any of alarm(), sleep(), or usleep() is unspecified.

 

—————————–
疑惑: 既然PHP的执行时间限制是使用setitimer来实现的,那么为什么官方文档还有那么多莫名其妙的解释呢?

如:http://us1.php.net/manual/zh/function.set-time-limit.php

Note:

set_time_limit()函数和配置指令max_execution_time只影响脚本本身执行的时间。任何发生在诸如使用 system()的系统调用,流操作,数据库操作等的脚本执行的最大时间不包括其中,当该脚本已运行。在测量时间是实值的Windows中,情况就不是如此了。