带外数据: Out-Of-Band data
从其命名和用途来看,它和普通数据使用的不是同一个通道,它可以通过一个紧急通道而不被普通数据阻塞,所以称之为“带外”
参考资料:
DevOps
带外数据: Out-Of-Band data
从其命名和用途来看,它和普通数据使用的不是同一个通道,它可以通过一个紧急通道而不被普通数据阻塞,所以称之为“带外”
参考资料:
如果syslog函数的调用并发很大的话,可能会因为syslogd消费太慢而阻塞;本实验观察其阻塞的几个决定因素:
1. 未消费报文数超过多少个会阻塞
2. 报文的长度允许最大多大
3. 如果报文数为超过最大值,则数据超过多少会阻塞
ubuntu12
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会自己重启的)
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可以显式定义数据报的大小?
创建了一个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. 和有经验的同事聊聊
2. 一边看一边熟悉一下北京地图
3. 去链家的店里面看看
4. 看好的房子去看看真房
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是要写日志的,阻塞在了写日志的地方了; 于是就不好玩了,关机吧!
但是关机也是要写日志的呀,关机也关不了了,只能断电了
1. 下载xhprof源代码: http://pecl.php.net/package/xhprof
2. 参看: xhprof-x.x.x/extention/xhprof.c 中函数:hp_begin
说明: xhprof 代理了zend的一些函数,在这些函数的开始和结束记录所关心的信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
/** * This function gets called once when xhprof gets enabled. * It replaces all the functions like zend_execute, zend_execute_internal, * etc that needs to be instrumented with their corresponding proxies. */ static void hp_begin(long level, long xhprof_flags TSRMLS_DC) { if (!hp_globals.enabled) { int hp_profile_flag = 1; hp_globals.enabled = 1; hp_globals.xhprof_flags = (uint32)xhprof_flags; /* Replace zend_compile with our proxy */ _zend_compile_file = zend_compile_file; zend_compile_file = hp_compile_file; /* Replace zend_execute with our proxy */ _zend_execute = zend_execute; zend_execute = hp_execute; /* Replace zend_execute_internal with our proxy */ _zend_execute_internal = zend_execute_internal; if (!(hp_globals.xhprof_flags & XHPROF_FLAGS_NO_BUILTINS)) { /* if NO_BUILTINS is not set (i.e. user wants to profile builtins), * then we intercept internal (builtin) function calls. */ zend_execute_internal = hp_execute_internal; } |
BEGINmodInit
1. http://kernel.org/ 下载源代码
2. 源代码目录中的 Documentation\sysctl 下面有不同方面的内核参数说明,然后再去相应的文件中找说明
转自: 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中的system和popen都是通过C中的popen来实现的
PHP中的 max_execution_time 是通过setitimer来实现的:
文件: Zend/zend_execute_API.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
/* This one doesn't exists on QNX */ #ifndef SIGPROF #define SIGPROF 27 #endif void zend_set_timeout(long seconds, int reset_signals) /* {{{ */ { TSRMLS_FETCH(); EG(timeout_seconds) = seconds; #ifdef ZEND_WIN32 if(!seconds) { return; } if (timeout_thread_initialized == 0 && InterlockedIncrement(&timeout_thread_initialized) == 1) { /* We start up this process-wide thread here and not in zend_startup(), because if Zend * is initialized inside a DllMain(), you're not supposed to start threads from it. */ zend_init_timeout_thread(); } PostThreadMessage(timeout_thread_id, WM_REGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) seconds); #else # ifdef HAVE_SETITIMER { struct itimerval t_r; /* timeout requested */ sigset_t sigset; if(seconds) { t_r.it_value.tv_sec = seconds; t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0; # ifdef __CYGWIN__ setitimer(ITIMER_REAL, &t_r, NULL); } if(reset_signals) { signal(SIGALRM, zend_timeout); sigemptyset(&sigset); sigaddset(&sigset, SIGALRM); } # else setitimer(ITIMER_PROF, &t_r, NULL); } if(reset_signals) { signal(SIGPROF, zend_timeout); sigemptyset(&sigset); sigaddset(&sigset, SIGPROF); } # endif if(reset_signals) { sigprocmask(SIG_UNBLOCK, &sigset, NULL); } } # endif #endif } |
说明: 当程序执行到最大时间时,将会收到一个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中,情况就不是如此了。