bash标准输出及文件重定向

标准输入输出

在Linux中,每个进程都会有三个文件,即打开的输入输出流,也叫标准I/O流。

并且这三个文件会进行重定向处理,标准输入(STDIN)对应的是键盘输入,

标准输出(STDOUT)、标准错误输出(STDERR)对应的是屏幕。

进程启动后,打开的进程描述符是从0开始依次递增的,所以前3个

对应的文件描述符为STDIN_FILENO(0),STDOUT_FILENO(1),STDERR_FILENO(2)

比如在Golang编程语言中,标准输入、标准输出、标准错误输出的定义如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
// standard output, and standard error file descriptors.
//
// Note that the Go runtime writes to standard error for panics and crashes;
// closing Stderr may cause those messages to go elsewhere, perhaps
// to a file opened later.
var (
	Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
	Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
	Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)

syscall.Stdin, syscall.Stdout, syscall.Stderr 对应的定义:

1
2
3
4
5
var (
	Stdin  = 0
	Stdout = 1
	Stderr = 2
)

文件重定向

默认情况下都是输出到终端,可以在程序启动时,自定义的将标准输出、标准错误重定向。

自定义重定向时,文件描述符和重写向符之间不能有空格(比如:0< 之间不能有空格),

程序的执行前,会先检查是否重定向,因此重定向符写在命令前后都可以,比如:

1
2
3
4
5
6
7
cat < file 

cat 0< file 

< file cat 

0< file cat

以上几种写法效果是一样的。

示例程序,读取标准输入字符串,并将字符串输出到标准输出和标准错误:

1
2
3
4
5
6
7
8
9
use std::io::{self, Read};

fn main() {
    let mut input = String::new();
    io::stdin().read_to_string(&mut input).unwrap();

    println!("stdout: '{}'", input.trim());
    eprintln!("stderr: '{}'", input.trim());
}

编译示例程序:

1
rustc hello.rs -o main

标准输入重定向文件

执行示例程序,将标准输入重定向到文件stdin.log

1
2
3
4
5
echo "stdin" > stdin.log

> ./main < stdin.log
stdout: 'stdin'
stderr: 'stdin'

标准输入重定向字符串

执行示例程序,将指定字符串作为标准输入内容

1
2
3
> ./main <<< "stdin"
stdout: 'stdin'
stderr: 'stdin'

标准输入重定向多行字符串

执行示例程序,将多行字符串作为标准输入内容

1
2
3
4
5
6
> ./main << xxx
stdin
stdin
xxx
stdout: 'stdin'
stderr: 'stdin'

标准输出重定向

command > file(等同 command 1> file)

将标准输出重定向到文件stdout.log

1
2
3
4
5
> ./main < stdin.log > stdout.log
stderr: 'stdin'

> cat stdout.log
stdout: 'stdin'

标准错误输出重定向

command 2> file

将标准输出重定向到文件stderr.log

1
2
3
4
5
6
7
> ./main < stdin.log > stdout.log 2> stderr.log

> cat stdout.log
stdout: 'stdin'

> cat stderr.log
stderr: 'stdin'

标准输出、标准错误重定向同个文件

command &> file (等同 command >& file 或 command > file 2>&1)

将标准输出、标准错误重定向到文件stdout.log

1
2
3
4
5
> ./main < stdin.log &> stdout.log 

> cat stdout.log
stdout: 'stdin'
stderr: 'stdin'

标准输出、标准错误重定向追加写入同个文件

command &» file (等同 command » file 2>&1)

将标准输出、标准错误重定向到文件stdout.log

1
2
3
4
5
6
7
> ./main < stdin.log >> stdout.log 2>&1 

> cat stdout.log
stdout: 'stdin'
stderr: 'stdin'
stdout: 'stdin'
stderr: 'stdin'

忽略标准输出

command &> /dev/null

1
> ./main < stdin.log &> /dev/null

/dev/null是linux中的一个特殊文件,写入其中的数据都会被丢弃,

从其中读取数据会返回EOF。

标准输出及错误输出重定向到指定tcp服务器

先用ncat命令开启一个tcp服务器,监听端口9999:

1
> ncat -l 9999

然后用以下命令,将所有输出都重定向到该服务器:

1
./main < stdin.log &> /dev/tcp/localhost/9999

程序后台运行,并将标准输出重定向文件

nohup command > file &

or

command > file &

使用nohup命令,不指定重定向文件时,默认输出到nohub.out文件。

让程序不受 hangups 信号影响,即忽略所有挂断(SIGHUP)信号。

参考