c - C 使用 execvp 执行带有另一个命令输出的命令
问题描述
我很好地执行诸如“ls”之类的命令和类似的东西,但我想做诸如“ls | sort”之类的事情,但 execvp 系统调用不支持“|”。我怎样才能只使用系统调用来做到这一点?当我尝试类似的东西时
char *arg[] = {"ls","|","sort",NULL};
execvp(arg[0],arg);
它不起作用,我该怎么做?
编辑:
char* execString (char string[]){
int link[2];
pipe(link);
if (fork() == 0){
int i = 0;
char *p = strtok(string," ");
char *x[spacecount(string)+2];
while(p){
x[i++] = p;
p = strtok(NULL," ");
}
x[i] = NULL;
dup2(link[1],1);
close(link[0]);
close(link[0]);
execvp(x[0],x);
_exit(0);
} else {
wait(NULL);
close(link[1]);
char buf[512];
int i = 0;
while (read(link[0],&buf[i++],1) == 1);
close(link[0]);
buf[i-2] = '\0';
return strdup(buf);
}
}
这是我正在执行以执行包含命令的字符串的函数,它的返回值是指向包含该命令输出的字符串的指针,我如何使用该输出作为使用 execvp 的新命令的输入或exec 家族的另一个功能?
Edit2:所以我创建了一个新函数,它接收两个字符串作为参数并执行第一个字符串,然后执行第二个字符串,使用第一个 exec 的输出作为输入,我认为它与 ls | 一起工作正常 head -1 和 ls 的其他变体,但是当我执行类似 ls | sort -R 它不起作用,我尝试了几件事,但我不明白为什么会这样,这是代码:
char* execStrings (char previousstring[], char string[]){
int link[2];
pipe(link);
if (fork() == 0){
int i = 0;
char *previouscommand[spacecount(previousstring)+2];
char *temp = strtok(previousstring," ");
while(temp){
previouscommand[i++] = temp;
temp = strtok(NULL," ");
}
previouscommand[i] = NULL;
dup2(link[1],1); /* stdout result redrecting to write end of pipe */
close(link[1]);
close(link[0]);
execvp(previouscommand[0],previouscommand);
} else {
wait(NULL);
int res[2];
pipe(res);
if(fork() == 0){
int i = 0;
char *temp = strtok(string," ");
char *command[spacecount(string)+2];
while(temp){
command[i++] = temp;
temp = strtok(NULL," ");
}
command[i] = NULL;
dup2(link[0],0);
close(link[0]);
close(link[1]);
dup2(res[1],1);
close(res[1]);
close(res[0]);
execvp(command[0],command)
} else {
wait(NULL);
close(res[1]);
char buf[512];
int i = 0;
while (read(res[0],&buf[i++],1) == 1);
close(res[0]);
buf[i-2] = '\0';
return strdup(buf);
}
}
}
解决方案
你想做一些类似的事情,ls | sort
但你做的方式喜欢
char *arg[] = {"ls","|","sort",NULL};
execvp(arg[0],arg); /*it won't work */
将不起作用,因为您在这里调用execvp
并且ls
这sort
是两个独立的进程而不是单个进程。还
ls | sort => output of process-1 make as input to process-2 & execute it
| |
process-1 process-2
为了实现上述创建两个进程,通过调用fork()
和使用exec()
family函数来替换ls
和sort
在子进程和父进程中。
这是示例代码
int main(void) {
int p[2];
pipe(p);
char *arg[] = {"ls","sort",NULL};
if(fork()==0) {
close(0);/* close the stdin stream so that this
process shoulbn't read from stdin */
dup(p[0]);/* read from read end of pipe */
close(p[1]);
execlp(arg[1],arg[1],(char*)NULL);
}
else{
close(1);/* close the stdout stream, so that o/p shouldn't print on monitor */
dup(p[1]); /* stdout result redrecting to write end of pipe */
close(p[0]);
execlp(arg[0],arg[0],(char*)NULL);
}
return 0;
}
推荐阅读
- html - 为什么我在输入电子邮件时没有显示我的订单状态?
- asp.net-mvc-5 - CS0012 类型“XtraReport”在未引用的程序集中定义
- c# - 当玩家移动时需要帮助退出 IEnumerator
- python-3.x - 在数据帧的所有元素中的特定位置插入子字符串(Python)
- php - Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpExceptionsgr
- c++ - 使用 Boost.Spirit X3 解析 CSS
- python - 在没有 for 循环的 Mako 模板中调用 json
- ruby-on-rails - 尝试在 Rails 5.2 中显示来自 ActiveStorage 的图像时出错
- android - 将 SDK 从 pc1 复制并粘贴到 pc2
- python - 散景:数据表和点击工具不能一起工作