LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 682|回复: 8

再问关于重定向(非重复贴,却是遇到问题了)

[复制链接]
发表于 2004-7-18 07:15:11 | 显示全部楼层 |阅读模式
stdout 重定向已经成功了。

但 stderr 却无论如何无法定向(看不到输出),

大侠们帮忙看看啊,调了好几天也没调通。  55555~~~

另:我已经测试过, rm用stderr进行输出。rm test.txt 2>a.txt,可以看到a.txt里有rm的提示信息

如果那位大侠有完全控制子进程IO的例子那就更好了。谢谢。


  1. #include        <sys/wait.h>
  2. #include        <errno.h>
  3. #include        <fcntl.h>
  4. #include <stdio.h>


  5. #define STDIN 0
  6. #define STDOUT 1
  7. #define STDERR 2


  8. void os_stdio_status(int s, int *readable, int *writeable, int *error)
  9. {
  10.         fd_set set;
  11.         struct timeval tv;
  12.         tv.tv_sec = 0;
  13.         tv.tv_usec = 0;
  14.         if(readable)
  15.         {
  16.                 FD_ZERO(&set);
  17.                 FD_SET(s, &set);
  18.                 select(s + 1, &set, NULL, NULL, &tv);
  19.                 *readable = FD_ISSET(s, &set);
  20.         }

  21.         if(writeable)
  22.         {
  23.                 FD_ZERO(&set);
  24.                 FD_SET(s, &set);
  25.                 select(s + 1, NULL, &set, NULL, &tv);
  26.                 *writeable = FD_ISSET(s, &set);
  27.         }
  28.         if(error)
  29.         {
  30.                 FD_ZERO(&set);
  31.                 FD_SET(s, &set);
  32.                 select(s + 1,  NULL, NULL, &set, &tv);
  33.                 *error = FD_ISSET(s, &set);
  34.         }
  35. }


  36. void my_run(char *command)
  37. {
  38.         /*  Define gints arrays to ref pipes */
  39.         int    stdin_pipe[2];
  40.         int    stdout_pipe[2];
  41.         int    stderr_pipe[2];

  42.         /*  Define buffs to copy your reads from the pipes to */
  43.         char buffer[BUFSIZ+1];
  44.         char buffer_err[BUFSIZ+1];

  45.         /* Def some vars to hold your results */
  46.         int fork_result;
  47.         int data_processed;
  48.         int data_processed_err;
  49.         int nchars=0;
  50.         int readable, writeable, error;
  51.        
  52.         /* Clear Your Buffers */
  53.         memset(buffer, '\0', sizeof(buffer));
  54.         memset(buffer_err, '\0', sizeof(buffer_err));

  55.         buffer[0] = 0;
  56.         buffer_err[0] = 0;
  57.         /* Do the fork and pipe - watch closely here */

  58.         /* Create pipes to read from and write too */
  59.         if( (        pipe(stdin_pipe) == 0)
  60.                 && (pipe(stdout_pipe) == 0)
  61.                 && (pipe(stderr_pipe) == 0)
  62.           )
  63.         {
  64.                 /* Perform the fork */
  65.                 fork_result = fork();

  66.                 /* fork attempt was not successful */
  67.                 if(fork_result == -1)
  68.                 {
  69.                         //fprintf(stderr, "Fork Failure\n");
  70.                         exit(-1);
  71.                 }

  72.                 /*  We're in the child process! */
  73.                 else if(fork_result == 0)
  74.                 {
  75.                         /* Close the Child process' STDIN */
  76.                         close(0);

  77.                         /* Duplicate the Child's STDIN to the stdin_pipe file descriptor */
  78.                         dup(stdin_pipe[0]);

  79.                         /* Close the read and write to for the pipe for the child.  The child will now only be able to read from it's STDIN (which is our pipe). */
  80.                         close(stdin_pipe[0]);
  81.                         close(stdin_pipe[1]);

  82.                         /* Close the Child process' STDOUT */
  83.                         close(1);
  84.                         dup(stdout_pipe[1]);       
  85.                         close(stdout_pipe[0]);
  86.                         close(stdout_pipe[1]);

  87.                         /* Close the Child process' STDERR */
  88.                         close(2);
  89.                         //dup(stdout_pipe[1]);
  90.                         dup(stderr_pipe[1]);
  91.                         close(stderr_pipe[0]);
  92.                         close(stderr_pipe[1]);

  93.                         /*  Make the exec call to run the javac program. */
  94.                         //execlp("javac","javac", "-d", codemonkey->current->class_path, codemonkey->current->file_name, (char *)0);
  95.                         //execlp(program,program, arg1, (char *)0);
  96.                         execl("/bin/sh", "sh", "-c", command, NULL);

  97.                         /*  If javac didn't take over the exec call failed. */
  98.                         exit(-1);
  99.                 }

  100.                 /* We're in the parent process. */
  101.                 else
  102.                 {
  103.                         // Close STDIN for read & write and close STDERR for write
  104.                         //close(stdin_pipe[0]);
  105.                         //close(stdin_pipe[1]);
  106.                         //close(stderr_pipe[0]);
  107.                         //close(stderr_pipe[1]);
  108.                        
  109.                         
  110.                         //close(stdin_pipe[0]);
  111.                         close(stderr_pipe[1]);
  112.                         close(stdout_pipe[1]);
  113.                        
  114.                         while(1)
  115.                         {

  116.                                                                
  117.                                 os_stdio_status(stderr_pipe[0], &readable, NULL, &error);
  118.                                 if(error)
  119.                                 {
  120.                                         //puts("stderr ERROR!!!!!!!!!!!!!!!!!!");
  121.                                         //break;
  122.                                 }
  123.                                 if(readable)
  124.                                 {
  125.                                         //puts("stderr readable");
  126.                                         data_processed_err=read(stderr_pipe[0],buffer_err,BUFSIZ);
  127.                                         if(data_processed_err >0 )
  128.                                                 write(STDOUT, buffer_err, data_processed_err);
  129.                                         //if(data_processed_err == 0) break;
  130.                                 }
  131.                                
  132.                                
  133.                                
  134.                                 os_stdio_status(stdout_pipe[0], &readable, NULL, &error);
  135.                                 if(error)
  136.                                 {
  137.                                         //puts("stdout ERROR!!!!!!!!!!!!!!!!!!");
  138.                                         //break;
  139.                                 }
  140.                                 if(readable)
  141.                                 {
  142.                                         //puts("stdout readable");
  143.                                         data_processed=read(stdout_pipe[0],buffer,BUFSIZ);
  144.                                         if(data_processed >0 )
  145.                                                 write(STDOUT, buffer, data_processed);
  146.                                         //if(data_processed == 0) break;
  147.                                 }
  148.                                
  149.                                
  150.                                 /*
  151.                                 os_stdio_status(stdin_pipe[1], NULL, &writeable, &error);
  152.                                 if(error)
  153.                                 {
  154.                                         puts("stdin ERROR!!!!!!!!!!!!!!!!!!");
  155.                                         break;
  156.                                 }                               
  157.                                 if(writeable)
  158.                                 {
  159.                                         puts("stdin writeable");
  160.                                         write(stdin_pipe[1], getchar(), 1);
  161.                                         //data_processed=read(stdout_pipe[0],buffer,BUFSIZ);
  162.                                         //write(STDOUT, buffer, data_processed);
  163.                                         //if(data_processed == 0) break;
  164.                                 }
  165.                                 */
  166.                         }
  167.                         /* Close the read end of STDERR */
  168.                         close(stderr_pipe[0]);
  169.                         /* Close the write end of STDOUT */
  170.                         close(stdout_pipe[1]);
  171.                         /* Close STDOUT for reading */
  172.                         close(stdout_pipe[0]);
  173.                 }
  174.         }
  175.         return;
  176.         /* THE END */
  177. }


  178. int main()
  179. {
  180.         system("ls > test.txt");
  181.         my_run("rm test.txt");      //这个总是有问题。
  182.         //my_run("ls *.gz");       //这个完全可以了
  183. }

复制代码
发表于 2004-7-18 07:59:24 | 显示全部楼层
用[php]会对'\0'产生转义解释,改成用[code]保持缩进。
发表于 2004-7-18 08:42:34 | 显示全部楼层
代码结构不清晰,仅看代码不可能搞清楚你的目的是什么?
我感觉你好象是要做一个shell。
 楼主| 发表于 2004-7-18 14:03:26 | 显示全部楼层
基本是这样的。


目的就是完全控制子进程的输入(stdin)和输出(stdout/stderr)


不知道到底应该怎样实现,哎!
发表于 2004-7-18 16:40:46 | 显示全部楼层
呵呵,你的程序在逻辑上已经乱了。
我写个小例子给你看看吧:

  1. /* 本程序把rm -i testfile的执行结果(包括正常输出和错误输出)重定向到temp文件 */
  2. #include <fcntl.h>
  3. #include <strings.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <stdio.h>


  7. int main()
  8. {
  9.         int fd;
  10.         pid_t pid;
  11.        
  12.         fd = open("temp",O_WRONLY|O_CREAT|O_TRUNC,0777);
  13.         if (pid = fork() == 0) {
  14.                 close(1);
  15.                 dup(fd);
  16.                 close(2);
  17.                 dup(fd);
  18.                 execlp("rm","rm","-i","testfile",0);
  19.                 perror("rm:");
  20.                 exit(1);
  21.         }
  22.        
  23.         wait(NULL);
  24.         exit(0);       
  25. }
复制代码


下面是执行结果:
[kj501@s2023 c]$ touch testfile
[kj501@s2023 c]$ ./a.out
y
[kj501@s2023 c]$ cat temp
rm:是否删除一般空文件‘testfile’?
[kj501@s2023 c]$ ./a.out
[kj501@s2023 c]$ cat temp
rm: lstat‘testfile’失败: No such file or directory
[kj501@s2023 c]$

你可以很清楚地看到,重定向不一定要用管道,关键是对文件描述符的作用要理解清楚。
发表于 2004-7-19 11:17:51 | 显示全部楼层
楼主,我有一疑问
close+dup这种方式能保证文件描述符一定复制到了你想要的位置吗?
根据man dup:
dup uses the lowest-numbered unused descriptor for the new  descriptor.
这一点是值得怀疑的,改用dup2试试?

<<UNIX环境高级编程>>中有很多与你程序类似的例子
发表于 2004-7-19 16:06:21 | 显示全部楼层
楼上的兄弟不用担心,在重定向时这样做是可以的。
重定向就是改变0,1,2这三个文件描述符,这三个文件描述符差不多是最小的。关闭掉其中一个,再马上dup,得到的文件描述符就应该正好是刚才关闭的文件描述符。比如说关闭掉文件描述符1,再dup(fd)时,此时最小的还没有使用的文件描述符不就是1吗?自然结果就是把fd复制到1了。
 楼主| 发表于 2004-7-20 09:11:59 | 显示全部楼层
终于知道rm test.txt没有提示的原因了。

eg:
控制台下: [chice@urwish chice]$rm test.txt 会有提示寻问是否删除。
但如果     [chice@urwish chice]$sh -c "rm test.txt"就没有提示了。当然不会有输出返回。


谢谢大家帮忙!

特别感谢斑竹多次出手相救    ^_^
发表于 2004-7-20 10:45:16 | 显示全部楼层
噢,多谢 kj501 的解释,我明白了

还有楼上的发现对我很有启发
应该 sh -c "rm -i a.out"就对了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表