在Linux上,如果一个程序中需要执行shell 命令,可以有以下几种方法:
- system(): 执行一个shell命令,返回该命令执行后的返回值
- popen():执行一个shell命令,从返回的文件描述符中读出命令执行后输出的内容
- 自己写fork(), dup2(), execl, wait4,通过execl中执行“/bin/sh -c <cmd>"来得到执行结果
system()只能得到命令执行返回值,得不到输出的结果。popen()正好相反。
下面的system_ex()可以兼而有之,它是通过第三种方法来执行shell命令。
int system_ex(char* cmd, char* output, int size)
{
int fd[2];
pid_t pid;
int n, count;
int wait_val = 0;
if(cmd == NULL){
return -1;
}
/* no need to save output, use original system() */
if(output == NULL || size <= 0){
return system(cmd);
}
if (pipe(fd) < 0){
return -1;
}
if ((pid = fork()) < 0){
close(fd[0]);
close(fd[1]);
return -1;
}
else if (pid > 0){//parent
close(fd[1]);//close write pipe
count = 0;
while (count < size){
n = read(fd[0], output + count, size-count);
if(n <= 0){
break;
}
count += n;
}
output[size - 1] = '\0'; /*terminate the string */
close(fd[0]);
if (wait4(pid, &wait_val, 0, 0) == -1){
wait_val = -1;
}
return wait_val;
}else{//child
close(fd[0]);//close read pipe
if (fd[1] != STDOUT_FILENO){
dup2(fd[1], STDOUT_FILENO);
close(fd[1]);
}
execl("/bin/sh", "sh", "-c", cmd, (char*)0);
//should not reach here, otherwise execl failed
/* SUSv3 mandates an exit code of 127 for the child if the
* command interpreter can not be invoked. */
_exit(127);
}
//should not reach here
return -1;
}