从shell脚本获取完整命令

时间:2015-01-08 01:10:16

标签: linux bash shell unix scripting

我正在寻找一种从shell脚本访问完整命令的方法,例如

假设我有一个名为 test.sh 的脚本。当我运行它时,命令行按原样传递给ruby(除了脚本本身被删除)。

$ test.sh print ENV['HOME']

相当于

$ ruby -e "print ENV['HOME']"

1 个答案:

答案 0 :(得分:1)

当你跑步时:

test.sh print ENV['HOME']

...然后,在启动 test.sh之前,shell运行字符串拆分,扩展和类似的进程。因此,最终运行的是(假设没有全局扩展):

execvp("test.sh", {"test.sh", "print", "ENV[HOME]"});

如果当前目录中有一个名为ENVH的文件,那么shell可能会将ENV['HOME']视为一个glob,通过将glob表达式替换为文件名来扩展它,从而运行:

execvp("test.sh", {"test.sh", "print", "ENVH"});

...无论如何,在运行新程序的execv* - 系列调用的另一端存在的内容没有原始shell本地的信息 - 因此无法知道在解析和扩展之前原始命令是什么。 因此,除非修改外壳以将其暴露在带外(通过环境变量),否则无法检索原始字符串。

这就是为什么您的调用约定应该要求:

test.sh "print ENV['HOME']"

或者,允许shell引用/转义语法更自由,通过stdin传递程序文本,如:

test.sh <<'EOF'
print ENV['HOME']
EOF

现在,如果您想修改shell来执行此操作,我建议使用一个公开BASH_COMMAND的函数。例如:

shopt -s extdebug
expose_command() {
  export SHELL_COMMAND="$BASH_COMMAND"
  return 0
}
trap expose_command DEBUG

...然后,在test.sh内,您可以参考SHELL_COMMAND。但是,这只会在调用shell配置了陷阱时才会起作用,就像在用户~/.bashrc中一样;您不能简单地将上述内容放在脚本中并希望它能够正常工作,因为它只是交互式shell - 脚本的父进程 - 可以访问此信息并且因此能够揭露它。