在上一篇文章中,我们讨论了参数和选项详细。今天,我们将讨论 shell 脚本中的一些基本内容,即输入、输出和重定向。
您可以通过两种方式显示 shell 脚本的输出:
标准文件描述符
Linux 中的一切都是文件,包括输入和输出。
每个进程可以同时打开九个文件描述符。文件描述符 0、1、2 保留供 bash shell 使用。
0 STDIN。
1 标准输出。
2 STDERR。
您可以使用上面的文件描述符来控制输入和输出。
您需要完全理解这三者,因为它们就像 shell 脚本的支柱。因此,我们将详细描述它们中的每一个。
STDIN
STDIN代表标准输入,默认就是键盘。
您可以使用输入重定向符号 (
当您不加任何内容地键入 cat 命令时,它会接受来自 STDIN 的输入。您键入的任何行,cat 命令都会将该行打印到屏幕上。
STDOUT
STDOUT代表标准输出,即默认的屏幕。
您可以使用 >> 符号将输出重定向到文件。
如果我们有一个包含数据的文件,您可以使用此符号将数据附加到其中,如下所示:
pwd >> myfile
pwd 生成的输出将附加到文件中,而不删除现有内容。
以下命令尝试使用 > 符号将输出重定向到文件。
ls –l xfile > myfile
我的 PC 上没有名为 xfile 的文件,这会生成发送到 STDERR 的错误。
STDERR
默认情况下,shell 将错误发送到屏幕。
如果您需要将错误重定向到日志文件而不是将其发送到屏幕,则可以使用重定向符号重定向错误。
重定向错误
我们可以通过将文件描述符(2)放在重定向符号之前来重定向错误,如下所示:
ls -l xfile 2>myfile
cat ./myfile
如您所见,现在错误出现在文件中,屏幕上没有任何内容。
重定向错误和正常输出
要重定向错误和正常输出,您必须在每个错误和正常输出之前添加正确的文件描述符,如下所示:
ls –l myfile xfile anotherfile 2> errorcontent 1> correctcontent
ls 命令结果使用以下命令发送到正确的内容文件1>象征。错误消息已使用以下命令发送到 errorcontent 文件2> symbol.
您可以使用以下命令将正常输出和错误重定向到同一文件&>像这样的符号:
ls –l myfile xfile anotherfile &> content
在这里,我们将错误和正常输出重定向到名为 content.txt 的文件。
输出重定向
输出重定向有两种方法:
临时重定向
对于临时重定向,您可以使用 >&2 符号,如下所示:
#!/bin/bash
echo "Error message" >&2
echo "Normal message"
因此,如果我们运行它,我们将看到两行都正常打印,因为众所周知,默认情况下错误会显示在屏幕上。
您可以将错误重定向到如下文件:
./myscript 2> myfile
Shell 脚本太棒了!正常输出被发送到屏幕,而带有 >&2 符号的回显消息将错误发送到文件。
永久重定向
如果您有大量数据需要重定向,可以使用 exec 命令进行永久重定向,如下所示:
#!/bin/bash
exec 1>outfile
echo "Permanent redirection"
echo "from a shell to a file."
echo "without redirecting every line"
如果我们查看名为 outfile 的文件,我们将看到 echo 行的输出。
我们在开头重定向 STDOUT,那么在这样的脚本中间呢:
#!/bin/bash
exec 2>myerror
echo "Script Begining ..."
echo "Redirecting Output"
exec 1>myfile
echo "Output goes to the myfile"
echo "Output goes to myerror file" >&2
exec 命令将所有错误重定向到文件 myerror,并将标准输出发送到屏幕。
我们使用语句 exec 1>myfile 将输出重定向到 myfile 文件,最后,错误使用 >&2 符号转到 myerror 文件。
重定向输入
您可以使用 exec 命令将输入重定向到文件而不是 STDIN,如下所示:
exec 0< myfile
此命令告诉 shell 从名为 myfile 而不是 STDIN 的文件中获取输入,下面是一个示例:
#!/bin/bash
exec 0<testfile
total=1
while read line; do
echo "#$total: $line"
total=$(($total + 1))
done
Shell 脚本编写很简单。
你知道如何使用读命令获取用户输入。如果将 STDIN 重定向到文件,则读取命令将尝试从指向该文件的 STDIN 读取。
一些 Linux 系统管理员使用这种技术来读取日志文件进行处理,我们将讨论更多以专业的方式阅读即将发布的日志的方法。
创建自定义重定向
您知道有九个文件描述符,您只使用其中的 3 个用于输入、输出和错误。
其余六个文件描述符可用于输入和输出重定向。
我们可以使用 exec 命令为输出分配文件描述符,如下所示:
#!/bin/bash
exec 3>myfile
echo "This line appears on the screen"
echo "This line stored on myfile" >&3
echo "This line appears on the screen"
创建输入文件描述符
要重定向输入文件描述符,请执行以下操作:
1- 将 STDIN 保存到另一个文件描述符。
2- 将其重定向到文件。
3- 将 STDIN 恢复到其原始位置。
查看以下代码以了解这些步骤:
#!/bin/bash
exec 7<&0
exec 0<myfile
total=1
while read line; do
echo "#$total: $line"
total=$(($total + 1))
done
exec 0<&7
read -p "Finished? " res
case $res in
y) echo "Goodbye" ;;
n) echo "Sorry, this is the end." ;;
esac
我们将 STDIN 保存到文件描述符 7,并将 STDIN 重定向到文件。
在迭代文件行后,STDIN 恢复到其原始位置。
最后读取命令只是为了确保 STDIN 已恢复,并且可以正常使用键盘。
关闭文件描述符
当脚本退出时,文件描述符将自动关闭。如果您想自己关闭文件描述符,请将文件描述符重定向到该符号&- 它将被关闭。
#!/bin/bash
exec 3> myfile
echo "Testing ..." >&3
exec 3>&-
echo "Nothing works" >&3
正如您所看到的,它给出了错误文件描述符的错误,因为它不再存在。
lsof 命令
The lsof命令用于列出系统上所有打开的文件和后台进程。
在许多 Linux 系统(例如 Fedora)上,lsof 命令位于 /usr/sbin 下。
这是 lsof 命令的一些重要选项:
-p:进程ID。
-d:文件描述符。
您可以使用 $$ 变量获取进程 PID。
我们可以使用 -a 来组合 -p 选项和 -d 选项的结果。
现在,从脚本测试命令:
#!/bin/bash
exec 4> myfile1
exec 5> myfile2
exec 6< myfile3
lsof -a -p $$ -d 0,1,2,4,5,6
shell 脚本创建文件描述符 4 和 5 用于写入,文件描述符 6 用于读取。
抑制命令输出
有时您不想看到任何输出。我们将输出重定向到黑洞,这是/dev/空.
例如,我们可以抑制这样的错误:
ls -al badfile anotherfile 2> /dev/null
您可以使用相同的命令截断文件而不完全删除它。
cat /dev/null > myfile
现在您了解了输入和输出、如何重定向它们、如何创建文件描述符并重定向到它。