第三节 管道与重定向

第三节 管道与重定向

管道

严格的说管道属于IO重定向的一部分,但是我们不思考那么多,管道在Shell操作中经常遇到,管道符号是“|”,它是我们在命令与命令之间(或者说进程与进程之间)通信的一种手段,我们先看下原理

在这里插入图片描述

我们实际来操作一下:

>>> ls -l |grep *.png |wc -l #查找当前目录的所有文件中的png文件并输出它们的数量
>>> cat testfile |grep error #过滤某个文件中的包含错误信息的行
重定向
类型文件描述符默认情况对应设备位置
标准输入0从键盘获得输入/dev/stdin
标准输出1输出到控制台/dev/stdout
错误输出2输出到控制台/dev/stderr

1.STDIN

stdin代表shell的标准输入,对终端来说,标准输入就是键盘,默认定向到控制台,当然我们可以使用“<”符号定向到其他地方作为stdin输入(累次开发中的生产消费模式),当然必须注意不是所有的命令都可以接收stdin输入。如下例子:

#测试输入,cat可以接受stdin的输入并把内容打印出来
>>> cat #随便输入点什么

在这里插入图片描述

#将某个文件作为stdin输入给cat命令使用
>>> echo "hello world" > testfile #创建testfile文件并保存一段话
>>> cat < testfile #讲testfile作为cat的输入

另外我们可以使用“<<”进行追加模式的stdin输入,相对于"<",“<<”我们更加常用:

>>> cat >testfile <<EOF #注意"<<"
>你好
>hello world
>EOF
#此时生成一个testfile文件,我们打开它
>>> cat testfile
#没错,这就是上节课的例子

2.STDOUT

stdout代表shell的标准输出,输出到终端显示器,shell和程序的绝大多数输出都是标准输出,默认是输出到控制台,当然我们可以使用“>”重定向到其他地方,">>"是它的追加模式

>>> ls -l #标准输出
>>> ls -l >test1 #输出到test1里面
>>> echo "追加文档到test1" >> test1

3.STDERR

shell对于错误消息的处理和普通的输出是分开的,某些开发写的程序不标准,经常会把标准输出和标准错误输出弄混,然后运维就更辛苦点了。标准错误输出和标准输出一样都是默认输出到控制台的。stderr的默认输出虽然是控制台但是却不会被“>”符号重定向,我们看个例子:

>>> ls -l ajflajfa >testfile #讲ajflajfa文件的属性输出到testfile里面,但是ajflajfa根本不存在
>>> cat testfile #查看文件

实验过后其实会发现stderr的输出不会像stdout那样被重定向到textfile里面,但是在日常工组中,我们会有要求把所有的正常的日志输出,非正常的日志输出都放在一个文件里面

#将标准输出,标准错误输出均输入到一个文件里面
>>> ls -l test1 test2 >testfile 2>&1  #test1存在,test2不存在,或:
>>> ls -l test1 test2 &>testfile #另外一种写法
>>> cat testfile
>>> ls -l test1 test2 2>errout 1>output #错误信息输出到errout 正确的信息输出到output

如下是符号的重定向对比列表

符号说明
>把stdout(标准输出)重定向到文件,文件内容会被覆盖
>>把stdout(标准输出)重定向到文件,内容追加到文件的末尾
2>把stderr(标准错误输出)重定向到文件,文件内容会被覆盖
2>>把stderr(标准错误输出)重定向到文件,内容追加到文件末尾
2>&1或&>把stdout和stderr作为一个数据流重定向到文件,文件内容会被覆盖
&>>把stdout和stderr作为一个数据流重定向到文件,内容追加到文件末尾
<将文件重定为stdin
<<作为stdin输入的文件可以被追加,不过需要使用EOF作为文件的截断符号

重定向在接下来的章节会比较长用到,这里列几个基于管道的命令工具传送门,这些工具可以根据兴趣练习。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Shell是一种用于与操作系统进行交互的命令行界面。下面是一个简单的Shell源代码示例,适用于Minix3操作系统,实现了一些基本功能,包括管道定向、后台运行以及history n显示最近执行的n条命令的功能。 ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define MAX_COMMAND_LENGTH 1024 void execute_command(char* command) { // 检查是否有管道符号,若有则执行管道命令 char* pipe_symbol = strchr(command, '|'); if (pipe_symbol != NULL) { // 若存在管道符号,则将命令分成两个子命令 *pipe_symbol = '\0'; char* command1 = command; char* command2 = pipe_symbol + 1; // 创建管道 int fd[2]; if (pipe(fd) == -1) { perror("Pipe failed"); return; } // 创建子进程执行第一个子命令 int pid1 = fork(); if (pid1 == 0) { // 将标准输出定向到管道的写入端 dup2(fd[1], STDOUT_FILENO); // 执行第一个子命令 execlp(command1, command1, (char*)NULL); perror("Exec failed"); exit(EXIT_FAILURE); } // 创建子进程执行第二个子命令 int pid2 = fork(); if (pid2 == 0) { // 将标准输入定向到管道的读取端 dup2(fd[0], STDIN_FILENO); // 执行第二个子命令 execlp(command2, command2, (char*)NULL); perror("Exec failed"); exit(EXIT_FAILURE); } // 父进程关闭管道的读写端 close(fd[0]); close(fd[1]); // 父进程等待子进程结束 waitpid(pid1, NULL, 0); waitpid(pid2, NULL, 0); } else { // 没有管道符号,直接执行命令 system(command); } } int main() { char command[MAX_COMMAND_LENGTH]; while (1) { printf("Shell> "); fflush(stdout); // 读取用户输入的命令 fgets(command, MAX_COMMAND_LENGTH, stdin); // 去掉输入命令的换行符 strtok(command, "\n"); // 检查是否是history n命令 if (strncmp(command, "history ", 8) == 0) { int n = atoi(command + 8); // TODO: 显示最近执行的n条命令 continue; } // 检查是否是后台运行命令 int is_background_command = 0; if (command[strlen(command) - 1] == '&') { command[strlen(command) - 1] = '\0'; is_background_command = 1; } // 执行命令 execute_command(command); // 如果是后台运行命令,则不等待命令执行完成 if (!is_background_command) { wait(NULL); } } return 0; } ``` 这是一个简化版本的Shell源代码示例,适用于Minix3操作系统。它实现了一些基本的功能,包括管道定向、后台运行以及history n显示最近执行的n条命令。然而,它仍然有很多不足之处,比如对输入命令的解析、错误处理等方面可能不够完善,但它可以作为一个基础的Shell框架,可以根据实际需要进行扩展和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莫慌搞安全

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值