我正在尝试创建一个 bash 脚本,将终端历史记录保存到名为 hist.txt 的文件中。history > hist.txt
在 bash 脚本中使用似乎不起作用,但在命令行中执行时可以正常工作。
非常感谢任何指导。
谢谢你朱迪
答案1
简短答案
source
使用或运行脚本.
:
source ./script_name.sh
或者
. ./script_name.sh
后者在不同的 shell 之间的兼容性稍微好一些。
长答案
这个问题突出了一个重要点,即 shell 脚本在其自己的上下文中运行。要了解这意味着什么,请考虑以下 shell 脚本:
#!/bin/bash
cd /
ls
如果你运行这个,你会得到类似这样的输出:
bin boot dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
但是您会注意到,运行脚本后,您仍然位于运行脚本之前所在的目录中:cd /
脚本内部实际上并没有影响您的会话 - 它只影响脚本运行的上下文,该上下文是为脚本运行而创建的,并在返回后销毁。
该source
命令将“在当前 shell 上下文中从 filename 参数读取并执行命令”,因此其中的任何命令cd
都会影响您当前的会话。如果您通过将上面的脚本传递给您来运行它,source
您会发现在它运行后您最终进入了根目录。
在这种情况下,问题在于该history
命令为您提供了当前 shell 上下文的历史记录;您的脚本在不使用的情况下运行的 shell 上下文source
没有历史记录,因此它不会将任何内容写入输出文件。如果您使用source
它,它将在正确的上下文中执行,并将按预期工作。
注意:source
是内置的 shell,而不是程序本身- 在 Bash 中,source
与 同义.
,但仅在某些 shell 中才.
有效 - 我source
在这个答案中使用了 ,因为它比 更容易阅读.
,但为了最大限度地兼容,.
应该使用。
答案2
首先,请注意,您的历史记录已在文件中。如果您正在运行 bash,其名称通常为~/.bash_history
。更具体地说,它是您为变量设置的任何内容HISTFILE
。如果您想将其复制到另一个文件,只需运行cat "$HISTFILE" > hist.txt
现在,至于为什么该history
命令在 bash shell 脚本中不起作用,那是因为脚本在当前 shell 会话的非交互式子 shell 中运行。子 shell 不会继承父级的所有环境(因此不是所有设置的变量),只会继承已导出的变量。为了说明这一点,下面的脚本将回显变量的值$var
:
#!/bin/bash
echo "$var"
现在,设置$var
某些内容并运行脚本:
$ var="foo"
$ foo.sh
VAR:
接下来,先导出变量:
$ var="foo"
$ export var
$ foo.sh
VAR: foo
如您所见,当变量被导出后,子 shell 就可以使用它。
正如我之前提到的,历史记录存储在变量指向的文件中$HISTFILENAME
。由于默认情况下不会导出该文件,因此在运行脚本时不会设置它:
$ cat foo.sh
#!/bin/bash
echo "HISTFILE: $HISTFILE"
$ ./foo.sh
HISTFILE:
$ echo $HISTFILE
/home/terdon/.bash_history
正如您在上面的示例中看到的,该变量HISTFILE
在我的正常 shell 会话中设置,但在运行脚本时为空。
因此,要获取历史记录,您有以下几种选择:
默认值为
HISTFILE
。$HOME/.bash_history
如果您尚未更改,则只需在脚本中运行此命令即可:cat "$HOME/.bash_history" > history
您可以将
$HISTFILE
变量传递给您的脚本,然后cat
:#!/bin/bash cat "$1" > history
将以上内容保存为
foo.sh
并运行如下:./foo.sh "$HISTORY"
确保变量已导出。将此行添加到您的
~/.bash_profile
(如果存在)或~/.profile
(如果~/.bash_profile
不存在)文件中:export HISTFILE
然后,注销并重新登录,您应该能够
history > hist.txt
按预期从脚本运行。这是因为export VAR
意味着“使 $VAR 可供子 shell 使用”。实际上,这意味着 的值HISTFILE
将由您用于运行脚本的非交互式 shell 继承。现在,虽然
HISTFILE
将设置,但运行脚本的 shell 尚未读取它。因此,要使其工作,您需要history -r
先读取它。整个脚本如下所示:$!/bin/bash history -r history > hist.txt
或者,在运行脚本之前手动导出它:
$ export HISTFILE
但您仍然需要
history -r
在脚本中这样做。您可以
source
按照建议进行@p0llard 的回答。