首页 > 解决方案 > 将命令存储在变量中;不使用 eval 实现

问题描述

这与这篇文章中的问题几乎完全相同,只是我不想使用eval

简短的快速问题,我想echo aaa | grep a通过首先将命令存储在字符串变量中来执行命令Command='echo aaa | grep a',然后在不使用 eval的情况下运行它。

在上面的帖子中,选择的答案使用了eval. 这也适用于我。我最担心的是下面有很多警告eval,然后是一些试图规避它的尝试。但是,他们都无法解决我的问题(本质上是 OP)。我已经在他们的尝试下方发表了评论,但是由于它已经存在了很长时间,我认为最好再次发布问题并限制使用eval.

具体例子

我想要的是一个在我高兴时运行我的命令的 shell 脚本:

#!/bin/bash
# This script run-this-if.sh runs the commands when I am happy
# Warning: the following script does not work (on nose)
if [ "$1" == "I-am-happy" ]; then
    "$2"
fi

$ run-if.sh I-am-happy [insert-any-command]

标签: shelleval

解决方案


您的示例用法永远无法与分配一起使用,因为分配的范围仅限于当前进程及其子进程。因为没有理由尝试支持作业,所以事情突然变得容易多了:

#!/bin/sh
if [ "$1" = "I-am-happy" ]; then
    shift; "$@"
fi

这随后可以使用所有常用技术来运行 shell 管道,例如:

run-if-happy "$happiness" \
  sh -c 'echo "$1" | grep "$2"' _ "$untrustedStringOne" "$untrustedStringTwo"

请注意,我们向execve()系统调用传递了一个包含六个元素的 argv:

  • sh(要运行的外壳;如果愿意,可以更改为bashetc)
  • -c(告诉 shell 以下参数是它运行的代码)
  • echo "$1" | grep "$2"(用于sh解析的代码)
  • _(变成 的常数$0
  • ...无论 shell 变量untrustedStringOne包含什么...(变为$1
  • ...无论 shell 变量untrustedStringTwo包含什么...(变为$2

请注意,这echo "$1" | grep "$2"是一个常量字符串——在单引号中,没有参数扩展或命令替换——并且不受信任的值被传递到填充$1和的插槽中$2,带外来自正在评估的代码;这对于提高安全性至关重要eval


推荐阅读