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