shell重定向小记

简介: 对于int型的,使用open,write,read,close操作,对于FILE*型的使用fopen,fwrite,fread,fclose操作 标准输入,int fd = 0,int fd = STDIN_FILENO,FILE *f = stdin,...

对于int型的,使用open,write,read,close操作,对于FILE*型的使用fopen,fwrite,fread,fclose操作


标准输入,int fd = 0,int fd = STDIN_FILENO,FILE *f = stdin,shell重定向标准输入使用"<",比如./hello <words.txt,那么hello可以从fd=0或者f=stdin里面读取words.txt文件中的内容,平时都是./hello words.txt这样,可以从argv[1]中读取文件名,然后再open/read/close。


有种特殊的情况是这样的,不一定需要使用EOF,任意单词都可以,首尾相同:

$ cat <<EOF
> hello
> world
> EOF
hello
world
$ cat >tmp <<EOF
hello
world
EOF

$ cat tmp
hello
world


有些程序可以接收参数"-",表示从标准输入中读取文件内容


标准输出,int fd = 1,int fd = STDOUT_FILENO,FILE *f = stdout,shell重定向标准输出使用">"(覆盖方式),或者">>"(append方式),">"和">>"前面的默认数字是"1",比如:

$ echo hello 1> tmp
$ echo world > tmp
$ cat tmp
world
$ echo hello >>tmp
$ echo world >>tmp
$ cat tmp
world
hello
world


错误输出,int fd = 2,int fd = STDERR_FILENO,FILE *f = stderr,shell重定向错误输出使用"2>"(覆盖方式),或者"2>>"(append方式),和标准输出类似,注意使用">"对错误输出无效:

$ cat <<EOF >x.c
> #include <stdio.h>
> int main(void)
> {
>     write(2,"hello world\n",12);
>     return 0;
> }
> EOF
$ gcc -o x x.c
$ ./x >tmp
hello world
$ ./x 2>tmp
$ ./x 2>tmp
$ cat tmp
hello world
$ ./x 2>>tmp
$ cat tmp
hello world
hello world
并不一定是2这个数字,而是指错误输出,例如:

$ cat <<EOF >x.c
> #include <stdio.h>
> #include <unistd.h>
> int main()
> {
>     int fd = dup(2);
>     write(fd,"hello world\n",12);
>     return 0;
> }
> EOF
$ gcc -o x x.c
$ ./x >/dev/null 2>&1
$


有时候常用到"2>&1"这种,是将错误输出重定向到标准输出,为什么要加"&"呢,因为不加就会重定向到一个名为"1"的文件

如果标准输出和错误输出都需要重定向,那么应该先写标准输出的,再写错误输出的:

$ ./x 2>&1 >/dev/null
hello world
$ ./x >/dev/null 2>&1
$
/dev/null就是个垃圾桶,扔进去的都没了,类似还有/dev/zero,从里面可以读出来无数的0


shell 使用"|"将上一条命令的标准输出,作为下一条命令的标准输入,例如:

$ cat x.c
#include <stdio.h>
int main(void)
{
    write(2,"hello world\n",12);
    return 0;
}
$ cat x.c | grep return
    return 0;


可以使用proc看到每个进程打开了多少fd,以及fd打开的是谁(self可以替换为具体的pid):

$ cd /proc/self/fd
$ ls -l
total 0
lrwx------ 1 xxxxxx users 64 Mar  7 22:31 0 -> /dev/pts/0
lrwx------ 1 xxxxxx users 64 Mar  7 22:31 1 -> /dev/pts/0
lrwx------ 1 xxxxxx users 64 Mar  7 22:31 2 -> /dev/pts/0
lrwx------ 1 xxxxxx users 64 Mar  7 22:46 255 -> /dev/pts/0


每一个终端都对应/dev/pts下面的一个文件,向对应的文件写入数据,那么将会显示在我们的终端上面,也可以和别的用户打招呼,如果你sudo的话:

$ cd /dev/pts/
$ ls -l
total 0
crw--w---- 1 xxxxxx  tty  136,  0 Mar  7 23:21 0
crw--w---- 1 root        tty  136, 12 May 27  2015 12
crw--w---- 1 root        tty  136,  9 May 18  2015 9
$ echo hello >0
hello


还有个比较有意思的就是pipe文件,注意ls -l显示出的文件类型为"p":

$ mkfifo mypipe
$ ls -l mypipe
prw-r--r-- 1 xxxxxx users 0 Mar  7 23:24 mypipe

可以一个进程将输出写到mypipe,另一个进程从mypipe文件读取第一个进程输出的内容,


甚至可以这样玩,先在一个终端上启动nc服务器:

tree@iZ28dbdyyxuZ:~$ nc -lvnp 8888
Listening on [0.0.0.0] (family 0, port 8888)
Connection from [127.0.0.1] port 8888 [tcp/*] accepted (family 2, sport 55010)
另一个终端使用pipe文件,将bash的标准输出给nc的标准输入,nc的标准输出给bash的标准输入:

/bin/bash <mypipe | nc localhost 8888 >mypipe

这样的话,就可以在第一个终端,输入shell命令了,控制了第二个终端所在的机器


关于time,你没法重定向time的输出:

$ time ls
log  mypipe  x  x.c

real    0m0.002s
user    0m0.000s
sys     0m0.000s
$ time ls >/dev/null 2>&1

real    0m0.002s
user    0m0.000s
sys     0m0.000s

因为time是shell builtin的命令,重定向是由shell自己来处理的,使用time命令的时候,重定向的东西被当做普通参数了。所以time得到的argv={"ls", ">/dev/null", "2>&1"},而不是{"ls"}

如果是普通的程序,比如/usr/bin/time,重定向的东西就是重定向,没法被当做普通参数,所以/usr/bin/time可以被重定向掉:

$ /usr/bin/time ls
log  mypipe  x  x.c
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3840maxresident)k
0inputs+0outputs (0major+298minor)pagefaults 0swaps
$ /usr/bin/time ls >/dev/null
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3840maxresident)k
0inputs+0outputs (0major+298minor)pagefaults 0swaps
$ /usr/bin/time ls >/dev/null 2>&1



目录
相关文章
|
6月前
|
Shell 数据处理
Shell编程中,输入/输出重定向和管道
Shell编程中,输入/输出重定向和管道
44 2
|
6月前
|
数据挖掘 Shell
在Shell中,标准输出重定向
在Shell中,标准输出重定向
67 1
|
1月前
|
Unix Shell Linux
Shell 输入/输出重定向
10月更文挑战第4天
21 8
|
5月前
|
Unix Shell Linux
Shell 重定向:控制数据流向的艺术
在Unix/Linux中,Shell提供输入输出重定向来灵活控制数据流。了解和运用重定向能提升Shell效率。标准输入(0)、输出(1)和错误输出(2)是基础。`&gt;`用于覆盖输出,`&gt;&gt;`用于追加,而`&lt;`用于改变输入源。错误输出可单独重定向,如`2&gt;`或`2&gt;&gt;`。组合使用如`2&gt;&1`可合并输出和错误到同一文件。输入重定向示例:`cat &lt;&lt;END`读取直到`END`。掌握这些,可高效管理命令输出。
48 0
|
6月前
|
Shell
shell 命令(一)概述【别名、 bash重定向 、定义变量】
shell 命令(一)概述【别名、 bash重定向 、定义变量】
58 0
|
6月前
|
Unix Shell Linux
在Unix/Linux Shell中,管道(`|`)和重定向
在Unix/Linux Shell中,管道(`|`)和重定向
91 1
|
6月前
|
Shell
在Shell中,您可以同时重定向标准输出(STDOUT)和错误输出(STDERR)
在Shell中,您可以同时重定向标准输出(STDOUT)和错误输出(STDERR)
462 1
|
6月前
|
Shell 数据处理
shell的重定向
shell的重定向
97 2
|
6月前
|
机器学习/深度学习 Unix Shell
Shell编程基础入门(Bash|变量与输入输出重定向2&1)
Shell编程基础入门(Bash|变量与输入输出重定向2&1)
119 0