为何int ret=system("cmd") 不能返回正确的返回值。

acange 2007-08-26 11:19:47

在linux 下面, 在一般的shell下,比如我运行一个命令。
machine$ ls /tm
/bin/ls: /tm: No such file or directory
machine$ echo $?
1
machine$


如果我把这个命令用system("ls /tm"); 为何我不能得到返回值1啊?


iclx012$ more dun.c
#include <unistd.h>
#include <iostream>

using namespace std;
int
main( int argc, char **argv )
{
int ret;

ret = system("ls /tm");

cout<<"ret="<<ret<<endl;
exit( ret );
}

iclx012$ g++ dun.c
iclx012$ ./a.out
ls: /tm: No such file or directory
ret=256
iclx012$ echo $?
0
iclx012$


有什么办法在我的程序里面得到我运行的命令的返回值啊?
分有的是。
...全文
966 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
dai_weitao 2007-08-30
  • 打赏
  • 举报
回复
system函数的返回值是终止状态+信号编号的值.
acange 2007-08-30
  • 打赏
  • 举报
回复
我 为什么不能揭帖阿.
老说我的 密码有问题. 明明是对的.
漂流的代码 2007-08-29
  • 打赏
  • 举报
回复
来了兴趣了,写个类似popen的函数,mypopen:

#include <stdio.h>
#include <unistd.h>

FILE* mypopen(const char *cmdstring,const char* strtype)
{
int btype; // read
int pfd[2];
pid_t pid;

if(cmdstring==NULL || strtype==NULL)
return NULL;

if(*strtype=='r' || *strtype=='R')
btype=0;
else if(*strtype=='w' || *strtype=='W')
btype=1;

pipe(pfd);

if((pid=fork())==0) //child
{
if(btype==0) // parent whild read
{
close(pfd[0]); //close the child read,
dup2(pfd[1],1);
dup2(pfd[1],2);
}
else
{
close(pfd[1]); //close the child write
dup2(pfd[0],0);
}
execlp(cmdstring,cmdstring,0); //这里,真正的写法应当分析cmdstring,
//例如cmdstring="ls -la",则实际调用是 execlp("ls","ls","-la",0);
}
else
{
int fd;
if(btype==0) //read
{
close(pfd[1]);
fd = pfd[0];
}
else
{
close(pfd[0]);
fd = pfd[1];
}
return fdopen(fd,strtype);
}
}
漂流的代码 2007-08-29
  • 打赏
  • 举报
回复
popen函数是专门解决这类问题的。

对于以stdin和stdout为输入输出的程序,popen创建一个管道,fork一个子进程,关闭管道不使用的端,exec一个shell执行该命令,等待命令的终止。

FILE* popen(const char* cmdstring,const char* type);

如果是type等于"r",则通过返回的FILE*可以阅读cmdstring输出的数据;
如果type等于"w",则通过返回的FILE*可以向cmdstring写入数据

例子如下:

#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>

int main(int argc,char*argv[])
{
char szline[256];
FILE *fin;
if(argc!=2)
{
printf("usage: %s command\n",argv[0]);
return 0;
}

if((fin=popen(argv[1],"r"))==NULL)
{
printf("the command %s not exist\n",argv[1]);
return 0;
}

while(fgets(szline,sizeof(szline)-1,fin)!=NULL)
{
printf("frome command:%s",szline);
}

pclose(fin);

return 0;
}
hifrog 2007-08-27
  • 打赏
  • 举报
回复
《UNIX环境高级编程》这本书写的不错,看了这本书的system函数一节就明白了。
acange 2007-08-27
  • 打赏
  • 举报
回复
有没有人补充?
WaterWalker 2007-08-27
  • 打赏
  • 举报
回复
cout << "ret=" << WEXITSTATUS(ret) << endl;
hzcpig 2007-08-27
  • 打赏
  • 举报
回复
The return value is `-1' if it wasn't possible to create the shell process, and otherwise is the status of the shell process. *Note Process Completion::, for details on how this status code can be interpreted.
acange 2007-08-27
  • 打赏
  • 举报
回复
看来还是在Linux版里面有高手阿.
我在C语言版里面没有得到这么好的回答.

多谢了.
我会最近马上接铁.
pacman2000 2007-08-27
  • 打赏
  • 举报
回复
因为system()返回的结果分两个部分,前面是命令的返回值,后面是运行因为信号终止时的信号值。所以要/256就是这个原因。
hzcpig 2007-08-27
  • 打赏
  • 举报
回复
测试代码:
#include <stdio.h>

int main()
{
char st;
int ret;

ret = system("exit 0");
printf("ret = %d\n", ret/256);

ret = system("exit 1");
printf("ret = %d\n", ret/256);

ret = system("exit 2");
printf("ret = %d\n", ret/256);

ret = system("exit 3");
printf("ret = %d\n", ret/256);

ret = system("exit 4");
printf("ret = %d\n", ret/256);

return 0;
}

结果:
ret = 0
ret = 1
ret = 2
ret = 3
ret = 4

可见,ret/256应该就是你要的结果....不过不知道为什么要除以256,仅供参考....
core 2007-08-27
  • 打赏
  • 举报
回复
int ret = system("ls /tmp");
printf("ret = %d\n", WEXITSTATUS(ret));
hzcpig 2007-08-26
  • 打赏
  • 举报
回复
mark
acange 2007-08-26
  • 打赏
  • 举报
回复
Avoid: 你的回帖没有理解我的意思。 我说得不太明白吗?

我的问题是为什么我在用 system("ls /tm")会得到另一个结果 (不是1). 有什么办法(比如用别的函数), 我可以得到和我在shell下运行一样的返回值.

Avoid 2007-08-26
  • 打赏
  • 举报
回复
pwd确定路径,然后加到/tm前
acange 2007-08-26
  • 打赏
  • 举报
回复
我上面给的是个列子。
/tm 不在根目录下, 所以如果我直接运行 "ls /tm", 它的exit code 是1
但是如果我在 system("ls /tm") 返回的不是 1, 而是另外的数字。

有什么办法在我的程序里面得到我运行的命令的返回值啊?
分有的是。
Avoid 2007-08-26
  • 打赏
  • 举报
回复
/tm这个目录你确定在根目录下?

如果不是,那么写全目录
cceczjxy 2007-08-26
  • 打赏
  • 举报
回复
exit时,退出状态码只能是一个字节,超过部分被截取.
在父进程获取其状态时,把这个字节的数据放在了低地址第二个字节位置了.这些都是对补码操作的.

因此,exit (-1) 和exit (255)时,父进程获取的状态码是一样的,你无法区分.


因此,我们一般只根据退出状态为0或则非0来判断成功或失败,而不做进一步的区分.

hifrog 2007-08-26
  • 打赏
  • 举报
回复
system函数是由fork、execve和waitpid三个系统调用实现的。
所以如果execve出错,则直接调用_exit(256),所以变量ret的值等于256
在system函数执行时,会启动一个子进程运行shell,然后通过将ls /tm作为参数传给shell,如果shell命令运行有错,就调用exit XXX作为system的返回值返回,而XXX是system函数的返回值,而不是shell运行ls /tm后的返回值。

23,120

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧