System函数与脚本的后台执行
2007-09-04 14:12
190 查看
昨天BSC测试组开了一个U0的Fault Report.
后来发现问题了:正常情况下当我们的CCP板插入机架后,本来OMCP板应该先配置其dhcp,然后restart dhcp,这样CCP板才能正常工作。但是现在看到的情况是,在dhcp配置完成之前,OMCP上的dhcp server就被restart了。细读trace和代码,最终发现了问题所在---->System函数调用后台执行的脚本。
先介绍一下System函数,在linux中man system得到的解释是:
system() executes a command specified in string by calling /bin/sh -c string, and returns after the command has been completed. During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.
system() 以字符串为参数,该字符串是一个shell命令或者shell脚本。shell命令或脚本返回后,system()才返回,在此过程中SIGCHLD会被阻塞,SIGINT和SIGQUIT会被忽略。
再回到前面我说的问题,在我的程序中:
int rc;
rc = system(/usr/local/bin/build_dhcp.sh &"); // (1)
......
rc = system("/etc/init.d/dhcpd restart"); // (2)
根据man system得到的信息,从字面上看,容易让人(比如我T_T)产生误会,以为(1)处的脚本完全执行完,dhcp配置好了,(1)处的system函数才会返回,接下来再执行(2)处的命令来restart dhcp。事实上,并非如此,(1)处的system函数调用shell脚本,该脚本转为后台执行,此时system函数就返回了,接下来(2)的system函数就开始执行了。由于build_dhcp.sh执行时间较长,因此,当dhcp还没有配置好的时候,dhcp server restart,最终导致插进去的这个CCP板无法正常工作。
工作的问题解决了,大快人心。顺便也就进一步了解一下system函数吧。
Linux中system()源码如下:
解释一下,当命令参数为NULL时直接返回,否则fork出一个子进程。
顺便说一下fork(),假如在进程A调用fork(),内核就创建一个新的进程B,并将A的内存映像复制到B的进程空间中。因此,进程A和进程B一模一样,只有根据fork()的返回值就才能知道谁是父进程,谁是子进程。fork在子进程中返回0,在父进程中返回子进程的pid。
在system()的源代码中,父进程使用waitpid等待子进程结束,子进程则是通过调用execl("/bin/sh", "sh", "-c", cmdstring, (char*)0)调用shell,这个shell的路径是/bin/sh,然后子进程就变成了一个shell进程,这个shell的参数就是system接受的参数,在windows中的shell是command。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#include <sys/types.h>
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#include <sys/wait.h>
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#include <errno.h>
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#include <unistd.h>
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
int system(const char * cmdstring)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
pid_t pid;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
int status;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
if(cmdstring == NULL)...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return (1);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
if((pid = fork())<0)...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
status = -1;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
else if(pid == 0)...{ //子进中运行脚本命令
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
-exit(127); //子进程正常执行则不会执行此语句
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
else...{ //父进程中等待子进程返回
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
while(waitpid(pid, &status, 0) < 0)...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
if(errno != EINTER)...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
status = -1;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
break;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return status;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
后来发现问题了:正常情况下当我们的CCP板插入机架后,本来OMCP板应该先配置其dhcp,然后restart dhcp,这样CCP板才能正常工作。但是现在看到的情况是,在dhcp配置完成之前,OMCP上的dhcp server就被restart了。细读trace和代码,最终发现了问题所在---->System函数调用后台执行的脚本。
先介绍一下System函数,在linux中man system得到的解释是:
system() executes a command specified in string by calling /bin/sh -c string, and returns after the command has been completed. During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.
system() 以字符串为参数,该字符串是一个shell命令或者shell脚本。shell命令或脚本返回后,system()才返回,在此过程中SIGCHLD会被阻塞,SIGINT和SIGQUIT会被忽略。
再回到前面我说的问题,在我的程序中:
int rc;
rc = system(/usr/local/bin/build_dhcp.sh &"); // (1)
......
rc = system("/etc/init.d/dhcpd restart"); // (2)
根据man system得到的信息,从字面上看,容易让人(比如我T_T)产生误会,以为(1)处的脚本完全执行完,dhcp配置好了,(1)处的system函数才会返回,接下来再执行(2)处的命令来restart dhcp。事实上,并非如此,(1)处的system函数调用shell脚本,该脚本转为后台执行,此时system函数就返回了,接下来(2)的system函数就开始执行了。由于build_dhcp.sh执行时间较长,因此,当dhcp还没有配置好的时候,dhcp server restart,最终导致插进去的这个CCP板无法正常工作。
工作的问题解决了,大快人心。顺便也就进一步了解一下system函数吧。
Linux中system()源码如下:
解释一下,当命令参数为NULL时直接返回,否则fork出一个子进程。
顺便说一下fork(),假如在进程A调用fork(),内核就创建一个新的进程B,并将A的内存映像复制到B的进程空间中。因此,进程A和进程B一模一样,只有根据fork()的返回值就才能知道谁是父进程,谁是子进程。fork在子进程中返回0,在父进程中返回子进程的pid。
在system()的源代码中,父进程使用waitpid等待子进程结束,子进程则是通过调用execl("/bin/sh", "sh", "-c", cmdstring, (char*)0)调用shell,这个shell的路径是/bin/sh,然后子进程就变成了一个shell进程,这个shell的参数就是system接受的参数,在windows中的shell是command。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#include <sys/types.h>
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#include <sys/wait.h>
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#include <errno.h>
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#include <unistd.h>
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
int system(const char * cmdstring)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
pid_t pid;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
int status;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
if(cmdstring == NULL)...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return (1);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
if((pid = fork())<0)...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
status = -1;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
else if(pid == 0)...{ //子进中运行脚本命令
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
-exit(127); //子进程正常执行则不会执行此语句
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
else...{ //父进程中等待子进程返回
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
while(waitpid(pid, &status, 0) < 0)...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
if(errno != EINTER)...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
status = -1;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
break;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return status;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
相关文章推荐
- system函数的返回值和执行脚本的返回值
- Zee之LR脚本练习之五:用system函数执行系统命令
- PHP守护进程函数–后台执行脚本
- 在后台 .cs 中执行前台的js 函数
- 后台执行UNIX/Linux命令和脚本的五种方法
- 如何后台执行脚本程序?
- 后台权限数据表和linux后台执行脚本命令例子
- Unix下两种后台执行SQL脚本的方法
- 后台执行的程序通过system()调用ffmpeg卡住 解决办法
- linux 后台执行oracle sql脚本
- 可以返回执行结果的system函数加强版本
- Java后台执行Shell脚本, Java方法不用等待Shell程序执行完成并保证关掉Java程序Shell脚本正常运行
- 后台执行js先执行前端的JS函数,再执行后台函数的按钮实
- 执行定时或者后台函数
- 解决system()函数执行命令弹出dos窗口问题
- 怎么让脚本或里面的函数在所有图片都载入完毕的时候执行
- Linux Shell脚本中,远程调用脚本或命令,并使后台执行
- PHP 执行系统外部命令的函数- system() exec() passthru()
- PHP 脚本后台执行