环境为Mac OS lion,在php中使用exec调用外部imagemagick命令进行图片处理,图片没有被处理,查看命令返回的状态码为5,没有任何提示,相同的命令在命令行中可以正常执行。为了获取具体的错误信息还花费了一番力气,关于获取错误输出可以参考:PHP 执行外部命名获取出错信息。
上述错误信息为:
dyld: Library not loaded: /ImageMagick-6.7.5/lib/libMagickCore.5.dylib
Referenced from: /usr/bin/convert
从错误信息可以得知命令没有加载到Library,从Imagemagick官网看到Mac OS下安装需要配置DYLD_LIBRARY_PATH,它的路径就是Imagemagick安装路径下的lib目录。由于在/etc/bashrc中配置了,所以命令行下执行是正常的。通过web方式执行php环境不一样,没有加载DYLD_LIBRARY_PATH配置,因此导致执行出错。有了错误信息,也知道错误的原因,解决起来就很简单了,只需要在执行命令的前面添加DYLD_LIBRARY_PATH配置即可。例如:
$cmd = 'export DYLD_LIBRARY_PATH="/{imagemagick install home}/lib/" && ';
$cmd .= 'convert -resize 120x60 src.jpg desc.jpg';
exec($cmd);
php中提供了四种方法来执行外部命令,外面命令可以是一个系统命令或自己实现的shell(Linux)、批处理(window)脚本。四种调用方法分别是exec()、passthru()、system()、shell_exec()。关于它们的区别可以参看:http://www.leapsoul.cn/?p=646。
本文主要介绍在linux系统下如何获取命令出错的信息。出错包括命令执行时候出错和命名拼写错误等。上述四种方法只会返回命令执行返回码,没有具体的出错信息。想要获取具体的出错信息,可以把命令执行的输出结果输出到一个文件。利用符号 “>”即可。例如:
$cmd = 'your command >/tmp/test.log 2>&1';
exec($cmd);
命令输出的信息可以在/tmp/test.log中找到。
php 中使用memcached扩展来访问memcached时,当安装memcached服务的服务器无法正常连接,在默认设置下会造成请求响应变慢。注意:无法正常连接指网络故障,如两台服务器无法进行通信等,只要能ping通,就算memcached服务没有开启或down掉,不会影响响应时间,只是memcached没有启作用。
设置timeout时间通过常量Memcached::OPT_CONNECT_TIMEOUT来控制,默认是4000毫秒(php 官网显示1000,我测试版本1.0.2和2.0.1都是4000)。另外1.0.2和2.0.1还有很大差别。1.0.2在执行addServer时就会连接memcached服务器,而且执行命令时候需要2倍的timeout时间,所有当memcached无法连接时候,花费时间是3倍的timeout时间。
2.0.1在php 5.2中似乎有bug,无法使用,具体参看:https://bugs.php.net/bug.php?id=61283。
通过设置hosts文件可以强制指定域名对应的IP,当修改hosts文件,想要浏览器生效,最直接的方法关闭浏览器后重新开启;如果不想重启浏览器,只需要清空浏览器的DNS缓存即可。清空DNS缓存在chrome、firefox下很容易做到。具体操作如下:
chrome:在浏览器的地址栏中输入 chrome://net-internals/#dns 并回车,该页面会显示当前所有DNS缓存,通过点击“Clear host cache”,可以清空所有DNS缓存。有时候此方法可能不能立刻生效,可以使用另外一个设置,在地址栏中输入 chrome://settings/ 并回车,通过搜索“预测网络操作”找到配置项“预测网络操作,以提高网页加载速度”,去掉前面的勾即可。
firefox:在地址栏中 about:config 并回车,可能会出现一个警告信息,直接点击按钮进入,会出现firefox的所有配置信息,通过搜索dns进行过滤,可以看到一项名为 network.dnsCacheExpirationGracePeriod 项,它对应的值就是DNS缓存的时间,双击此项,会出现修改的提示框,填入 0 (不缓存DNS)即可。
时间过的真快,四月都是在忙碌中马上就要到头,其实不止四月,准确的说从春节上班开始就一直处于忙碌状态中。期间也碰到过很多问题,很想写Blog来记录下来,实在是从工作中抽不出时间,不想让自己的Blog在四月出现空挡,特此写点什么来充数好了,:)。
select框操作
获取值
$('#select').val()
设置值为xx的项为选中
$('#select').val(xx)
设置文本信息为yy的项为选中
$('#select option[text="yy"]').attr("selected", true);
radio box 操作
获取值
$('input[name="xx"]:checked').val()
设置值为xx的为选中
$('input[name="xx"]:radio[value="yy"]').attr('checked', 'checked');
在使用jquery时,很多时候都需要获取当前节点的父节点,包括直接父节点和祖先父节点。用的最多的方法是parent([expr])和parents([expr])。从方法的名字上就可以判断前一个方法是单数,也就是返回一个真正的父节点,后面是返回所有的祖先节点集合(不包含根节点)。假设需要获取当前节点的祖父节点(父节点的父节点),其有属性class=”pp”,那么获取的方法为:
$('#cur').parent().parent();
或
$('#cur').parent().parent('.pp');
或
$('#cur').parent('.pp');
上述操作在理想情况下,都没有问题。例如后来修改页面,在当前节点上又加了一个父节点,那么前两种获取的到的节点就不是当初节点;另外如果其祖先节点中还有属性class=”pp” 的节点,第三种获取的节点也不是自己想要的。
现在介绍另外一个获取父节点的方法closest([expr])。closest会首先检查当前元素是否匹配,如果匹配则直接返回元素本身。如果不匹配则向上查找父元素,一层一层往上,直到找到匹配选择器的元素。否则返回一个空的jquery对象。
$('#cur').closest('.pp');
使用上述操作获取含义特定属性的祖父节点相对要安全一些,即使在当前节点和祖父节点中增加或者减少节点,只要增加的节点没有相同的属性,已有的js代码可能都不需要进行修改。
最后说一下closest和parents的主要区别是:
- 前者从当前元素开始匹配寻找,后者从父元素开始匹配寻找
- 前者逐级向上查找,直到发现匹配的元素后 就停止了,后者一直向上查找直到根元素,然后把这些元素放进一个临时集合中,再用给定的选择器表达式去过滤
- 前者返回0或1个元素,后者可能包含0 个,1个,或者多个元素
通过js获取页面两个数字输入框的值,并对其进行大小比较。此时出来的结果可能让你迷惑不解,例如代码:
var v1 = $('#input1').val();
var v2 = $('#input2').val();
alert(v1 > v2);
假如input1中输入10,input2中输入2。10肯定是大于2的,所以上面的alert框应该弹出true,但实际上给出的是false。原因何在?对应数字10大于2是毫无疑问的,如果是作为字符串比较,那么结果刚好相反。而上述从页面获取值得到的类型是String。
如果明确是要进行数字比较,则需要显示的转化为数字,例如使用parseInt、parseFloat;还有一种方法是使用减法运算符,如:v1 – v2 > 0,此时js在运算前内部会进行类型转换。
另外由于加法运算符同时支持数字和字符串,使用这个时候也要小心。例如 a + b ,如果其中一个是字符串类型,一个是数字类型,在执行运算前会把另外一个转化为字符串类型,所以实际是进行字符串链接操作,而不是想要的算术运算。在确定是要做算术运算的情况下,对于未知类型的参数,保险的情况下还是使用parseInt进行类型转换。
在http://www.ruanyifeng.com/blog/2011/04/quicksort_in_javascript.html这篇文章中详细描述了快速排序的原理,同时也给出了javascript的实现,其具体代码如下:
function quickSort(arr) {
if (arr.length <= 1) {
return arr;
}
var pivotIndex = Math.floor(arr.length / 2);
var pivot = arr.splice(pivotIndex, 1)[0];
var left = [];
var right = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot], quickSort(right));
}
上述代码也是比较通俗易懂,自己生成一个随机数组测试,排序正确,所以功能上也没有问题。但上述代码还是有一个隐藏的小bug,当对同一个数组调用两次quickSort,发现第二次条用后出来的元素数量会比原始数据少一个。导致这个问题是根源是arr.splice(pivotIndex, 1)[0],它会把arr中指定位置的元素删掉。其操作是针对该方法的参数,但是同时影响到了传给方法的实际数组,所以结论是javascript中数组参数的是传引用(地址),而非传值。
为了不影响原始数组数据,可以对上述代码进行一个小修改,修改后的代码如下:
function quickSort(arr) {
if (arr.length <= 1) {
return arr;
}
var pivotIndex = Math.floor(arr.length / 2);
var pivot = arr[pivotIndex];
var left = [];
var right = [];
for (var i = 0; i < arr.length; i++) {
if (i == pivotIndex) {
continue;
}
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot], quickSort(right));
}
当使用js来操作html,经常遇到需要处理多行字符串的问题,如果采用一行或多行拼接的方式都不好维护。像python、php中提供多行字符串的定义方式,真是方便不少。例如:
python
pstr = '''
line1
line2
line3
line4
'''
php
$pstr = <<<eof
line1
line2
line3
line4
eof
上述定义完全保留字符串中的所有字符,包括回车换行已经引号等。
js本身没有提供类似的定义方式,但是可以通过多行注释(/* */),已经借助function的方式来达到多行字符的定义,例如代码:
var jstr = function() {
var fun = function() {
/*line1
line2
line3
line4*/
}
var lines = new String(fun);
return lines.substring(lines.indexOf("/*") + 3,
lines.lastIndexOf("*/"));
}