今天使用Fiddler构造一个POST请求,server端的PHP脚本的 $_POST数组中怎么也获取不到值,后来偶然发现是因为缺少了一个http头:
Content-Type: application/x-www-form-urlencoded
另外提示一点的是: 鉴于有如下功能,我们不需要去计算post数据的长度,然后手动添加Content-Length 头了:
DevOps
今天使用Fiddler构造一个POST请求,server端的PHP脚本的 $_POST数组中怎么也获取不到值,后来偶然发现是因为缺少了一个http头:
Content-Type: application/x-www-form-urlencoded
另外提示一点的是: 鉴于有如下功能,我们不需要去计算post数据的长度,然后手动添加Content-Length 头了:
PHP的代码包中提供了一个 .gdbinit 的gdb脚本文件,里面提供了20多个 gdb 的自定义命令,用于方便PHP的调试,下面举几个例子:
测试脚本a.php:
1 2 3 4 5 6 7 8 9 10 |
<?php $a = "AAA"; $b = "BBB"; test("phpor"); function test($name) { $m = "MMM"; $n = "NNN"; sleep(1); echo$name; } |
gdb 调试命令:
———————–
gdb php
set args a.php
break sleep
r
…
———————–
1. print_cvs 打印当前执行环境中已编译的PHP变量, 如:
1 2 3 4 5 6 7 8 9 |
(gdb) print_cvs Compiled variables count: 3 0 = name [0x9543f7c] (refcount=2) string(5): "phpor" 1 = m [0x9543f98] (refcount=1) string(3): "MMM" 2 = n [0x9543fb4] (refcount=1) string(3): "NNN" (gdb) |
2. printzv 打印指定的PHP变量, 需要指定地址, 如:
(gdb) printzv 0x9543f98
[0x9543f98] (refcount=1) string(3): “MMM”
(gdb)
3. 打印PHP的函数调用栈, 如:
(gdb) zbacktrace
[0x95770a4] sleep(1) /usr/home/junjie2/a.php:11
[0x9576fe0] test(“phpor”) /usr/home/junjie2/a.php:7
(gdb)
4. print_ft 打印函数表( HashTable )
(gdb) set $eg = executor_globals
(gdb) print $eg.function_table
$6 = (HashTable *) 0xa5bd450
(gdb) print_ft $eg.function_table
[0xa5bd450] {
“zend_version\0” => “zend_version”
“func_num_args\0” => “func_num_args”
“func_get_arg\0” => “func_get_arg”
“func_get_args\0” => “func_get_args”
“strlen\0” => “strlen”
“strcmp\0” => “strcmp”
“strncmp\0” => “strncmp”
“strcasecmp\0” => “strcasecmp”
“strncasecmp\0” => “strncasecmp”
“each\0” => “each”
…
学习:
1. 通过阅读 print_cvs 命令的实现,可以知道可以通过prev_execute_data来打印上一执行空间的PHP变量,如:
(gdb) printzv *executor_globals.current_execute_data->prev_execute_data->CVs[1]
[0x9543408] (refcount=1) string(3): “AAA”
(gdb) printzv *executor_globals.current_execute_data->prev_execute_data->CVs[2]
[0x95433ec] (refcount=1) string(3): “BBB”
(gdb)
2. 通过 op_array->vars 来找到对应的变量的名字
(gdb) printf “%s\n” ,executor_globals.current_execute_data->prev_execute_data->op_array->vars[1].name
a
(gdb) printf “%s\n” ,executor_globals.current_execute_data->prev_execute_data->op_array->vars[2].name
b
3. 修改了一下 print_cvs 命令,通过参数来获取每个执行空间的PHP的已编译变量
使用方法:
———————
(gdb) zbacktrace #查看PHP的调用栈
[0x8ce2078] sleep(1) /usr/home/junjie2/a.php:9
[0x8ce1fe0] test(“phpor”) /usr/home/junjie2/a.php:5
(gdb) print_cvs #查看当前执行空间中的PHP变量
Compiled variables count: 3
0 = name
[0x8cae3d0] (refcount=2) string(5): “phpor”
1 = m
[0x8cae93c] (refcount=1) string(3): “MMM”
2 = n
[0x8cae958] (refcount=1) string(3): “NNN”
(gdb) print_cvs 2 # 查看指定执行空间中的PHP变量, 这个参数给大了也没关系,最多打印最外层的PHP变量
Compiled variables count: 2
0 = a
[0x8cae408] (refcount=1) string(3): “AAA”
1 = b
[0x8cae3ec] (refcount=1) string(3): “BBB”
(gdb)
———————
4. 有时候需要借助环境变量,如:
(gdb) print_ft (HashTable *)0xa5bd450
A syntax error in expression, near `’.
(gdb) set $phpor=(HashTable *)0xa5bd450
(gdb) print_ft $phpor
[0xa5bd450] {
“zend_version\0” => “zend_version”
“func_num_args\0” => “func_num_args”
“func_get_arg\0” => “func_get_arg”
“func_get_args\0” => “func_get_args”
“strlen\0” => “strlen”
“strcmp\0” => “strcmp”
“strncmp\0” => “strncmp”
5. 打印指定的PHP变量
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 |
define print_pval ____executor_globals set $p = $eg.current_execute_data.CVs set $c = $eg.current_execute_data.op_array.last_var set $v = $eg.current_execute_data.op_array.vars set $i = 0 set $name = $arg0 #printf "search php var: %s c:%d\n", $name, $c while $i < $c #printf "name: %s\n", $name set $n = $v[$i].name # use strcmp but == if strcmp($n, $name) == 0 if $p[$i] != 0 printzv *$p[$i] # use loop_break but break loop_break end end #printf "i %d, %s\n", $i, $v[$i].name set $i = $i + 1 end if $i == $c printf "no found var named: %s\n", $name end end |
PHP 的一个错误
如果使用PHP来写一个后台程序,可能会考虑在程序中将标准输入、标准输出、标准错误给重定向,这样就不需要在启动程序的时候来做重定向(因为这样很容易忘记);在C中有比较正规的写法,但是PHP中没有找见对应的实现,今天想到一个变通的办法:
1. 使用ob_start(function); 来设置自定义的输出过滤器
2. 使用set_error_handler(function); 来实现自定义的标准错误处理器
然后,在自定义函数中就可以随意处理了,实例:
man 中说到:
Read and execute commands from filename in the current shell environment and return the exit status of the last command executed from filename.
例子:
—— a1.sh ——
#!/bin/sh
./b.sh #如此执行则b.sh 必须有可执行权限
——————-
—— a2.sh ——
#!/bin/sh
. b.sh #如此写法则b.sh 可以没有可执行权限
——————-
—— b.sh ——
#!/bin/sh
sleep 100
——————-
执行:
sh a1.sh #进程中会看到 b.sh
sh a2.sh #进程中不会看到 b.sh
PHP不支持多线程编程,于是,当需要同时执行多个任务的时候,就有些力不从心了;对于有些任务可以通过异步的方式来处理,如: 同时执行多个http请求;对于有些计算型的需求,或者是异步实现很麻烦的时候就不好办了。
当我再一次看fork/exec/system/source等类似的命令或系统调用的时候,觉得他们和之间的异同比较有意思,比如:
fork: 创建子进程,当前进程继续运行
exec: 当前进程直接让位于要执行的程序,用不返回
system: 使用当前进程的环境,创建一个子进程,等待子进程执行完成后返回; system=fork+exec+waitpid
于是想到了PHP中的popen,该方法可以和执行一个外部命令,但是不阻塞当前进程,只需要使用循环去收集执行结果就行了。
对于web程序,通过异步的http请求将任务提交给本机的web server或许比popen更加合算一些。
情景:
从机器A到机器B发起连接,连接超时时间设置为1s,有一定概率的连接失败的情况,使用下面脚本来测试,不断连接,放过成功的连接,只显示失败的连接,并且显示连接失败的时间,脚本如下:
nc -z -v -w 1 10.79.40.43 11231 2>&1 | grep -v succe
;if [ "x$r" != "x" ]; then d=
date +"%H:%M";echo -n "$d "; echo $r; fi ; done检查网络连通性:
while :; do nc -z -v -w 1 10.79.40.43 11231 | grep -v succe; done
1. 了解了使用程序创建jira提案的方法
2. jQuery中查找表单中所有可以提交的元素(input select checkbox textarea)的方法: $("#formid").find(":input")
3. 有如下svn命令:
svn log –limit 1 –username xxx –password xxx https://xxx.xx.xx/xxxx
由于该svn没有购买https证书,而且自制的证书的domain都不匹配,于是就会出现提示信息如下:
如果使用(p)选择永远接受,则下次不再有该提示信息,因为他可以将你的输入信息保存的你的家目录下的文件中;但是不行的是,该命令需要通过webserver执行,而执行web的用户是nologin的,没地方保存该信息,于是这里可以通过(t)暂时接受的方式来解决该问题,PHP脚本如下:
注意:这里的错误重定向也是不能忽视的。