“exec 1>/var/opt/log/my_logs/MYPROG_`date '+%Y%m%d_%H%M%S'`.log 2>&1”有什么作用?

IA3*_*A39 3 command-line bash scripts execute-command

我试图了解下面的 shell 脚本在做什么。我知道没有任何参数的 exec 会重定向当前 shell 的输出,但无法理解以下命令的作用:

exec 1>/var/opt/log/my_logs/MYPROG_`date '+%Y%m%d_%H%M%S'`.log 2>&1
Run Code Online (Sandbox Code Playgroud)

Ser*_*nyy 8

实际上有 4 个重要的信息正在发生:

  1. exec内置的用于将所有输出的命令行会话重定向到文件

  2. 1><FILENAME>告诉shell重定向stdout标准流,即命令的正常的非错误输出会去<FILENAME>。该>会创建如果<FILENAME>不存在,或截形,如果<FILENAME>已经存在。

  3. 重定向的文件名是通过使用date '+%Y%m%d_%H%M%S'命令添加反引号创建的。反引号是命令替换的$(date '+%Y%m%d_%H%M%S')形式, 在功能上等同于形式,现在$(...)由于可读性而首选,因为这种形式可以轻松嵌套(即具有多个级别)。因此,date具有指定格式的输出'+%Y%m%d_%H%M%S'将创建带有 时间戳的文件名。如果您的命令在 2018 年 7 月 4 日 4:20:20 运行,则输出将为/var/opt/log/my_logs/MYPROG_20180704_042020.log.

  4. 2>&1也将stderr流重定向到该文件,它是一个标准的、符合 POSIX 的(这意味着除了bash理解它之外的类似 Bourne 的 shell )形式。这在功能上等同于&>特定bash 的语法。shell 中指定重定向的顺序很重要,因此在1>重定向后会出现这种情况。

总之,该命令本身不应该有任何输出。它应该只重新连接所有连续命令的两个输出流以进入您指定的文件。

有趣的是,使用此命令,我将bash 4.4所有内容输出到文件中,其中包括提示和我键入的任何内容(所以在这里我不得不盲目键入echo hello world并在之后按 Ctrl+D 退出):

$ bash --posix
bash-4.4$ exec 1>./mylog_`date '+%Y%m%d_%H%M%S'`.log 2>&1
$ cat ./mylog_20180424_010800.log 
bash-4.4$ echo hello world
hello world
bash-4.4$ exit
Run Code Online (Sandbox Code Playgroud)

一点一点地做,显示bash输出提示stderr流式传输,并且令人惊讶地与我输入的任何内容一起:

bash-4.4$ exec 1> ./mylog.txt
bash-4.4$ echo Hello World
bash-4.4$ cat ./mylog.txt
cat: ./mylog.txt: input file is output file
bash-4.4$ exec 2>&1
Run Code Online (Sandbox Code Playgroud)

如果发生ksh同样的事情,但我可以看到正在输入的内容,只有提示转到文件,即标准输入没有被重定向:

bash-4.4$ ksh
$ exec 1>./mylog 2>&1
echo hello askubuntu
bash-4.4$ cat ./mylog
$ hello askubuntu
$ 
bash-4.4$ 
Run Code Online (Sandbox Code Playgroud)

所以在这里我们可以看到 shell 可以选择将提示PS1也输出到标准流之一,以便将其包含到文件中。