Shell 输入/输出重定向

Unix/Linux系统每个命令运行时都会打开三个文件:

  • 标准输入设备(stdin):stdin文件描述符为0,默认从stdin读取数据。
  • 标准输出设备(stdout):stdout 文件描述符为1,默认向stdout输出数据。
  • 标准错误设备(stderr):stderr文件描述符为2,默认向stderr写入错误信息。

终端命令模式下标准输入/输出设备就你的终端屏幕。

输入/输出重定向指的是将输入/输出设备指向非标准设备,如文件等

重定向方式如下:

方式说明
command > file将命令输出重定向到文件(覆盖式),如:echo 'abc' > a.txt
command >> file将命令输出重定向到文件,但是以内容追加方式
command < file将命令输入重定向到文件
n > file将文件描述符为 n 的文件重定向到 file。
n >> file将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m将输出文件 m 和 n 合并。
n <& m将输入文件 m 和 n 合并。
<< tag将开始标记 tag 和结束标记 tag 之间的内容作为输入,常用于交互式脚本输入

输出重定向示例:

执行下面的 who 命令,它将命令的完整的输出重定向在用户文件中(users):

# 将命令echo结果输出到a.txt文件,如果文件不存在则新建
$ echo "new out chars" > a.txt

# 将命令ps结果输出追加到a.txt
$ ps -ef|grep java >> a.txt
$ cat a.txt 
new out chars
oper       311     1  0 8月01 ?       00:02:42 /usr/local/jdk1.8/bin/java -server -Xms386m -Xmx786m -jar biz.jar
oper       312     1  0 8月01 ?       00:03:26 /usr/local/jdk1.8/bin/java -server -Xms386m -Xmx786m -jar mch.jar
oper       431     1  0 8月01 ?       00:02:57 /usr/local/jdk1.8/bin/java -server -Xms386m -Xmx786m -jar admin.jar

命令执行后并没有在终端输出信息,这是因为输出已被从默认的标准输出设备重定向到指定的文件。

将命令错误输出重定向到文件:command 2>file

[oper@test96 ~]$ wc -a c.txt 
wc:无效选项 -- a
Try 'wc --help' for more information.
[oper@test96 ~]$ wc -a 2>c.txt 
[oper@test96 ~]$ cat c.txt 
wc:无效选项 -- a
Try 'wc --help' for more information.

将 stderr和 stdout 合并后重定向到 file

 command > file 2>&1

记忆提示:先理解1是标准输出,2个标准错误输出,&是合并的意思,2>&1可以读作2大与1

输入重定向示例:

统计文件行数

[oper@test96 ~]$ wc -l b.txt 
14 b.txt
[oper@test96 ~]$ wc -l < b.txt 
14

注意:上面两个例子的结果不同:第一个命令,会输出文件名,第二个不会,因为文件内容被重定向到了标准输入,命令读取内容是从标准输入读取所以没有文件名

同时重定向输入和输出

command1 < infile > outfile

执行command1,从文件infile读取内容,然后将内容写入到outfile中

如果希望将 stdout 和 stderr 合并后重定向到file,可以这样写:

$ command > file 2>&1
或者
$ command >> file 2>&1

java程序后台启动命令示例:

nohup java -jar xx.jar >> out.log 2>&1 &

输入重定向到交互式shell 脚本或程序, 如脚本中需要执行sudo命令时,因为sudo命令是需要输入密码的,此时就可以利用该重定向方式实现提前输入密码。

它的命令形式如下:

command << delimiter
    document
delimiter

将两个 delimiter 之间的内容作为输入传递给 command,delimiter通用使用EOF符号.

示例:

sudo -S sh xxx.sh <<EOF
>password
>EOF

shell脚本进入mysql client 并执行sql语句

#!/bin/bash
#连接mysql数据库,并查询结果,将结果输出到文件中
mysql_u="root"
mysql_p="123123"
result_file="/home/result.sql"

echo "开始链接数据库..."

result=`mysql -u$mysql_u -p$mysql_p<< EOF 
use db1;
select * from user where a='b';
quit
EOF`

if [ $? = 0 ]
then
    echo "连接成功。。。"
else
    echo "连接失败。。。"
exit
fi
echo "写入查询结果..."
echo "$result" > $result_file
echo "写入完成..."

/dev/null 文件

/dev/null 是一个特殊的空设备文件,写入到它的内容都会被丢弃, 因此将命令输出重定向到/dev/null相当于忽略任何输出

$ command > /dev/null
$ command > /dev/null 2>&1

利用/dev/null清空文件内容:

cat /dev/null > access.log