我看网上应该有不少搜索这个区别的问题,但是回答的都不全面,其中sigterm与sigint尤其有一点区别比较重要,但大都没有提及,今天我就遇到了这个问题,纠结了20分钟才搞明白咋回事。
首先,对于说这几个信号都是终止程序运行的说法不太准确,因为程序收到信号后,如果不对信号处理,就会导致程序退出,但如果程序捕获信号进行处理,按照它的逻辑,它是不一定会退出的。
在这三个信号中,sigkill是不能被捕获的,程序收到这个信号后,一定会退出。这就是kill -9一定能保证将程序杀死的原因。
下面说一下sigterm与sigint的区别,其中有一点区别区别很多文章都没有提及,也是我写这篇blog的原因(如果人家都写了,我就不用写了呗)
| 信号 |
产生方式 |
对进程的影响 |
| sigint |
通过ctrl+c将会对当进程发送此信号 |
信号被当前进程树接收到,也就是说,不仅当前进程会收到信号,它的子进程也会收到 |
| sigterm |
kill命令不加参数就是发送这个信号 |
只有当前进程收到信号,子进程不会收到。如果当前进程被kill了,那么它的子进程的父进程将会是init,也就是pid为1的进程 |
下面这两个代码片段就能够验证这种情况(注意使用pcntl的时候,一定要declare ticks,要不然会杯具的发现函数没有被调用,进程不退出,信号发过去没有作用。php手册竟然没有强调这一点):
文件:loadhelper.php
#为了pcntl能够截获信号
declare(ticks = 1);
$arr_processes = array();
function terminate($signo){
echo "aaaaaaaaaaa\n";
}
pcntl_signal(SIGTERM, "terminate", true);
pcntl_signal(SIGINT, "terminate", true);
foreach($argv as $key => $operation){
if(0 === $key){
continue;
}
$pipes = array();
$process = proc_open($operation, array(), &$pipes);
if(false === $process){
exit(-1);
}
$arr_processes[] = $process;
}
while(true){
sleep(100);
}
文件:child.php
declare(ticks=1);
pcntl_signal(SIGINT, "terminate");
pcntl_signal(SIGTERM, "terminate");
function terminate($signo){
echo "test_child\n";
}
while(true){
sleep(100);
}
使用命令php loadhelper.php “php test.php”可以启动这个测试。
1.输入ctrl+c发送sigint可以看到,父进程与子进程的terminate都得到了执行,都有输出,但父进程不会退出,因为子进程还没有退出
2.通过kill向父进程的pid发送sigterm,可以看到,只有父进程输出
遗留问题:
父进程(loadhelper)接受到一次信号后,如果在terminate函数中调用exit,它还是不能退出的,因为还有子进程没有退出。但是从此以后它就不能再接收信号了(子进程还是能够接收到sigint),可能是exit使进程进入了待回收状态,具体还 需要后续在分析一把。
---------------------------------------------------------------
本站作品根据创作共同协议进行授权, 转载时请务必以超链接形式标明文章原始出处
原文地址:http://www.mirecle.com/2010/05/20/sigterm-sigint-sigkill-difference.html
---------------------------------------------------------------
在这里,我不得不再一次感叹php语言库函数的山寨与不专业。getopt函数就是一个典型的例子,通常用的时候,大家可能觉得没有什么,但在某些情况 下,就真的让人很囧。一个简单的函数,稍微多花几分钟就弄得更好一些了,但这个语言有个随意的开端,就有个随意的实现啊。
在linux中,使用getopt时候,有两种情况:
1.取得的参数解析成字符串:“php test_arg.php -c abc”,这种情况c参数取得的结果就是abc这个字符串
2.取得的参数解析成数组:“php test_arg.php -c abc -c abc123”,这种情况c参数取得的结果就是包含abc与abc123的数组
但是遇到这种情况呢:“php test_arg.php -c abc*”?由于linux的shell已经帮程序做了输入参数的解析,这时候c参数得到的既不是abc*这个结果也不是一个数组,而是被shell展开成了很多文件名后的第一个。
可能getopt用的童鞋很少,但这种山寨的设计,实在太让人憋屈了,自己花个10分钟写一个就比它的要好,为了避免大家重复劳动,分享一个代码片段
function mygetopt(){
global $argv;
$result = array();
$current_key = false;
foreach($argv as $opt){
$matches = array();
if(1 === preg_match("/^-{1,2}(.*)$/", $opt, $matches)){
$current_key = $matches[1];
if(false === isset($result[$current_key])){
$result[$current_key] = false;
}
}else if (false !== $current_key){
if(false === $result[$current_key]){
$result[$current_key] = $opt;
}else{
if(false === is_array($result[$current_key])){
$result[$current_key] = array($result[$current_key]);
}
$result[$current_key][] = $opt;
}
}
}
return $result;
}
为了方便使用,将新版本的getopt函数设置为不接受任何参数,但是解析的结果可以输出所有的参数内容。因为php官方的getopt函数使用后,也无非是对输出的数组进行foreach之后进行switch,还不如方便点,直接解析所有呢。除了这一点,这个getopt函数的输出结果与php官方的完全一致
php官方getopt函数参考文档:http://cn.php.net/manual/en/function.getopt.php
---------------------------------------------------------------
本站作品根据创作共同协议进行授权, 转载时请务必以超链接形式标明文章原始出处
原文地址:http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html
---------------------------------------------------------------
以前写的一个小脚本,用在linux的shell批量修改大量文件名的情况下。昨天不小心删除了大量文件,找回的时候,又一次用到了它,在遇到大批量文件的时候,还是挺有效果的,共享一下。
用法:
1.将你要改名的文件都放在同一个文件夹下,运行”ls -l > oldnames”,然后“vi oldnames”,这时候看到的大概是这个样子:
total 1224
drwxrwxr-x 3 yanpeng yanpeng 4096 Sep 17 16:13 app
drwxrwxr-x 2 yanpeng yanpeng 4096 May 19 2009 bin
drwxrwxr-x 2 yanpeng yanpeng 8192 Jan 26 16:40 docpay
2.输入”ctrl+v”,移动光标,选中要删除的那一堆内容,其实就是文件名前面的那些列,输入“d”,得到的文件大概为
app
bin
docpay
3.删除掉第一行的空行,保存退出vi,然后”cp oldnames newnames”。
4.修改newnames文件中想要改名的文件为新文件名
5.将change_name.sh脚本放在你的那个放置文件的夹下,运行./change_name.sh就可以了(注意有执行权限,加执行权限的方法chmod a+x change_name.sh)
change_name.sh脚本内容,拷贝下,存好就能用了
#!/bin/sh
OLDNAMES='oldnames'
NEWNAMES='newnames'
fileline=`sed -n '$=' $OLDNAMES`
echo $fileline
index=1
while [ $index -le $fileline ]
do
oldname=`sed -n "${index}p" $OLDNAMES`
newname=`sed -n "${index}p" $NEWNAMES`
mv $oldname $newname
index=`expr $index + 1`
done
---------------------------------------------------------------
本站作品根据创作共同协议进行授权, 转载时请务必以超链接形式标明文章原始出处
原文地址:http://www.mirecle.com/2010/01/27/batch-rename-files-in-shell.html
---------------------------------------------------------------